@akanjs/cli 3.0.0-beta.18 → 3.0.0-beta.19

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 (75) hide show
  1. package/.build-stamp +1 -1
  2. package/{CodeAgent-0035exh3.js → CodeAgent-6cm97kay.js} +2 -2
  3. package/{CodeAgentRpcHost-qvwfv0n9.js → CodeAgentRpcHost-p7h6n2hp.js} +1 -1
  4. package/CodeAgentRpcListener-7p7z5dd7.js +97 -0
  5. package/{CodeTui-eweg1hep.js → CodeTui-za4jsm41.js} +1 -1
  6. package/{TunnelShare-r5tc2qk5.js → TunnelShare-2j6s511d.js} +2 -2
  7. package/{agent.command-65zqfkg0.js → agent.command-e0wpbbyg.js} +5 -5
  8. package/akanCode.js +4 -4
  9. package/{application.command-2wcj5da3.js → application.command-8wyxqc8q.js} +15 -9
  10. package/{applicationBuildRunner-m0hhgwsx.js → applicationBuildRunner-n9gzaxd0.js} +31 -7
  11. package/{applicationReleasePackager-vykfzgx3.js → applicationReleasePackager-vpggfqgq.js} +1 -1
  12. package/buildBatch.proc.js +3 -3
  13. package/{capacitorApp-2daqhb5h.js → capacitorApp-q3z0qht0.js} +2 -2
  14. package/{cloud.command-960bgbf4.js → cloud.command-4zwa5dsx.js} +34 -12
  15. package/cloud.script-fwx3vb34.js +20 -0
  16. package/{code.command-4feh3ef7.js → code.command-468c9d7s.js} +41 -19
  17. package/commandManifest.json +1 -1
  18. package/{context.command-kzehkx48.js → context.command-dsnw0jby.js} +13 -13
  19. package/context.runner-rs4rj15d.js +22 -0
  20. package/{dependencyScanner-shs82ynp.js → dependencyScanner-0z2h2tks.js} +1 -1
  21. package/{guideline.command-3w2g20x4.js → guideline.command-vhw13pqr.js} +2 -2
  22. package/guidelines/agentRule/agentRule.instruction.md +27 -10
  23. package/guidelines/conventions/conventions.instruction.md +16 -4
  24. package/guidelines/queryRule/queryRule.instruction.md +16 -6
  25. package/guidelines/runtimeRule/runtimeRule.instruction.md +74 -0
  26. package/incrementalBuilder.proc.js +3 -2
  27. package/{index-dw943k93.js → index-10dkrrww.js} +4 -4
  28. package/{index-rpgxs245.js → index-18zybgkc.js} +2 -2
  29. package/{index-mt2154s2.js → index-22xtgmhn.js} +1 -1
  30. package/{index-yw6g3bbv.js → index-2446k7b4.js} +1 -1
  31. package/{index-cjw1sj1x.js → index-3jrp517k.js} +10 -10
  32. package/{index-q9c3c0hy.js → index-4m929vvn.js} +2 -2
  33. package/{index-ef228gzf.js → index-53176s7j.js} +3 -3
  34. package/{index-jwrpsrg3.js → index-667w0yah.js} +1 -1
  35. package/{index-6q589y9t.js → index-7ep8qtvp.js} +2 -2
  36. package/{index-w8kmx1b6.js → index-89hy31kf.js} +30 -7
  37. package/{index-jd01kj5r.js → index-9d6nvkz2.js} +1 -1
  38. package/{index-zq0mr3hh.js → index-a1w6934z.js} +3 -3
  39. package/{index-sbfk9daf.js → index-ab0c38ea.js} +4 -4
  40. package/index-bc88j1ry.js +1166 -0
  41. package/{index-h94faz96.js → index-bftkz6cp.js} +274 -60
  42. package/{index-kcxmv48c.js → index-bhtmj233.js} +4 -1
  43. package/{index-m41ptvat.js → index-bwf965h6.js} +3 -3
  44. package/{index-bwxpk2cj.js → index-crmeqnmf.js} +52 -26
  45. package/{index-8k16atqy.js → index-d2242ksy.js} +23 -6
  46. package/{index-jwexzh42.js → index-e4v6vhxq.js} +222 -56
  47. package/{index-pn8mhpps.js → index-esk82rvk.js} +4 -4
  48. package/{index-4r42ext5.js → index-kwaq3n9n.js} +1 -1
  49. package/{index-gm76f0qb.js → index-n3cv0tm4.js} +1 -1
  50. package/{index-ycy302an.js → index-qdgzsnhg.js} +1 -1
  51. package/{index-wcg582a8.js → index-sq2dzkzm.js} +35 -10
  52. package/{index-myj01w9r.js → index-srmay5jw.js} +15 -2
  53. package/{index-zmj143x7.js → index-txr7dj2g.js} +3 -3
  54. package/{index-erfc1x40.js → index-vqx8bdxz.js} +1 -1
  55. package/{index-d9fjz06h.js → index-zqgj2rt2.js} +4 -4
  56. package/index.js +21 -21
  57. package/{library.command-fp0nhr62.js → library.command-cqr175dy.js} +3 -3
  58. package/{localRegistry.command-8y0ecxb9.js → localRegistry.command-49z55qqz.js} +9 -9
  59. package/{module.command-kqkn48t2.js → module.command-9p8mm3b0.js} +5 -5
  60. package/{package.command-qverjh22.js → package.command-wxyz909t.js} +4 -4
  61. package/package.json +2 -2
  62. package/{page.command-94bwhd0g.js → page.command-gsrsfqqs.js} +3 -3
  63. package/{primitive.command-2ydvtah2.js → primitive.command-ns1mptje.js} +6 -6
  64. package/{quality.command-fa0gth4p.js → quality.command-e76k2q9k.js} +17 -15
  65. package/{repair.command-4qng2hpm.js → repair.command-pkrsm3cw.js} +5 -5
  66. package/{scalar.command-pb2y95sh.js → scalar.command-0cpt3fc8.js} +4 -4
  67. package/{subspace.command-vkxmwp74.js → subspace.command-fktpwp0g.js} +20 -10
  68. package/templates/appSample/lib/task/task.signal.test.ts +1 -1
  69. package/templates/localDev/docker-compose.yaml.template +3 -14
  70. package/{tunnel.command-02cvp9nf.js → tunnel.command-d5jy9gk8.js} +4 -4
  71. package/{workflow.command-132txnrh.js → workflow.command-6tkcysmx.js} +9 -9
  72. package/{workspace.command-d5wkswek.js → workspace.command-gv84eh1p.js} +24 -23
  73. package/cloud.script-qhcnqt1n.js +0 -20
  74. package/context.runner-z0rrcz7b.js +0 -22
  75. package/index-3hpxeys1.js +0 -462
@@ -2,16 +2,16 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-ycy302an.js";
5
+ } from "./index-qdgzsnhg.js";
6
6
  import {
7
7
  WorkspaceExecutor,
8
8
  AppExecutor,
9
9
  LibExecutor,
10
10
  PkgExecutor
11
- } from "./index-bwxpk2cj.js";
11
+ } from "./index-crmeqnmf.js";
12
12
  import {
13
13
  LibraryScript
14
- } from "./index-6q589y9t.js";
14
+ } from "./index-7ep8qtvp.js";
15
15
  import {
16
16
  HmrWatcher,
17
17
  WatchRootResolver
@@ -22,7 +22,7 @@ import {
22
22
  import {
23
23
  SlicePlanner,
24
24
  formatSlicePlan
25
- } from "./index-4r42ext5.js";
25
+ } from "./index-kwaq3n9n.js";
26
26
  import {
27
27
  resolveMobileTargets
28
28
  } from "./index-47pj3aee.js";
@@ -1344,16 +1344,18 @@ ${this.#backendStderrTail.join(`
1344
1344
  this.#recycleBuilderForRss(settledBytes === null ? reason : `${reason}; still ${asMib(settledBytes)}MiB after settling`);
1345
1345
  }
1346
1346
  static async readProcessRssBytes(pid) {
1347
+ if (process.platform === "win32")
1348
+ return await AkanAppHost.#readRssKbVia(["tasklist", "/FI", `PID eq ${pid}`, "/FO", "CSV", "/NH"], AkanAppHost.#tasklistRssKb);
1347
1349
  const status = await Bun.file(`/proc/${pid}/status`).text().catch(() => null);
1348
1350
  const vmRssKb = status === null ? null : /VmRSS:\s+(\d+) kB/.exec(status)?.[1];
1349
1351
  if (vmRssKb)
1350
1352
  return Number(vmRssKb) * 1024;
1351
- return await AkanAppHost.#readRssViaPs(pid);
1353
+ return await AkanAppHost.#readRssKbVia(["ps", "-o", "rss=", "-p", String(pid)], (output) => Number(output.trim()));
1352
1354
  }
1353
- static async#readRssViaPs(pid, timeoutMs = PS_RSS_TIMEOUT_MS) {
1355
+ static async#readRssKbVia(command, parseKb, timeoutMs = PS_RSS_TIMEOUT_MS) {
1354
1356
  let proc;
1355
1357
  try {
1356
- proc = Bun.spawn(["ps", "-o", "rss=", "-p", String(pid)], { stdio: ["ignore", "pipe", "ignore"] });
1358
+ proc = Bun.spawn(command, { stdio: ["ignore", "pipe", "ignore"] });
1357
1359
  } catch {
1358
1360
  return null;
1359
1361
  }
@@ -1361,7 +1363,7 @@ ${this.#backendStderrTail.join(`
1361
1363
  try {
1362
1364
  const output = await new Response(proc.stdout).text();
1363
1365
  await proc.exited;
1364
- const rssKb = Number(output.trim());
1366
+ const rssKb = parseKb(output);
1365
1367
  return Number.isFinite(rssKb) && rssKb > 0 ? rssKb * 1024 : null;
1366
1368
  } catch {
1367
1369
  return null;
@@ -1369,6 +1371,10 @@ ${this.#backendStderrTail.join(`
1369
1371
  clearTimeout(killer);
1370
1372
  }
1371
1373
  }
1374
+ static #tasklistRssKb(output) {
1375
+ const memUsage = /"([^"]*)"\s*$/m.exec(output)?.[1];
1376
+ return memUsage ? Number(memUsage.replace(/\D/g, "")) : Number.NaN;
1377
+ }
1372
1378
  #cancelRssRecycle() {
1373
1379
  this.#rssRecycleReason = null;
1374
1380
  this.#rssRecycleOver = null;
@@ -1959,9 +1965,9 @@ ${uniqueCandidates.map((candidate) => ` - ${candidate}`).join(`
1959
1965
 
1960
1966
  // pkgs/@akanjs/cli/application/application.runner.ts
1961
1967
  import { Logger as Logger4 } from "akanjs/common";
1962
- var loadBuildRunner = async () => (await import("./applicationBuildRunner-m0hhgwsx.js")).ApplicationBuildRunner;
1963
- var loadReleasePackager = async () => (await import("./applicationReleasePackager-vykfzgx3.js")).ApplicationReleasePackager;
1964
- var loadCapacitorApp = async () => (await import("./capacitorApp-2daqhb5h.js")).CapacitorApp;
1968
+ var loadBuildRunner = async () => (await import("./applicationBuildRunner-n9gzaxd0.js")).ApplicationBuildRunner;
1969
+ var loadReleasePackager = async () => (await import("./applicationReleasePackager-vpggfqgq.js")).ApplicationReleasePackager;
1970
+ var loadCapacitorApp = async () => (await import("./capacitorApp-q3z0qht0.js")).CapacitorApp;
1965
1971
  var loadPrompts = async () => await import("@inquirer/prompts");
1966
1972
 
1967
1973
  class ApplicationRunner extends runner("application") {
@@ -2004,7 +2010,7 @@ class ApplicationRunner extends runner("application") {
2004
2010
  if (!await app.exists(scriptPath))
2005
2011
  throw new Error(`Script file not found: apps/${app.name}/${scriptPath}`);
2006
2012
  await app.spawn("bun", [scriptPath], {
2007
- env: app.getCommandEnv({ AKAN_COMMAND_TYPE: "script" }),
2013
+ env: app.getCommandEnv({ AKAN_COMMAND_TYPE: "script", ...await app.getDatabaseModeEnv() }),
2008
2014
  stdio: "inherit"
2009
2015
  });
2010
2016
  }
@@ -2095,7 +2101,29 @@ try {
2095
2101
  }
2096
2102
  `;
2097
2103
  await app.spawn("bun", ["-e", code], {
2098
- env: app.getCommandEnv({ AKAN_COMMAND_TYPE: "console" }),
2104
+ env: app.getCommandEnv({ AKAN_COMMAND_TYPE: "console", ...await app.getDatabaseModeEnv() }),
2105
+ stdio: "inherit"
2106
+ });
2107
+ }
2108
+ async transferDatabase(app, direction, dir) {
2109
+ const serverPath = `${app.cwdPath}/server.ts`;
2110
+ if (!await app.exists("server.ts"))
2111
+ throw new Error(`Server file not found: apps/${app.name}/server.ts`);
2112
+ const target = path5.resolve(app.workspace.workspaceRoot, dir);
2113
+ const code = `
2114
+ const { server } = await import(${JSON.stringify(serverPath)});
2115
+ const { DatabaseAdaptorRole, DocumentTransfer } = await import("akanjs/service");
2116
+ await server.start({ listen: false, web: false });
2117
+ try {
2118
+ const transfer = new DocumentTransfer(server.get(DatabaseAdaptorRole));
2119
+ const reports = await transfer.${direction === "export" ? "exportTo" : "importFrom"}(${JSON.stringify(target)});
2120
+ for (const { table, rows } of reports) console.info(\`${direction === "export" ? "exported" : "imported"} \${table}: \${rows} rows\`);
2121
+ } finally {
2122
+ await server.stop();
2123
+ }
2124
+ `;
2125
+ await app.spawn("bun", ["-e", code], {
2126
+ env: app.getCommandEnv({ AKAN_COMMAND_TYPE: "script", ...await app.getDatabaseModeEnv() }),
2099
2127
  stdio: "inherit"
2100
2128
  });
2101
2129
  }
@@ -2255,9 +2283,15 @@ try {
2255
2283
  if (mode === "single")
2256
2284
  return [];
2257
2285
  if (mode === "multiple")
2258
- return ["redis", "libsql"];
2286
+ return ["redis"];
2259
2287
  return ["redis", "postgres"];
2260
2288
  }
2289
+ async#assertComposeHas(workspace, services) {
2290
+ const compose = Bun.YAML.parse(await Bun.file(`${workspace.workspaceRoot}/local/docker-compose.yaml`).text());
2291
+ const missing = services.filter((service) => !compose?.services?.[service]);
2292
+ if (missing.length)
2293
+ throw new Error(`local/docker-compose.yaml declares no ${missing.join(" or ")} service. Add it, or move the file aside so the next akan dbup writes the current template.`);
2294
+ }
2261
2295
  async#isLocalDatabaseUp(workspace, mode) {
2262
2296
  const requiredServices = this.#getLocalDatabaseServices(mode);
2263
2297
  if (!requiredServices.length)
@@ -2271,16 +2305,18 @@ try {
2271
2305
  async dbup(workspace, mode = "multiple") {
2272
2306
  if (mode === "single")
2273
2307
  return true;
2308
+ const services = this.#getLocalDatabaseServices(mode);
2309
+ await workspace.applyTemplate({
2310
+ basePath: "local",
2311
+ template: "localDev",
2312
+ dict: { repoName: workspace.repoName },
2313
+ overwrite: false
2314
+ });
2315
+ await this.#assertComposeHas(workspace, services);
2274
2316
  try {
2275
- await workspace.applyTemplate({
2276
- basePath: "local",
2277
- template: "localDev",
2278
- dict: { repoName: workspace.repoName },
2279
- overwrite: false
2280
- });
2281
2317
  const wasAlreadyUp = await this.#isLocalDatabaseUp(workspace, mode);
2282
2318
  if (!wasAlreadyUp)
2283
- await workspace.spawn(`docker`, ["compose", "up", "-d", ...this.#getLocalDatabaseServices(mode)], {
2319
+ await workspace.spawn(`docker`, ["compose", "up", "-d", ...services], {
2284
2320
  cwd: `${workspace.workspaceRoot}/local`
2285
2321
  });
2286
2322
  return wasAlreadyUp;
@@ -2341,9 +2377,187 @@ ${detail}`
2341
2377
  }
2342
2378
  }
2343
2379
 
2380
+ // pkgs/@akanjs/cli/application/hostProcessProbe.ts
2381
+ import { readdirSync, readFileSync, readlinkSync } from "fs";
2382
+
2383
+ class HostProcessProbe {
2384
+ static timeoutMs = 3000;
2385
+ static win32TimeoutMs = 20000;
2386
+ static #procTcpListen = "0A";
2387
+ static #win32ProcessQuery = "[Console]::OutputEncoding=[Text.Encoding]::UTF8; Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine,CreationDate | ConvertTo-Json -Compress";
2388
+ platform;
2389
+ #win32Table = null;
2390
+ constructor(platform = process.platform) {
2391
+ this.platform = platform;
2392
+ }
2393
+ async listenersOn(port) {
2394
+ if (this.platform === "win32")
2395
+ return HostProcessProbe.parseNetstat(await HostProcessProbe.run(["netstat", "-ano"]), port);
2396
+ if (this.platform === "linux")
2397
+ return HostProcessProbe.#procListenersOn(port);
2398
+ const output = await HostProcessProbe.run(["lsof", "-ti", `tcp:${port}`, "-sTCP:LISTEN"]);
2399
+ return [
2400
+ ...new Set(output.split(`
2401
+ `).map((line) => Number(line.trim())).filter((pid) => Number.isInteger(pid) && pid > 0))
2402
+ ];
2403
+ }
2404
+ async parentOf(pid) {
2405
+ if (this.platform === "win32") {
2406
+ const child = await this.#win32Process(pid);
2407
+ const parent = child ? await this.#win32Process(child.ppid) : null;
2408
+ return child && parent ? HostProcessProbe.parentPidOf(child, parent) : null;
2409
+ }
2410
+ if (this.platform === "linux") {
2411
+ const stat = HostProcessProbe.#readProc(pid, "stat");
2412
+ return stat === null ? null : HostProcessProbe.parseProcStatPpid(stat);
2413
+ }
2414
+ const parsed = Number((await HostProcessProbe.run(["ps", "-p", String(pid), "-o", "ppid="])).trim());
2415
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
2416
+ }
2417
+ async commandOf(pid) {
2418
+ if (this.platform === "win32")
2419
+ return (await this.#win32Process(pid))?.command ?? null;
2420
+ if (this.platform === "linux") {
2421
+ const cmdline = HostProcessProbe.#readProc(pid, "cmdline");
2422
+ return cmdline?.split("\x00").filter(Boolean).join(" ") || null;
2423
+ }
2424
+ return (await HostProcessProbe.run(["ps", "-ww", "-p", String(pid), "-o", "command="])).trim() || null;
2425
+ }
2426
+ static parentPidOf(child, parent) {
2427
+ if (child.ppid !== parent.pid)
2428
+ return null;
2429
+ if (parent.startedAt !== null && child.startedAt !== null && parent.startedAt > child.startedAt)
2430
+ return null;
2431
+ return parent.pid;
2432
+ }
2433
+ static parseNetstat(output, port) {
2434
+ const pids = new Set;
2435
+ for (const line of output.split(/\r?\n/)) {
2436
+ const fields = line.trim().split(/\s+/);
2437
+ if (fields[0] !== "TCP" || fields.length < 5)
2438
+ continue;
2439
+ const [, local, remote] = fields;
2440
+ if (!local?.endsWith(`:${port}`) || !remote?.endsWith(":0"))
2441
+ continue;
2442
+ const pid = Number(fields.at(-1));
2443
+ if (Number.isInteger(pid) && pid > 0)
2444
+ pids.add(pid);
2445
+ }
2446
+ return [...pids];
2447
+ }
2448
+ static parseProcNetTcp(text, port) {
2449
+ const inodes = [];
2450
+ for (const line of text.split(`
2451
+ `).slice(1)) {
2452
+ const fields = line.trim().split(/\s+/);
2453
+ const [, local, , state, , , , , , inode] = fields;
2454
+ if (!local || !inode || state !== HostProcessProbe.#procTcpListen || inode === "0")
2455
+ continue;
2456
+ if (Number.parseInt(local.slice(local.lastIndexOf(":") + 1), 16) === port)
2457
+ inodes.push(inode);
2458
+ }
2459
+ return inodes;
2460
+ }
2461
+ static parseProcStatPpid(stat) {
2462
+ const ppid = Number(stat.slice(stat.lastIndexOf(")") + 2).split(" ")[1]);
2463
+ return Number.isInteger(ppid) && ppid > 0 ? ppid : null;
2464
+ }
2465
+ static parseWin32Processes(json) {
2466
+ const table = new Map;
2467
+ let parsed;
2468
+ try {
2469
+ parsed = JSON.parse(json.trim() || "[]");
2470
+ } catch {
2471
+ return table;
2472
+ }
2473
+ const rows = Array.isArray(parsed) ? parsed : [parsed];
2474
+ for (const row of rows) {
2475
+ if (typeof row?.ProcessId !== "number")
2476
+ continue;
2477
+ table.set(row.ProcessId, {
2478
+ pid: row.ProcessId,
2479
+ ppid: row.ParentProcessId ?? 0,
2480
+ command: row.CommandLine?.trim() || null,
2481
+ startedAt: HostProcessProbe.#parseCimDate(row.CreationDate)
2482
+ });
2483
+ }
2484
+ return table;
2485
+ }
2486
+ static async run(command, timeoutMs = HostProcessProbe.timeoutMs) {
2487
+ let proc;
2488
+ try {
2489
+ proc = Bun.spawn(command, { stdio: ["ignore", "pipe", "ignore"], windowsHide: true });
2490
+ } catch {
2491
+ return "";
2492
+ }
2493
+ const timer = setTimeout(() => proc.kill("SIGKILL"), timeoutMs);
2494
+ try {
2495
+ return await new Response(proc.stdout).text();
2496
+ } catch {
2497
+ return "";
2498
+ } finally {
2499
+ clearTimeout(timer);
2500
+ }
2501
+ }
2502
+ async#win32Process(pid) {
2503
+ this.#win32Table ??= await HostProcessProbe.#queryWin32Processes();
2504
+ if (!this.#win32Table.has(pid))
2505
+ this.#win32Table = await HostProcessProbe.#queryWin32Processes();
2506
+ return this.#win32Table.get(pid) ?? null;
2507
+ }
2508
+ static async#queryWin32Processes() {
2509
+ const output = await HostProcessProbe.run(["powershell", "-NoProfile", "-NonInteractive", "-Command", HostProcessProbe.#win32ProcessQuery], HostProcessProbe.win32TimeoutMs);
2510
+ return HostProcessProbe.parseWin32Processes(output);
2511
+ }
2512
+ static #parseCimDate(value) {
2513
+ if (!value)
2514
+ return null;
2515
+ const legacy = /\/Date\((\d+)/.exec(value)?.[1];
2516
+ const ms = legacy ? Number(legacy) : Date.parse(value);
2517
+ return Number.isFinite(ms) ? ms : null;
2518
+ }
2519
+ static #procListenersOn(port) {
2520
+ const inodes = new Set(["tcp", "tcp6"].flatMap((table) => HostProcessProbe.parseProcNetTcp(HostProcessProbe.#readProc("net", table) ?? "", port)));
2521
+ if (!inodes.size)
2522
+ return [];
2523
+ const pids = [];
2524
+ for (const entry of HostProcessProbe.#listDir("/proc")) {
2525
+ if (!/^\d+$/.test(entry))
2526
+ continue;
2527
+ const holds = HostProcessProbe.#listDir(`/proc/${entry}/fd`).some((fd) => {
2528
+ const inode = /^socket:\[(\d+)\]$/.exec(HostProcessProbe.#readLink(`/proc/${entry}/fd/${fd}`))?.[1];
2529
+ return !!inode && inodes.has(inode);
2530
+ });
2531
+ if (holds)
2532
+ pids.push(Number(entry));
2533
+ }
2534
+ return pids;
2535
+ }
2536
+ static #readProc(pid, file) {
2537
+ try {
2538
+ return readFileSync(`/proc/${pid}/${file}`, "utf8");
2539
+ } catch {
2540
+ return null;
2541
+ }
2542
+ }
2543
+ static #listDir(dir) {
2544
+ try {
2545
+ return readdirSync(dir);
2546
+ } catch {
2547
+ return [];
2548
+ }
2549
+ }
2550
+ static #readLink(link) {
2551
+ try {
2552
+ return readlinkSync(link);
2553
+ } catch {
2554
+ return "";
2555
+ }
2556
+ }
2557
+ }
2558
+
2344
2559
  // pkgs/@akanjs/cli/application/devPortReclaimer.ts
2345
2560
  class DevPortReclaimer {
2346
- static lsofTimeoutMs = 3000;
2347
2561
  static releaseTimeoutMs = 8000;
2348
2562
  static maxAncestorDepth = 8;
2349
2563
  static #releasePollMs = 100;
@@ -2352,7 +2566,12 @@ class DevPortReclaimer {
2352
2566
  return [...new Set(ports.flatMap((port) => [port, port + DevPortReclaimer.wsPortOffset]))].sort((left, right) => left - right);
2353
2567
  }
2354
2568
  static isAkanCommand(command) {
2355
- return /(^|\/)akan(\s|$)/.test(command) || command.includes("@akanjs/cli") || command.includes("akanjs/server") || /\bapps\/[^/\s]+\/main\.ts\b/.test(command) || command.includes("incrementalBuilder.proc") || command.includes("rscWorker");
2569
+ const normalized = command.replaceAll("\\", "/");
2570
+ return /(^|\/)akan(\.exe)?"?(\s|$)/.test(normalized) || normalized.includes("@akanjs/cli") || normalized.includes("akanjs/server") || /\bapps\/[^/\s]+\/main\.ts\b/.test(normalized) || normalized.includes("incrementalBuilder.proc") || normalized.includes("rscWorker");
2571
+ }
2572
+ #probe;
2573
+ constructor(probe = new HostProcessProbe) {
2574
+ this.#probe = probe;
2356
2575
  }
2357
2576
  async reclaim(ports) {
2358
2577
  const killed = [];
@@ -2377,10 +2596,10 @@ class DevPortReclaimer {
2377
2596
  }
2378
2597
  async holdersOf(port) {
2379
2598
  const holders = [];
2380
- for (const listenerPid of await this.#pidsOn(port)) {
2599
+ for (const listenerPid of await this.#probe.listenersOn(port)) {
2381
2600
  if (listenerPid === process.pid || listenerPid === process.ppid)
2382
2601
  continue;
2383
- const command = await this.#commandOf(listenerPid);
2602
+ const command = await this.#probe.commandOf(listenerPid);
2384
2603
  if (!command)
2385
2604
  continue;
2386
2605
  if (!DevPortReclaimer.isAkanCommand(command)) {
@@ -2395,44 +2614,37 @@ class DevPortReclaimer {
2395
2614
  async#akanRootOf(pid, command) {
2396
2615
  let root = { pid, command };
2397
2616
  for (let depth = 0;depth < DevPortReclaimer.maxAncestorDepth; depth += 1) {
2398
- const parentPid = await this.#ppidOf(root.pid);
2617
+ const parentPid = await this.#probe.parentOf(root.pid);
2399
2618
  if (parentPid === null || parentPid <= 1 || parentPid === process.pid || parentPid === process.ppid)
2400
2619
  break;
2401
- const parentCommand = await this.#commandOf(parentPid);
2620
+ const parentCommand = await this.#probe.commandOf(parentPid);
2402
2621
  if (!parentCommand || !DevPortReclaimer.isAkanCommand(parentCommand))
2403
2622
  break;
2404
2623
  root = { pid: parentPid, command: parentCommand };
2405
2624
  }
2406
2625
  return root;
2407
2626
  }
2408
- async#ppidOf(pid) {
2409
- const output = await this.#run(["ps", "-p", String(pid), "-o", "ppid="]);
2410
- const parsed = Number(output.trim());
2411
- return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
2412
- }
2413
- async#pidsOn(port) {
2414
- const output = await this.#run(["lsof", "-ti", `tcp:${port}`, "-sTCP:LISTEN"]);
2415
- return [
2416
- ...new Set(output.split(`
2417
- `).map((line) => Number(line.trim())).filter((pid) => Number.isInteger(pid) && pid > 0))
2418
- ];
2419
- }
2420
- async#commandOf(pid) {
2421
- const output = await this.#run(["ps", "-p", String(pid), "-o", "command="]);
2422
- return output.trim() || null;
2423
- }
2424
2627
  async#terminate(pid) {
2628
+ if (this.#probe.platform === "win32") {
2629
+ await HostProcessProbe.run(["taskkill", "/PID", String(pid), "/T", "/F"]);
2630
+ return await this.#released(pid);
2631
+ }
2425
2632
  if (!this.#signal(pid, "SIGTERM"))
2426
2633
  return !this.#alive(pid);
2634
+ if (await this.#released(pid))
2635
+ return true;
2636
+ this.#signal(pid, "SIGKILL");
2637
+ await Bun.sleep(DevPortReclaimer.#releasePollMs);
2638
+ return !this.#alive(pid);
2639
+ }
2640
+ async#released(pid) {
2427
2641
  const deadline = Date.now() + DevPortReclaimer.releaseTimeoutMs;
2428
2642
  while (Date.now() < deadline) {
2429
2643
  if (!this.#alive(pid))
2430
2644
  return true;
2431
2645
  await Bun.sleep(DevPortReclaimer.#releasePollMs);
2432
2646
  }
2433
- this.#signal(pid, "SIGKILL");
2434
- await Bun.sleep(DevPortReclaimer.#releasePollMs);
2435
- return !this.#alive(pid);
2647
+ return false;
2436
2648
  }
2437
2649
  #signal(pid, signal) {
2438
2650
  try {
@@ -2450,17 +2662,6 @@ class DevPortReclaimer {
2450
2662
  return error.code === "EPERM";
2451
2663
  }
2452
2664
  }
2453
- async#run(command) {
2454
- const proc = Bun.spawn(command, { stdio: ["ignore", "pipe", "ignore"] });
2455
- const timer = setTimeout(() => proc.kill("SIGKILL"), DevPortReclaimer.lsofTimeoutMs);
2456
- try {
2457
- return await new Response(proc.stdout).text();
2458
- } catch {
2459
- return "";
2460
- } finally {
2461
- clearTimeout(timer);
2462
- }
2463
- }
2464
2665
  }
2465
2666
 
2466
2667
  // pkgs/@akanjs/cli/application/devStreamView.ts
@@ -3175,7 +3376,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3175
3376
  async startOne(app, { open = false, dbup = true, stdio = "inherit", write = true, onDevEvent } = {}) {
3176
3377
  await app.scanSync({ write });
3177
3378
  const akanConfig = await app.getConfig();
3178
- const databaseMode = process.env.AKAN_DATABASE_MODE ?? akanConfig.defaultDatabaseMode ?? "single";
3379
+ const databaseMode = akanConfig.resolveDatabaseMode();
3179
3380
  await this.syncDatabaseModeDependencies(app, akanConfig, databaseMode);
3180
3381
  if (app.getEnv() === "local" && dbup && databaseMode !== "single") {
3181
3382
  const wasDbAlreadyUp = await this.dbup(app.workspace, databaseMode);
@@ -3233,7 +3434,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3233
3434
  if (app.getEnv() !== "local")
3234
3435
  continue;
3235
3436
  const akanConfig = await app.getConfig();
3236
- const mode = process.env.AKAN_DATABASE_MODE ?? akanConfig.defaultDatabaseMode ?? "single";
3437
+ const mode = akanConfig.resolveDatabaseMode();
3237
3438
  await this.syncDatabaseModeDependencies(app, akanConfig, mode);
3238
3439
  if (mode !== "single")
3239
3440
  modes.add(mode);
@@ -3321,6 +3522,19 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3321
3522
  async codepush(app, os) {
3322
3523
  await this.applicationRunner.codepush(app, os);
3323
3524
  }
3525
+ async transferDatabase(app, direction, dir) {
3526
+ await this.applicationRunner.transferDatabase(app, direction, dir);
3527
+ }
3528
+ async dbupDeclared(workspace, mode) {
3529
+ const declared = mode ? [mode] : await Promise.all((await workspace.getApps()).map(async (appName) => (await AppExecutor.from(workspace, appName).getConfig()).database.modes)).then((modes) => [...new Set(modes.flat())]);
3530
+ const needing = declared.filter((each) => each !== "single");
3531
+ if (!needing.length) {
3532
+ workspace.log("No app here declares a database mode that runs on local services; single needs none.");
3533
+ return;
3534
+ }
3535
+ for (const each of needing)
3536
+ await this.dbup(workspace, each);
3537
+ }
3324
3538
  async dbup(workspace, mode = "multiple") {
3325
3539
  const spinner = workspace.spinning(`Starting local database (${mode})...`);
3326
3540
  const wasAlreadyUp = await this.applicationRunner.dbup(workspace, mode);
@@ -3344,7 +3558,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3344
3558
  await Promise.all(shares.map(async (share) => await share.close()));
3345
3559
  }, "Abandoning the tunnel release; the shares expire on their own.");
3346
3560
  await Promise.all(apps.map(async (app) => {
3347
- const { TunnelShare } = await import("./TunnelShare-r5tc2qk5.js");
3561
+ const { TunnelShare } = await import("./TunnelShare-2j6s511d.js");
3348
3562
  const share = await TunnelShare.open(app, { workspace: app.workspace });
3349
3563
  shares.push(share);
3350
3564
  urls.set(app.name, share.url);
@@ -10,7 +10,10 @@ import ignore from "ignore";
10
10
  import ts from "typescript";
11
11
  var testFileRegex = /\.(?:test|spec)\.[cm]?[tj]sx?$/;
12
12
  var skipDirs = ["node_modules", "dist", "build", ".git", ".next", "public", "ios", "android", "__fixtures__"];
13
- var isSkippedPath = (filePath) => skipDirs.some((dir) => filePath.includes(`/${dir}/`) || filePath.startsWith(`${dir}/`));
13
+ var isSkippedPath = (filePath) => {
14
+ const posixPath = filePath.split(path.sep).join("/");
15
+ return skipDirs.some((dir) => posixPath.includes(`/${dir}/`) || posixPath.startsWith(`${dir}/`));
16
+ };
14
17
  var builtinModuleSet = new Set([...builtinModules, ...builtinModules.map((mod) => `node:${mod}`)]);
15
18
  var stripShebang = (source) => source.replace(/^#!.*(?:\r?\n|$)/, "");
16
19
 
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-ycy302an.js";
5
+ } from "./index-qdgzsnhg.js";
6
6
  import {
7
7
  AGENT_BLOCK_START,
8
8
  AGENT_BLOCK_END,
@@ -13,14 +13,14 @@ import {
13
13
  CLAUDE_COMMENT_RULE,
14
14
  AppExecutor,
15
15
  LibExecutor
16
- } from "./index-bwxpk2cj.js";
16
+ } from "./index-crmeqnmf.js";
17
17
  import {
18
18
  collectRecipeSources2,
19
19
  scanRecipes2
20
20
  } from "./index-by5gpp8x.js";
21
21
  import {
22
22
  AkanContextAnalyzer
23
- } from "./index-rpgxs245.js";
23
+ } from "./index-18zybgkc.js";
24
24
  import {
25
25
  Prompter2
26
26
  } from "./index-s5rhm04y.js";