apiblaze 0.6.1 → 0.8.0
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 +473 -115
- 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,27 @@ 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
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
var types_exports = {};
|
|
35
|
+
__export(types_exports, {
|
|
36
|
+
ApiError: () => ApiError
|
|
37
|
+
});
|
|
38
|
+
var ApiError;
|
|
39
|
+
var init_types = __esm({
|
|
40
|
+
"src/types.ts"() {
|
|
41
|
+
"use strict";
|
|
42
|
+
ApiError = class extends Error {
|
|
43
|
+
constructor(status, message, body) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.status = status;
|
|
46
|
+
this.body = body;
|
|
47
|
+
this.name = "ApiError";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
40
50
|
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// src/commands/login.ts
|
|
44
|
-
var import_chalk2 = __toESM(require("chalk"));
|
|
45
|
-
var import_ora = __toESM(require("ora"));
|
|
51
|
+
});
|
|
46
52
|
|
|
47
53
|
// 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
54
|
function saveCredentials(creds) {
|
|
54
55
|
fs.mkdirSync(APIBLAZE_DIR, { recursive: true });
|
|
55
56
|
fs.writeFileSync(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
@@ -81,13 +82,34 @@ function getAccessToken() {
|
|
|
81
82
|
}
|
|
82
83
|
return creds.accessToken;
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
var fs, os, path, APIBLAZE_DIR, CREDENTIALS_PATH;
|
|
86
|
+
var init_auth = __esm({
|
|
87
|
+
"src/lib/auth.ts"() {
|
|
88
|
+
"use strict";
|
|
89
|
+
fs = __toESM(require("fs"));
|
|
90
|
+
os = __toESM(require("os"));
|
|
91
|
+
path = __toESM(require("path"));
|
|
92
|
+
APIBLAZE_DIR = path.join(os.homedir(), ".apiblaze");
|
|
93
|
+
CREDENTIALS_PATH = path.join(APIBLAZE_DIR, "credentials.json");
|
|
94
|
+
}
|
|
95
|
+
});
|
|
87
96
|
|
|
88
97
|
// src/lib/api.ts
|
|
89
|
-
var
|
|
90
|
-
|
|
98
|
+
var api_exports = {};
|
|
99
|
+
__export(api_exports, {
|
|
100
|
+
agentCall: () => agentCall,
|
|
101
|
+
checkProxyName: () => checkProxyName,
|
|
102
|
+
claimProxy: () => claimProxy,
|
|
103
|
+
claimTeam: () => claimTeam,
|
|
104
|
+
createProxy: () => createProxy,
|
|
105
|
+
createProxyAnonymous: () => createProxyAnonymous,
|
|
106
|
+
deleteDevTunnel: () => deleteDevTunnel,
|
|
107
|
+
getLocalhostTargets: () => getLocalhostTargets,
|
|
108
|
+
getProjects: () => getProjects,
|
|
109
|
+
getTeams: () => getTeams,
|
|
110
|
+
putDevTunnel: () => putDevTunnel,
|
|
111
|
+
sidecarInitAnonymous: () => sidecarInitAnonymous
|
|
112
|
+
});
|
|
91
113
|
async function createProxyAnonymous(body) {
|
|
92
114
|
const res = await fetch(`${PUBLIC_API_BASE}/proxy`, {
|
|
93
115
|
method: "POST",
|
|
@@ -105,9 +127,9 @@ async function createProxyAnonymous(body) {
|
|
|
105
127
|
}
|
|
106
128
|
return res.json();
|
|
107
129
|
}
|
|
108
|
-
async function apiFetch(
|
|
130
|
+
async function apiFetch(path5, options = {}) {
|
|
109
131
|
const token = getAccessToken();
|
|
110
|
-
const url = `${DASHBOARD_BASE}${
|
|
132
|
+
const url = `${DASHBOARD_BASE}${path5}`;
|
|
111
133
|
const res = await fetch(url, {
|
|
112
134
|
...options,
|
|
113
135
|
headers: {
|
|
@@ -121,8 +143,9 @@ async function apiFetch(path4, options = {}) {
|
|
|
121
143
|
let parsed;
|
|
122
144
|
try {
|
|
123
145
|
parsed = await res.json();
|
|
146
|
+
const pick2 = (v) => typeof v === "string" ? v : v && typeof v === "object" ? pick2(v.message) ?? pick2(v.error) : void 0;
|
|
124
147
|
const b = parsed;
|
|
125
|
-
message = b.message ?? b.error ?? message;
|
|
148
|
+
message = pick2(b.message) ?? pick2(b.error) ?? pick2(b.details) ?? message;
|
|
126
149
|
} catch {
|
|
127
150
|
}
|
|
128
151
|
throw new ApiError(res.status, message, parsed);
|
|
@@ -132,12 +155,12 @@ async function apiFetch(path4, options = {}) {
|
|
|
132
155
|
}
|
|
133
156
|
return res.json();
|
|
134
157
|
}
|
|
135
|
-
async function agentCall(
|
|
158
|
+
async function agentCall(path5, method, body) {
|
|
136
159
|
const token = getAccessToken();
|
|
137
160
|
const res = await fetch(`${DASHBOARD_BASE}/api/cli/agents`, {
|
|
138
161
|
method: "POST",
|
|
139
162
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
140
|
-
body: JSON.stringify({ path:
|
|
163
|
+
body: JSON.stringify({ path: path5, method, body })
|
|
141
164
|
});
|
|
142
165
|
let data = null;
|
|
143
166
|
try {
|
|
@@ -177,6 +200,22 @@ async function claimProxy(claimCode, teamId) {
|
|
|
177
200
|
body: JSON.stringify({ claimCode, team_id: teamId })
|
|
178
201
|
});
|
|
179
202
|
}
|
|
203
|
+
async function claimTeam(code) {
|
|
204
|
+
return apiFetch("/api/cli/claim-team", {
|
|
205
|
+
method: "POST",
|
|
206
|
+
body: JSON.stringify({ code })
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
async function sidecarInitAnonymous() {
|
|
210
|
+
const res = await fetch(`${PUBLIC_API_BASE}/sidecar/init`, {
|
|
211
|
+
method: "POST",
|
|
212
|
+
headers: { "content-type": "application/json" },
|
|
213
|
+
body: "{}"
|
|
214
|
+
});
|
|
215
|
+
const data = await res.json().catch(() => ({}));
|
|
216
|
+
if (!res.ok) throw new ApiError(res.status, data?.error ?? "init_failed", data);
|
|
217
|
+
return data;
|
|
218
|
+
}
|
|
180
219
|
async function putDevTunnel(payload) {
|
|
181
220
|
return apiFetch("/api/cli/dev-tunnel", {
|
|
182
221
|
method: "PUT",
|
|
@@ -189,8 +228,103 @@ async function deleteDevTunnel(restore) {
|
|
|
189
228
|
body: JSON.stringify({ restore })
|
|
190
229
|
});
|
|
191
230
|
}
|
|
231
|
+
var DASHBOARD_BASE, PUBLIC_API_BASE;
|
|
232
|
+
var init_api = __esm({
|
|
233
|
+
"src/lib/api.ts"() {
|
|
234
|
+
"use strict";
|
|
235
|
+
init_auth();
|
|
236
|
+
init_types();
|
|
237
|
+
DASHBOARD_BASE = "https://dashboard.apiblaze.com";
|
|
238
|
+
PUBLIC_API_BASE = "https://api.apiblaze.com";
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// src/lib/anon-cred.ts
|
|
243
|
+
var anon_cred_exports = {};
|
|
244
|
+
__export(anon_cred_exports, {
|
|
245
|
+
clearAnonCred: () => clearAnonCred,
|
|
246
|
+
cpFetch: () => cpFetch,
|
|
247
|
+
loadAnonCred: () => loadAnonCred,
|
|
248
|
+
saveAnonCred: () => saveAnonCred
|
|
249
|
+
});
|
|
250
|
+
function loadAnonCred() {
|
|
251
|
+
try {
|
|
252
|
+
const c = JSON.parse(fs2.readFileSync(FILE, "utf8"));
|
|
253
|
+
return c?.cp_key ? c : null;
|
|
254
|
+
} catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function saveAnonCred(cp_key, team_id, claim_code) {
|
|
259
|
+
try {
|
|
260
|
+
fs2.mkdirSync(DIR, { recursive: true });
|
|
261
|
+
const prev = loadAnonCred();
|
|
262
|
+
const merged = {
|
|
263
|
+
cp_key,
|
|
264
|
+
team_id,
|
|
265
|
+
claim_code: claim_code ?? prev?.claim_code,
|
|
266
|
+
created_at: prev?.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
267
|
+
};
|
|
268
|
+
fs2.writeFileSync(FILE, JSON.stringify(merged, null, 2));
|
|
269
|
+
} catch {
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function clearAnonCred() {
|
|
273
|
+
try {
|
|
274
|
+
fs2.unlinkSync(FILE);
|
|
275
|
+
} catch {
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async function cpFetch(cpKey, apiPath, opts = {}) {
|
|
279
|
+
const res = await fetch(`${CP_EDGE}${apiPath}`, {
|
|
280
|
+
...opts,
|
|
281
|
+
headers: { "Content-Type": "application/json", "X-API-Key": cpKey, ...opts.headers ?? {} }
|
|
282
|
+
});
|
|
283
|
+
const text = await res.text();
|
|
284
|
+
let parsed;
|
|
285
|
+
try {
|
|
286
|
+
parsed = text ? JSON.parse(text) : void 0;
|
|
287
|
+
} catch {
|
|
288
|
+
parsed = text;
|
|
289
|
+
}
|
|
290
|
+
if (!res.ok) {
|
|
291
|
+
const msg = parsed && typeof parsed === "object" && (parsed.details ?? parsed.error) || res.statusText;
|
|
292
|
+
throw new ApiError(res.status, typeof msg === "string" ? msg : JSON.stringify(msg), parsed);
|
|
293
|
+
}
|
|
294
|
+
return parsed;
|
|
295
|
+
}
|
|
296
|
+
var fs2, path2, os2, DIR, FILE, CP_EDGE;
|
|
297
|
+
var init_anon_cred = __esm({
|
|
298
|
+
"src/lib/anon-cred.ts"() {
|
|
299
|
+
"use strict";
|
|
300
|
+
fs2 = __toESM(require("fs"));
|
|
301
|
+
path2 = __toESM(require("path"));
|
|
302
|
+
os2 = __toESM(require("os"));
|
|
303
|
+
init_types();
|
|
304
|
+
DIR = path2.join(os2.homedir(), ".apiblaze");
|
|
305
|
+
FILE = path2.join(DIR, "anon.json");
|
|
306
|
+
CP_EDGE = process.env.APIBLAZE_API_BASE ? `${process.env.APIBLAZE_API_BASE}/1.0.0/prod` : "https://api.apiblaze.com/1.0.0/prod";
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// src/index.ts
|
|
311
|
+
var import_commander = require("commander");
|
|
312
|
+
var import_chalk30 = __toESM(require("chalk"));
|
|
313
|
+
|
|
314
|
+
// package.json
|
|
315
|
+
var version = "0.8.0";
|
|
316
|
+
|
|
317
|
+
// src/index.ts
|
|
318
|
+
init_types();
|
|
319
|
+
|
|
320
|
+
// src/commands/login.ts
|
|
321
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
322
|
+
var import_ora = __toESM(require("ora"));
|
|
323
|
+
init_auth();
|
|
192
324
|
|
|
193
325
|
// src/lib/team.ts
|
|
326
|
+
var import_chalk = __toESM(require("chalk"));
|
|
327
|
+
init_api();
|
|
194
328
|
async function resolveLinkedTeam(opts) {
|
|
195
329
|
let teams;
|
|
196
330
|
try {
|
|
@@ -319,6 +453,37 @@ ${import_chalk2.default.cyan("\u2192")} Team: ${import_chalk2.default.bold(teamN
|
|
|
319
453
|
teamName
|
|
320
454
|
});
|
|
321
455
|
console.log(import_chalk2.default.green("\n\u2714 Logged in successfully!"));
|
|
456
|
+
await offerClaimPendingAnon();
|
|
457
|
+
}
|
|
458
|
+
async function offerClaimPendingAnon() {
|
|
459
|
+
const { loadAnonCred: loadAnonCred2, clearAnonCred: clearAnonCred2 } = await Promise.resolve().then(() => (init_anon_cred(), anon_cred_exports));
|
|
460
|
+
const cred = loadAnonCred2();
|
|
461
|
+
if (!cred?.claim_code) return;
|
|
462
|
+
let doClaim = true;
|
|
463
|
+
if (process.stdin.isTTY) {
|
|
464
|
+
const { default: inquirer2 } = await import("inquirer");
|
|
465
|
+
const { yes } = await inquirer2.prompt([{
|
|
466
|
+
type: "confirm",
|
|
467
|
+
name: "yes",
|
|
468
|
+
message: "You created proxies anonymously before logging in. Claim them into this account?",
|
|
469
|
+
default: true
|
|
470
|
+
}]);
|
|
471
|
+
doClaim = yes;
|
|
472
|
+
}
|
|
473
|
+
if (!doClaim) {
|
|
474
|
+
console.log(import_chalk2.default.dim(" Left unclaimed \u2014 run `apiblaze claim` anytime to keep them (they GC after inactivity)."));
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
try {
|
|
478
|
+
const { claimTeam: claimTeam2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
479
|
+
const t = await claimTeam2(cred.claim_code);
|
|
480
|
+
clearAnonCred2();
|
|
481
|
+
console.log(import_chalk2.default.green(` \u2714 Claimed your anonymous proxies into your account (team ${import_chalk2.default.bold(t.team_id)}).`));
|
|
482
|
+
} catch (err) {
|
|
483
|
+
const { ApiError: ApiError2 } = await Promise.resolve().then(() => (init_types(), types_exports));
|
|
484
|
+
const why = err instanceof ApiError2 ? err.message : err instanceof Error ? err.message : "error";
|
|
485
|
+
console.log(import_chalk2.default.yellow(` Couldn't auto-claim (${why}). Run \`apiblaze claim\` to retry.`));
|
|
486
|
+
}
|
|
322
487
|
}
|
|
323
488
|
|
|
324
489
|
// src/commands/dev.ts
|
|
@@ -326,6 +491,8 @@ var import_fs = __toESM(require("fs"));
|
|
|
326
491
|
var import_chalk4 = __toESM(require("chalk"));
|
|
327
492
|
var import_ora2 = __toESM(require("ora"));
|
|
328
493
|
var import_inquirer = __toESM(require("inquirer"));
|
|
494
|
+
init_auth();
|
|
495
|
+
init_api();
|
|
329
496
|
|
|
330
497
|
// src/lib/traffic.ts
|
|
331
498
|
var import_chalk3 = __toESM(require("chalk"));
|
|
@@ -420,11 +587,11 @@ function decodeJwt(token) {
|
|
|
420
587
|
return null;
|
|
421
588
|
}
|
|
422
589
|
}
|
|
423
|
-
function maskPath(
|
|
424
|
-
const q =
|
|
425
|
-
if (q < 0) return
|
|
426
|
-
const base =
|
|
427
|
-
const query =
|
|
590
|
+
function maskPath(path5) {
|
|
591
|
+
const q = path5.indexOf("?");
|
|
592
|
+
if (q < 0) return path5;
|
|
593
|
+
const base = path5.slice(0, q);
|
|
594
|
+
const query = path5.slice(q + 1);
|
|
428
595
|
const masked = query.split("&").map((pair) => {
|
|
429
596
|
const eq = pair.indexOf("=");
|
|
430
597
|
if (eq < 0) return pair;
|
|
@@ -1018,6 +1185,8 @@ Tunneling ${selectedTargets.length} project(s) to localhost:${options.port}
|
|
|
1018
1185
|
// src/commands/projects.ts
|
|
1019
1186
|
var import_chalk5 = __toESM(require("chalk"));
|
|
1020
1187
|
var import_ora3 = __toESM(require("ora"));
|
|
1188
|
+
init_auth();
|
|
1189
|
+
init_api();
|
|
1021
1190
|
async function runProjects() {
|
|
1022
1191
|
const creds = loadCredentials();
|
|
1023
1192
|
if (!creds) {
|
|
@@ -1077,6 +1246,8 @@ ${projects.length} project${projects.length === 1 ? "" : "s"}`));
|
|
|
1077
1246
|
var import_fs2 = __toESM(require("fs"));
|
|
1078
1247
|
var import_chalk6 = __toESM(require("chalk"));
|
|
1079
1248
|
var import_ora4 = __toESM(require("ora"));
|
|
1249
|
+
init_auth();
|
|
1250
|
+
init_api();
|
|
1080
1251
|
function normalizeName(raw) {
|
|
1081
1252
|
return (raw || "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1082
1253
|
}
|
|
@@ -1345,10 +1516,23 @@ async function runAnonymousCreate(opts) {
|
|
|
1345
1516
|
if (opts.displayName) body.display_name = opts.displayName;
|
|
1346
1517
|
if (opts.apiversion) body.api_version = opts.apiversion;
|
|
1347
1518
|
if (opts.auth && opts.auth !== "api_key") body.auth_type = opts.auth;
|
|
1348
|
-
const
|
|
1519
|
+
const { loadAnonCred: loadAnonCred2, saveAnonCred: saveAnonCred2, clearAnonCred: clearAnonCred2, cpFetch: cpFetch2 } = await Promise.resolve().then(() => (init_anon_cred(), anon_cred_exports));
|
|
1520
|
+
if (opts.newSession) clearAnonCred2();
|
|
1521
|
+
const cred = loadAnonCred2();
|
|
1522
|
+
const spinner = !opts.json ? (0, import_ora4.default)(cred ? "Creating proxy (in your anonymous workspace)..." : "Creating proxy...").start() : null;
|
|
1349
1523
|
let result;
|
|
1350
1524
|
try {
|
|
1351
|
-
|
|
1525
|
+
if (cred) {
|
|
1526
|
+
result = await cpFetch2(cred.cp_key, "/projects", { method: "POST", body: JSON.stringify(body) });
|
|
1527
|
+
if (Array.isArray(result.endpoints)) {
|
|
1528
|
+
result.endpoints = result.endpoints.map((e) => e.replace(/:\/\/[^/]+/, `://${result.project_id}.tryabz.run`));
|
|
1529
|
+
}
|
|
1530
|
+
} else {
|
|
1531
|
+
result = await createProxyAnonymous(body);
|
|
1532
|
+
if (result.cp_key && result.team_id) {
|
|
1533
|
+
saveAnonCred2(result.cp_key, result.team_id, result.team_claim_code);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1352
1536
|
spinner?.succeed(import_chalk6.default.green("Proxy created!"));
|
|
1353
1537
|
} catch (err) {
|
|
1354
1538
|
spinner?.fail("Failed to create proxy.");
|
|
@@ -1380,17 +1564,27 @@ async function runAnonymousCreate(opts) {
|
|
|
1380
1564
|
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
1565
|
}
|
|
1382
1566
|
if (prodEndpoint) printCurlExample(prodEndpoint, opts.auth || "api_key", apiKey, result.portal);
|
|
1383
|
-
|
|
1567
|
+
const claimCode = result.team_claim_code || cred?.claim_code;
|
|
1568
|
+
if (claimCode) {
|
|
1569
|
+
console.log();
|
|
1570
|
+
console.log(` ${import_chalk6.default.yellow("\u26A0 Anonymous \u2014 claim within 30 days or it expires.")} All your anonymous proxies`);
|
|
1571
|
+
console.log(` on this machine share ONE workspace. To keep them all:`);
|
|
1572
|
+
console.log(` ${import_chalk6.default.cyan("apiblaze login")} ${import_chalk6.default.dim("(prompts to claim them into your account)")}`);
|
|
1573
|
+
console.log(import_chalk6.default.dim(` From another machine: apiblaze claim ${claimCode}`));
|
|
1574
|
+
} else if (result.claim_url) {
|
|
1384
1575
|
console.log();
|
|
1385
1576
|
console.log(` ${import_chalk6.default.yellow("\u26A0 Anonymous proxy \u2014 claim it to your account within 30 days or it expires:")}`);
|
|
1386
1577
|
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
1578
|
}
|
|
1389
1579
|
console.log();
|
|
1390
1580
|
}
|
|
1391
1581
|
|
|
1392
1582
|
// src/commands/claim.ts
|
|
1393
1583
|
var import_chalk7 = __toESM(require("chalk"));
|
|
1584
|
+
init_auth();
|
|
1585
|
+
init_anon_cred();
|
|
1586
|
+
init_api();
|
|
1587
|
+
init_types();
|
|
1394
1588
|
function fail2(message) {
|
|
1395
1589
|
console.error(import_chalk7.default.red(`Error: ${message}`));
|
|
1396
1590
|
process.exit(1);
|
|
@@ -1401,6 +1595,14 @@ async function runClaim(claimCodeArg, opts) {
|
|
|
1401
1595
|
fail2("Not logged in. Run `apiblaze login` first, then claim.");
|
|
1402
1596
|
}
|
|
1403
1597
|
let claimCode = (claimCodeArg ?? "").trim();
|
|
1598
|
+
let fromLocalSession = false;
|
|
1599
|
+
if (!claimCode) {
|
|
1600
|
+
const sess = loadAnonCred();
|
|
1601
|
+
if (sess?.claim_code) {
|
|
1602
|
+
claimCode = sess.claim_code;
|
|
1603
|
+
fromLocalSession = true;
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1404
1606
|
if (!claimCode && process.stdin.isTTY) {
|
|
1405
1607
|
const { default: inquirer2 } = await import("inquirer");
|
|
1406
1608
|
const { code } = await inquirer2.prompt([{
|
|
@@ -1411,7 +1613,30 @@ async function runClaim(claimCodeArg, opts) {
|
|
|
1411
1613
|
claimCode = (code ?? "").trim();
|
|
1412
1614
|
}
|
|
1413
1615
|
if (!claimCode) {
|
|
1414
|
-
fail2("
|
|
1616
|
+
fail2("Nothing to claim on this machine. Run `apiblaze claim <code>` with a code, or `apiblaze create`/`init` first.");
|
|
1617
|
+
}
|
|
1618
|
+
try {
|
|
1619
|
+
const t = await claimTeam(claimCode);
|
|
1620
|
+
if (fromLocalSession) clearAnonCred();
|
|
1621
|
+
if (opts.json) {
|
|
1622
|
+
console.log(JSON.stringify(t, null, 2));
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
console.log(import_chalk7.default.green(`
|
|
1626
|
+
\u2714 Claimed the whole team into your account.`));
|
|
1627
|
+
console.log(` Team: ${import_chalk7.default.bold(t.team_id)}`);
|
|
1628
|
+
console.log(` Its proxies + keys are now yours. Switch to it with ${import_chalk7.default.cyan(`apiblaze team ${t.team_id}`)}.`);
|
|
1629
|
+
console.log(`
|
|
1630
|
+
Manage it at ${import_chalk7.default.cyan("https://dashboard.apiblaze.com/dashboard")}`);
|
|
1631
|
+
return;
|
|
1632
|
+
} catch (err) {
|
|
1633
|
+
if (err instanceof ApiError && err.status !== 404) {
|
|
1634
|
+
const code = typeof err.body === "object" && err.body ? err.body.error : void 0;
|
|
1635
|
+
if (code === "already_claimed") fail2("That claim code has already been used.");
|
|
1636
|
+
if (code === "expired") fail2("That claim code has expired. Create a fresh setup with `apiblaze init`.");
|
|
1637
|
+
if (code === "not_claimable") fail2("That team can no longer be claimed (it already belongs to an account).");
|
|
1638
|
+
fail2(`Could not claim: ${err.message}`);
|
|
1639
|
+
}
|
|
1415
1640
|
}
|
|
1416
1641
|
const teams = await getTeams().catch(() => []);
|
|
1417
1642
|
if (teams.length === 0) {
|
|
@@ -1443,7 +1668,13 @@ async function runClaim(claimCodeArg, opts) {
|
|
|
1443
1668
|
fail2(`Specify a team: \`apiblaze claim ${claimCode} --team <name|id>\`. Available: ${teams.map((t) => t.name).join(", ")}.`);
|
|
1444
1669
|
}
|
|
1445
1670
|
const teamName = teams.find((t) => t.teamId === teamId)?.name ?? teamId;
|
|
1446
|
-
|
|
1671
|
+
let result;
|
|
1672
|
+
try {
|
|
1673
|
+
result = await claimProxy(claimCode, teamId);
|
|
1674
|
+
} catch (err) {
|
|
1675
|
+
if (err instanceof ApiError) fail2(`That claim code isn't valid \u2014 it may be mistyped, already claimed, or expired.`);
|
|
1676
|
+
throw err;
|
|
1677
|
+
}
|
|
1447
1678
|
if (opts.json) {
|
|
1448
1679
|
console.log(JSON.stringify(result, null, 2));
|
|
1449
1680
|
return;
|
|
@@ -1461,32 +1692,33 @@ async function runClaim(claimCodeArg, opts) {
|
|
|
1461
1692
|
|
|
1462
1693
|
// src/commands/logout.ts
|
|
1463
1694
|
var import_chalk8 = __toESM(require("chalk"));
|
|
1695
|
+
init_auth();
|
|
1464
1696
|
|
|
1465
1697
|
// src/lib/consumer-auth.ts
|
|
1466
|
-
var
|
|
1467
|
-
var
|
|
1468
|
-
var
|
|
1698
|
+
var fs5 = __toESM(require("fs"));
|
|
1699
|
+
var os3 = __toESM(require("os"));
|
|
1700
|
+
var path3 = __toESM(require("path"));
|
|
1469
1701
|
var crypto = __toESM(require("crypto"));
|
|
1470
1702
|
var import_child_process = require("child_process");
|
|
1471
1703
|
var AUTH_BASE = process.env.APIBLAZE_AUTH_BASE || "https://auth.apiblaze.com";
|
|
1472
|
-
var APIBLAZE_DIR2 =
|
|
1473
|
-
var CONSUMER_PATH =
|
|
1704
|
+
var APIBLAZE_DIR2 = path3.join(os3.homedir(), ".apiblaze");
|
|
1705
|
+
var CONSUMER_PATH = path3.join(APIBLAZE_DIR2, "consumer.json");
|
|
1474
1706
|
var DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
1475
1707
|
function loadConsumer() {
|
|
1476
1708
|
try {
|
|
1477
|
-
return JSON.parse(
|
|
1709
|
+
return JSON.parse(fs5.readFileSync(CONSUMER_PATH, "utf-8"));
|
|
1478
1710
|
} catch {
|
|
1479
1711
|
return null;
|
|
1480
1712
|
}
|
|
1481
1713
|
}
|
|
1482
1714
|
function saveConsumer(creds) {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1715
|
+
fs5.mkdirSync(APIBLAZE_DIR2, { recursive: true });
|
|
1716
|
+
fs5.writeFileSync(CONSUMER_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
1717
|
+
fs5.chmodSync(CONSUMER_PATH, 384);
|
|
1486
1718
|
}
|
|
1487
1719
|
function clearConsumer() {
|
|
1488
1720
|
try {
|
|
1489
|
-
|
|
1721
|
+
fs5.unlinkSync(CONSUMER_PATH);
|
|
1490
1722
|
return true;
|
|
1491
1723
|
} catch {
|
|
1492
1724
|
return false;
|
|
@@ -1628,6 +1860,7 @@ async function runLogout(opts = {}) {
|
|
|
1628
1860
|
|
|
1629
1861
|
// src/commands/whoami.ts
|
|
1630
1862
|
var import_chalk9 = __toESM(require("chalk"));
|
|
1863
|
+
init_auth();
|
|
1631
1864
|
async function runWhoami(opts = {}) {
|
|
1632
1865
|
const creds = loadCredentials();
|
|
1633
1866
|
const consumer2 = loadConsumer();
|
|
@@ -1668,6 +1901,8 @@ async function runWhoami(opts = {}) {
|
|
|
1668
1901
|
|
|
1669
1902
|
// src/commands/team.ts
|
|
1670
1903
|
var import_chalk10 = __toESM(require("chalk"));
|
|
1904
|
+
init_auth();
|
|
1905
|
+
init_api();
|
|
1671
1906
|
function fail3(message) {
|
|
1672
1907
|
console.error(import_chalk10.default.red(`Error: ${message}`));
|
|
1673
1908
|
process.exit(1);
|
|
@@ -1712,10 +1947,13 @@ async function runTeam(arg) {
|
|
|
1712
1947
|
|
|
1713
1948
|
// src/commands/authz.ts
|
|
1714
1949
|
var import_chalk12 = __toESM(require("chalk"));
|
|
1950
|
+
init_auth();
|
|
1951
|
+
init_api();
|
|
1715
1952
|
|
|
1716
1953
|
// src/lib/agent-chat.ts
|
|
1717
1954
|
var import_readline = __toESM(require("readline"));
|
|
1718
1955
|
var import_chalk11 = __toESM(require("chalk"));
|
|
1956
|
+
init_api();
|
|
1719
1957
|
async function runAgentChatRepl(opts) {
|
|
1720
1958
|
const { title, subtitle, endpoint, buildBody, seedPrompt, summarizeProposal, commands } = opts;
|
|
1721
1959
|
console.log("\n" + import_chalk11.default.cyan.bold(title));
|
|
@@ -1885,6 +2123,8 @@ async function runAuthz(projectArg, apiVersionArg) {
|
|
|
1885
2123
|
|
|
1886
2124
|
// src/commands/openapi.ts
|
|
1887
2125
|
var import_chalk13 = __toESM(require("chalk"));
|
|
2126
|
+
init_auth();
|
|
2127
|
+
init_api();
|
|
1888
2128
|
async function runOpenapi(projectArg, apiVersionArg) {
|
|
1889
2129
|
const creds = loadCredentials();
|
|
1890
2130
|
if (!creds) throw new Error("Not authenticated. Run `apiblaze login` first.");
|
|
@@ -1949,6 +2189,8 @@ async function runOpenapi(projectArg, apiVersionArg) {
|
|
|
1949
2189
|
|
|
1950
2190
|
// src/commands/mcp.ts
|
|
1951
2191
|
var import_chalk14 = __toESM(require("chalk"));
|
|
2192
|
+
init_auth();
|
|
2193
|
+
init_api();
|
|
1952
2194
|
async function runMcp(projectArg, apiVersionArg, opts) {
|
|
1953
2195
|
const creds = loadCredentials();
|
|
1954
2196
|
if (!creds) throw new Error("Not authenticated. Run `apiblaze login` first.");
|
|
@@ -1994,6 +2236,7 @@ var import_ora5 = __toESM(require("ora"));
|
|
|
1994
2236
|
|
|
1995
2237
|
// src/lib/admin.ts
|
|
1996
2238
|
var import_chalk16 = __toESM(require("chalk"));
|
|
2239
|
+
init_auth();
|
|
1997
2240
|
|
|
1998
2241
|
// src/lib/trace.ts
|
|
1999
2242
|
var import_chalk15 = __toESM(require("chalk"));
|
|
@@ -2036,6 +2279,7 @@ function renderTrace() {
|
|
|
2036
2279
|
}
|
|
2037
2280
|
|
|
2038
2281
|
// src/lib/admin.ts
|
|
2282
|
+
init_types();
|
|
2039
2283
|
var DASHBOARD_BASE3 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
|
|
2040
2284
|
async function admin(call) {
|
|
2041
2285
|
const token = getAccessToken();
|
|
@@ -2068,6 +2312,8 @@ function maybePrintBilling(data) {
|
|
|
2068
2312
|
|
|
2069
2313
|
// src/lib/resolve.ts
|
|
2070
2314
|
var import_chalk17 = __toESM(require("chalk"));
|
|
2315
|
+
init_auth();
|
|
2316
|
+
init_api();
|
|
2071
2317
|
function requireAuth() {
|
|
2072
2318
|
const creds = loadCredentials();
|
|
2073
2319
|
if (!creds) {
|
|
@@ -2175,6 +2421,7 @@ async function runDelete(project, version2, opts) {
|
|
|
2175
2421
|
// src/commands/export.ts
|
|
2176
2422
|
var import_chalk19 = __toESM(require("chalk"));
|
|
2177
2423
|
var import_fs3 = require("fs");
|
|
2424
|
+
init_auth();
|
|
2178
2425
|
var DASHBOARD_BASE4 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
|
|
2179
2426
|
async function runExport(projectArg, versionArg, opts) {
|
|
2180
2427
|
const token = getAccessToken();
|
|
@@ -2581,7 +2828,7 @@ async function runKeyRevoke(keyId, opts) {
|
|
|
2581
2828
|
}
|
|
2582
2829
|
|
|
2583
2830
|
// src/commands/spec.ts
|
|
2584
|
-
var
|
|
2831
|
+
var fs6 = __toESM(require("fs"));
|
|
2585
2832
|
var import_chalk24 = __toESM(require("chalk"));
|
|
2586
2833
|
var import_ora10 = __toESM(require("ora"));
|
|
2587
2834
|
async function runSpecGet(project, opts) {
|
|
@@ -2601,7 +2848,7 @@ async function runSpecSet(project, opts) {
|
|
|
2601
2848
|
}
|
|
2602
2849
|
let specContent;
|
|
2603
2850
|
try {
|
|
2604
|
-
specContent =
|
|
2851
|
+
specContent = fs6.readFileSync(opts.file, "utf-8");
|
|
2605
2852
|
} catch {
|
|
2606
2853
|
console.error(import_chalk24.default.red(`Cannot read file: ${opts.file}`));
|
|
2607
2854
|
process.exit(1);
|
|
@@ -2627,9 +2874,11 @@ async function runSpecSet(project, opts) {
|
|
|
2627
2874
|
// src/commands/agent.ts
|
|
2628
2875
|
var import_chalk26 = __toESM(require("chalk"));
|
|
2629
2876
|
var import_ora11 = __toESM(require("ora"));
|
|
2877
|
+
init_auth();
|
|
2630
2878
|
|
|
2631
2879
|
// src/lib/tools.ts
|
|
2632
2880
|
var import_chalk25 = __toESM(require("chalk"));
|
|
2881
|
+
init_api();
|
|
2633
2882
|
async function proj(teamId, name, version2) {
|
|
2634
2883
|
return resolveProject(teamId, name, version2);
|
|
2635
2884
|
}
|
|
@@ -2779,6 +3028,7 @@ function findTool(name) {
|
|
|
2779
3028
|
}
|
|
2780
3029
|
|
|
2781
3030
|
// src/commands/agent.ts
|
|
3031
|
+
init_types();
|
|
2782
3032
|
var DASHBOARD_BASE5 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
|
|
2783
3033
|
var MAX_TOOL_STEPS = 6;
|
|
2784
3034
|
async function callAgent(messages, teamId) {
|
|
@@ -3040,44 +3290,59 @@ async function runConsumerApikeys(opts) {
|
|
|
3040
3290
|
// src/commands/sidecar.ts
|
|
3041
3291
|
var import_chalk28 = __toESM(require("chalk"));
|
|
3042
3292
|
var import_ora13 = __toESM(require("ora"));
|
|
3043
|
-
var
|
|
3044
|
-
var
|
|
3293
|
+
var fs7 = __toESM(require("fs"));
|
|
3294
|
+
var path4 = __toESM(require("path"));
|
|
3295
|
+
init_auth();
|
|
3045
3296
|
function detectNextProject(root) {
|
|
3046
|
-
const hasConfig = ["next.config.js", "next.config.mjs", "next.config.ts"].some((f) =>
|
|
3297
|
+
const hasConfig = ["next.config.js", "next.config.mjs", "next.config.ts"].some((f) => fs7.existsSync(path4.join(root, f)));
|
|
3047
3298
|
let hasDep = false;
|
|
3048
3299
|
try {
|
|
3049
|
-
const pkg = JSON.parse(
|
|
3300
|
+
const pkg = JSON.parse(fs7.readFileSync(path4.join(root, "package.json"), "utf8"));
|
|
3050
3301
|
hasDep = !!(pkg.dependencies?.next || pkg.devDependencies?.next);
|
|
3051
3302
|
} catch {
|
|
3052
3303
|
}
|
|
3053
|
-
const appDir =
|
|
3054
|
-
const pagesDir =
|
|
3304
|
+
const appDir = fs7.existsSync(path4.join(root, "app")) || fs7.existsSync(path4.join(root, "src", "app"));
|
|
3305
|
+
const pagesDir = fs7.existsSync(path4.join(root, "pages")) || fs7.existsSync(path4.join(root, "src", "pages"));
|
|
3055
3306
|
return { found: hasConfig || hasDep || appDir || pagesDir, router: appDir ? "app" : pagesDir ? "pages" : null };
|
|
3056
3307
|
}
|
|
3057
3308
|
function upsertEnvLocal(root, token) {
|
|
3058
|
-
const p =
|
|
3309
|
+
const p = path4.join(root, ".env.local");
|
|
3059
3310
|
let existing = "";
|
|
3060
3311
|
try {
|
|
3061
|
-
existing =
|
|
3312
|
+
existing = fs7.readFileSync(p, "utf8");
|
|
3062
3313
|
} catch {
|
|
3063
3314
|
}
|
|
3064
|
-
const had = /^APIBLAZE_TOKEN=/m.test(existing);
|
|
3065
|
-
|
|
3315
|
+
const had = /^APIBLAZE_API_KEY=/m.test(existing) || /^APIBLAZE_TOKEN=/m.test(existing);
|
|
3316
|
+
let next = existing.replace(/^APIBLAZE_TOKEN=.*\n?/m, "");
|
|
3317
|
+
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}
|
|
3318
|
+
`;
|
|
3319
|
+
if (!/^APIBLAZE_SIDECAR=/m.test(next)) {
|
|
3320
|
+
next = (next.endsWith("\n") ? next : next + "\n") + `APIBLAZE_SIDECAR=on
|
|
3066
3321
|
`;
|
|
3067
|
-
|
|
3322
|
+
}
|
|
3323
|
+
fs7.writeFileSync(p, next);
|
|
3068
3324
|
return had ? "rotated" : "created";
|
|
3069
3325
|
}
|
|
3326
|
+
function readEnvKey(root) {
|
|
3327
|
+
try {
|
|
3328
|
+
const s = fs7.readFileSync(path4.join(root, ".env.local"), "utf8");
|
|
3329
|
+
const m = s.match(/^APIBLAZE_API_KEY=(.+)$/m) ?? s.match(/^APIBLAZE_TOKEN=(.+)$/m);
|
|
3330
|
+
return m ? m[1].trim() : null;
|
|
3331
|
+
} catch {
|
|
3332
|
+
return null;
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3070
3335
|
function ensureGitignored(root) {
|
|
3071
|
-
const p =
|
|
3336
|
+
const p = path4.join(root, ".gitignore");
|
|
3072
3337
|
let c = "";
|
|
3073
3338
|
try {
|
|
3074
|
-
c =
|
|
3339
|
+
c = fs7.readFileSync(p, "utf8");
|
|
3075
3340
|
} catch {
|
|
3076
3341
|
}
|
|
3077
|
-
if (!/^\.env\.local$/m.test(c) && !/^\.env\*/m.test(c))
|
|
3342
|
+
if (!/^\.env\.local$/m.test(c) && !/^\.env\*/m.test(c)) fs7.writeFileSync(p, (c && !c.endsWith("\n") ? c + "\n" : c) + ".env.local\n");
|
|
3078
3343
|
}
|
|
3079
3344
|
function wireInstrumentation(root) {
|
|
3080
|
-
const existing = ["instrumentation.ts", "instrumentation.js",
|
|
3345
|
+
const existing = ["instrumentation.ts", "instrumentation.js", path4.join("src", "instrumentation.ts")].map((c) => path4.join(root, c)).find((f) => fs7.existsSync(f));
|
|
3081
3346
|
const body = `import { register as apiblaze } from "apiblaze/sidecar";
|
|
3082
3347
|
|
|
3083
3348
|
export function register() {
|
|
@@ -3085,18 +3350,18 @@ export function register() {
|
|
|
3085
3350
|
}
|
|
3086
3351
|
`;
|
|
3087
3352
|
if (!existing) {
|
|
3088
|
-
|
|
3353
|
+
fs7.writeFileSync(path4.join(root, "instrumentation.ts"), body);
|
|
3089
3354
|
return "created";
|
|
3090
3355
|
}
|
|
3091
|
-
const cur =
|
|
3356
|
+
const cur = fs7.readFileSync(existing, "utf8");
|
|
3092
3357
|
if (cur.includes("apiblaze/sidecar")) return "present";
|
|
3093
3358
|
if (/export\s+function\s+register\s*\(/.test(cur)) {
|
|
3094
|
-
|
|
3359
|
+
fs7.writeFileSync(existing, `import { register as apiblaze } from "apiblaze/sidecar";
|
|
3095
3360
|
` + cur.replace(/export\s+function\s+register\s*\(\s*\)\s*\{/, (m) => `${m}
|
|
3096
3361
|
apiblaze();`));
|
|
3097
3362
|
return "patched";
|
|
3098
3363
|
}
|
|
3099
|
-
|
|
3364
|
+
fs7.writeFileSync(existing, `import { register as apiblaze } from "apiblaze/sidecar";
|
|
3100
3365
|
${cur}
|
|
3101
3366
|
// call apiblaze() inside your register() export.
|
|
3102
3367
|
`);
|
|
@@ -3132,51 +3397,99 @@ export default async function Page() {
|
|
|
3132
3397
|
function generateInspector(root, router) {
|
|
3133
3398
|
try {
|
|
3134
3399
|
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
|
|
3400
|
+
const dir2 = fs7.existsSync(path4.join(root, "src", "pages")) ? path4.join(root, "src", "pages") : path4.join(root, "pages");
|
|
3401
|
+
const f2 = path4.join(dir2, "abz-inspector.tsx");
|
|
3402
|
+
fs7.writeFileSync(f2, INSPECTOR_PAGE);
|
|
3403
|
+
return path4.relative(root, f2);
|
|
3404
|
+
}
|
|
3405
|
+
const base = fs7.existsSync(path4.join(root, "src", "app")) ? path4.join(root, "src", "app") : path4.join(root, "app");
|
|
3406
|
+
const dir = path4.join(base, "abz-inspector");
|
|
3407
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
3408
|
+
const f = path4.join(dir, "page.tsx");
|
|
3409
|
+
fs7.writeFileSync(f, INSPECTOR_PAGE);
|
|
3410
|
+
return path4.relative(root, f);
|
|
3146
3411
|
} catch {
|
|
3147
3412
|
return null;
|
|
3148
3413
|
}
|
|
3149
3414
|
}
|
|
3150
|
-
async function
|
|
3151
|
-
const
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3415
|
+
async function runAnonymousInit(root, router, opts) {
|
|
3416
|
+
const { sidecarInitAnonymous: sidecarInitAnonymous2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
3417
|
+
const { saveAnonCred: saveAnonCred2, clearAnonCred: clearAnonCred2 } = await Promise.resolve().then(() => (init_anon_cred(), anon_cred_exports));
|
|
3418
|
+
if (opts.newSession) clearAnonCred2();
|
|
3419
|
+
const spinner = (0, import_ora13.default)("Setting up a sidecar (no login needed)...").start();
|
|
3420
|
+
let out;
|
|
3421
|
+
try {
|
|
3422
|
+
out = await sidecarInitAnonymous2();
|
|
3423
|
+
spinner.succeed("Sidecar ready (anonymous trial).");
|
|
3424
|
+
} catch (err) {
|
|
3425
|
+
spinner.fail("Setup failed.");
|
|
3426
|
+
throw err;
|
|
3427
|
+
}
|
|
3428
|
+
if (out.cp_key && out.team_id) saveAnonCred2(out.cp_key, out.team_id, out.claim_code);
|
|
3429
|
+
const envState = upsertEnvLocal(root, out.token);
|
|
3430
|
+
ensureGitignored(root);
|
|
3431
|
+
console.log(` ${import_chalk28.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
|
|
3432
|
+
console.log(` ${import_chalk28.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
|
|
3433
|
+
let inspectorPath = null;
|
|
3434
|
+
if (!opts.noInspector) {
|
|
3435
|
+
inspectorPath = generateInspector(root, router);
|
|
3436
|
+
if (inspectorPath) console.log(` ${import_chalk28.default.green("\u2713")} inspector at ${inspectorPath}`);
|
|
3155
3437
|
}
|
|
3438
|
+
console.log("");
|
|
3439
|
+
console.log(import_chalk28.default.bold("Done (no account needed). What happens next:"));
|
|
3440
|
+
console.log(` 1. ${import_chalk28.default.cyan("npm install apiblaze")} then ${import_chalk28.default.cyan("npm run dev")} and use your app.`);
|
|
3441
|
+
console.log(` 2. Each external origin your app calls is logged in the console \u2014 approve one with:`);
|
|
3442
|
+
console.log(` ${import_chalk28.default.cyan("apiblaze origins approve api.stripe.com")} (no login needed)`);
|
|
3443
|
+
console.log("");
|
|
3444
|
+
console.log(import_chalk28.default.bold(" \u{1F511} Keep your setup \u2014 claim it into an account:"));
|
|
3445
|
+
console.log(` ${import_chalk28.default.cyan("apiblaze login")} then ${import_chalk28.default.cyan("apiblaze claim")} ${import_chalk28.default.dim("(no code needed here)")}`);
|
|
3446
|
+
console.log(import_chalk28.default.dim(` From another machine: apiblaze claim ${out.claim_code} \xB7 expires in 30 days`));
|
|
3447
|
+
}
|
|
3448
|
+
async function runSidecar(opts) {
|
|
3449
|
+
const root = path4.resolve(opts.dir ?? process.cwd());
|
|
3156
3450
|
const detected = detectNextProject(root);
|
|
3157
3451
|
if (!detected.found) {
|
|
3158
3452
|
console.log(import_chalk28.default.yellow(`No Next.js project detected in ${root}.`));
|
|
3159
3453
|
console.log("Create one (e.g. `npx create-next-app`) and re-run `apiblaze init` inside it.");
|
|
3160
3454
|
return;
|
|
3161
3455
|
}
|
|
3456
|
+
if (!loadCredentials() && !readEnvKey(root)) {
|
|
3457
|
+
await runAnonymousInit(root, detected.router, opts);
|
|
3458
|
+
return;
|
|
3459
|
+
}
|
|
3460
|
+
if (!loadCredentials()) {
|
|
3461
|
+
upsertEnvLocal(root, readEnvKey(root));
|
|
3462
|
+
ensureGitignored(root);
|
|
3463
|
+
console.log(` ${import_chalk28.default.green("\u2713")} .env.local present (APIBLAZE_API_KEY) \u2014 reusing`);
|
|
3464
|
+
console.log(` ${import_chalk28.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
|
|
3465
|
+
console.log(import_chalk28.default.dim(" Log in and run `apiblaze claim <code>` to keep this setup, or `apiblaze login` to manage it."));
|
|
3466
|
+
return;
|
|
3467
|
+
}
|
|
3162
3468
|
const { teamId, teamName } = await resolveTeam(opts.team);
|
|
3163
|
-
const
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3469
|
+
const existingKey = readEnvKey(root);
|
|
3470
|
+
const switchingTeam = !!opts.team;
|
|
3471
|
+
const mustMint = !existingKey || opts.rotate || switchingTeam;
|
|
3472
|
+
let token = existingKey ?? "";
|
|
3473
|
+
if (mustMint) {
|
|
3474
|
+
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();
|
|
3475
|
+
try {
|
|
3476
|
+
const out = await admin({
|
|
3477
|
+
method: "POST",
|
|
3478
|
+
path: `/teams/${encodeURIComponent(teamId)}/sidecar/setup`,
|
|
3479
|
+
summary: `Set up sidecar for team ${teamName ?? teamId}`
|
|
3480
|
+
});
|
|
3481
|
+
token = out.token;
|
|
3482
|
+
spinner.succeed(existingKey ? `Sidecar re-established on team ${teamName ?? teamId}.` : "Sidecar ready.");
|
|
3483
|
+
} catch (err) {
|
|
3484
|
+
spinner.fail("Setup failed.");
|
|
3485
|
+
throw err;
|
|
3486
|
+
}
|
|
3487
|
+
} else {
|
|
3488
|
+
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
3489
|
}
|
|
3177
3490
|
const envState = upsertEnvLocal(root, token);
|
|
3178
3491
|
ensureGitignored(root);
|
|
3179
|
-
console.log(` ${import_chalk28.default.green("\u2713")} .env.local ${envState} (
|
|
3492
|
+
console.log(` ${import_chalk28.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
|
|
3180
3493
|
const wireState = wireInstrumentation(root);
|
|
3181
3494
|
console.log(` ${import_chalk28.default.green("\u2713")} instrumentation.ts ${wireState}`);
|
|
3182
3495
|
let inspectorPath = null;
|
|
@@ -3191,22 +3504,39 @@ async function runSidecar(opts) {
|
|
|
3191
3504
|
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
3505
|
console.log(` 4. Approve the ones to route: ${import_chalk28.default.cyan("apiblaze origins approve api.stripe.com")} (or in the dashboard)`);
|
|
3193
3506
|
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 ${
|
|
3507
|
+
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)`);
|
|
3508
|
+
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>\`.`));
|
|
3509
|
+
console.log("");
|
|
3510
|
+
console.log(import_chalk28.default.dim(" Manage: apiblaze origins (list/approve/deny/remove)"));
|
|
3511
|
+
console.log(import_chalk28.default.dim(" Rotate: apiblaze init --rotate \xB7 Switch team: apiblaze init --team <name>"));
|
|
3512
|
+
console.log(import_chalk28.default.dim(" Turn off: set APIBLAZE_SIDECAR=off in .env.local (flip back to on anytime; key stays put)."));
|
|
3195
3513
|
console.log("");
|
|
3196
|
-
console.log(import_chalk28.default.yellow(" \u26A0
|
|
3514
|
+
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
3515
|
console.log(import_chalk28.default.dim(" Your control-plane login stays in ~/.apiblaze \u2014 it never entered this project."));
|
|
3198
3516
|
}
|
|
3199
3517
|
|
|
3200
3518
|
// src/commands/origins.ts
|
|
3201
3519
|
var import_chalk29 = __toESM(require("chalk"));
|
|
3202
3520
|
var import_ora14 = __toESM(require("ora"));
|
|
3521
|
+
init_auth();
|
|
3522
|
+
init_anon_cred();
|
|
3203
3523
|
async function runOriginsList(opts) {
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3524
|
+
let out;
|
|
3525
|
+
if (!loadCredentials()) {
|
|
3526
|
+
const cred = loadAnonCred();
|
|
3527
|
+
if (!cred) {
|
|
3528
|
+
console.log(import_chalk29.default.yellow("No anonymous workspace here. Run `apiblaze init` first."));
|
|
3529
|
+
return;
|
|
3530
|
+
}
|
|
3531
|
+
out = await cpFetch(cred.cp_key, `/teams/${encodeURIComponent(cred.team_id)}/sidecar/candidates`, { method: "GET" });
|
|
3532
|
+
} else {
|
|
3533
|
+
const { teamId, teamName } = await resolveTeam(opts.team);
|
|
3534
|
+
out = await admin({
|
|
3535
|
+
method: "GET",
|
|
3536
|
+
path: `/teams/${encodeURIComponent(teamId)}/sidecar/candidates`,
|
|
3537
|
+
summary: `List sidecar origins for team ${teamName ?? teamId}`
|
|
3538
|
+
});
|
|
3539
|
+
}
|
|
3210
3540
|
if (opts.json) {
|
|
3211
3541
|
console.log(JSON.stringify(out));
|
|
3212
3542
|
return;
|
|
@@ -3230,6 +3560,22 @@ Candidates \u2014 going direct, not yet approved (${candidates.length})`));
|
|
|
3230
3560
|
}
|
|
3231
3561
|
}
|
|
3232
3562
|
async function runOriginsApprove(origin, opts) {
|
|
3563
|
+
if (!loadCredentials()) {
|
|
3564
|
+
const cred = loadAnonCred();
|
|
3565
|
+
if (!cred) {
|
|
3566
|
+
console.error(import_chalk29.default.red("Not logged in and no anonymous workspace. Run `apiblaze init` first."));
|
|
3567
|
+
process.exit(1);
|
|
3568
|
+
}
|
|
3569
|
+
const spinner2 = (0, import_ora14.default)(`Approving ${origin} (anonymous)...`).start();
|
|
3570
|
+
try {
|
|
3571
|
+
const out = await cpFetch(cred.cp_key, `/teams/${encodeURIComponent(cred.team_id)}/sidecar/approve`, { method: "POST", body: JSON.stringify({ origin }) });
|
|
3572
|
+
spinner2.succeed(`Approved ${origin} \u2192 proxy ${out.project_id}. Routing within ~5 min.`);
|
|
3573
|
+
} catch (err) {
|
|
3574
|
+
spinner2.fail("Approve failed.");
|
|
3575
|
+
throw err;
|
|
3576
|
+
}
|
|
3577
|
+
return;
|
|
3578
|
+
}
|
|
3233
3579
|
const { teamId } = await resolveTeam(opts.team);
|
|
3234
3580
|
const spinner = (0, import_ora14.default)(`Approving ${origin}...`).start();
|
|
3235
3581
|
try {
|
|
@@ -3257,6 +3603,17 @@ async function runOriginsDeny(origin, opts) {
|
|
|
3257
3603
|
throw err;
|
|
3258
3604
|
}
|
|
3259
3605
|
}
|
|
3606
|
+
async function runOriginsRemove(origin, opts) {
|
|
3607
|
+
const { teamId } = await resolveTeam(opts.team);
|
|
3608
|
+
const spinner = (0, import_ora14.default)(`Removing the proxy for ${origin}...`).start();
|
|
3609
|
+
try {
|
|
3610
|
+
await admin({ method: "POST", path: `/teams/${encodeURIComponent(teamId)}/sidecar/remove`, body: { origin }, summary: `Un-route sidecar origin ${origin}` });
|
|
3611
|
+
spinner.succeed(`Removed ${origin}. Your app will stop routing it (goes direct) within ~5 min.`);
|
|
3612
|
+
} catch (err) {
|
|
3613
|
+
spinner.fail("Remove failed.");
|
|
3614
|
+
throw err;
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3260
3617
|
|
|
3261
3618
|
// src/index.ts
|
|
3262
3619
|
var program = new import_commander.Command();
|
|
@@ -3285,7 +3642,7 @@ program.command("login").description("Authenticate with APIblaze").action(async
|
|
|
3285
3642
|
process.exit(1);
|
|
3286
3643
|
}
|
|
3287
3644
|
});
|
|
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) => {
|
|
3645
|
+
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
3646
|
try {
|
|
3290
3647
|
await runCreate(opts);
|
|
3291
3648
|
} catch (err) {
|
|
@@ -3297,10 +3654,11 @@ var agent = program.command("agent").description("Chat with an assistant that bu
|
|
|
3297
3654
|
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
3655
|
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
3656
|
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 })));
|
|
3657
|
+
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
3658
|
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
3659
|
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
3660
|
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)));
|
|
3661
|
+
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
3662
|
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
3663
|
try {
|
|
3306
3664
|
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