apiblaze 0.21.29 → 0.21.31

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 +118 -6
  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.29";
37
+ version = "0.21.31";
38
38
  }
39
39
  });
40
40
 
@@ -7521,6 +7521,7 @@ __export(demo_exports, {
7521
7521
  DEMO_GINO_ADMIN_EMAIL: () => DEMO_GINO_ADMIN_EMAIL,
7522
7522
  DEMO_RPS: () => DEMO_RPS,
7523
7523
  demoName: () => demoName,
7524
+ isDemoProcess: () => isDemoProcess,
7524
7525
  routesOf: () => routesOf,
7525
7526
  runDemo: () => runDemo,
7526
7527
  runDemoLogs: () => runDemoLogs,
@@ -7602,12 +7603,40 @@ function appCtl(dir, arg) {
7602
7603
  const r = (0, import_child_process4.spawnSync)(process.execPath, [import_path5.default.join(dir, "start.js"), arg], { cwd: dir, stdio: "ignore", timeout: 15e3 });
7603
7604
  return r.status === 0;
7604
7605
  }
7606
+ function isDemoProcess(args) {
7607
+ return /[\\/](apiblaze|mcpblaze)-demo[\\/]start\.js(\s|$)/.test(args) || /\sdemo --serve\s/.test(args);
7608
+ }
7609
+ function demoProcesses() {
7610
+ if (process.platform === "win32") return [];
7611
+ const r = (0, import_child_process4.spawnSync)("ps", ["-Ao", "pid=,args="], { encoding: "utf8" });
7612
+ if (r.status !== 0 || !r.stdout) return [];
7613
+ const out = [];
7614
+ for (const line of r.stdout.split("\n")) {
7615
+ const m = /^\s*(\d+)\s+(.*)$/.exec(line);
7616
+ if (m && Number(m[1]) !== process.pid && isDemoProcess(m[2])) out.push(Number(m[1]));
7617
+ }
7618
+ return out;
7619
+ }
7605
7620
  async function stopDemos() {
7606
7621
  const dirs = [...new Set(readRegistry().map((r) => r.dir))];
7607
7622
  const n = await stopTunnels();
7608
7623
  for (const d of dirs) appCtl(d, "--stop");
7609
7624
  writeRegistry([]);
7610
- return n;
7625
+ const left = demoProcesses();
7626
+ for (const pid of left) {
7627
+ try {
7628
+ process.kill(pid, "SIGTERM");
7629
+ } catch {
7630
+ }
7631
+ }
7632
+ for (let i = 0; i < 40 && left.some(alive); i++) await new Promise((r) => setTimeout(r, 100));
7633
+ for (const pid of left) if (alive(pid)) {
7634
+ try {
7635
+ process.kill(pid, "SIGKILL");
7636
+ } catch {
7637
+ }
7638
+ }
7639
+ return n + left.length;
7611
7640
  }
7612
7641
  function writeApp(dir) {
7613
7642
  import_fs6.default.mkdirSync(dir, { recursive: true });
@@ -9205,6 +9234,80 @@ function fromNode(dir, out) {
9205
9234
  out.configuredPort = portFromScripts(scripts);
9206
9235
  out.start = scripts.dev ? "npm run dev" : scripts.start ? "npm start" : void 0;
9207
9236
  }
9237
+ var ENTRY_FILES = [
9238
+ "server.js",
9239
+ "app.js",
9240
+ "index.js",
9241
+ "main.js",
9242
+ "server.mjs",
9243
+ "app.mjs",
9244
+ "index.mjs",
9245
+ "server.cjs",
9246
+ "server.ts",
9247
+ "app.ts",
9248
+ "index.ts",
9249
+ "main.ts",
9250
+ "src/server.ts",
9251
+ "src/index.ts",
9252
+ "src/app.ts",
9253
+ "src/main.ts",
9254
+ "src/server.js",
9255
+ "src/index.js",
9256
+ "src/app.js",
9257
+ "main.py",
9258
+ "app.py",
9259
+ "server.py",
9260
+ "main.go",
9261
+ "server.go"
9262
+ ];
9263
+ var NODE_MODULE_SERVERS = [
9264
+ [/\b(?:require\(\s*|from\s+)['"]express['"]/, "Express"],
9265
+ [/\b(?:require\(\s*|from\s+)['"]fastify['"]/, "Fastify"],
9266
+ [/\b(?:require\(\s*|from\s+)['"]koa['"]/, "Koa"],
9267
+ [/\b(?:require\(\s*|from\s+)['"]hono['"]/, "Hono"],
9268
+ [/\b(?:require\(\s*|from\s+)['"](?:node:)?https?['"]/, "a Node server"]
9269
+ ];
9270
+ function portInSource(text) {
9271
+ const m = /\.listen\(\s*(\d{2,5})\b/.exec(text) ?? /\bPORT\b[^\n]{0,40}?(?:\|\||\?\?|or)\s*['"]?(\d{2,5})\b/.exec(text) ?? /\bport\s*[:=]\s*(\d{2,5})\b/.exec(text) ?? /ListenAndServe\(\s*"[^":]*:(\d{2,5})"/.exec(text) ?? /\.run\([^)]*port\s*=\s*(\d{2,5})/.exec(text);
9272
+ return m ? Number(m[1]) : void 0;
9273
+ }
9274
+ function fromEntryFiles(dir, out) {
9275
+ for (const rel of ENTRY_FILES) {
9276
+ const text = readText(import_path4.default.join(dir, rel));
9277
+ if (!text) continue;
9278
+ let fw;
9279
+ let def;
9280
+ if (/\.(c|m)?[jt]s$/.test(rel)) {
9281
+ if (!/\.listen\(|createServer\(|\bserve\(|export default\s+app\b/.test(text)) continue;
9282
+ fw = NODE_MODULE_SERVERS.find(([re]) => re.test(text))?.[1] ?? "a Node server";
9283
+ def = 3e3;
9284
+ } else if (rel.endsWith(".py")) {
9285
+ if (/\bFastAPI\(/.test(text)) {
9286
+ fw = "FastAPI";
9287
+ def = 8e3;
9288
+ } else if (/\bFlask\(/.test(text)) {
9289
+ fw = "Flask";
9290
+ def = 5e3;
9291
+ } else if (/HTTPServer\(|http\.server/.test(text)) {
9292
+ fw = "a Python server";
9293
+ def = 8e3;
9294
+ } else continue;
9295
+ } else if (rel.endsWith(".go")) {
9296
+ if (!/ListenAndServe\(|\.Run\(|\.Start\(|\.Listen\(/.test(text)) continue;
9297
+ fw = GO_SERVERS.find(([re]) => re.test(text))?.[1] ?? "a Go server";
9298
+ def = 8080;
9299
+ }
9300
+ if (!fw) continue;
9301
+ if (!out.framework) {
9302
+ out.framework = fw;
9303
+ out.source = rel;
9304
+ out.defaultPort = def;
9305
+ }
9306
+ if (!out.configuredPort) out.configuredPort = portInSource(text);
9307
+ if (!out.start && rel.endsWith(".js")) out.start = `node ${rel}`;
9308
+ return;
9309
+ }
9310
+ }
9208
9311
  function fromPython(dir, out) {
9209
9312
  for (const f of ["requirements.txt", "pyproject.toml", "Pipfile"]) {
9210
9313
  const text = readText(import_path4.default.join(dir, f));
@@ -9278,6 +9381,7 @@ async function detectBackend(dir, opts = {}) {
9278
9381
  fromNode(dir, out);
9279
9382
  if (!out.framework) fromPython(dir, out);
9280
9383
  if (!out.framework) fromOthers(dir, out);
9384
+ if (!out.frontendOnly && (!out.framework || !out.configuredPort)) fromEntryFiles(dir, out);
9281
9385
  const spec2 = findSpecFile(dir);
9282
9386
  if (spec2) {
9283
9387
  out.specFile = spec2.file;
@@ -9340,7 +9444,7 @@ function folderReport(f, opts = {}) {
9340
9444
  // A person may know what that is; an agent would only be distracted by it.
9341
9445
  opts.forPerson && f.strayPorts?.length ? ` Something answers on localhost:${f.strayPorts[0]}, but nothing in this folder points at it.` : ""
9342
9446
  ].join("");
9343
- return { lines: [`No backend here: no server framework in the project files and no OpenAPI spec.${extra}`], question: demoQuestion, ownApi: false };
9447
+ return { lines: [`No backend in this folder: no server framework in the project files and no OpenAPI spec.${extra}`], question: demoQuestion, ownApi: false };
9344
9448
  }
9345
9449
  const port = backendPort(f);
9346
9450
  const spec2 = f.specFile ? `Spec: ${f.specFile}.` : f.specUrl ? `It serves its spec at ${f.specUrl}.` : "No OpenAPI spec yet.";
@@ -9885,11 +9989,19 @@ async function runForPerson(found) {
9885
9989
  return;
9886
9990
  }
9887
9991
  if (report.ownApi) {
9888
- console.log(` Start it${found.start ? ` (${found.start})` : ""}, then put it on the internet:`);
9889
- console.log(` ${import_chalk25.default.cyan(`${run2} dev --port ${port ?? "<port>"}${found.specFile ? ` --openapi ${found.specFile}` : ""}`)}`);
9992
+ const args = ["dev", "--port", String(port ?? 3e3), ...found.specFile ? ["--openapi", found.specFile] : []];
9993
+ const startHint = found.start ? `, once you start it (${found.start})` : ", once it runs";
9994
+ if (!await ask2(` ${import_chalk25.default.bold("?")} Put it behind ${P} now? It reaches your app on port ${port ?? 3e3}${startHint}. ${import_chalk25.default.dim("(Y/n)")} `)) {
9995
+ console.log(` Any time: ${import_chalk25.default.cyan(`${run2} ${args.join(" ")}`)}`);
9996
+ return;
9997
+ }
9998
+ console.log(import_chalk25.default.dim(` $ ${run2} ${args.join(" ")}`));
9999
+ const { spawnSync: spawnSync4 } = await import("child_process");
10000
+ const r = spawnSync4(process.execPath, [process.argv[1], ...args], { stdio: "inherit" });
10001
+ process.exitCode = r.status ?? 0;
9890
10002
  return;
9891
10003
  }
9892
- if (!await ask2(` ${import_chalk25.default.bold("?")} See it on a sample app first? ${import_chalk25.default.dim("(Y/n)")} `)) {
10004
+ if (!await ask2(` ${import_chalk25.default.bold("?")} Create a demo app to try out ${P}? ${import_chalk25.default.dim("(Y/n)")} `)) {
9893
10005
  console.log(` Your own app, when it runs: ${import_chalk25.default.cyan(`${run2} dev --port <port>`)}`);
9894
10006
  return;
9895
10007
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.21.29",
3
+ "version": "0.21.31",
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",