apiblaze 0.1.9 → 0.1.10
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 +151 -76
- package/package.json +1 -1
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", {
|
|
@@ -677,7 +678,7 @@ function normalizeName(raw) {
|
|
|
677
678
|
}
|
|
678
679
|
function isHttpUrl(s) {
|
|
679
680
|
try {
|
|
680
|
-
const u = new URL(s.trim());
|
|
681
|
+
const u = new URL((s || "").trim());
|
|
681
682
|
return u.protocol === "http:" || u.protocol === "https:";
|
|
682
683
|
} catch {
|
|
683
684
|
return false;
|
|
@@ -695,78 +696,144 @@ function stripTenantFromPortal(devPortal) {
|
|
|
695
696
|
return devPortal;
|
|
696
697
|
}
|
|
697
698
|
}
|
|
698
|
-
|
|
699
|
+
function fail(message) {
|
|
700
|
+
console.error(import_chalk5.default.red(`Error: ${message}`));
|
|
701
|
+
process.exit(1);
|
|
702
|
+
}
|
|
703
|
+
var VALID_AUTH = ["api_key", "none", "oauth"];
|
|
704
|
+
async function runCreate(opts = {}) {
|
|
699
705
|
const creds = loadCredentials();
|
|
700
706
|
if (!creds) {
|
|
701
|
-
|
|
702
|
-
|
|
707
|
+
fail("Not logged in. Run `apiblaze login` first.");
|
|
708
|
+
}
|
|
709
|
+
const interactive = !!process.stdin.isTTY && !opts.json;
|
|
710
|
+
const auth = (opts.auth ?? "api_key").toLowerCase();
|
|
711
|
+
if (!VALID_AUTH.includes(auth)) {
|
|
712
|
+
fail(`Invalid --auth "${auth}". Use one of: ${VALID_AUTH.join(", ")}.`);
|
|
713
|
+
}
|
|
714
|
+
let teamId = creds.teamId;
|
|
715
|
+
if (opts.team) {
|
|
716
|
+
if (opts.team.startsWith("team_")) {
|
|
717
|
+
teamId = opts.team;
|
|
718
|
+
} else {
|
|
719
|
+
const teams = await getTeams().catch(() => []);
|
|
720
|
+
const match = teams.find(
|
|
721
|
+
(t) => t.teamId === opts.team || t.name.toLowerCase() === opts.team.toLowerCase()
|
|
722
|
+
);
|
|
723
|
+
if (!match) {
|
|
724
|
+
fail(`Team "${opts.team}" not found. Run \`apiblaze team\` to see your teams.`);
|
|
725
|
+
}
|
|
726
|
+
teamId = match.teamId;
|
|
727
|
+
}
|
|
703
728
|
}
|
|
704
|
-
console.log(import_chalk5.default.bold("\nCreate an API proxy\n"));
|
|
705
|
-
const { default: inquirer2 } = await import("inquirer");
|
|
729
|
+
if (!opts.json) console.log(import_chalk5.default.bold("\nCreate an API proxy\n"));
|
|
706
730
|
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;
|
|
731
|
+
if (opts.name !== void 0) {
|
|
732
|
+
name = normalizeName(opts.name);
|
|
733
|
+
if (name.length < 3) fail("Proxy name must be at least 3 characters (letters and digits only).");
|
|
734
|
+
const check = await checkProxyName(name, teamId).catch(() => null);
|
|
735
|
+
if (check && (!check.canUseProjectName || !check.canUseApiVersion)) {
|
|
736
|
+
fail(`Proxy name "${name}" is not available${check.message ? ` \u2014 ${check.message}` : ""}.`);
|
|
718
737
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
738
|
+
} else if (interactive) {
|
|
739
|
+
const { default: inquirer2 } = await import("inquirer");
|
|
740
|
+
for (; ; ) {
|
|
741
|
+
const { rawName } = await inquirer2.prompt([{
|
|
742
|
+
type: "input",
|
|
743
|
+
name: "rawName",
|
|
744
|
+
message: "Proxy name (your API will live at <name>.apiblaze.com):",
|
|
745
|
+
transformer: (v) => normalizeName(v)
|
|
746
|
+
}]);
|
|
747
|
+
name = normalizeName(rawName);
|
|
748
|
+
if (name.length < 3) {
|
|
749
|
+
console.log(import_chalk5.default.yellow(" Name must be at least 3 characters (letters and digits only).\n"));
|
|
727
750
|
continue;
|
|
728
751
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
752
|
+
const spinner2 = (0, import_ora5.default)("Checking availability...").start();
|
|
753
|
+
try {
|
|
754
|
+
const check = await checkProxyName(name, teamId);
|
|
755
|
+
spinner2.stop();
|
|
756
|
+
if (!check.canUseProjectName || !check.canUseApiVersion) {
|
|
757
|
+
console.log(import_chalk5.default.yellow(` "${name}" is not available${check.message ? ` \u2014 ${check.message}` : ""}. Try another.
|
|
758
|
+
`));
|
|
759
|
+
continue;
|
|
760
|
+
}
|
|
761
|
+
} catch {
|
|
762
|
+
spinner2.stop();
|
|
763
|
+
console.log(import_chalk5.default.dim(" (could not verify availability; continuing)"));
|
|
764
|
+
}
|
|
765
|
+
console.log(`${import_chalk5.default.cyan("\u2192")} Your API will live at ${import_chalk5.default.bold(`https://${name}.apiblaze.com`)}
|
|
734
766
|
`);
|
|
735
|
-
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
} else {
|
|
770
|
+
fail("--name is required in non-interactive mode.");
|
|
736
771
|
}
|
|
737
772
|
let targetUrl = "";
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
773
|
+
if (opts.target !== void 0) {
|
|
774
|
+
if (!isHttpUrl(opts.target)) fail("--target must be a valid http(s) URL.");
|
|
775
|
+
targetUrl = opts.target.trim();
|
|
776
|
+
} else if (interactive) {
|
|
777
|
+
const { default: inquirer2 } = await import("inquirer");
|
|
778
|
+
for (; ; ) {
|
|
779
|
+
const { url } = await inquirer2.prompt([{
|
|
780
|
+
type: "input",
|
|
781
|
+
name: "url",
|
|
782
|
+
message: "Target URL to forward requests to (e.g. https://httpbin.org):"
|
|
783
|
+
}]);
|
|
784
|
+
if (!isHttpUrl(url)) {
|
|
785
|
+
console.log(import_chalk5.default.yellow(" Enter a valid http(s) URL.\n"));
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
targetUrl = url.trim();
|
|
789
|
+
break;
|
|
790
|
+
}
|
|
791
|
+
} else {
|
|
792
|
+
fail("--target is required in non-interactive mode.");
|
|
793
|
+
}
|
|
794
|
+
if (interactive && !opts.yes) {
|
|
795
|
+
const { default: inquirer2 } = await import("inquirer");
|
|
796
|
+
console.log(`${import_chalk5.default.cyan("\u2192")} Auth: ${import_chalk5.default.bold(auth)}${auth === "api_key" ? " \u2014 consumers send an X-API-Key header" : ""}`);
|
|
797
|
+
const { ok } = await inquirer2.prompt([{
|
|
798
|
+
type: "confirm",
|
|
799
|
+
name: "ok",
|
|
800
|
+
message: `Create proxy "${name}" \u2192 ${targetUrl}?`,
|
|
801
|
+
default: true
|
|
743
802
|
}]);
|
|
744
|
-
if (!
|
|
745
|
-
console.log(import_chalk5.default.yellow("
|
|
746
|
-
|
|
803
|
+
if (!ok) {
|
|
804
|
+
console.log(import_chalk5.default.yellow("Cancelled."));
|
|
805
|
+
return;
|
|
747
806
|
}
|
|
748
|
-
targetUrl = url.trim();
|
|
749
|
-
break;
|
|
750
807
|
}
|
|
751
|
-
|
|
752
|
-
`);
|
|
753
|
-
const spinner = (0, import_ora5.default)("Creating proxy (tenant, keys, dev portal)...").start();
|
|
808
|
+
const spinner = !opts.json ? (0, import_ora5.default)("Creating proxy (tenant, keys, dev portal)...").start() : null;
|
|
754
809
|
let result;
|
|
755
810
|
try {
|
|
756
|
-
result = await createProxy({ name, target_url: targetUrl, auth_type:
|
|
757
|
-
spinner
|
|
811
|
+
result = await createProxy({ name, target_url: targetUrl, auth_type: auth, team_id: teamId });
|
|
812
|
+
spinner?.succeed(import_chalk5.default.green("Proxy created!"));
|
|
758
813
|
} catch (err) {
|
|
759
|
-
spinner
|
|
814
|
+
spinner?.fail("Failed to create proxy.");
|
|
760
815
|
throw err;
|
|
761
816
|
}
|
|
762
817
|
const version = result.api_version || "1.0.0";
|
|
763
818
|
const keys = result.api_keys ?? {};
|
|
764
819
|
const adminKey = keys.dev ?? Object.values(keys)[0];
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
if (
|
|
768
|
-
|
|
820
|
+
const proxyUrl = `https://${name}.apiblaze.com/${version}/dev`;
|
|
821
|
+
const devPortal = result.devPortal ? stripTenantFromPortal(result.devPortal) : void 0;
|
|
822
|
+
if (opts.json) {
|
|
823
|
+
process.stdout.write(JSON.stringify({
|
|
824
|
+
project_id: result.project_id,
|
|
825
|
+
api_version: version,
|
|
826
|
+
proxy_url: proxyUrl,
|
|
827
|
+
dev_portal: devPortal,
|
|
828
|
+
api_key: adminKey,
|
|
829
|
+
api_keys: keys,
|
|
830
|
+
team_id: teamId
|
|
831
|
+
}) + "\n");
|
|
832
|
+
return;
|
|
769
833
|
}
|
|
834
|
+
console.log();
|
|
835
|
+
console.log(` ${import_chalk5.default.dim("Proxy URL: ")} ${import_chalk5.default.bold(proxyUrl)}`);
|
|
836
|
+
if (devPortal) console.log(` ${import_chalk5.default.dim("Dev portal:")} ${import_chalk5.default.bold(devPortal)}`);
|
|
770
837
|
if (adminKey) {
|
|
771
838
|
console.log();
|
|
772
839
|
console.log(` ${import_chalk5.default.dim("Consumer admin API key (dev):")}`);
|
|
@@ -784,38 +851,46 @@ async function runCreate() {
|
|
|
784
851
|
var import_chalk6 = __toESM(require("chalk"));
|
|
785
852
|
init_auth();
|
|
786
853
|
init_api();
|
|
787
|
-
|
|
854
|
+
function fail2(message) {
|
|
855
|
+
console.error(import_chalk6.default.red(`Error: ${message}`));
|
|
856
|
+
process.exit(1);
|
|
857
|
+
}
|
|
858
|
+
async function runTeam(arg) {
|
|
788
859
|
const creds = loadCredentials();
|
|
789
860
|
if (!creds) {
|
|
790
|
-
|
|
791
|
-
process.exit(1);
|
|
861
|
+
fail2("Not logged in. Run `apiblaze login` first.");
|
|
792
862
|
}
|
|
793
863
|
const teams = await getTeams().catch(() => []);
|
|
794
864
|
if (teams.length === 0) {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
865
|
+
fail2("No teams found for your account.");
|
|
866
|
+
}
|
|
867
|
+
let chosen;
|
|
868
|
+
if (arg) {
|
|
869
|
+
chosen = teams.find(
|
|
870
|
+
(t) => t.teamId === arg || t.name.toLowerCase() === arg.toLowerCase()
|
|
871
|
+
);
|
|
872
|
+
if (!chosen) {
|
|
873
|
+
fail2(`Team "${arg}" not found. Available: ${teams.map((t) => t.name).join(", ")}.`);
|
|
874
|
+
}
|
|
875
|
+
} else if (teams.length === 1) {
|
|
876
|
+
chosen = teams[0];
|
|
877
|
+
console.log(`${import_chalk6.default.cyan("\u2192")} You only have one team: ${import_chalk6.default.bold(chosen.name)}`);
|
|
878
|
+
} else if (process.stdin.isTTY) {
|
|
805
879
|
const { default: inquirer2 } = await import("inquirer");
|
|
806
|
-
const {
|
|
880
|
+
const { picked } = await inquirer2.prompt([{
|
|
807
881
|
type: "list",
|
|
808
|
-
name: "
|
|
882
|
+
name: "picked",
|
|
809
883
|
message: "Switch to which team?",
|
|
810
884
|
default: creds.teamId,
|
|
811
885
|
choices: teams.map((t) => ({ name: t.name, value: t.teamId }))
|
|
812
886
|
}]);
|
|
813
|
-
|
|
814
|
-
|
|
887
|
+
chosen = teams.find((t) => t.teamId === picked);
|
|
888
|
+
} else {
|
|
889
|
+
fail2(`Specify a team: \`apiblaze team <name|id>\`. Available: ${teams.map((t) => t.name).join(", ")}.`);
|
|
815
890
|
}
|
|
816
|
-
saveCredentials({ ...creds, teamId, teamName });
|
|
891
|
+
saveCredentials({ ...creds, teamId: chosen.teamId, teamName: chosen.name });
|
|
817
892
|
console.log(import_chalk6.default.green(`
|
|
818
|
-
\u2714 Active team: ${import_chalk6.default.bold(
|
|
893
|
+
\u2714 Active team: ${import_chalk6.default.bold(chosen.name)}`));
|
|
819
894
|
}
|
|
820
895
|
|
|
821
896
|
// src/index.ts
|
|
@@ -829,17 +904,17 @@ program.command("login").description("Authenticate with APIblaze").action(async
|
|
|
829
904
|
process.exit(1);
|
|
830
905
|
}
|
|
831
906
|
});
|
|
832
|
-
program.command("create").description("Create a new API proxy").action(async () => {
|
|
907
|
+
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
908
|
try {
|
|
834
|
-
await runCreate();
|
|
909
|
+
await runCreate(opts);
|
|
835
910
|
} catch (err) {
|
|
836
911
|
printError(err);
|
|
837
912
|
process.exit(1);
|
|
838
913
|
}
|
|
839
914
|
});
|
|
840
|
-
program.command("team").description("Switch the active team").action(async () => {
|
|
915
|
+
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
916
|
try {
|
|
842
|
-
await runTeam();
|
|
917
|
+
await runTeam(team);
|
|
843
918
|
} catch (err) {
|
|
844
919
|
printError(err);
|
|
845
920
|
process.exit(1);
|