apiblaze 0.21.74 → 0.21.75

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.
Files changed (2) hide show
  1. package/dist/index.js +84 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ var __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__
34
34
  var version;
35
35
  var init_package = __esm({
36
36
  "package.json"() {
37
- version = "0.21.74";
37
+ version = "0.21.75";
38
38
  }
39
39
  });
40
40
 
@@ -4243,9 +4243,9 @@ async function openServerProxy(project) {
4243
4243
  }
4244
4244
  function discoverLocalSpecs() {
4245
4245
  const cwd = process.cwd();
4246
- const known = ["openapi.yaml", "openapi.yml", "openapi.json", "swagger.yaml", "swagger.yml", "swagger.json", "api.yaml", "api.yml", "api.json"];
4246
+ const known2 = ["openapi.yaml", "openapi.yml", "openapi.json", "swagger.yaml", "swagger.yml", "swagger.json", "api.yaml", "api.yml", "api.json"];
4247
4247
  const found = [];
4248
- for (const n of known) {
4248
+ for (const n of known2) {
4249
4249
  try {
4250
4250
  if (fs9.statSync(path9.join(cwd, n)).isFile()) found.push(n);
4251
4251
  } catch {
@@ -5680,7 +5680,9 @@ function withBrandSource(url, cli = B.cli) {
5680
5680
  }
5681
5681
  function pageLinkOf(r, proj2, anchor) {
5682
5682
  const base2 = r?.progress?.pageUrl ?? `${DASHBOARD_BASE6}/directory/${encodeURIComponent(proj2.projectId)}/${encodeURIComponent(proj2.apiVersion)}`;
5683
- const page = withBrandSource(base2);
5683
+ const team = proj2.teamId && !proj2.teamId.startsWith("team_anon_") ? proj2.teamId : null;
5684
+ let page = withBrandSource(base2);
5685
+ if (team) page += `${page.includes("?") ? "&" : "?"}team=${encodeURIComponent(team)}`;
5684
5686
  return anchor ? `${page}${anchor.startsWith("#") ? anchor : `#${anchor}`}` : page;
5685
5687
  }
5686
5688
  function stepOf(r, id) {
@@ -6658,7 +6660,31 @@ async function printDevOutcome(o, port) {
6658
6660
  }
6659
6661
  if (o.anon) printLegalNotice(" ");
6660
6662
  }
6663
+ function printListingOutcome(o) {
6664
+ const where = { tenant: o.tenant, anon: o.anon };
6665
+ const mcp = mcpUrl(o.name, o.version, o.env, where);
6666
+ const s = o.secure;
6667
+ const applied = s?.applied ?? [];
6668
+ console.log();
6669
+ console.log(` ${import_chalk20.default.green("\u2713")} ${B.thing} ${import_chalk20.default.bold(o.name)}: ${import_chalk20.default.bold(mcp)}`);
6670
+ if (applied.length && s?.enforced) console.log(` ${import_chalk20.default.green("\u2713")} Each person can only change the ${describeFamilies(applied)} they made ${import_chalk20.default.dim("(lists stay open: your backend filters them)")}`);
6671
+ else if (applied.length && s?.pending) console.log(` ${import_chalk20.default.dim("\u2013")} ${describeFamilies(applied)}: the who-can-change-what rules are being applied`);
6672
+ else console.log(` ${import_chalk20.default.dim("\u2013")} ${import_chalk20.default.dim(`Who can change what: not set yet. Later: npx ${B.cli} rule ${o.name}`)}`);
6673
+ if (o.auth.doors.includes("api_key") && o.apiKey) {
6674
+ const saved = process.stdout.isTTY ? null : saveEnvLocal(process.cwd(), {
6675
+ APIBLAZE_URL: restUrl(o.name, o.version, o.env, where),
6676
+ APIBLAZE_MCP_URL: mcp,
6677
+ APIBLAZE_SERVER_KEY: o.apiKey,
6678
+ ...o.tenant ? { APIBLAZE_TENANT: o.tenant } : {}
6679
+ });
6680
+ if (saved?.ok) console.log(` ${import_chalk20.default.green("\u2713")} Backend key saved to .env.local as APIBLAZE_SERVER_KEY`);
6681
+ else console.log(` ${import_chalk20.default.green("\u2713")} Backend key ${import_chalk20.default.dim("(shown once, save it):")} ${import_chalk20.default.bold.green(o.apiKey)}`);
6682
+ }
6683
+ if (o.claim?.claimCode || o.claim?.claimUrl) console.log(import_chalk20.default.dim(` Anonymous: it expires in 30 days unless you sign in (npx ${B.cli} login claims it).`));
6684
+ if (o.anon) printLegalNotice(" ");
6685
+ }
6661
6686
  async function printOutcome(o) {
6687
+ if (o.listing) return printListingOutcome(o);
6662
6688
  const where = { tenant: o.tenant, anon: o.anon };
6663
6689
  const mcp = mcpUrl(o.name, o.version, o.env, where);
6664
6690
  const shown = BRAND === "mcpblaze" ? mcp : B.liveUrl(o.name, o.version, o.env, where);
@@ -6752,8 +6778,11 @@ async function runCreate(opts = {}) {
6752
6778
  opts.target = void 0;
6753
6779
  }
6754
6780
  }
6755
- const creds = loadCredentials();
6781
+ const saved = loadCredentials();
6782
+ const expired = !!saved && Date.now() >= saved.expiresAt && !process.env.APIBLAZE_TOKEN?.trim();
6783
+ const creds = expired ? null : saved;
6756
6784
  if (!creds) {
6785
+ if (expired && !opts.json) console.log(import_chalk20.default.dim(`Your saved login has expired, so this is made anonymously. \`${B.cli} login\` then claims it into your team.`));
6757
6786
  await runAnonymousCreate(opts);
6758
6787
  return;
6759
6788
  }
@@ -6939,6 +6968,7 @@ Create an ${B.thing}
6939
6968
  return;
6940
6969
  }
6941
6970
  await finishSetup({
6971
+ listing: !!opts.directoryReady,
6942
6972
  name,
6943
6973
  version: version2,
6944
6974
  env: "dev",
@@ -7174,7 +7204,8 @@ Create an ${B.thing}`));
7174
7204
  });
7175
7205
  }
7176
7206
  if (name) await applyCreateToggles(name, opts);
7177
- const directory = anonProjectId ? await directoryAfterCreate(anonProjectId, version2, opts) : null;
7207
+ if (anonProjectId) opts.onCreated?.({ name: anonProjectId, version: version2, tenant, teamId: result.team_id });
7208
+ const directory = anonProjectId && !opts.skipDirectoryReport ? await directoryAfterCreate(anonProjectId, version2, opts) : null;
7178
7209
  if (opts.json) {
7179
7210
  process.stdout.write(JSON.stringify({
7180
7211
  project_id: result.project_id,
@@ -7198,6 +7229,7 @@ Create an ${B.thing}`));
7198
7229
  return;
7199
7230
  }
7200
7231
  await finishSetup({
7232
+ listing: !!opts.directoryReady,
7201
7233
  name: anonProjectId,
7202
7234
  version: version2,
7203
7235
  env: "prod",
@@ -8013,10 +8045,10 @@ function orderTools(tools) {
8013
8045
  const rank = { read: 0, create: 1, update: 2, write: 3, delete: 4 };
8014
8046
  return [...tools].sort((a, b) => rank[toolRole(a)] - rank[toolRole(b)] || a.name.localeCompare(b.name));
8015
8047
  }
8016
- function exampleValue(name, p, known = {}, given = {}) {
8048
+ function exampleValue(name, p, known2 = {}, given = {}) {
8017
8049
  if (given[name] !== void 0) return given[name];
8018
8050
  if (p.example !== void 0 && p.example !== null) return p.example;
8019
- if (known[name] !== void 0) return known[name];
8051
+ if (known2[name] !== void 0) return known2[name];
8020
8052
  if (Array.isArray(p.enum) && p.enum.length) return p.enum[0];
8021
8053
  const t = (p.type ?? "string").toLowerCase();
8022
8054
  const fmt = (p.format ?? "").toLowerCase();
@@ -8033,14 +8065,14 @@ function exampleValue(name, p, known = {}, given = {}) {
8033
8065
  if (/(^|_)(q|query|search|term|text|name|title)$/i.test(name)) return "test";
8034
8066
  return "example";
8035
8067
  }
8036
- function validArgs(t, known = {}, given = {}) {
8068
+ function validArgs(t, known2 = {}, given = {}) {
8037
8069
  const out = {};
8038
8070
  const props = t.inputProperties ?? {};
8039
8071
  const pathParams = new Set([...(t.path ?? "").matchAll(/\{([^}]+)\}/g)].map((m) => m[1]));
8040
8072
  for (const [name, p] of Object.entries(props)) {
8041
- const wanted = p.required || pathParams.has(name) || p.example !== void 0 && p.example !== null || known[name] !== void 0 || given[name] !== void 0;
8073
+ const wanted = p.required || pathParams.has(name) || p.example !== void 0 && p.example !== null || known2[name] !== void 0 || given[name] !== void 0;
8042
8074
  if (!wanted) continue;
8043
- out[name] = exampleValue(name, p, known, given);
8075
+ out[name] = exampleValue(name, p, known2, given);
8044
8076
  }
8045
8077
  return out;
8046
8078
  }
@@ -8056,11 +8088,11 @@ function candidateFromPrompts(name, p, prompts) {
8056
8088
  const quoted = text.match(/["“']([^"”']{1,80})["”']/);
8057
8089
  return quoted ? quoted[1].trim() : null;
8058
8090
  }
8059
- function invalidArgs(t, known = {}, given = {}) {
8091
+ function invalidArgs(t, known2 = {}, given = {}) {
8060
8092
  const props = t.inputProperties ?? {};
8061
8093
  const names = Object.keys(props);
8062
8094
  if (!names.length) return null;
8063
- const base2 = validArgs(t, known, given);
8095
+ const base2 = validArgs(t, known2, given);
8064
8096
  const withEnum = names.find((n) => Array.isArray(props[n].enum) && props[n].enum.length);
8065
8097
  if (withEnum) return { args: { ...base2, [withEnum]: "not-a-valid-choice" }, broke: `${withEnum}: out of enum` };
8066
8098
  const typed = names.find((n) => ["integer", "number", "boolean"].includes((props[n].type ?? "").toLowerCase()));
@@ -13764,11 +13796,10 @@ async function ensureHostedUpstream(caller, teamId, proj2, r, opts, interactive2
13764
13796
  let chosen = header;
13765
13797
  let open = !!opts.upstreamOpen;
13766
13798
  if (!chosen && !open && interactive2) {
13767
- if (shape(cur).hosts?.upstreamKind === "public" && !shape(cur).hosts?.upstreamHeader) say(import_chalk32.default.dim(" An open backend can be called around sign-in and the per-user rules; a shared secret header closes that."));
13768
13799
  const { default: inquirer3 } = await import("inquirer");
13769
- const { name } = await inquirer3.prompt([{ type: "input", name: "name", message: `Does the backend need a header to accept calls from ${B.product}, such as an API key or a shared secret? (Header name; Enter = no, it checks its own credentials)` }]);
13800
+ const { name } = await inquirer3.prompt([{ type: "input", name: "name", message: "Secret header your backend checks? (e.g. X-Api-Key; Enter if none)" }]);
13770
13801
  if (name?.trim()) {
13771
- const { value } = await inquirer3.prompt([{ type: "password", name: "value", mask: "*", message: `Value of ${name.trim()} (stored encrypted, never shown again):`, validate: (v) => (v ?? "").length > 0 ? true : "A value is needed; Ctrl-C leaves." }]);
13802
+ const { value } = await inquirer3.prompt([{ type: "password", name: "value", mask: "*", message: `Its value (stored encrypted):`, validate: (v) => (v ?? "").length > 0 ? true : "A value is needed; Ctrl-C leaves." }]);
13772
13803
  chosen = { name: name.trim(), value };
13773
13804
  } else open = true;
13774
13805
  }
@@ -13881,8 +13912,6 @@ function installInterrupt(ctx) {
13881
13912
  return () => process.off("SIGINT", handler);
13882
13913
  }
13883
13914
  async function runConnector(target2, opts) {
13884
- const caller = requireCaller();
13885
- const { teamId } = await resolveActingTeam(caller, opts.team);
13886
13915
  const json = !!opts.json;
13887
13916
  const interactive2 = !!process.stdin.isTTY && !json && !opts.yes;
13888
13917
  const say = (s) => {
@@ -13898,8 +13927,9 @@ async function runConnector(target2, opts) {
13898
13927
  const created = await createFromSpec(specSource, opts, say);
13899
13928
  projectName = created.name;
13900
13929
  version2 = created.version;
13901
- say(import_chalk32.default.green(` ${B.thing} ${import_chalk32.default.bold(created.name)} created.`));
13902
13930
  }
13931
+ const caller = requireCaller();
13932
+ const { teamId } = await resolveActingTeam(caller, opts.team);
13903
13933
  const proj2 = await resolveProjectVia(caller, teamId, projectName, version2);
13904
13934
  const flagBody = directoryBodyFromFlags(opts);
13905
13935
  const onlyAttest = !!opts.attest?.length && !flagBody.directory_metadata && !opts.full && !specSource && !only && !opts.status;
@@ -13947,9 +13977,23 @@ ${claudeCodeText(cc)}`);
13947
13977
  r = await fetchDirectoryReport(caller, proj2, reportOpts());
13948
13978
  }
13949
13979
  const link = pageLinkOf(r, proj2);
13950
- const sum = summaryOf(r);
13951
- if (sum) {
13952
- say(`${import_chalk32.default.bold("Finish this here or at")} ${import_chalk32.default.cyan(link)} ${import_chalk32.default.dim("\xB7")} ${import_chalk32.default.bold(sum)}`);
13980
+ if (r.progress) {
13981
+ const pct = r.progress.readiness?.percent;
13982
+ const where = platforms.map((p) => p === "claude" ? "Claude" : "ChatGPT").join(" and ");
13983
+ const rule = import_chalk32.default.dim("\u2500".repeat(64));
13984
+ say("");
13985
+ say(rule);
13986
+ say(` ${import_chalk32.default.bold(`Get it listed in ${where}`)}${typeof pct === "number" ? import_chalk32.default.dim(` \xB7 ${pct}% ready`) : ""}`);
13987
+ if (caller.mode === "anon") {
13988
+ say(` A listing needs an account (your own MCP address is billed to it). Sign in, then carry on:`);
13989
+ say(` ${import_chalk32.default.cyan(`npx ${B.cli}@latest login`)} ${import_chalk32.default.dim(`it keeps ${proj2.projectId}, moving it into your team`)}`);
13990
+ say(` ${import_chalk32.default.cyan(`npx ${B.cli}@latest connector ${proj2.projectId}`)} ${import_chalk32.default.dim("or finish on the page it links")}`);
13991
+ say(rule);
13992
+ return;
13993
+ }
13994
+ say(` ${import_chalk32.default.bold("Here:")} answer the questions below. Stop any time; every answer is kept.`);
13995
+ say(` ${import_chalk32.default.bold("Or in your browser:")} ${import_chalk32.default.cyan(link)}`);
13996
+ say(rule);
13953
13997
  const done = doneLine(r);
13954
13998
  if (done) say(import_chalk32.default.dim(` ${done}`));
13955
13999
  } else {
@@ -24038,9 +24082,27 @@ but this build does not have it, your npx cache is serving an older copy \u2014
24038
24082
  return program2;
24039
24083
  }
24040
24084
 
24085
+ // src/lib/bare-create.ts
24086
+ var SPEC = /^(https?:\/\/\S+|\S+\.(ya?ml|json))$/i;
24087
+ function bareCreateArgv(args, commands) {
24088
+ if (!args.length) return args;
24089
+ for (let i = 0; i < args.length; i += 1) {
24090
+ const a = args[i];
24091
+ if (a.startsWith("-")) continue;
24092
+ const prev = args[i - 1];
24093
+ const isValue = !!prev && prev.startsWith("--") && !prev.includes("=");
24094
+ if (!isValue && commands.has(a)) return args;
24095
+ }
24096
+ if (SPEC.test(args[0])) return ["create", "--target", ...args];
24097
+ if (args.some((a) => a === "--target" || a.startsWith("--target="))) return ["create", ...args];
24098
+ return args;
24099
+ }
24100
+
24041
24101
  // src/index.ts
24042
24102
  installBrandFilter();
24043
24103
  var program = buildProgram();
24104
+ var known = new Set(program.commands.flatMap((c) => [c.name(), ...c.aliases()]).concat(["help"]));
24105
+ process.argv = [...process.argv.slice(0, 2), ...bareCreateArgv(process.argv.slice(2), known)];
24044
24106
  process.on("exit", () => renderTrace());
24045
24107
  installFetchGuard(version);
24046
24108
  var firstCommand = process.argv.slice(2).find((a) => !a.startsWith("-"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.21.74",
3
+ "version": "0.21.75",
4
4
  "description": "APIblaze CLI — Chat with your APIs, Manage your API keys, users and groups with the APIblaze serverless proxy",
5
5
  "keywords": [
6
6
  "apiblaze",