apiblaze 0.1.9 → 0.1.12
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 +232 -137
- package/package.json +2 -4
package/dist/index.js
CHANGED
|
@@ -134,8 +134,9 @@ async function getLocalhostTargets(teamId) {
|
|
|
134
134
|
async function getProjects(teamId) {
|
|
135
135
|
return apiFetch(`/api/cli/projects?team_id=${encodeURIComponent(teamId)}`);
|
|
136
136
|
}
|
|
137
|
-
async function checkProxyName(name) {
|
|
138
|
-
|
|
137
|
+
async function checkProxyName(name, teamId) {
|
|
138
|
+
const q = teamId ? `&team_id=${encodeURIComponent(teamId)}` : "";
|
|
139
|
+
return apiFetch(`/api/cli/check-name?name=${encodeURIComponent(name)}${q}`);
|
|
139
140
|
}
|
|
140
141
|
async function createProxy(payload) {
|
|
141
142
|
return apiFetch("/api/cli/create-proxy", {
|
|
@@ -149,8 +150,11 @@ async function putDevTunnel(payload) {
|
|
|
149
150
|
body: JSON.stringify(payload)
|
|
150
151
|
});
|
|
151
152
|
}
|
|
152
|
-
async function deleteDevTunnel() {
|
|
153
|
-
return apiFetch("/api/cli/dev-tunnel", {
|
|
153
|
+
async function deleteDevTunnel(restore) {
|
|
154
|
+
return apiFetch("/api/cli/dev-tunnel", {
|
|
155
|
+
method: "DELETE",
|
|
156
|
+
body: JSON.stringify({ restore })
|
|
157
|
+
});
|
|
154
158
|
}
|
|
155
159
|
var DASHBOARD_BASE;
|
|
156
160
|
var init_api = __esm({
|
|
@@ -404,9 +408,7 @@ function killCloudflared(proc) {
|
|
|
404
408
|
}
|
|
405
409
|
|
|
406
410
|
// src/lib/traffic.ts
|
|
407
|
-
var import_ws = __toESM(require("ws"));
|
|
408
411
|
var import_chalk2 = __toESM(require("chalk"));
|
|
409
|
-
init_auth();
|
|
410
412
|
var METHOD_COLORS = {
|
|
411
413
|
GET: import_chalk2.default.cyan,
|
|
412
414
|
POST: import_chalk2.default.green,
|
|
@@ -438,35 +440,51 @@ function formatLogLine(entry) {
|
|
|
438
440
|
const ts = now.toTimeString().slice(0, 8);
|
|
439
441
|
return `${import_chalk2.default.gray(`[${ts}]`)} ${colorMethod(entry.method)} ${import_chalk2.default.white(entry.path)} ${import_chalk2.default.gray("\u2192")} ${colorStatus(entry.status)} ${import_chalk2.default.gray(`(${colorLatency(entry.latency)})`)}`;
|
|
440
442
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
443
|
+
|
|
444
|
+
// src/lib/proxy-logger.ts
|
|
445
|
+
var import_http = __toESM(require("http"));
|
|
446
|
+
var import_net = __toESM(require("net"));
|
|
447
|
+
function startPassthroughProxy(targetPort, onEntry) {
|
|
448
|
+
return new Promise((resolve, reject) => {
|
|
449
|
+
const server = import_http.default.createServer((req, res) => {
|
|
450
|
+
const start = Date.now();
|
|
451
|
+
const method = req.method ?? "GET";
|
|
452
|
+
const path3 = req.url ?? "/";
|
|
453
|
+
const proxyReq = import_http.default.request(
|
|
454
|
+
{ host: "127.0.0.1", port: targetPort, method, path: path3, headers: req.headers },
|
|
455
|
+
(proxyRes) => {
|
|
456
|
+
onEntry({ method, path: path3, status: proxyRes.statusCode ?? 0, latency: Date.now() - start });
|
|
457
|
+
res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
|
|
458
|
+
proxyRes.pipe(res);
|
|
459
|
+
}
|
|
460
|
+
);
|
|
461
|
+
proxyReq.on("error", () => {
|
|
462
|
+
onEntry({ method, path: path3, status: 502, latency: Date.now() - start });
|
|
463
|
+
if (!res.headersSent) res.writeHead(502);
|
|
464
|
+
res.end();
|
|
465
|
+
});
|
|
466
|
+
req.pipe(proxyReq);
|
|
454
467
|
});
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
468
|
+
server.on("upgrade", (req, clientSocket, head) => {
|
|
469
|
+
const upstream = import_net.default.connect(targetPort, "127.0.0.1", () => {
|
|
470
|
+
const headerLines = Object.entries(req.headers).map(([k, v]) => `${k}: ${Array.isArray(v) ? v.join(", ") : v}`).join("\r\n");
|
|
471
|
+
upstream.write(`${req.method} ${req.url} HTTP/1.1\r
|
|
472
|
+
${headerLines}\r
|
|
473
|
+
\r
|
|
474
|
+
`);
|
|
475
|
+
if (head && head.length) upstream.write(head);
|
|
476
|
+
upstream.pipe(clientSocket);
|
|
477
|
+
clientSocket.pipe(upstream);
|
|
478
|
+
});
|
|
479
|
+
upstream.on("error", () => clientSocket.destroy());
|
|
480
|
+
clientSocket.on("error", () => upstream.destroy());
|
|
462
481
|
});
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
482
|
+
server.on("error", reject);
|
|
483
|
+
server.listen(0, "127.0.0.1", () => {
|
|
484
|
+
const { port } = server.address();
|
|
485
|
+
resolve({ port, close: () => server.close() });
|
|
466
486
|
});
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
return connect();
|
|
487
|
+
});
|
|
470
488
|
}
|
|
471
489
|
|
|
472
490
|
// src/commands/dev.ts
|
|
@@ -551,60 +569,58 @@ Tunneling ${selectedTargets.length} project(s) to localhost:${options.port}
|
|
|
551
569
|
`)
|
|
552
570
|
);
|
|
553
571
|
await ensureCloudflared();
|
|
572
|
+
const logger = await startPassthroughProxy(options.port, (entry) => {
|
|
573
|
+
console.log(formatLogLine(entry));
|
|
574
|
+
});
|
|
554
575
|
let cfProcess;
|
|
555
576
|
let tunnelUrl;
|
|
556
577
|
{
|
|
557
578
|
const spinner = (0, import_ora3.default)("Starting Cloudflare tunnel...").start();
|
|
558
579
|
try {
|
|
559
|
-
({ process: cfProcess, tunnelUrl } = await spawnCloudflared(
|
|
580
|
+
({ process: cfProcess, tunnelUrl } = await spawnCloudflared(logger.port));
|
|
560
581
|
spinner.succeed(`Tunnel active: ${import_chalk3.default.bold.cyan(tunnelUrl)}`);
|
|
561
582
|
} catch (err) {
|
|
562
583
|
spinner.fail("Failed to start cloudflared tunnel.");
|
|
584
|
+
logger.close();
|
|
563
585
|
throw err;
|
|
564
586
|
}
|
|
565
587
|
}
|
|
588
|
+
let restore = [];
|
|
566
589
|
{
|
|
567
590
|
const spinner = (0, import_ora3.default)("Registering tunnel with APIblaze...").start();
|
|
568
|
-
let wsUrl;
|
|
569
591
|
try {
|
|
570
592
|
const result = await putDevTunnel({
|
|
571
593
|
tunnelUrl,
|
|
572
594
|
targets: selectedTargets.map((t) => ({ projectId: t.projectId, tenantId: t.tenantId }))
|
|
573
595
|
});
|
|
574
|
-
|
|
596
|
+
restore = result.restore ?? [];
|
|
575
597
|
spinner.succeed("Tunnel registered. Proxying traffic.");
|
|
576
598
|
} catch (err) {
|
|
577
599
|
spinner.fail("Failed to register tunnel.");
|
|
600
|
+
logger.close();
|
|
578
601
|
killCloudflared(cfProcess);
|
|
579
602
|
throw err;
|
|
580
603
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
isCleaningUp = true;
|
|
592
|
-
console.log(import_chalk3.default.gray("\n\nShutting down..."));
|
|
593
|
-
try {
|
|
594
|
-
ws.close();
|
|
595
|
-
} catch {
|
|
596
|
-
}
|
|
597
|
-
await deleteDevTunnel().catch(() => {
|
|
598
|
-
});
|
|
599
|
-
killCloudflared(cfProcess);
|
|
600
|
-
console.log(import_chalk3.default.green("Tunnel stopped."));
|
|
601
|
-
process.exit(0);
|
|
602
|
-
}
|
|
603
|
-
process.on("SIGINT", () => void cleanup());
|
|
604
|
-
process.on("SIGTERM", () => void cleanup());
|
|
605
|
-
await new Promise(() => {
|
|
604
|
+
}
|
|
605
|
+
console.log("\n" + import_chalk3.default.gray("\u2500".repeat(60)));
|
|
606
|
+
console.log(import_chalk3.default.bold("Live traffic") + import_chalk3.default.gray(" (Ctrl+C to stop)"));
|
|
607
|
+
console.log(import_chalk3.default.gray("\u2500".repeat(60)) + "\n");
|
|
608
|
+
let isCleaningUp = false;
|
|
609
|
+
async function cleanup() {
|
|
610
|
+
if (isCleaningUp) return;
|
|
611
|
+
isCleaningUp = true;
|
|
612
|
+
console.log(import_chalk3.default.gray("\n\nShutting down..."));
|
|
613
|
+
await deleteDevTunnel(restore).catch(() => {
|
|
606
614
|
});
|
|
615
|
+
logger.close();
|
|
616
|
+
killCloudflared(cfProcess);
|
|
617
|
+
console.log(import_chalk3.default.green("Tunnel stopped."));
|
|
618
|
+
process.exit(0);
|
|
607
619
|
}
|
|
620
|
+
process.on("SIGINT", () => void cleanup());
|
|
621
|
+
process.on("SIGTERM", () => void cleanup());
|
|
622
|
+
await new Promise(() => {
|
|
623
|
+
});
|
|
608
624
|
}
|
|
609
625
|
|
|
610
626
|
// src/commands/projects.ts
|
|
@@ -677,7 +693,7 @@ function normalizeName(raw) {
|
|
|
677
693
|
}
|
|
678
694
|
function isHttpUrl(s) {
|
|
679
695
|
try {
|
|
680
|
-
const u = new URL(s.trim());
|
|
696
|
+
const u = new URL((s || "").trim());
|
|
681
697
|
return u.protocol === "http:" || u.protocol === "https:";
|
|
682
698
|
} catch {
|
|
683
699
|
return false;
|
|
@@ -695,78 +711,144 @@ function stripTenantFromPortal(devPortal) {
|
|
|
695
711
|
return devPortal;
|
|
696
712
|
}
|
|
697
713
|
}
|
|
698
|
-
|
|
714
|
+
function fail(message) {
|
|
715
|
+
console.error(import_chalk5.default.red(`Error: ${message}`));
|
|
716
|
+
process.exit(1);
|
|
717
|
+
}
|
|
718
|
+
var VALID_AUTH = ["api_key", "none", "oauth"];
|
|
719
|
+
async function runCreate(opts = {}) {
|
|
699
720
|
const creds = loadCredentials();
|
|
700
721
|
if (!creds) {
|
|
701
|
-
|
|
702
|
-
process.exit(1);
|
|
722
|
+
fail("Not logged in. Run `apiblaze login` first.");
|
|
703
723
|
}
|
|
704
|
-
|
|
705
|
-
const
|
|
724
|
+
const interactive = !!process.stdin.isTTY && !opts.json;
|
|
725
|
+
const auth = (opts.auth ?? "api_key").toLowerCase();
|
|
726
|
+
if (!VALID_AUTH.includes(auth)) {
|
|
727
|
+
fail(`Invalid --auth "${auth}". Use one of: ${VALID_AUTH.join(", ")}.`);
|
|
728
|
+
}
|
|
729
|
+
let teamId = creds.teamId;
|
|
730
|
+
if (opts.team) {
|
|
731
|
+
if (opts.team.startsWith("team_")) {
|
|
732
|
+
teamId = opts.team;
|
|
733
|
+
} else {
|
|
734
|
+
const teams = await getTeams().catch(() => []);
|
|
735
|
+
const match = teams.find(
|
|
736
|
+
(t) => t.teamId === opts.team || t.name.toLowerCase() === opts.team.toLowerCase()
|
|
737
|
+
);
|
|
738
|
+
if (!match) {
|
|
739
|
+
fail(`Team "${opts.team}" not found. Run \`apiblaze team\` to see your teams.`);
|
|
740
|
+
}
|
|
741
|
+
teamId = match.teamId;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
if (!opts.json) console.log(import_chalk5.default.bold("\nCreate an API proxy\n"));
|
|
706
745
|
let name = "";
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
}]);
|
|
714
|
-
name = normalizeName(rawName);
|
|
715
|
-
if (name.length < 3) {
|
|
716
|
-
console.log(import_chalk5.default.yellow(" Name must be at least 3 characters (letters and digits only).\n"));
|
|
717
|
-
continue;
|
|
746
|
+
if (opts.name !== void 0) {
|
|
747
|
+
name = normalizeName(opts.name);
|
|
748
|
+
if (name.length < 3) fail("Proxy name must be at least 3 characters (letters and digits only).");
|
|
749
|
+
const check = await checkProxyName(name, teamId).catch(() => null);
|
|
750
|
+
if (check && (!check.canUseProjectName || !check.canUseApiVersion)) {
|
|
751
|
+
fail(`Proxy name "${name}" is not available${check.message ? ` \u2014 ${check.message}` : ""}.`);
|
|
718
752
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
753
|
+
} else if (interactive) {
|
|
754
|
+
const { default: inquirer2 } = await import("inquirer");
|
|
755
|
+
for (; ; ) {
|
|
756
|
+
const { rawName } = await inquirer2.prompt([{
|
|
757
|
+
type: "input",
|
|
758
|
+
name: "rawName",
|
|
759
|
+
message: "Proxy name (your API will live at <name>.apiblaze.com):",
|
|
760
|
+
transformer: (v) => normalizeName(v)
|
|
761
|
+
}]);
|
|
762
|
+
name = normalizeName(rawName);
|
|
763
|
+
if (name.length < 3) {
|
|
764
|
+
console.log(import_chalk5.default.yellow(" Name must be at least 3 characters (letters and digits only).\n"));
|
|
727
765
|
continue;
|
|
728
766
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
767
|
+
const spinner2 = (0, import_ora5.default)("Checking availability...").start();
|
|
768
|
+
try {
|
|
769
|
+
const check = await checkProxyName(name, teamId);
|
|
770
|
+
spinner2.stop();
|
|
771
|
+
if (!check.canUseProjectName || !check.canUseApiVersion) {
|
|
772
|
+
console.log(import_chalk5.default.yellow(` "${name}" is not available${check.message ? ` \u2014 ${check.message}` : ""}. Try another.
|
|
773
|
+
`));
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
} catch {
|
|
777
|
+
spinner2.stop();
|
|
778
|
+
console.log(import_chalk5.default.dim(" (could not verify availability; continuing)"));
|
|
779
|
+
}
|
|
780
|
+
console.log(`${import_chalk5.default.cyan("\u2192")} Your API will live at ${import_chalk5.default.bold(`https://${name}.apiblaze.com`)}
|
|
734
781
|
`);
|
|
735
|
-
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
} else {
|
|
785
|
+
fail("--name is required in non-interactive mode.");
|
|
736
786
|
}
|
|
737
787
|
let targetUrl = "";
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
788
|
+
if (opts.target !== void 0) {
|
|
789
|
+
if (!isHttpUrl(opts.target)) fail("--target must be a valid http(s) URL.");
|
|
790
|
+
targetUrl = opts.target.trim();
|
|
791
|
+
} else if (interactive) {
|
|
792
|
+
const { default: inquirer2 } = await import("inquirer");
|
|
793
|
+
for (; ; ) {
|
|
794
|
+
const { url } = await inquirer2.prompt([{
|
|
795
|
+
type: "input",
|
|
796
|
+
name: "url",
|
|
797
|
+
message: "Target URL to forward requests to (e.g. https://httpbin.org):"
|
|
798
|
+
}]);
|
|
799
|
+
if (!isHttpUrl(url)) {
|
|
800
|
+
console.log(import_chalk5.default.yellow(" Enter a valid http(s) URL.\n"));
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
targetUrl = url.trim();
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
} else {
|
|
807
|
+
fail("--target is required in non-interactive mode.");
|
|
808
|
+
}
|
|
809
|
+
if (interactive && !opts.yes) {
|
|
810
|
+
const { default: inquirer2 } = await import("inquirer");
|
|
811
|
+
console.log(`${import_chalk5.default.cyan("\u2192")} Auth: ${import_chalk5.default.bold(auth)}${auth === "api_key" ? " \u2014 consumers send an X-API-Key header" : ""}`);
|
|
812
|
+
const { ok } = await inquirer2.prompt([{
|
|
813
|
+
type: "confirm",
|
|
814
|
+
name: "ok",
|
|
815
|
+
message: `Create proxy "${name}" \u2192 ${targetUrl}?`,
|
|
816
|
+
default: true
|
|
743
817
|
}]);
|
|
744
|
-
if (!
|
|
745
|
-
console.log(import_chalk5.default.yellow("
|
|
746
|
-
|
|
818
|
+
if (!ok) {
|
|
819
|
+
console.log(import_chalk5.default.yellow("Cancelled."));
|
|
820
|
+
return;
|
|
747
821
|
}
|
|
748
|
-
targetUrl = url.trim();
|
|
749
|
-
break;
|
|
750
822
|
}
|
|
751
|
-
|
|
752
|
-
`);
|
|
753
|
-
const spinner = (0, import_ora5.default)("Creating proxy (tenant, keys, dev portal)...").start();
|
|
823
|
+
const spinner = !opts.json ? (0, import_ora5.default)("Creating proxy (tenant, keys, dev portal)...").start() : null;
|
|
754
824
|
let result;
|
|
755
825
|
try {
|
|
756
|
-
result = await createProxy({ name, target_url: targetUrl, auth_type:
|
|
757
|
-
spinner
|
|
826
|
+
result = await createProxy({ name, target_url: targetUrl, auth_type: auth, team_id: teamId });
|
|
827
|
+
spinner?.succeed(import_chalk5.default.green("Proxy created!"));
|
|
758
828
|
} catch (err) {
|
|
759
|
-
spinner
|
|
829
|
+
spinner?.fail("Failed to create proxy.");
|
|
760
830
|
throw err;
|
|
761
831
|
}
|
|
762
832
|
const version = result.api_version || "1.0.0";
|
|
763
833
|
const keys = result.api_keys ?? {};
|
|
764
834
|
const adminKey = keys.dev ?? Object.values(keys)[0];
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
if (
|
|
768
|
-
|
|
835
|
+
const proxyUrl = `https://${name}.apiblaze.com/${version}/dev`;
|
|
836
|
+
const devPortal = result.devPortal ? stripTenantFromPortal(result.devPortal) : void 0;
|
|
837
|
+
if (opts.json) {
|
|
838
|
+
process.stdout.write(JSON.stringify({
|
|
839
|
+
project_id: result.project_id,
|
|
840
|
+
api_version: version,
|
|
841
|
+
proxy_url: proxyUrl,
|
|
842
|
+
dev_portal: devPortal,
|
|
843
|
+
api_key: adminKey,
|
|
844
|
+
api_keys: keys,
|
|
845
|
+
team_id: teamId
|
|
846
|
+
}) + "\n");
|
|
847
|
+
return;
|
|
769
848
|
}
|
|
849
|
+
console.log();
|
|
850
|
+
console.log(` ${import_chalk5.default.dim("Proxy URL: ")} ${import_chalk5.default.bold(proxyUrl)}`);
|
|
851
|
+
if (devPortal) console.log(` ${import_chalk5.default.dim("Dev portal:")} ${import_chalk5.default.bold(devPortal)}`);
|
|
770
852
|
if (adminKey) {
|
|
771
853
|
console.log();
|
|
772
854
|
console.log(` ${import_chalk5.default.dim("Consumer admin API key (dev):")}`);
|
|
@@ -784,43 +866,51 @@ async function runCreate() {
|
|
|
784
866
|
var import_chalk6 = __toESM(require("chalk"));
|
|
785
867
|
init_auth();
|
|
786
868
|
init_api();
|
|
787
|
-
|
|
869
|
+
function fail2(message) {
|
|
870
|
+
console.error(import_chalk6.default.red(`Error: ${message}`));
|
|
871
|
+
process.exit(1);
|
|
872
|
+
}
|
|
873
|
+
async function runTeam(arg) {
|
|
788
874
|
const creds = loadCredentials();
|
|
789
875
|
if (!creds) {
|
|
790
|
-
|
|
791
|
-
process.exit(1);
|
|
876
|
+
fail2("Not logged in. Run `apiblaze login` first.");
|
|
792
877
|
}
|
|
793
878
|
const teams = await getTeams().catch(() => []);
|
|
794
879
|
if (teams.length === 0) {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
880
|
+
fail2("No teams found for your account.");
|
|
881
|
+
}
|
|
882
|
+
let chosen;
|
|
883
|
+
if (arg) {
|
|
884
|
+
chosen = teams.find(
|
|
885
|
+
(t) => t.teamId === arg || t.name.toLowerCase() === arg.toLowerCase()
|
|
886
|
+
);
|
|
887
|
+
if (!chosen) {
|
|
888
|
+
fail2(`Team "${arg}" not found. Available: ${teams.map((t) => t.name).join(", ")}.`);
|
|
889
|
+
}
|
|
890
|
+
} else if (teams.length === 1) {
|
|
891
|
+
chosen = teams[0];
|
|
892
|
+
console.log(`${import_chalk6.default.cyan("\u2192")} You only have one team: ${import_chalk6.default.bold(chosen.name)}`);
|
|
893
|
+
} else if (process.stdin.isTTY) {
|
|
805
894
|
const { default: inquirer2 } = await import("inquirer");
|
|
806
|
-
const {
|
|
895
|
+
const { picked } = await inquirer2.prompt([{
|
|
807
896
|
type: "list",
|
|
808
|
-
name: "
|
|
897
|
+
name: "picked",
|
|
809
898
|
message: "Switch to which team?",
|
|
810
899
|
default: creds.teamId,
|
|
811
900
|
choices: teams.map((t) => ({ name: t.name, value: t.teamId }))
|
|
812
901
|
}]);
|
|
813
|
-
|
|
814
|
-
|
|
902
|
+
chosen = teams.find((t) => t.teamId === picked);
|
|
903
|
+
} else {
|
|
904
|
+
fail2(`Specify a team: \`apiblaze team <name|id>\`. Available: ${teams.map((t) => t.name).join(", ")}.`);
|
|
815
905
|
}
|
|
816
|
-
saveCredentials({ ...creds, teamId, teamName });
|
|
906
|
+
saveCredentials({ ...creds, teamId: chosen.teamId, teamName: chosen.name });
|
|
817
907
|
console.log(import_chalk6.default.green(`
|
|
818
|
-
\u2714 Active team: ${import_chalk6.default.bold(
|
|
908
|
+
\u2714 Active team: ${import_chalk6.default.bold(chosen.name)}`));
|
|
819
909
|
}
|
|
820
910
|
|
|
821
911
|
// src/index.ts
|
|
822
912
|
var program = new import_commander.Command();
|
|
823
|
-
program.name("apiblaze").description("APIblaze dev tunnel CLI").version("0.1.
|
|
913
|
+
program.name("apiblaze").description("APIblaze dev tunnel CLI").version("0.1.11");
|
|
824
914
|
program.command("login").description("Authenticate with APIblaze").action(async () => {
|
|
825
915
|
try {
|
|
826
916
|
await runLogin();
|
|
@@ -829,17 +919,17 @@ program.command("login").description("Authenticate with APIblaze").action(async
|
|
|
829
919
|
process.exit(1);
|
|
830
920
|
}
|
|
831
921
|
});
|
|
832
|
-
program.command("create").description("Create a new API proxy").action(async () => {
|
|
922
|
+
program.command("create").description("Create a new API proxy").option("--name <name>", "Proxy name (becomes <name>.apiblaze.com)").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("-y, --yes", "Skip the confirmation prompt").option("--json", "Output machine-readable JSON (non-interactive)").action(async (opts) => {
|
|
833
923
|
try {
|
|
834
|
-
await runCreate();
|
|
924
|
+
await runCreate(opts);
|
|
835
925
|
} catch (err) {
|
|
836
926
|
printError(err);
|
|
837
927
|
process.exit(1);
|
|
838
928
|
}
|
|
839
929
|
});
|
|
840
|
-
program.command("team").description("Switch the active team").action(async () => {
|
|
930
|
+
program.command("team").description("Switch the active team").argument("[team]", "Team name or id to switch to (omit to choose interactively)").action(async (team) => {
|
|
841
931
|
try {
|
|
842
|
-
await runTeam();
|
|
932
|
+
await runTeam(team);
|
|
843
933
|
} catch (err) {
|
|
844
934
|
printError(err);
|
|
845
935
|
process.exit(1);
|
|
@@ -853,9 +943,14 @@ program.command("projects").description("List the projects in your team").action
|
|
|
853
943
|
process.exit(1);
|
|
854
944
|
}
|
|
855
945
|
});
|
|
856
|
-
program.command("dev").description("Start a dev tunnel for your localhost projects").option("-p, --port <number>", "Local port to tunnel", "3000").action(async (opts) => {
|
|
946
|
+
program.command("dev").description("Start a dev tunnel for your localhost projects").argument("[port]", "Local port to tunnel (positional; overrides --port)").option("-p, --port <number>", "Local port to tunnel", "3000").action(async (port, opts) => {
|
|
857
947
|
try {
|
|
858
|
-
|
|
948
|
+
const resolved = parseInt(port ?? opts.port, 10);
|
|
949
|
+
if (Number.isNaN(resolved)) {
|
|
950
|
+
console.error(import_chalk7.default.red(`Invalid port: ${port ?? opts.port}`));
|
|
951
|
+
process.exit(1);
|
|
952
|
+
}
|
|
953
|
+
await runDev({ port: resolved });
|
|
859
954
|
} catch (err) {
|
|
860
955
|
printError(err);
|
|
861
956
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apiblaze",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Dev tunnel CLI for APIblaze — route localhost projects through Cloudflare tunnels",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"apiblaze",
|
|
@@ -32,13 +32,11 @@
|
|
|
32
32
|
"chalk": "^4.1.2",
|
|
33
33
|
"commander": "^11.1.0",
|
|
34
34
|
"inquirer": "^8.2.6",
|
|
35
|
-
"ora": "^5.4.1"
|
|
36
|
-
"ws": "^8.17.0"
|
|
35
|
+
"ora": "^5.4.1"
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
39
38
|
"@types/inquirer": "^8.2.10",
|
|
40
39
|
"@types/node": "^20.0.0",
|
|
41
|
-
"@types/ws": "^8.5.10",
|
|
42
40
|
"tsup": "^8.0.0",
|
|
43
41
|
"typescript": "^5.4.0"
|
|
44
42
|
}
|