apiblaze 0.21.9 → 0.21.11
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 +109 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1342,7 +1342,7 @@ var import_commander = require("commander");
|
|
|
1342
1342
|
var import_chalk63 = __toESM(require("chalk"));
|
|
1343
1343
|
|
|
1344
1344
|
// package.json
|
|
1345
|
-
var version = "0.21.
|
|
1345
|
+
var version = "0.21.11";
|
|
1346
1346
|
|
|
1347
1347
|
// src/index.ts
|
|
1348
1348
|
init_types();
|
|
@@ -4848,10 +4848,30 @@ async function mintConsumerKey(o) {
|
|
|
4848
4848
|
raw: out
|
|
4849
4849
|
};
|
|
4850
4850
|
}
|
|
4851
|
+
async function tenantKeyEndUserMode(caller, teamId, tenant2) {
|
|
4852
|
+
try {
|
|
4853
|
+
const p = await producer(caller, {
|
|
4854
|
+
method: "GET",
|
|
4855
|
+
path: `/teams/${encodeURIComponent(teamId)}/tenants/${encodeURIComponent(tenant2)}/key-policy`,
|
|
4856
|
+
summary: "Read the tenant key policy (default holder)"
|
|
4857
|
+
});
|
|
4858
|
+
return p?.key_end_user_mode === "one" ? "one" : "many";
|
|
4859
|
+
} catch {
|
|
4860
|
+
return "many";
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
function defaultHolderRefusal(tenant2) {
|
|
4864
|
+
return `Tenant ${tenant2} issues one key per end user (1 API key = 1 end user): add --for <email|id>. To create a different key anyway, pass --backend (a server key that names each caller) or --client.`;
|
|
4865
|
+
}
|
|
4851
4866
|
async function runConsumerKeyMint(opts) {
|
|
4852
4867
|
const kind = resolveHolder(opts);
|
|
4853
4868
|
const who = (opts.for ?? "").trim();
|
|
4854
4869
|
const tenant2 = (opts.tenant ?? "").trim();
|
|
4870
|
+
if (tenant2 && !who && !opts.backend && !opts.client) {
|
|
4871
|
+
const caller = requireCaller();
|
|
4872
|
+
const { teamId } = await resolveActingTeam(caller, opts.team);
|
|
4873
|
+
if (await tenantKeyEndUserMode(caller, teamId, tenant2) === "one") throw new Error(defaultHolderRefusal(tenant2));
|
|
4874
|
+
}
|
|
4855
4875
|
const spinner = (0, import_ora3.default)(who ? `Minting a key for ${who} in ${tenant2}...` : `Minting a ${kind} key in ${tenant2}...`).start();
|
|
4856
4876
|
let out;
|
|
4857
4877
|
try {
|
|
@@ -10156,29 +10176,74 @@ var import_chalk44 = __toESM(require("chalk"));
|
|
|
10156
10176
|
var import_ora16 = __toESM(require("ora"));
|
|
10157
10177
|
init_admin();
|
|
10158
10178
|
init_resolve();
|
|
10179
|
+
var KINDS = ["api", "mcp", "portal", "auth"];
|
|
10180
|
+
var TENANT_KINDS = ["portal", "auth"];
|
|
10181
|
+
async function scopeFor(project, opts) {
|
|
10182
|
+
const { teamId } = await resolveTeam(opts.team);
|
|
10183
|
+
if (project) {
|
|
10184
|
+
const proj2 = await resolveProject(teamId, project, opts.apiversion);
|
|
10185
|
+
return { kind: "project", base: `/projects/${proj2.projectId}/domains`, label: `${proj2.projectName} v${proj2.apiVersion}`, apiVersion: proj2.apiVersion };
|
|
10186
|
+
}
|
|
10187
|
+
if (!opts.tenant) {
|
|
10188
|
+
console.error(import_chalk44.default.red("Give a <project> (api / mcp domains) or --tenant <slug> (portal / auth domains)."));
|
|
10189
|
+
process.exit(1);
|
|
10190
|
+
}
|
|
10191
|
+
const tenant2 = opts.tenant.toLowerCase();
|
|
10192
|
+
return {
|
|
10193
|
+
kind: "tenant",
|
|
10194
|
+
base: `/teams/${encodeURIComponent(teamId)}/tenants/${encodeURIComponent(tenant2)}/domains`,
|
|
10195
|
+
label: `tenant ${tenant2}`
|
|
10196
|
+
};
|
|
10197
|
+
}
|
|
10198
|
+
function describeKind(d) {
|
|
10199
|
+
return d?.target ? `${d.kind ?? "api"} \u2192 stands in for ${d.target}` : d?.kind ?? "api";
|
|
10200
|
+
}
|
|
10201
|
+
function statusColor2(s) {
|
|
10202
|
+
if (s === "active") return import_chalk44.default.green(s);
|
|
10203
|
+
if (s === "failed" || s === "missing" || s === "suspended") return import_chalk44.default.red(s);
|
|
10204
|
+
return import_chalk44.default.yellow(s ?? "unknown");
|
|
10205
|
+
}
|
|
10159
10206
|
async function runDomainAdd(project, opts) {
|
|
10160
10207
|
if (!opts.domain) {
|
|
10161
10208
|
console.error(import_chalk44.default.red("--domain is required."));
|
|
10162
10209
|
process.exit(1);
|
|
10163
10210
|
}
|
|
10164
|
-
const
|
|
10165
|
-
|
|
10211
|
+
const kind = (opts.kind ?? (project ? "api" : "")).toLowerCase();
|
|
10212
|
+
if (!KINDS.includes(kind)) {
|
|
10213
|
+
console.error(import_chalk44.default.red(`--kind must be one of ${KINDS.join(", ")}${project ? "" : " (portal or auth for a --tenant)"}.`));
|
|
10214
|
+
process.exit(1);
|
|
10215
|
+
}
|
|
10216
|
+
const tenantKind = TENANT_KINDS.includes(kind);
|
|
10217
|
+
if (tenantKind && project) {
|
|
10218
|
+
console.error(import_chalk44.default.red(`A ${kind} domain belongs to a tenant, not a proxy: apiblaze domain add --tenant <slug> --kind ${kind} --domain ${opts.domain}`));
|
|
10219
|
+
process.exit(1);
|
|
10220
|
+
}
|
|
10221
|
+
if (tenantKind && !opts.tenant) {
|
|
10222
|
+
console.error(import_chalk44.default.red(`--tenant <slug> is required for a ${kind} domain.`));
|
|
10223
|
+
process.exit(1);
|
|
10224
|
+
}
|
|
10225
|
+
if (!tenantKind && !project) {
|
|
10226
|
+
console.error(import_chalk44.default.red(`A ${kind} domain belongs to a proxy: apiblaze domain add <project> --kind ${kind} --domain ${opts.domain}`));
|
|
10227
|
+
process.exit(1);
|
|
10228
|
+
}
|
|
10229
|
+
const scope = await scopeFor(project, opts);
|
|
10166
10230
|
const spinner = (0, import_ora16.default)(`Registering ${opts.domain}...`).start();
|
|
10167
10231
|
try {
|
|
10232
|
+
const body = scope.kind === "project" ? { hostname: opts.domain, api_version: scope.apiVersion, kind, ...opts.tenant ? { tenant_name: opts.tenant.toLowerCase() } : {} } : { hostname: opts.domain, kind };
|
|
10168
10233
|
const out = await admin({
|
|
10169
10234
|
method: "POST",
|
|
10170
|
-
path:
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
summary: `Add custom domain ${opts.domain} to ${proj2.projectName} v${proj2.apiVersion}${opts.tenant ? ` (tenant ${opts.tenant})` : ""}`
|
|
10235
|
+
path: scope.base,
|
|
10236
|
+
body,
|
|
10237
|
+
summary: `Add custom ${kind} domain ${opts.domain} to ${scope.label}${scope.kind === "project" && opts.tenant ? ` (tenant ${opts.tenant})` : ""}`
|
|
10174
10238
|
});
|
|
10175
|
-
spinner.succeed(`Registered ${opts.domain}. Add these DNS records, then run \`apiblaze domain status\`:`);
|
|
10239
|
+
spinner.succeed(`Registered ${out?.hostname ?? opts.domain} (${describeKind(out)}). Add these DNS records, then run \`apiblaze domain status\`:`);
|
|
10176
10240
|
if (opts.json) {
|
|
10177
10241
|
console.log(JSON.stringify(out));
|
|
10178
10242
|
return;
|
|
10179
10243
|
}
|
|
10180
|
-
if (out?.cnameRecord) console.log(` ${import_chalk44.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value
|
|
10244
|
+
if (out?.cnameRecord) console.log(` ${import_chalk44.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value}`);
|
|
10181
10245
|
if (out?.dcv) console.log(` ${import_chalk44.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
|
|
10246
|
+
if (typeof out?.monthlyCents === "number") console.log(import_chalk44.default.dim(` billed $${(out.monthlyCents / 100).toFixed(2)}/month (first month pro rata)`));
|
|
10182
10247
|
if (out?.id) console.log(import_chalk44.default.dim(` domain id: ${out.id}`));
|
|
10183
10248
|
} catch (err) {
|
|
10184
10249
|
spinner.fail("Domain registration failed.");
|
|
@@ -10186,12 +10251,11 @@ async function runDomainAdd(project, opts) {
|
|
|
10186
10251
|
}
|
|
10187
10252
|
}
|
|
10188
10253
|
async function runDomainList(project, opts) {
|
|
10189
|
-
const
|
|
10190
|
-
const proj2 = await resolveProject(teamId, project, opts.apiversion);
|
|
10254
|
+
const scope = await scopeFor(project, opts);
|
|
10191
10255
|
const out = await admin({
|
|
10192
10256
|
method: "GET",
|
|
10193
|
-
path:
|
|
10194
|
-
summary: `List custom domains for ${
|
|
10257
|
+
path: scope.kind === "project" ? `${scope.base}?api_version=${encodeURIComponent(scope.apiVersion)}` : scope.base,
|
|
10258
|
+
summary: `List custom domains for ${scope.label}`
|
|
10195
10259
|
});
|
|
10196
10260
|
const domains = out?.domains ?? [];
|
|
10197
10261
|
if (opts.json) {
|
|
@@ -10202,37 +10266,50 @@ async function runDomainList(project, opts) {
|
|
|
10202
10266
|
console.log(import_chalk44.default.yellow("No custom domains."));
|
|
10203
10267
|
return;
|
|
10204
10268
|
}
|
|
10205
|
-
for (const d of domains)
|
|
10269
|
+
for (const d of domains) {
|
|
10270
|
+
const pin = scope.kind === "project" && d.tenant ? import_chalk44.default.dim(` tenant ${d.tenant}`) : "";
|
|
10271
|
+
console.log(` ${import_chalk44.default.bold(d.hostname)} ${statusColor2(d.status)} ${import_chalk44.default.dim(describeKind(d))}${pin} ${import_chalk44.default.dim(d.id ?? "")}`);
|
|
10272
|
+
}
|
|
10206
10273
|
}
|
|
10207
10274
|
async function runDomainStatus(project, opts) {
|
|
10208
10275
|
if (!opts.id) {
|
|
10209
10276
|
console.error(import_chalk44.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
|
|
10210
10277
|
process.exit(1);
|
|
10211
10278
|
}
|
|
10212
|
-
const
|
|
10213
|
-
const proj2 = await resolveProject(teamId, project, opts.apiversion);
|
|
10279
|
+
const scope = await scopeFor(project, opts);
|
|
10214
10280
|
const out = await admin({
|
|
10215
10281
|
method: "GET",
|
|
10216
|
-
path:
|
|
10282
|
+
path: `${scope.base}/${encodeURIComponent(opts.id)}/status`,
|
|
10217
10283
|
summary: `Check custom-domain status`
|
|
10218
10284
|
});
|
|
10219
|
-
|
|
10285
|
+
if (opts.json) {
|
|
10286
|
+
console.log(JSON.stringify(out));
|
|
10287
|
+
return;
|
|
10288
|
+
}
|
|
10289
|
+
console.log(` ${import_chalk44.default.bold(out?.hostname ?? opts.id)}: ${statusColor2(out?.status)} ${import_chalk44.default.dim(describeKind(out))}`);
|
|
10290
|
+
if (out?.status !== "active") {
|
|
10291
|
+
if (out?.status === "suspended") console.log(import_chalk44.default.red(" Suspended for non-payment \u2014 add credit to restore it."));
|
|
10292
|
+
else if (out?.status === "missing") console.log(import_chalk44.default.red(" No longer registered at Cloudflare \u2014 remove it and add it again."));
|
|
10293
|
+
else {
|
|
10294
|
+
if (out?.cnameRecord) console.log(` ${import_chalk44.default.cyan("CNAME")} ${out.cnameRecord.name} \u2192 ${out.cnameRecord.value}`);
|
|
10295
|
+
if (out?.dcv) console.log(` ${import_chalk44.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
|
|
10296
|
+
}
|
|
10297
|
+
}
|
|
10220
10298
|
}
|
|
10221
10299
|
async function runDomainRemove(project, opts) {
|
|
10222
10300
|
if (!opts.id) {
|
|
10223
10301
|
console.error(import_chalk44.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
|
|
10224
10302
|
process.exit(1);
|
|
10225
10303
|
}
|
|
10226
|
-
const
|
|
10227
|
-
const proj2 = await resolveProject(teamId, project, opts.apiversion);
|
|
10304
|
+
const scope = await scopeFor(project, opts);
|
|
10228
10305
|
const spinner = (0, import_ora16.default)("Removing domain...").start();
|
|
10229
10306
|
try {
|
|
10230
10307
|
await admin({
|
|
10231
10308
|
method: "DELETE",
|
|
10232
|
-
path:
|
|
10309
|
+
path: `${scope.base}/${encodeURIComponent(opts.id)}`,
|
|
10233
10310
|
summary: `Remove custom domain ${opts.id}`
|
|
10234
10311
|
});
|
|
10235
|
-
spinner.succeed("Removed.");
|
|
10312
|
+
spinner.succeed("Removed. Billing for it stops now.");
|
|
10236
10313
|
} catch (err) {
|
|
10237
10314
|
spinner.fail("Remove failed.");
|
|
10238
10315
|
throw err;
|
|
@@ -14446,11 +14523,16 @@ program.command("config").description("Browse and change every proxy setting & f
|
|
|
14446
14523
|
program.command("target").description("Change where a proxy forwards requests").argument("<project>", "Project name or id").requiredOption("--url <url>", "Target URL to forward to").option("--env <env>", "Environment to scope the target to (e.g. prod, dev)").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version (defaults to the first match)").option("--json", "Output machine-readable JSON").action(action((project, opts) => runTargetSet(project, opts)));
|
|
14447
14524
|
program.command("throttle").description("Set rate limits and quotas for a proxy").argument("<project>", "Project name or id").option("--rate <n>", "User rate limit (requests/sec)").option("--end-user-rate <n>", "Per-end-user rate limit (requests/sec)").option("--quota <n>", "Proxy quota (requests/period)").option("--period <p>", "Quota period: daily | weekly | monthly").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runThrottleSet(project, opts)));
|
|
14448
14525
|
program.command("rename").description("Change a proxy's display name").argument("<project>", "Project name or id").requiredOption("--display-name <name>", "New human-friendly display name").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runRename(project, opts)));
|
|
14449
|
-
var domain = program.command("domain").description("Use your own domain for
|
|
14450
|
-
domain.command("add").description("Add your own domain (shows the DNS records to set)").argument("
|
|
14451
|
-
|
|
14452
|
-
|
|
14453
|
-
|
|
14526
|
+
var domain = program.command("domain").description("Use your own domain for your API, MCP server, developer portal or login pages (billed monthly)");
|
|
14527
|
+
domain.command("add").description("Add your own domain (shows the DNS records to set)").argument("[project]", "Project name or id (for api / mcp domains; omit with --tenant for portal / auth)").requiredOption("--domain <host>", "Custom hostname to add, e.g. api.example.com").option("--kind <kind>", "api (default) | mcp \u2014 on a project; portal | auth \u2014 on a --tenant").option("--tenant <slug>", "portal/auth: the tenant the domain belongs to. api/mcp: pin the domain to one of the project's tenants").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").addHelpText("after", `
|
|
14528
|
+
Examples:
|
|
14529
|
+
apiblaze domain add shop --domain api.acme.com # the API
|
|
14530
|
+
apiblaze domain add shop --domain mcp.acme.com --kind mcp # the MCP server
|
|
14531
|
+
apiblaze domain add --tenant acme --kind portal --domain developers.acme.com
|
|
14532
|
+
apiblaze domain add --tenant acme --kind auth --domain login.acme.com`).action(action((project, opts) => runDomainAdd(project, opts)));
|
|
14533
|
+
domain.command("list").description("List a project's custom domains, or a tenant's portal/login domains").argument("[project]", "Project name or id (omit with --tenant)").option("--tenant <slug>", "List the tenant's portal / auth domains").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runDomainList(project, opts)));
|
|
14534
|
+
domain.command("status").description("Check a custom domain's validation status (and show the DNS records still needed)").argument("[project]", "Project name or id (omit with --tenant)").requiredOption("--id <domainId>", "Domain id (see `domain list`)").option("--tenant <slug>", "The tenant, for a portal / auth domain").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runDomainStatus(project, opts)));
|
|
14535
|
+
domain.command("rm").description("Remove a custom domain (billing for it stops)").argument("[project]", "Project name or id (omit with --tenant)").requiredOption("--id <domainId>", "Domain id (see `domain list`)").option("--tenant <slug>", "The tenant, for a portal / auth domain").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").action(action((project, opts) => runDomainRemove(project, opts)));
|
|
14454
14536
|
domain.command("set-base").description("Choose which version/environment your main URL serves").argument("<project>", "Project name or id").option("--env <env>", "Environment (default: prod)").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").action(action((project, opts) => runDomainSetBase(project, opts)));
|
|
14455
14537
|
var group = program.command("group").description("Manage a tenant's users & groups \u2014 bare command lists groups").action(action(() => runGroupList({})));
|
|
14456
14538
|
group.command("list").description("List groups").option("--tenant <slug>", "Tenant").option("--json", "Machine-readable output").action(action((opts) => runGroupList(opts)));
|