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

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 (95) hide show
  1. package/.build-stamp +1 -1
  2. package/{CodeAgent-6cm97kay.js → CodeAgent-awv258wb.js} +2 -2
  3. package/{CodeTui-za4jsm41.js → CodeTui-1nqh35ez.js} +20 -22
  4. package/TunnelShare-scf4e4pd.js +9 -0
  5. package/{agent.command-e0wpbbyg.js → agent.command-1s9ag7sb.js} +8 -9
  6. package/akanCode.js +4 -4
  7. package/{application.command-8wyxqc8q.js → application.command-49hwy6va.js} +25 -56
  8. package/{applicationBuildRunner-n9gzaxd0.js → applicationBuildRunner-ybyp97pv.js} +33 -59
  9. package/{applicationReleasePackager-vpggfqgq.js → applicationReleasePackager-esnrphw8.js} +40 -60
  10. package/buildBatch.proc.js +19 -24
  11. package/{capacitorApp-q3z0qht0.js → capacitorApp-1synz4en.js} +3 -4
  12. package/{cloud.command-4zwa5dsx.js → cloud.command-d7rqtzt9.js} +16 -26
  13. package/cloud.script-bkbpcr96.js +19 -0
  14. package/{code.command-468c9d7s.js → code.command-nn48xzej.js} +22 -37
  15. package/context.command-s3mcmvpa.js +48 -0
  16. package/context.runner-k99nb5pk.js +21 -0
  17. package/{dependencyScanner-0z2h2tks.js → dependencyScanner-ye2e6pdz.js} +2 -2
  18. package/{devTui-ffjsarqa.js → devTui-q7k7bakd.js} +5 -9
  19. package/fileSys-5ngz93ga.js +9 -0
  20. package/{guideline.command-vhw13pqr.js → guideline.command-sct4qnt5.js} +4 -5
  21. package/guidelines/conventions/conventions.instruction.md +5 -1
  22. package/guidelines/mcpRule/mcpRule.instruction.md +7 -5
  23. package/incrementalBuilder.proc.js +30 -48
  24. package/{index-s5rhm04y.js → index-0bq14vr1.js} +1 -1
  25. package/{index-10dkrrww.js → index-13ffe9wp.js} +4 -4
  26. package/{index-srmay5jw.js → index-22d57v4c.js} +84 -67
  27. package/{index-53176s7j.js → index-31yr441d.js} +10 -17
  28. package/index-3hx1z96c.js +87 -0
  29. package/{index-4m929vvn.js → index-3sq321ak.js} +10 -18
  30. package/{index-bhtmj233.js → index-3t7g9e4r.js} +41 -78
  31. package/{index-q0y2jq9j.js → index-5b6tavv3.js} +6 -3
  32. package/{index-47pj3aee.js → index-5e0n4hqx.js} +11 -12
  33. package/{index-7ep8qtvp.js → index-5pc1qrbv.js} +5 -8
  34. package/{index-esk82rvk.js → index-8mna0947.js} +34 -71
  35. package/{index-sq2dzkzm.js → index-8sf7wmdr.js} +6 -6
  36. package/{index-crmeqnmf.js → index-9d9bgcx4.js} +283 -722
  37. package/{index-bwf965h6.js → index-ahemdr5n.js} +6 -6
  38. package/{index-ab0c38ea.js → index-as7xmyz8.js} +20 -20
  39. package/{index-bc88j1ry.js → index-axzjaqve.js} +94 -142
  40. package/{index-3d9y066c.js → index-bjwxs904.js} +9 -8
  41. package/{index-667w0yah.js → index-c6eggbee.js} +2 -5
  42. package/{index-a1w6934z.js → index-ddxvdd1p.js} +169 -305
  43. package/{index-92zztqy1.js → index-dy0jx9ay.js} +2 -17
  44. package/{index-22xtgmhn.js → index-dzf3r49a.js} +1 -1
  45. package/{index-89hy31kf.js → index-fgq75haa.js} +172 -287
  46. package/{index-by5gpp8x.js → index-hj6w4ka1.js} +2 -1
  47. package/{index-hwkygn9s.js → index-khpfpcsd.js} +302 -33
  48. package/{index-vqx8bdxz.js → index-mxav6j3c.js} +78 -231
  49. package/{index-2446k7b4.js → index-myhc3c1j.js} +512 -588
  50. package/{index-3jrp517k.js → index-nv5976x3.js} +45 -128
  51. package/{index-zqgj2rt2.js → index-przybvy5.js} +69 -147
  52. package/{index-n3cv0tm4.js → index-smme4r47.js} +1 -1
  53. package/{index-qdgzsnhg.js → index-w2zdcw3k.js} +110 -231
  54. package/{index-14zrtgfa.js → index-wa5jbxj1.js} +6 -39
  55. package/{index-bftkz6cp.js → index-ww4z397j.js} +198 -555
  56. package/{index-kwaq3n9n.js → index-xqjwd384.js} +4 -7
  57. package/{index-txr7dj2g.js → index-xqpzbab5.js} +106 -240
  58. package/{index-e4v6vhxq.js → index-xsjh6nzh.js} +178 -165
  59. package/{index-18zybgkc.js → index-ygn77a5w.js} +47 -99
  60. package/{index-9d6nvkz2.js → index-ztp3e73t.js} +79 -35
  61. package/index.js +23 -24
  62. package/{library.command-cqr175dy.js → library.command-1gx04jgn.js} +4 -5
  63. package/{localRegistry.command-49z55qqz.js → localRegistry.command-zndxj1q6.js} +21 -42
  64. package/{module.command-9p8mm3b0.js → module.command-3waddk95.js} +6 -7
  65. package/{package.command-wxyz909t.js → package.command-zrc7br1y.js} +5 -6
  66. package/package.json +2 -2
  67. package/{page.command-gsrsfqqs.js → page.command-vpjgardh.js} +4 -5
  68. package/{primitive.command-ns1mptje.js → primitive.command-sz84tk4t.js} +9 -20
  69. package/{prompter-1f8d9pcc.js → prompter-ptaa3nk0.js} +2 -2
  70. package/{quality.command-e76k2q9k.js → quality.command-g869hafs.js} +129 -363
  71. package/{recipeScanner-fpagtgc1.js → recipeScanner-4b69ybe0.js} +1 -1
  72. package/{repair.command-pkrsm3cw.js → repair.command-chsnjvvv.js} +11 -35
  73. package/{scalar.command-0cpt3fc8.js → scalar.command-2v21newx.js} +5 -6
  74. package/skills/akan-code/SKILL.md +12 -4
  75. package/{subspace.command-fktpwp0g.js → subspace.command-ckcbwfp1.js} +39 -58
  76. package/templates/appSample/srvkit/{AuthGuard.ts → guards.ts} +3 -3
  77. package/templates/appSample/srvkit/{SessionInternalArg.ts → internalArgs.ts} +3 -3
  78. package/templates/client.ts +7 -30
  79. package/templates/lib/__lib/lib.dictionary.ts +0 -2
  80. package/templates/lib/__lib/lib.document.ts +0 -2
  81. package/templates/lib/sig.ts +8 -30
  82. package/templates/server.ts +0 -2
  83. package/{tunnel.command-d5jy9gk8.js → tunnel.command-kd2yr4fx.js} +5 -6
  84. package/{typeChecker-3xgrzc2v.js → typeChecker-px49mezc.js} +1 -1
  85. package/typecheck.proc.js +1 -1
  86. package/workflow.command-44252cqv.js +79 -0
  87. package/{workspace.command-gv84eh1p.js → workspace.command-fqcztt5p.js} +72 -107
  88. package/TunnelShare-2j6s511d.js +0 -9
  89. package/cloud.script-fwx3vb34.js +0 -20
  90. package/context.command-dsnw0jby.js +0 -80
  91. package/context.runner-rs4rj15d.js +0 -22
  92. package/devTuiView-1q1mdgrv.js +0 -9
  93. package/getDirname-dr3jz1xg.js +0 -7
  94. package/index-6wwzs1bc.js +0 -7
  95. package/workflow.command-6tkcysmx.js +0 -105
@@ -1,89 +1,74 @@
1
1
  // @bun
2
+ import {
3
+ ApplicationBuildReporter,
4
+ BUILDER_MIN_RSS_RECYCLE_INTERVAL_MS,
5
+ SOURCE_EXTS,
6
+ shouldRestartBackendByDevPlan,
7
+ shouldRestartBuilderByDevPlan,
8
+ shouldAbandonBackendRecovery,
9
+ normalizeBackendReportedGeneration,
10
+ shouldRestartDevHostByDevPlan,
11
+ devHostStateOf,
12
+ isLegacyBackendFallbackFile,
13
+ shouldMarkBuildPhaseRecovered,
14
+ createBackendBuildStatus,
15
+ backendRestartReasonFromMessage,
16
+ mergeBackendRestartReasons,
17
+ shouldReplaceLastGoodMessage,
18
+ shouldQueueBuildStatusReplay,
19
+ hasBuildFailureForGeneration,
20
+ decideBuilderRssRecycle,
21
+ decideBuilderRssSettle,
22
+ decideIdleSuspend,
23
+ resolveIdleSuspendMs,
24
+ hasAnyBuildFailure,
25
+ shouldRefreshConfigOnIdleWake,
26
+ shouldHoldForReturningBuilder,
27
+ shouldWarnBuilderRssCeilingTight,
28
+ isRssCeilingUnreachable,
29
+ shouldRelayRecycledFrontendState,
30
+ mergeInvalidateMessages,
31
+ buildStatusReplaySequence,
32
+ filesChangedSince,
33
+ HmrWatcher,
34
+ WatchRootResolver
35
+ } from "./index-khpfpcsd.js";
2
36
  import {
3
37
  runner,
4
38
  script
5
- } from "./index-qdgzsnhg.js";
39
+ } from "./index-w2zdcw3k.js";
6
40
  import {
7
41
  WorkspaceExecutor,
8
42
  AppExecutor,
9
43
  LibExecutor,
10
44
  PkgExecutor
11
- } from "./index-crmeqnmf.js";
45
+ } from "./index-9d9bgcx4.js";
12
46
  import {
13
47
  LibraryScript
14
- } from "./index-7ep8qtvp.js";
15
- import {
16
- HmrWatcher,
17
- WatchRootResolver
18
- } from "./index-hwkygn9s.js";
48
+ } from "./index-5pc1qrbv.js";
19
49
  import {
20
50
  stripAnsi
21
51
  } from "./index-7md2g9vw.js";
22
52
  import {
23
53
  SlicePlanner,
24
54
  formatSlicePlan
25
- } from "./index-kwaq3n9n.js";
55
+ } from "./index-xqjwd384.js";
26
56
  import {
27
57
  resolveMobileTargets
28
- } from "./index-47pj3aee.js";
58
+ } from "./index-5e0n4hqx.js";
29
59
  import {
30
60
  openBrowser
31
61
  } from "./index-9dp031by.js";
32
62
 
33
- // pkgs/@akanjs/devkit/applicationBuildReporter.ts
34
- import { Logger } from "akanjs/common";
35
-
36
- class ApplicationBuildReporter {
37
- static create() {
38
- return {
39
- phaseDone: (phase) => Logger.rawLog(ApplicationBuildReporter.formatPhaseLine(phase))
40
- };
41
- }
42
- static printSummary(result) {
43
- Logger.rawLog("");
44
- Logger.rawLog(`Route artifacts: ${result.artifactDir}`);
45
- Logger.rawLog(`Server output: ${result.outputDir}`);
46
- Logger.rawLog(`Done in ${ApplicationBuildReporter.formatDuration(result.durationMs)}`);
47
- }
48
- static formatError(error) {
49
- if (error instanceof AggregateError) {
50
- const nestedMessages = error.errors.map((nestedError, index) => ApplicationBuildReporter.formatError(nestedError).trim() || `Unknown error ${index + 1}`).map((message) => message.replace(/^/gm, " ")).join(`
51
- `);
52
- return nestedMessages ? `${error.message}
53
- ${nestedMessages}` : error.message;
54
- }
55
- if (error instanceof Error) {
56
- const causeMessage = error.cause ? `
57
- Caused by: ${ApplicationBuildReporter.formatError(error.cause)}` : "";
58
- return `${error.message}${causeMessage}`;
59
- }
60
- if (typeof error === "object" && error !== null && "message" in error)
61
- return String(error.message);
62
- return String(error);
63
- }
64
- static formatDuration(ms) {
65
- if (ms < 1000)
66
- return `${ms}ms`;
67
- if (ms < 60000)
68
- return `${Math.round(ms / 100) / 10}s`;
69
- const seconds = Math.floor(ms / 1000);
70
- return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
71
- }
72
- static formatPhaseLine(phase) {
73
- const summary = phase.summary ? `: ${phase.summary}` : "";
74
- return `\u2713 ${phase.label}${summary} (${ApplicationBuildReporter.formatDuration(phase.durationMs)})`;
75
- }
76
- }
77
-
78
63
  // pkgs/@akanjs/cli/application/application.script.ts
79
64
  import { confirm } from "@inquirer/prompts";
80
- import { Logger as Logger7 } from "akanjs/common";
65
+ import { Logger as Logger6 } from "akanjs/common";
81
66
 
82
67
  // pkgs/@akanjs/cli/application/application.runner.ts
83
- import path5 from "path";
68
+ import path4 from "path";
84
69
 
85
70
  // pkgs/@akanjs/devkit/akanApp/akanApp.host.ts
86
- import { Logger as Logger3 } from "akanjs/common";
71
+ import { Logger as Logger2 } from "akanjs/common";
87
72
 
88
73
  // pkgs/@akanjs/devkit/sshTunnel.ts
89
74
  import { Client } from "ssh2";
@@ -172,7 +157,7 @@ var createSshTunnel = async (options) => {
172
157
  for (const socket of sockets)
173
158
  closeSocket(socket, error);
174
159
  closeQuietly(() => client.end());
175
- closeBunServer(server);
160
+ server.stop();
176
161
  };
177
162
  client.once("error", (error) => closeTunnel(error));
178
163
  client.once("close", () => closeTunnel());
@@ -192,22 +177,10 @@ var closeBunSocket = (socket, error) => {
192
177
  socket.data.stream?.end();
193
178
  closeQuietly(() => socket.end());
194
179
  };
195
- var closeBunServer = (server) => {
196
- server.stop();
197
- };
198
180
 
199
181
  // pkgs/@akanjs/devkit/createTunnel.ts
200
- var getSshTunnelOptions = (app, environment) => {
201
- const { serveDomain, repoName } = WorkspaceExecutor.getBaseDevEnv();
202
- return {
203
- host: `${app.name}-${environment}.${serveDomain}`,
204
- port: process.env.SSH_TUNNEL_PORT ? parseInt(process.env.SSH_TUNNEL_PORT) : 32767,
205
- username: process.env.SSH_TUNNEL_USERNAME ?? "root",
206
- password: process.env.SSH_TUNNEL_PASSWORD ?? repoName
207
- };
208
- };
209
182
  var createTunnel = async (service, { app, environment, port = service === "postgres" ? 5432 : 6379 }) => {
210
- const sshOptions = getSshTunnelOptions(app, environment);
183
+ const { serveDomain, repoName } = WorkspaceExecutor.getBaseDevEnv();
211
184
  await createSshTunnel({
212
185
  localHost: "0.0.0.0",
213
186
  localPort: port,
@@ -215,13 +188,18 @@ var createTunnel = async (service, { app, environment, port = service === "postg
215
188
  srcPort: port,
216
189
  dstHost: `${service}-0.${service}-svc.${app.name}-${environment}.svc.cluster.local`,
217
190
  dstPort: service === "postgres" ? 5432 : 6379,
218
- sshOptions
191
+ sshOptions: {
192
+ host: `${app.name}-${environment}.${serveDomain}`,
193
+ port: process.env.SSH_TUNNEL_PORT ? parseInt(process.env.SSH_TUNNEL_PORT) : 32767,
194
+ username: process.env.SSH_TUNNEL_USERNAME ?? "root",
195
+ password: process.env.SSH_TUNNEL_PASSWORD ?? repoName
196
+ }
219
197
  });
220
198
  return `localhost:${port}`;
221
199
  };
222
200
  // pkgs/@akanjs/devkit/incrementalBuilder/incrementalBuilder.host.ts
223
201
  import path from "path";
224
- import { Logger as Logger2 } from "akanjs/common";
202
+ import { Logger } from "akanjs/common";
225
203
  import { MemoryLimit } from "akanjs/server/memoryLimit";
226
204
  var builderMsgTypeSet = new Set([
227
205
  "build-route-res",
@@ -239,7 +217,7 @@ class IncrementalBuilderHost {
239
217
  static #restartMaxDelayMs = 30000;
240
218
  static #recycleDrainTimeoutMs = 30000;
241
219
  static #devMaxRssBytes = 1200 * 1024 * 1024;
242
- logger = new Logger2("IncrementalBuilderHost");
220
+ logger = new Logger("IncrementalBuilderHost");
243
221
  entry;
244
222
  env;
245
223
  app;
@@ -429,12 +407,8 @@ class IncrementalBuilderHost {
429
407
  const lost = [...this.#inFlight];
430
408
  this.#inFlight.clear();
431
409
  this.logger.warn(`failing ${lost.length} unanswered builder request(s): ${reason}`);
432
- for (const [id, type] of lost) {
433
- if (type === "build-route")
434
- this.#onMessage({ type: "build-route-res", id, ok: false, error: reason });
435
- else
436
- this.#onMessage({ type: "build-csr-res", id, ok: false, error: reason });
437
- }
410
+ for (const [id, type] of lost)
411
+ this.#onMessage({ type: `${type}-res`, id, ok: false, error: reason });
438
412
  }
439
413
  stop() {
440
414
  this.#manualStop = true;
@@ -503,211 +477,7 @@ class BuilderRequestRouter {
503
477
 
504
478
  // pkgs/@akanjs/devkit/akanApp/BackendImportGraph.ts
505
479
  import { stat } from "fs/promises";
506
- import path3 from "path";
507
-
508
- // pkgs/@akanjs/devkit/akanApp/devHostPolicy.ts
509
480
  import path2 from "path";
510
- var BACKEND_RECOVERY_MAX_ATTEMPTS = 5;
511
- var HELD_BUILDER_REQUEST_LIMIT = 64;
512
- var BUILDER_MIN_RSS_RECYCLE_INTERVAL_MS = 30000;
513
- var BUILDER_TIGHT_RSS_REPORT_LIMIT = 2;
514
- var BUILDER_RSS_HARD_MULTIPLE = 1.5;
515
- var DEV_IDLE_SUSPEND_MS = 300000;
516
- var DEV_IDLE_MIN_UPTIME_MS = 30000;
517
- var SOURCE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
518
- var SERVER_SUFFIXES = [".service.ts", ".document.ts"];
519
- var SHARED_SUFFIXES = [".constant.ts", ".dictionary.ts", ".signal.ts"];
520
- var RUNTIME_METADATA_BASENAMES = new Set(["dict.ts", "sig.ts", "useClient.ts", "useServer.ts"]);
521
- var shouldRestartBackendByDevPlan = (message) => {
522
- if (!message.devPlan)
523
- return null;
524
- if (message.devPlan.actions.includes("report-error"))
525
- return false;
526
- if (message.devPlan.actions.includes("restart-builder"))
527
- return false;
528
- return message.devPlan.actions.includes("restart-backend");
529
- };
530
- var shouldRestartBuilderByDevPlan = (message) => message.devPlan?.actions.includes("restart-builder") ?? false;
531
- var shouldAbandonBackendRecovery = (attempts, maxAttempts = BACKEND_RECOVERY_MAX_ATTEMPTS) => attempts >= maxAttempts;
532
- var normalizeBackendReportedGeneration = (generation) => generation >= 0 ? generation : undefined;
533
- var shouldRestartDevHostByDevPlan = (message) => message.devPlan?.actions.includes("restart-dev-host") ?? message.kinds.includes("config");
534
- var devHostStateByBackendState = {
535
- starting: "starting",
536
- ready: "ready",
537
- "restart-pending": "restarting",
538
- recovering: "recovering",
539
- stopping: "stopped",
540
- stopped: "stopped"
541
- };
542
- var devHostStateOf = (state, gaveUp) => state === "stopped" && gaveUp ? "failed" : devHostStateByBackendState[state];
543
- var RESTART_ROLE_ORDER = ["server", "shared", "barrel", "config"];
544
- var generationValue = (generation) => generation ?? -1;
545
- var isLegacyBackendFallbackFile = (file, workspaceRoot) => {
546
- const abs = path2.resolve(file);
547
- const ext = path2.extname(abs).toLowerCase();
548
- if (!SOURCE_EXTS.has(ext))
549
- return false;
550
- const rel = path2.relative(path2.resolve(workspaceRoot), abs);
551
- if (!rel || rel.startsWith("..") || path2.isAbsolute(rel))
552
- return false;
553
- const parts = rel.split(path2.sep).filter(Boolean);
554
- const [scope] = parts;
555
- if (scope !== "apps" && scope !== "libs" && scope !== "pkgs")
556
- return false;
557
- const base = path2.basename(abs);
558
- return parts.includes("srvkit") || parts.includes("common") || SERVER_SUFFIXES.some((suffix) => base.endsWith(suffix)) || SHARED_SUFFIXES.some((suffix) => base.endsWith(suffix)) || RUNTIME_METADATA_BASENAMES.has(base) || base === "main.ts" || base === "server.ts";
559
- };
560
- var shouldMarkBuildPhaseRecovered = (previousByPhase, status) => {
561
- const previous = previousByPhase.get(status.phase);
562
- return Boolean(previous && status.ok && !previous.ok && generationValue(status.generation) >= previous.generation);
563
- };
564
- var createBackendBuildStatus = ({
565
- generation,
566
- ok,
567
- files = [],
568
- message
569
- }) => ({
570
- generation,
571
- phase: "backend",
572
- ok,
573
- files,
574
- message
575
- });
576
- var backendRestartReasonFromMessage = (message) => {
577
- const roleSet = new Set;
578
- for (const role of message.devPlan?.roles ?? []) {
579
- if (role === "server" || role === "shared" || role === "barrel" || role === "config")
580
- roleSet.add(role);
581
- }
582
- return {
583
- generation: message.devPlan?.generation ?? message.generation,
584
- files: [...new Set(message.files)].sort(),
585
- roles: RESTART_ROLE_ORDER.filter((role) => roleSet.has(role))
586
- };
587
- };
588
- var mergeBackendRestartReasons = (current, next) => ({
589
- generation: generationValue(next.generation) >= generationValue(current?.generation) ? next.generation : current?.generation,
590
- files: [...new Set([...current?.files ?? [], ...next.files])].sort(),
591
- roles: RESTART_ROLE_ORDER.filter((role) => current?.roles.includes(role) || next.roles.includes(role))
592
- });
593
- var shouldReplaceLastGoodMessage = (current, next) => !current || generationValue(next.data.generation) >= generationValue(current.data.generation);
594
- var shouldQueueBuildStatusReplay = (backendReady, pendingReplayCount) => !backendReady || pendingReplayCount > 0;
595
- var hasBuildFailureForGeneration = (statusByPhase, generation) => {
596
- if (typeof generation !== "number")
597
- return false;
598
- for (const status of statusByPhase.values()) {
599
- if (!status.ok && status.generation === generation)
600
- return true;
601
- }
602
- return false;
603
- };
604
- var decideBuilderRssRecycle = ({
605
- rssBytes,
606
- ceilingBytes,
607
- buildFailed,
608
- msSinceLastRecycle,
609
- minIntervalMs = BUILDER_MIN_RSS_RECYCLE_INTERVAL_MS
610
- }) => {
611
- if (!ceilingBytes)
612
- return "unbounded";
613
- if (rssBytes < ceilingBytes)
614
- return "below-ceiling";
615
- if (buildFailed)
616
- return "build-failed";
617
- if (msSinceLastRecycle !== null && msSinceLastRecycle < minIntervalMs)
618
- return "too-soon";
619
- return "recycle";
620
- };
621
- var decideBuilderRssSettle = ({
622
- rssBytes,
623
- ceilingBytes,
624
- hardMultiple = BUILDER_RSS_HARD_MULTIPLE
625
- }) => rssBytes >= ceilingBytes * hardMultiple ? "recycle-now" : "wait-and-recheck";
626
- var decideIdleSuspend = ({
627
- enabled,
628
- suspended,
629
- builderReady,
630
- backendReady,
631
- buildFailed,
632
- restartPending,
633
- msSinceWake,
634
- minUptimeMs = DEV_IDLE_MIN_UPTIME_MS
635
- }) => {
636
- if (!enabled)
637
- return "disabled";
638
- if (suspended)
639
- return "already-suspended";
640
- if (!builderReady)
641
- return "builder-not-ready";
642
- if (!backendReady)
643
- return "backend-not-ready";
644
- if (buildFailed)
645
- return "build-failed";
646
- if (restartPending)
647
- return "restart-pending";
648
- if (msSinceWake !== null && msSinceWake < minUptimeMs)
649
- return "too-soon";
650
- return "suspend";
651
- };
652
- var resolveIdleSuspendMs = (raw) => {
653
- if (raw === undefined || raw === "")
654
- return DEV_IDLE_SUSPEND_MS;
655
- const parsed = Number(raw);
656
- if (!Number.isFinite(parsed) || parsed <= 0)
657
- return null;
658
- return Math.round(parsed);
659
- };
660
- var hasAnyBuildFailure = (statusByPhase) => [...statusByPhase.values()].some((status) => !status.ok);
661
- var shouldRefreshConfigOnIdleWake = (batch) => !!batch && batch.kinds.has("config");
662
- var RETURNING_BUILDER_STATUSES = new Set(["starting", "recycling", "restarting"]);
663
- var shouldHoldForReturningBuilder = ({
664
- status,
665
- heldCount,
666
- limit = HELD_BUILDER_REQUEST_LIMIT
667
- }) => RETURNING_BUILDER_STATUSES.has(status) && heldCount < limit;
668
- var shouldWarnBuilderRssCeilingTight = (reportsSinceRecycle, limit = BUILDER_TIGHT_RSS_REPORT_LIMIT) => reportsSinceRecycle >= limit;
669
- var isRssCeilingUnreachable = (freshRssBytes, ceilingBytes) => freshRssBytes !== null && ceilingBytes !== null && freshRssBytes >= ceilingBytes;
670
- var shouldRelayRecycledFrontendState = (current, next) => {
671
- if (!current || current.type !== next.type)
672
- return true;
673
- if (current.type === "pages-updated" && next.type === "pages-updated")
674
- return current.data.bundlePath !== next.data.bundlePath;
675
- if (current.type === "css-updated" && next.type === "css-updated")
676
- return JSON.stringify(current.data.cssAssets) !== JSON.stringify(next.data.cssAssets);
677
- return true;
678
- };
679
- var mergeDevPlans = (current, next) => {
680
- if (!current)
681
- return next;
682
- if (!next)
683
- return current;
684
- const reasonByFile = { ...current.reasonByFile };
685
- for (const [file, reasons] of Object.entries(next.reasonByFile)) {
686
- reasonByFile[file] = [...new Set([...reasonByFile[file] ?? [], ...reasons])].sort();
687
- }
688
- return {
689
- generation: Math.max(current.generation, next.generation),
690
- files: [...new Set([...current.files, ...next.files])].sort(),
691
- generatedFiles: [...new Set([...current.generatedFiles, ...next.generatedFiles])].sort(),
692
- roles: [...new Set([...current.roles, ...next.roles])].sort(),
693
- actions: [...new Set([...current.actions, ...next.actions])].sort(),
694
- reasonByFile
695
- };
696
- };
697
- var mergeInvalidateMessages = (current, next) => {
698
- const generation = Math.max(generationValue(current.generation), generationValue(next.generation));
699
- return {
700
- type: "invalidate",
701
- kinds: [...new Set([...current.kinds, ...next.kinds])].sort(),
702
- files: [...new Set([...current.files, ...next.files])].sort(),
703
- generation: generation >= 0 ? generation : undefined,
704
- devPlan: mergeDevPlans(current.devPlan, next.devPlan)
705
- };
706
- };
707
- var buildStatusReplaySequence = (pendingReplay, latestByPhase) => [...pendingReplay, ...latestByPhase.values()];
708
- var filesChangedSince = (before, after) => [...before].filter(([file, stamp]) => after.get(file) !== stamp).map(([file]) => file);
709
-
710
- // pkgs/@akanjs/devkit/akanApp/BackendImportGraph.ts
711
481
  var NON_SOURCE_EXT_RE = /\.(css|scss|sass|less|json|svg|png|jpe?g|webp|gif|avif|ico|woff2?|ttf|otf|mp3|mp4|wav|html)$/i;
712
482
  var GRAPH_IMPORT_KINDS = new Set([
713
483
  "import-statement",
@@ -738,7 +508,7 @@ class BackendImportGraph {
738
508
  return this.#lastRefreshSucceeded;
739
509
  }
740
510
  has(file) {
741
- return this.#files.has(path3.resolve(file));
511
+ return this.#files.has(path2.resolve(file));
742
512
  }
743
513
  async fingerprint() {
744
514
  const stamps = await Promise.all([...this.#files].map(async (file) => {
@@ -766,9 +536,9 @@ class BackendImportGraph {
766
536
  const roots = await this.#entrypoints();
767
537
  const files = new Set;
768
538
  const queue = [...roots];
769
- const workspaceRoot = path3.resolve(this.#app.workspace.workspaceRoot);
539
+ const workspaceRoot = path2.resolve(this.#app.workspace.workspaceRoot);
770
540
  while (queue.length > 0) {
771
- const current = path3.resolve(queue.pop());
541
+ const current = path2.resolve(queue.pop());
772
542
  if (files.has(current))
773
543
  continue;
774
544
  if (!this.#isWorkspaceSource(current, workspaceRoot))
@@ -777,7 +547,7 @@ class BackendImportGraph {
777
547
  if (!imports)
778
548
  continue;
779
549
  files.add(current);
780
- const importerDir = path3.dirname(current);
550
+ const importerDir = path2.dirname(current);
781
551
  for (const imp of imports) {
782
552
  if (!GRAPH_IMPORT_KINDS.has(imp.kind) || !imp.path || NON_SOURCE_EXT_RE.test(imp.path))
783
553
  continue;
@@ -808,7 +578,7 @@ class BackendImportGraph {
808
578
  const roots = [`${this.#app.cwdPath}/main.ts`, `${this.#app.cwdPath}/server.ts`];
809
579
  const existing = [];
810
580
  for (const root of roots) {
811
- const abs = path3.resolve(root);
581
+ const abs = path2.resolve(root);
812
582
  if (await Bun.file(abs).exists())
813
583
  existing.push(abs);
814
584
  }
@@ -817,25 +587,25 @@ class BackendImportGraph {
817
587
  #resolve(specifier, importerDir) {
818
588
  try {
819
589
  const resolved = Bun.resolveSync(specifier, importerDir);
820
- if (!path3.isAbsolute(resolved))
590
+ if (!path2.isAbsolute(resolved))
821
591
  return null;
822
- if (!SOURCE_EXTS.has(path3.extname(resolved).toLowerCase()))
592
+ if (!SOURCE_EXTS.has(path2.extname(resolved).toLowerCase()))
823
593
  return null;
824
- return path3.resolve(resolved);
594
+ return path2.resolve(resolved);
825
595
  } catch {
826
596
  return null;
827
597
  }
828
598
  }
829
599
  #isWorkspaceSource(file, workspaceRoot) {
830
- const rel = path3.relative(workspaceRoot, file);
831
- if (rel.startsWith("..") || path3.isAbsolute(rel))
600
+ const rel = path2.relative(workspaceRoot, file);
601
+ if (rel.startsWith("..") || path2.isAbsolute(rel))
832
602
  return false;
833
- if (rel.includes(`${path3.sep}node_modules${path3.sep}`) || rel.includes(`${path3.sep}.akan${path3.sep}`))
603
+ if (rel.includes(`${path2.sep}node_modules${path2.sep}`) || rel.includes(`${path2.sep}.akan${path2.sep}`))
834
604
  return false;
835
- return SOURCE_EXTS.has(path3.extname(file).toLowerCase());
605
+ return SOURCE_EXTS.has(path2.extname(file).toLowerCase());
836
606
  }
837
607
  #scanImports(file, source) {
838
- const ext = path3.extname(file).toLowerCase();
608
+ const ext = path2.extname(file).toLowerCase();
839
609
  if (ext === ".tsx")
840
610
  return this.#tsxTranspiler.scanImports(source);
841
611
  if (ext === ".jsx")
@@ -848,6 +618,7 @@ class BackendImportGraph {
848
618
 
849
619
  // pkgs/@akanjs/devkit/akanApp/akanApp.host.ts
850
620
  var backendMsgTypeSet = new Set(["build-route", "build-csr"]);
621
+ var asMib = (bytes) => Math.round(bytes / 1024 / 1024);
851
622
  var BACKEND_RESTART_DEBOUNCE_MS = 120;
852
623
  var BACKEND_GRACEFUL_TIMEOUT_MS = 8000;
853
624
  var BACKEND_RECOVERY_BASE_DELAY_MS = 1000;
@@ -863,7 +634,7 @@ var BUILDER_RECOVERY_MAX_DELAY_MS = 60000;
863
634
 
864
635
  class AkanAppHost {
865
636
  app;
866
- logger = new Logger3("AkanAppHost");
637
+ logger = new Logger2("AkanAppHost");
867
638
  stdio;
868
639
  env;
869
640
  #onDevEvent;
@@ -941,23 +712,18 @@ class AkanAppHost {
941
712
  async stop() {
942
713
  this.#cancelIdleSuspend();
943
714
  this.#stopIdleWatcher();
944
- if (this.#restartTimer) {
945
- clearTimeout(this.#restartTimer);
946
- this.#restartTimer = null;
947
- }
948
- if (this.#backendRecoveryTimer) {
949
- clearTimeout(this.#backendRecoveryTimer);
950
- this.#backendRecoveryTimer = null;
951
- }
952
- if (this.#builderRecoveryTimer) {
953
- clearTimeout(this.#builderRecoveryTimer);
954
- this.#builderRecoveryTimer = null;
955
- }
715
+ this.#clearRestartTimers();
956
716
  this.#failPendingBuilderMessages("dev server is shutting down");
957
717
  await this.#stopBackend();
958
718
  this.#stopBuilder();
959
719
  return this;
960
720
  }
721
+ #clearRestartTimers() {
722
+ for (const timer of [this.#restartTimer, this.#backendRecoveryTimer, this.#builderRecoveryTimer])
723
+ if (timer)
724
+ clearTimeout(timer);
725
+ this.#restartTimer = this.#backendRecoveryTimer = this.#builderRecoveryTimer = null;
726
+ }
961
727
  kill() {
962
728
  this.stop();
963
729
  }
@@ -1253,7 +1019,6 @@ ${this.#backendStderrTail.join(`
1253
1019
  if (this.#rssCeilingAbandoned)
1254
1020
  return;
1255
1021
  const ceilingBytes = IncrementalBuilderHost.maxRssBytes();
1256
- const asMib = (bytes) => Math.round(bytes / 1024 / 1024);
1257
1022
  const decision = decideBuilderRssRecycle({
1258
1023
  rssBytes: metrics.rssBytes,
1259
1024
  ceilingBytes,
@@ -1291,7 +1056,6 @@ ${this.#backendStderrTail.join(`
1291
1056
  if (!isRssCeilingUnreachable(freshRssBytes, ceilingBytes))
1292
1057
  return;
1293
1058
  this.#rssCeilingAbandoned = true;
1294
- const asMib = (bytes) => Math.round(bytes / 1024 / 1024);
1295
1059
  this.logger.error(`[builder-recycle] a freshly recycled builder is already at ${asMib(freshRssBytes ?? 0)}MiB with nothing built on demand, so the ${asMib(ceilingBytes)}MiB ceiling cannot be met for this app; no longer enforcing it this session. Raise AKAN_BUILDER_MAX_RSS_MB, or set it to 0 to leave the builder unbounded.`);
1296
1060
  }
1297
1061
  #armRssRecycle(reason, over) {
@@ -1318,7 +1082,6 @@ ${this.#backendStderrTail.join(`
1318
1082
  }, BUILDER_RSS_RECYCLE_QUIET_MS);
1319
1083
  }
1320
1084
  async#recycleBuilderForRssWhenStillOver(reason, { rssBytes, ceilingBytes }) {
1321
- const asMib = (bytes) => Math.round(bytes / 1024 / 1024);
1322
1085
  if (decideBuilderRssSettle({ rssBytes, ceilingBytes }) === "recycle-now") {
1323
1086
  this.#recycleBuilderForRss(reason);
1324
1087
  return;
@@ -1510,7 +1273,7 @@ ${this.#backendStderrTail.join(`
1510
1273
  await this.#backendGraph.refresh();
1511
1274
  await this.#startBuilder({ announceBootState: true });
1512
1275
  const missed = await this.#takeBuilderGapChanges();
1513
- const backendFiles = [...new Set([...files.filter((file) => this.#isBackendFile(file)), ...missed])];
1276
+ const backendFiles = [...new Set([...files.filter((file) => this.#backendGraph.has(file)), ...missed])];
1514
1277
  if (backendFiles.length === 0)
1515
1278
  return;
1516
1279
  this.logger.verbose(`[idle-suspend] ${backendFiles.length} backend file(s) changed while suspended`);
@@ -1565,10 +1328,6 @@ ${this.#backendStderrTail.join(`
1565
1328
  for (const message of pending)
1566
1329
  this.#sendToBuilder(message);
1567
1330
  }
1568
- #holdUntilBuilderReady(message) {
1569
- this.#pendingBuilderMessages.push(message);
1570
- this.logger.verbose(`[builder] holding ${message.type} until the builder is ready (${this.#pendingBuilderMessages.length} waiting)`);
1571
- }
1572
1331
  #discardPendingBuilderMessages(reason) {
1573
1332
  const held = this.#pendingBuilderMessages.splice(0);
1574
1333
  if (held.length === 0)
@@ -1580,12 +1339,17 @@ ${this.#backendStderrTail.join(`
1580
1339
  if (held.length === 0)
1581
1340
  return;
1582
1341
  this.logger.warn(`failing ${held.length} held builder request(s): ${reason}`);
1583
- for (const message of held) {
1584
- if (message.type === "build-route")
1585
- this.#sendToBackend({ type: "build-route-res", id: message.id, ok: false, error: reason });
1586
- else if (message.type === "build-csr")
1587
- this.#sendToBackend({ type: "build-csr-res", id: message.id, ok: false, error: reason });
1588
- }
1342
+ for (const message of held)
1343
+ this.#failBuilderRequest(message, reason);
1344
+ }
1345
+ #failBuilderRequest(message, error) {
1346
+ if (message.type === "build-route")
1347
+ this.#sendToBackend({ type: "build-route-res", id: message.id, ok: false, error });
1348
+ else if (message.type === "build-csr")
1349
+ this.#sendToBackend({ type: "build-csr-res", id: message.id, ok: false, error });
1350
+ else
1351
+ return false;
1352
+ return true;
1589
1353
  }
1590
1354
  #recycleBuilderForRss(reason) {
1591
1355
  if (this.#pendingRecycle || this.#restartTimer) {
@@ -1706,18 +1470,7 @@ ${this.#backendStderrTail.join(`
1706
1470
  }
1707
1471
  async#recycleDevChildren(message, { refreshConfig = false } = {}) {
1708
1472
  const generation = message.devPlan?.generation ?? message.generation;
1709
- if (this.#restartTimer) {
1710
- clearTimeout(this.#restartTimer);
1711
- this.#restartTimer = null;
1712
- }
1713
- if (this.#backendRecoveryTimer) {
1714
- clearTimeout(this.#backendRecoveryTimer);
1715
- this.#backendRecoveryTimer = null;
1716
- }
1717
- if (this.#builderRecoveryTimer) {
1718
- clearTimeout(this.#builderRecoveryTimer);
1719
- this.#builderRecoveryTimer = null;
1720
- }
1473
+ this.#clearRestartTimers();
1721
1474
  this.#builderRecoveryAttempts = 0;
1722
1475
  this.#pendingRestartReason = null;
1723
1476
  this.#lastGoodFrontend = {};
@@ -1807,7 +1560,7 @@ ${this.#backendStderrTail.join(`
1807
1560
  }
1808
1561
  if (message.kinds.includes("code"))
1809
1562
  await this.#backendGraph.refresh();
1810
- if (message.files.some((file) => this.#isBackendFile(file)))
1563
+ if (message.files.some((file) => this.#backendGraph.has(file)))
1811
1564
  return true;
1812
1565
  if (!this.#backendGraph.lastRefreshSucceeded) {
1813
1566
  const fallbackFiles = message.files.filter((file) => isLegacyBackendFallbackFile(file, this.app.workspace.workspaceRoot));
@@ -1818,9 +1571,6 @@ ${this.#backendStderrTail.join(`
1818
1571
  }
1819
1572
  return false;
1820
1573
  }
1821
- #isBackendFile(file) {
1822
- return this.#backendGraph.has(file);
1823
- }
1824
1574
  async#startBuilder({
1825
1575
  announceBootState = false
1826
1576
  } = {}) {
@@ -1906,27 +1656,12 @@ ${this.#backendStderrTail.join(`
1906
1656
  return;
1907
1657
  const status = this.#builder?.status ?? "stopped";
1908
1658
  if (shouldHoldForReturningBuilder({ status, heldCount: this.#pendingBuilderMessages.length })) {
1909
- this.#holdUntilBuilderReady(message);
1910
- return;
1911
- }
1912
- if (message.type === "build-route") {
1913
- this.#sendToBackend({
1914
- type: "build-route-res",
1915
- id: message.id,
1916
- ok: false,
1917
- error: `builder is ${status}; reload after the builder is ready`
1918
- });
1659
+ this.#pendingBuilderMessages.push(message);
1660
+ this.logger.verbose(`[builder] holding ${message.type} until the builder is ready (${this.#pendingBuilderMessages.length} waiting)`);
1919
1661
  return;
1920
1662
  }
1921
- if (message.type === "build-csr") {
1922
- this.#sendToBackend({
1923
- type: "build-csr-res",
1924
- id: message.id,
1925
- ok: false,
1926
- error: `builder is ${status}; reload after the builder is ready`
1927
- });
1663
+ if (this.#failBuilderRequest(message, `builder is ${status}; reload after the builder is ready`))
1928
1664
  return;
1929
- }
1930
1665
  this.logger.warn("akanAppHost builder is not running");
1931
1666
  }
1932
1667
  #stopBuilder() {
@@ -1938,25 +1673,20 @@ ${this.#backendStderrTail.join(`
1938
1673
  }
1939
1674
  }
1940
1675
  // pkgs/@akanjs/devkit/applicationTestPreload.ts
1941
- import path4 from "path";
1676
+ import path3 from "path";
1942
1677
  var SIGNAL_TEST_PRELOAD_PATH = "test/signalTest.preload.ts";
1943
1678
  async function resolveSignalTestPreloadPath(target) {
1944
1679
  const candidates = [];
1945
- const addResolvedPackageCandidate = (basePath) => {
1680
+ for (const basePath of [target.cwdPath, process.cwd(), path3.dirname(Bun.main), import.meta.dir]) {
1946
1681
  try {
1947
- candidates.push(path4.join(path4.dirname(Bun.resolveSync("akanjs/package.json", basePath)), SIGNAL_TEST_PRELOAD_PATH));
1682
+ candidates.push(path3.join(path3.dirname(Bun.resolveSync("akanjs/package.json", basePath)), SIGNAL_TEST_PRELOAD_PATH));
1948
1683
  } catch {}
1949
- };
1950
- addResolvedPackageCandidate(target.cwdPath);
1951
- addResolvedPackageCandidate(process.cwd());
1952
- addResolvedPackageCandidate(path4.dirname(Bun.main));
1953
- addResolvedPackageCandidate(import.meta.dir);
1954
- candidates.push(path4.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path4.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path4.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path4.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path4.join(path4.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path4.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
1684
+ }
1685
+ candidates.push(path3.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path3.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path3.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path3.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path3.join(path3.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path3.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
1955
1686
  const uniqueCandidates = [...new Set(candidates)];
1956
- for (const candidate of uniqueCandidates) {
1687
+ for (const candidate of uniqueCandidates)
1957
1688
  if (await Bun.file(candidate).exists())
1958
1689
  return candidate;
1959
- }
1960
1690
  throw new Error(`Failed to locate ${SIGNAL_TEST_PRELOAD_PATH} from ${target.cwdPath}.
1961
1691
  Probed paths:
1962
1692
  ${uniqueCandidates.map((candidate) => ` - ${candidate}`).join(`
@@ -1964,10 +1694,10 @@ ${uniqueCandidates.map((candidate) => ` - ${candidate}`).join(`
1964
1694
  }
1965
1695
 
1966
1696
  // pkgs/@akanjs/cli/application/application.runner.ts
1967
- import { Logger as Logger4 } from "akanjs/common";
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;
1697
+ import { Logger as Logger3 } from "akanjs/common";
1698
+ var loadBuildRunner = async () => (await import("./applicationBuildRunner-ybyp97pv.js")).ApplicationBuildRunner;
1699
+ var loadReleasePackager = async () => (await import("./applicationReleasePackager-esnrphw8.js")).ApplicationReleasePackager;
1700
+ var loadCapacitorApp = async () => (await import("./capacitorApp-1synz4en.js")).CapacitorApp;
1971
1701
  var loadPrompts = async () => await import("@inquirer/prompts");
1972
1702
 
1973
1703
  class ApplicationRunner extends runner("application") {
@@ -1986,9 +1716,6 @@ class ApplicationRunner extends runner("application") {
1986
1716
  async removeApplication(app) {
1987
1717
  await app.workspace.removeDir(`apps/${app.name}`);
1988
1718
  }
1989
- async getConfig(app) {
1990
- return await app.getConfig();
1991
- }
1992
1719
  async getScriptFilename(app) {
1993
1720
  if (!await app.exists("script")) {
1994
1721
  await app.mkdir("script");
@@ -2015,7 +1742,7 @@ class ApplicationRunner extends runner("application") {
2015
1742
  });
2016
1743
  }
2017
1744
  #runtimeDirOf(app, override) {
2018
- return path5.resolve(override ?? process.env.AKAN_RUNTIME_DIR ?? path5.join(app.workspace.workspaceRoot, "local", "apps", app.name, "runtime"));
1745
+ return path4.resolve(override ?? process.env.AKAN_RUNTIME_DIR ?? path4.join(app.workspace.workspaceRoot, "local", "apps", app.name, "runtime"));
2019
1746
  }
2020
1747
  async runLogs(app, options) {
2021
1748
  const { LogControlUnavailableError, LogTailClient } = await import("akanjs/server/logging/logTailClient");
@@ -2025,13 +1752,10 @@ class ApplicationRunner extends runner("application") {
2025
1752
  const { level, grep, endpoint, trace, child, role, origin, since } = options;
2026
1753
  const query = Object.fromEntries(Object.entries({ level, grep, endpoint, trace, child, role, origin, since }).filter(([, value]) => value !== undefined && value !== null && value !== ""));
2027
1754
  const print = (record) => process.stdout.write(options.json ? `${JSON.stringify(record)}
2028
- ` : Logger4.render(record));
1755
+ ` : Logger3.render(record));
2029
1756
  const note = (text) => process.stderr.write(`[akan logs] ${text}
2030
1757
  `);
2031
- let finish = null;
2032
- const closed = new Promise((resolve) => {
2033
- finish = resolve;
2034
- });
1758
+ const { promise: closed, resolve: finish } = Promise.withResolvers();
2035
1759
  let client;
2036
1760
  try {
2037
1761
  client = await LogTailClient.connect(socketPath, {
@@ -2040,11 +1764,11 @@ class ApplicationRunner extends runner("application") {
2040
1764
  if (response.type === "dropped")
2041
1765
  note(`${response.count} records dropped (reader too slow)`);
2042
1766
  },
2043
- onClose: () => finish?.()
1767
+ onClose: () => finish()
2044
1768
  });
2045
1769
  } catch (error) {
2046
1770
  if (error instanceof LogControlUnavailableError)
2047
- throw new Error(`${app.name} is not running (no ${path5.basename(socketPath)} in ${runtimeDir}). Start it with \`akan start ${app.name}\`, or pass --runtime-dir for a built app.`);
1771
+ throw new Error(`${app.name} is not running (no ${path4.basename(socketPath)} in ${runtimeDir}). Start it with \`akan start ${app.name}\`, or pass --runtime-dir for a built app.`);
2048
1772
  throw error;
2049
1773
  }
2050
1774
  const sinceMs = since ? LogQueryMatcher.parseSince(since) : undefined;
@@ -2109,7 +1833,7 @@ try {
2109
1833
  const serverPath = `${app.cwdPath}/server.ts`;
2110
1834
  if (!await app.exists("server.ts"))
2111
1835
  throw new Error(`Server file not found: apps/${app.name}/server.ts`);
2112
- const target = path5.resolve(app.workspace.workspaceRoot, dir);
1836
+ const target = path4.resolve(app.workspace.workspaceRoot, dir);
2113
1837
  const code = `
2114
1838
  const { server } = await import(${JSON.stringify(serverPath)});
2115
1839
  const { DatabaseAdaptorRole, DocumentTransfer } = await import("akanjs/service");
@@ -2205,13 +1929,7 @@ try {
2205
1929
  await new (await loadCapacitorApp())(app, mobileTarget.config).buildAndroid("apk", { env, regenerate });
2206
1930
  });
2207
1931
  }
2208
- async startAndroid(app, {
2209
- open = false,
2210
- operation = "local",
2211
- env = "local",
2212
- target,
2213
- regenerate = false
2214
- } = {}) {
1932
+ async startAndroid(app, { open = false, operation = "local", env = "local", target, regenerate = false } = {}) {
2215
1933
  const targets = await resolveMobileTargets(app, target);
2216
1934
  if (operation === "release")
2217
1935
  await this.#buildMobileCsr(app, env);
@@ -2268,16 +1986,20 @@ try {
2268
1986
  return;
2269
1987
  for (const failure of failures) {
2270
1988
  const message = failure.error instanceof Error ? failure.error.message : String(failure.error);
2271
- Logger4.rawLog(`Mobile target ${failure.target} failed: ${message}`, undefined, "error");
1989
+ Logger3.rawLog(`Mobile target ${failure.target} failed: ${message}`, undefined, "error");
2272
1990
  }
2273
1991
  throw new Error(`${failures.length}/${results.length} mobile targets failed`);
2274
1992
  }
2275
- async codepush(app, os) {
1993
+ async codepush(app) {
1994
+ throw new Error(`akan codepush is still in development and deploys nothing yet, so ${app.name} was not updated. To release the app's source with OTA update support, run \`akan release-source ${app.name}\`.`);
1995
+ }
1996
+ async#initCapacitorApp(app) {
2276
1997
  const [target] = await resolveMobileTargets(app, undefined);
2277
1998
  if (!target)
2278
1999
  throw new Error(`No mobile target configured for ${app.name}`);
2279
2000
  const capacitorApp = new (await loadCapacitorApp())(app, target.config);
2280
2001
  await capacitorApp.init();
2002
+ return capacitorApp;
2281
2003
  }
2282
2004
  #getLocalDatabaseServices(mode) {
2283
2005
  if (mode === "single")
@@ -2335,11 +2057,7 @@ ${detail}`
2335
2057
  await workspace.spawn(`docker`, ["compose", "down"], { cwd: `${workspace.workspaceRoot}/local` });
2336
2058
  }
2337
2059
  async configureApp(app) {
2338
- const [target] = await resolveMobileTargets(app, undefined);
2339
- if (!target)
2340
- throw new Error(`No mobile target configured for ${app.name}`);
2341
- const capacitorApp = new (await loadCapacitorApp())(app, target.config);
2342
- await capacitorApp.init();
2060
+ const capacitorApp = await this.#initCapacitorApp(app);
2343
2061
  if (await (await loadPrompts()).confirm({ message: "want to add camera permission?" }))
2344
2062
  await capacitorApp.addCamera();
2345
2063
  if (await (await loadPrompts()).confirm({ message: "want to add contact permission?" }))
@@ -2349,31 +2067,10 @@ ${detail}`
2349
2067
  await capacitorApp.save();
2350
2068
  }
2351
2069
  async releaseSource(app, { rebuild, buildNum = 0, environment = "debug", local = true } = {}) {
2352
- await new (await loadReleasePackager())(app, { build: () => this.build(app).then(() => {
2070
+ const packager = new (await loadReleasePackager())(app, { build: () => this.build(app).then(() => {
2353
2071
  return;
2354
- }) }).releaseSource({
2355
- rebuild,
2356
- buildNum,
2357
- environment,
2358
- local
2359
- });
2360
- return;
2361
- }
2362
- async createApplicationTemplate(workspace, appName) {
2363
- await workspace.applyTemplate({ basePath: `apps/${appName}`, template: "appRoot", dict: { appName } });
2364
- }
2365
- async compressProjectFiles(app, { rebuild, buildNum = 0, environment = "debug", local = true } = {}) {
2366
- await new (await loadReleasePackager())(app, {
2367
- build: () => this.build(app).then(() => {
2368
- return;
2369
- })
2370
- }).compressProjectFiles({
2371
- rebuild,
2372
- buildNum,
2373
- environment,
2374
- local
2375
- });
2376
- return;
2072
+ }) });
2073
+ await packager.releaseSource({ rebuild, buildNum, environment, local });
2377
2074
  }
2378
2075
  }
2379
2076
 
@@ -2525,7 +2222,8 @@ class HostProcessProbe {
2525
2222
  if (!/^\d+$/.test(entry))
2526
2223
  continue;
2527
2224
  const holds = HostProcessProbe.#listDir(`/proc/${entry}/fd`).some((fd) => {
2528
- const inode = /^socket:\[(\d+)\]$/.exec(HostProcessProbe.#readLink(`/proc/${entry}/fd/${fd}`))?.[1];
2225
+ const link = HostProcessProbe.#orElse(() => readlinkSync(`/proc/${entry}/fd/${fd}`), "");
2226
+ const inode = /^socket:\[(\d+)\]$/.exec(link)?.[1];
2529
2227
  return !!inode && inodes.has(inode);
2530
2228
  });
2531
2229
  if (holds)
@@ -2534,24 +2232,16 @@ class HostProcessProbe {
2534
2232
  return pids;
2535
2233
  }
2536
2234
  static #readProc(pid, file) {
2537
- try {
2538
- return readFileSync(`/proc/${pid}/${file}`, "utf8");
2539
- } catch {
2540
- return null;
2541
- }
2235
+ return HostProcessProbe.#orElse(() => readFileSync(`/proc/${pid}/${file}`, "utf8"), null);
2542
2236
  }
2543
2237
  static #listDir(dir) {
2544
- try {
2545
- return readdirSync(dir);
2546
- } catch {
2547
- return [];
2548
- }
2238
+ return HostProcessProbe.#orElse(() => readdirSync(dir), []);
2549
2239
  }
2550
- static #readLink(link) {
2240
+ static #orElse(read, fallback) {
2551
2241
  try {
2552
- return readlinkSync(link);
2242
+ return read();
2553
2243
  } catch {
2554
- return "";
2244
+ return fallback;
2555
2245
  }
2556
2246
  }
2557
2247
  }
@@ -2665,12 +2355,12 @@ class DevPortReclaimer {
2665
2355
  }
2666
2356
 
2667
2357
  // pkgs/@akanjs/cli/application/devStreamView.ts
2668
- import { Logger as Logger5 } from "akanjs/common";
2358
+ import { Logger as Logger4 } from "akanjs/common";
2669
2359
  import chalk from "chalk";
2670
2360
  var appColors = ["cyan", "magenta", "yellow", "green", "blue", "red"];
2671
2361
 
2672
2362
  class DevStreamView {
2673
- #logger = new Logger5("akan start");
2363
+ #logger = new Logger4("akan start");
2674
2364
  #partial = new Map;
2675
2365
  #lastState = new Map;
2676
2366
  #color = new Map;
@@ -2774,7 +2464,7 @@ class DevBootConcurrency {
2774
2464
 
2775
2465
  // pkgs/@akanjs/cli/application/devSessionLog.ts
2776
2466
  import { mkdir, rename } from "fs/promises";
2777
- import path6 from "path";
2467
+ import path5 from "path";
2778
2468
  import dayjs from "dayjs";
2779
2469
 
2780
2470
  class DevSessionLog {
@@ -2798,19 +2488,19 @@ class DevSessionLog {
2798
2488
  return [...this.#appNames];
2799
2489
  }
2800
2490
  pathOf(app) {
2801
- return path6.join(this.#runtimeDirOf(app), DevSessionLog.fileName);
2491
+ return path5.join(this.#runtimeDirOf(app), DevSessionLog.fileName);
2802
2492
  }
2803
2493
  previousPathOf(app) {
2804
- return path6.join(this.#runtimeDirOf(app), DevSessionLog.previousFileName);
2494
+ return path5.join(this.#runtimeDirOf(app), DevSessionLog.previousFileName);
2805
2495
  }
2806
2496
  relativePathOf(app) {
2807
- return path6.relative(this.#workspaceRoot, this.pathOf(app));
2497
+ return path5.relative(this.#workspaceRoot, this.pathOf(app));
2808
2498
  }
2809
2499
  async open() {
2810
2500
  const stamp = dayjs(this.#now()).format("YYYY-MM-DD HH:mm:ss");
2811
2501
  for (const app of this.#appNames) {
2812
2502
  const file = this.pathOf(app);
2813
- await mkdir(path6.dirname(file), { recursive: true });
2503
+ await mkdir(path5.dirname(file), { recursive: true });
2814
2504
  await rename(file, this.previousPathOf(app)).catch(() => {
2815
2505
  return;
2816
2506
  });
@@ -2854,7 +2544,7 @@ class DevSessionLog {
2854
2544
  this.#writers.clear();
2855
2545
  }
2856
2546
  #runtimeDirOf(app) {
2857
- return path6.join(this.#workspaceRoot, "local", "apps", app, "runtime");
2547
+ return path5.join(this.#workspaceRoot, "local", "apps", app, "runtime");
2858
2548
  }
2859
2549
  #writeLine(app, text) {
2860
2550
  const writer = this.#writers.get(app);
@@ -2877,6 +2567,16 @@ class DevSessionLog {
2877
2567
 
2878
2568
  // pkgs/@akanjs/cli/application/devSupervisor.ts
2879
2569
  class DevSupervisor {
2570
+ static resolveDevUi(plain, {
2571
+ isTty = !!process.stdout.isTTY,
2572
+ columns = process.stdout.columns ?? 0
2573
+ } = {}) {
2574
+ if (plain)
2575
+ return { mode: "stream", downgraded: false };
2576
+ if (!isTty || columns <= 0)
2577
+ return { mode: "stream", downgraded: true };
2578
+ return { mode: "tui", downgraded: false };
2579
+ }
2880
2580
  static supervisedEnvKey = "AKAN_DEV_SUPERVISED";
2881
2581
  static childHooks() {
2882
2582
  if (process.env[DevSupervisor.supervisedEnvKey] !== "1" || !process.send)
@@ -2940,10 +2640,7 @@ class DevSupervisor {
2940
2640
  return ports;
2941
2641
  }
2942
2642
  #makeChild(app, port) {
2943
- let markReady;
2944
- const ready = new Promise((resolve) => {
2945
- markReady = resolve;
2946
- });
2643
+ const { promise: ready, resolve: markReady } = Promise.withResolvers();
2947
2644
  return {
2948
2645
  status: {
2949
2646
  app,
@@ -2980,16 +2677,18 @@ class DevSupervisor {
2980
2677
  }
2981
2678
  }
2982
2679
  async#waitForReady(child) {
2983
- let timer = null;
2680
+ if (await DevSupervisor.timesOut(child.ready, DevSupervisor.readyTimeoutMs))
2681
+ this.#note(`${child.status.name} has not reported ready after ${Math.round(DevSupervisor.readyTimeoutMs / 1000)}s; starting the next app anyway`, "warn");
2682
+ }
2683
+ static async timesOut(work, ms) {
2684
+ let timer;
2984
2685
  const expired = new Promise((resolve) => {
2985
- timer = setTimeout(() => resolve("expired"), DevSupervisor.readyTimeoutMs);
2686
+ timer = setTimeout(() => resolve(true), ms);
2986
2687
  });
2987
2688
  try {
2988
- if (await Promise.race([child.ready.then(() => "ready"), expired]) === "expired")
2989
- this.#note(`${child.status.name} has not reported ready after ${Math.round(DevSupervisor.readyTimeoutMs / 1000)}s; starting the next app anyway`, "warn");
2689
+ return await Promise.race([work.then(() => false), expired]);
2990
2690
  } finally {
2991
- if (timer)
2992
- clearTimeout(timer);
2691
+ clearTimeout(timer);
2993
2692
  }
2994
2693
  }
2995
2694
  static childArgs(name, { write = true } = {}) {
@@ -3111,37 +2810,19 @@ class DevSupervisor {
3111
2810
  for (const child of running)
3112
2811
  child.proc.kill("SIGTERM");
3113
2812
  const exited = Promise.all(running.map(async (child) => await child.proc.exited));
3114
- let timer = null;
3115
- const expired = new Promise((resolve) => {
3116
- timer = setTimeout(() => resolve("expired"), DevSupervisor.shutdownGraceMs);
3117
- });
3118
- try {
3119
- if (await Promise.race([exited.then(() => "exited"), expired]) === "expired") {
3120
- for (const child of running) {
3121
- if (!child.proc.killed) {
3122
- this.#note(`${child.status.name} did not exit in time; killing it`, "warn");
3123
- child.proc.kill("SIGKILL");
3124
- }
3125
- }
3126
- }
3127
- } finally {
3128
- if (timer)
3129
- clearTimeout(timer);
2813
+ if (!await DevSupervisor.timesOut(exited, DevSupervisor.shutdownGraceMs))
2814
+ return;
2815
+ for (const child of running) {
2816
+ if (child.proc.killed)
2817
+ continue;
2818
+ this.#note(`${child.status.name} did not exit in time; killing it`, "warn");
2819
+ child.proc.kill("SIGKILL");
3130
2820
  }
3131
2821
  }
3132
2822
  }
3133
2823
 
3134
- // pkgs/@akanjs/cli/application/devUiMode.ts
3135
- var resolveDevUi = (plain, { isTty = !!process.stdout.isTTY, columns = process.stdout.columns ?? 0 } = {}) => {
3136
- if (plain)
3137
- return { mode: "stream", downgraded: false };
3138
- if (!isTty || columns <= 0)
3139
- return { mode: "stream", downgraded: true };
3140
- return { mode: "tui", downgraded: false };
3141
- };
3142
-
3143
2824
  // pkgs/@akanjs/cli/application/interruptTeardown.ts
3144
- import { Logger as Logger6 } from "akanjs/common";
2825
+ import { Logger as Logger5 } from "akanjs/common";
3145
2826
 
3146
2827
  class InterruptTeardown {
3147
2828
  #teardowns = [];
@@ -3155,7 +2836,7 @@ class InterruptTeardown {
3155
2836
  this.#listen = listen ?? ((onSignal) => {
3156
2837
  process.on("SIGINT", onSignal);
3157
2838
  });
3158
- this.#report = report ?? ((message) => Logger6.rawLog(message, undefined, "error"));
2839
+ this.#report = report ?? ((message) => Logger5.rawLog(message, undefined, "error"));
3159
2840
  }
3160
2841
  add(run, abandoned) {
3161
2842
  this.#teardowns.push({ run, abandoned, running: false });
@@ -3190,10 +2871,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3190
2871
  #interrupt = new InterruptTeardown;
3191
2872
  async confirmDatabaseModeDependencyInstall(databaseMode, installSpecs) {
3192
2873
  return await confirm({
3193
- message: [
3194
- `Database mode '${databaseMode}' requires missing dependencies: ${installSpecs.join(", ")}.`,
3195
- "Install them now?"
3196
- ].join(" "),
2874
+ message: `Database mode '${databaseMode}' requires missing dependencies: ${installSpecs.join(", ")}. Install them now?`,
3197
2875
  default: true
3198
2876
  });
3199
2877
  }
@@ -3204,21 +2882,11 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3204
2882
  const shouldInstall = await this.confirmDatabaseModeDependencyInstall(databaseMode, installSpecs);
3205
2883
  if (!shouldInstall)
3206
2884
  throw new Error(`Database mode '${databaseMode}' requires missing dependencies: ${installSpecs.join(", ")}.`);
3207
- const spinner = app.workspace.spinning(`Installing database dependencies for ${databaseMode} mode...`);
3208
- try {
3209
- await app.workspace.spawn("bun", ["add", ...installSpecs], {
3210
- stdio: "inherit"
3211
- });
3212
- await app.workspace.getPackageJson({ refresh: true });
3213
- spinner.succeed(`Installed database dependencies for ${databaseMode} mode`);
3214
- } catch (error) {
3215
- spinner.fail(`Failed to install database dependencies for ${databaseMode} mode`);
3216
- throw error;
3217
- }
2885
+ await this.#addDependencies(app, installSpecs, `database dependencies for ${databaseMode} mode`);
3218
2886
  }
3219
2887
  async confirmMobileDependencyInstall(installSpecs) {
3220
2888
  return await confirm({
3221
- message: [`Mobile builds require missing dependencies: ${installSpecs.join(", ")}.`, "Install them now?"].join(" "),
2889
+ message: `Mobile builds require missing dependencies: ${installSpecs.join(", ")}. Install them now?`,
3222
2890
  default: true
3223
2891
  });
3224
2892
  }
@@ -3229,15 +2897,16 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3229
2897
  const shouldInstall = await this.confirmMobileDependencyInstall(installSpecs);
3230
2898
  if (!shouldInstall)
3231
2899
  throw new Error(`Mobile builds require missing dependencies: ${installSpecs.join(", ")}.`);
3232
- const spinner = app.workspace.spinning("Installing mobile dependencies...");
2900
+ await this.#addDependencies(app, installSpecs, "mobile dependencies");
2901
+ }
2902
+ async#addDependencies(app, installSpecs, what) {
2903
+ const spinner = app.workspace.spinning(`Installing ${what}...`);
3233
2904
  try {
3234
- await app.workspace.spawn("bun", ["add", ...installSpecs], {
3235
- stdio: "inherit"
3236
- });
2905
+ await app.workspace.spawn("bun", ["add", ...installSpecs], { stdio: "inherit" });
3237
2906
  await app.workspace.getPackageJson({ refresh: true });
3238
- spinner.succeed("Installed mobile dependencies");
2907
+ spinner.succeed(`Installed ${what}`);
3239
2908
  } catch (error) {
3240
- spinner.fail("Failed to install mobile dependencies");
2909
+ spinner.fail(`Failed to install ${what}`);
3241
2910
  throw error;
3242
2911
  }
3243
2912
  }
@@ -3279,7 +2948,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3279
2948
  const spinner = app.spinning("Planning distributable slice...");
3280
2949
  const plan = await this.applicationRunner.planSlice(app);
3281
2950
  spinner.succeed(`Slice planned (${plan.libs.length} libs, ${plan.warnings.length} warnings)`);
3282
- Logger7.rawLog(format === "json" ? JSON.stringify(plan, null, 2) : formatSlicePlan(plan));
2951
+ Logger6.rawLog(format === "json" ? JSON.stringify(plan, null, 2) : formatSlicePlan(plan));
3283
2952
  }
3284
2953
  async sync(sys) {
3285
2954
  if (sys.type === "app")
@@ -3302,18 +2971,15 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3302
2971
  async build(app, { write = true, fast = false, quiet = false } = {}) {
3303
2972
  await app.scanSync({ write });
3304
2973
  if (!quiet)
3305
- Logger7.rawLog(`Creating an optimized production build for ${app.name}...`);
2974
+ Logger6.rawLog(`Creating an optimized production build for ${app.name}...`);
3306
2975
  try {
3307
- const result = await this.applicationRunner.build(app, {
3308
- fast,
3309
- spinner: !quiet
3310
- });
3311
- Logger7.rawLog(`${app.name} built in dist/apps/${app.name}`);
2976
+ const result = await this.applicationRunner.build(app, { fast, spinner: !quiet });
2977
+ Logger6.rawLog(`${app.name} built in dist/apps/${app.name}`);
3312
2978
  if (!quiet)
3313
2979
  ApplicationBuildReporter.printSummary(result);
3314
2980
  } catch (error) {
3315
- Logger7.rawLog(`${app.name} build failed in dist/apps/${app.name}`, undefined, "error");
3316
- Logger7.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
2981
+ Logger6.rawLog(`${app.name} build failed in dist/apps/${app.name}`, undefined, "error");
2982
+ Logger6.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
3317
2983
  throw error;
3318
2984
  }
3319
2985
  }
@@ -3325,15 +2991,14 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3325
2991
  spinner.succeed(`${app.name} typechecked`);
3326
2992
  } catch (error) {
3327
2993
  spinner.fail(`${app.name} typecheck failed`);
3328
- Logger7.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
2994
+ Logger6.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
3329
2995
  throw error;
3330
2996
  }
3331
2997
  }
3332
2998
  async test(exec, { write = true } = {}) {
3333
2999
  if (exec instanceof LibExecutor) {
3334
3000
  await this.libraryScript.syncLibrary(exec);
3335
- const spinner = exec.spinning(`Preparing ${exec.name}...`);
3336
- spinner.succeed(`${exec.name} prepared`);
3001
+ exec.spinning(`Preparing ${exec.name}...`).succeed(`${exec.name} prepared`);
3337
3002
  await this.applicationRunner.test(exec);
3338
3003
  return;
3339
3004
  }
@@ -3362,7 +3027,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3362
3027
  const first = apps[0];
3363
3028
  if (!first)
3364
3029
  throw new Error("No app selected to start");
3365
- const { mode, downgraded } = resolveDevUi(plain);
3030
+ const { mode, downgraded } = DevSupervisor.resolveDevUi(plain);
3366
3031
  if (downgraded)
3367
3032
  first.workspace.log("no sized terminal to draw on; printing prefixed lines instead");
3368
3033
  if (kill)
@@ -3384,15 +3049,12 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3384
3049
  this.#stopDatabaseOnInterrupt(app.workspace);
3385
3050
  }
3386
3051
  const spinner = app.spinning("Preparing backend...");
3387
- const akanAppHost = await this.applicationRunner.start(app, {
3052
+ return await this.applicationRunner.start(app, {
3388
3053
  open,
3389
- onStart: () => {
3390
- spinner.succeed(`${app.name} prepared, ready to start`);
3391
- },
3054
+ onStart: () => spinner.succeed(`${app.name} prepared, ready to start`),
3392
3055
  onDevEvent,
3393
3056
  stdio
3394
3057
  });
3395
- return akanAppHost;
3396
3058
  }
3397
3059
  async reclaimDevPorts(apps) {
3398
3060
  const workspace = apps[0]?.workspace;
@@ -3403,7 +3065,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3403
3065
  for (const holder of killed)
3404
3066
  workspace.log(`freed port ${holder.port} \u2014 killed pid ${holder.pid} (${holder.command})`);
3405
3067
  for (const holder of foreign)
3406
- Logger7.rawLog(`port ${holder.port} is held by pid ${holder.pid} and was left alone: ${holder.command}`, undefined, "error");
3068
+ Logger6.rawLog(`port ${holder.port} is held by pid ${holder.pid} and was left alone: ${holder.command}`, undefined, "error");
3407
3069
  if (killed.length === 0 && foreign.length === 0)
3408
3070
  workspace.log("dev ports are free; nothing to kill");
3409
3071
  }
@@ -3420,7 +3082,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3420
3082
  throw new Error("No app selected to start");
3421
3083
  const startedDatabase = dbup ? await this.#prepareSharedDatabase(apps) : false;
3422
3084
  const supervisor = new DevSupervisor({ apps, mode, concurrency, open, write, shares });
3423
- const view = mode === "tui" ? await (await import("./devTuiView-1q1mdgrv.js")).createDevTuiView(supervisor) : new DevStreamView(apps.map((app) => app.name));
3085
+ const view = mode === "tui" ? new (await import("./devTui-q7k7bakd.js")).DevTui(supervisor) : new DevStreamView(apps.map((app) => app.name));
3424
3086
  await supervisor.run(view);
3425
3087
  if (startedDatabase)
3426
3088
  await this.#stopDatabase(workspace);
@@ -3495,23 +3157,13 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3495
3157
  const akanConfig = await app.getConfig();
3496
3158
  await this.syncMobileDependencies(app, akanConfig);
3497
3159
  await this.syncMobileAppCapacitorPlugins(app, akanConfig);
3498
- await this.applicationRunner.startAndroid(app, {
3499
- open,
3500
- operation,
3501
- env,
3502
- target,
3503
- regenerate
3504
- });
3160
+ await this.applicationRunner.startAndroid(app, { open, operation, env, target, regenerate });
3505
3161
  }
3506
3162
  async releaseAndroid(app, assembleType, { write = true, target, env = "main", regenerate = false, allowLocalRelease = false } = {}) {
3507
3163
  await app.scanSync({ write });
3508
3164
  if (env === "local" && !allowLocalRelease)
3509
3165
  throw new Error("releaseAndroid --env local is blocked. Pass allowLocalRelease only for explicit local release testing.");
3510
- await this.applicationRunner.releaseAndroid(app, assembleType, {
3511
- target,
3512
- env,
3513
- regenerate
3514
- });
3166
+ await this.applicationRunner.releaseAndroid(app, assembleType, { target, env, regenerate });
3515
3167
  }
3516
3168
  async configureApp(app) {
3517
3169
  await this.applicationRunner.configureApp(app);
@@ -3519,8 +3171,8 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3519
3171
  async releaseSource(app, options) {
3520
3172
  await this.applicationRunner.releaseSource(app, options);
3521
3173
  }
3522
- async codepush(app, os) {
3523
- await this.applicationRunner.codepush(app, os);
3174
+ async codepush(app) {
3175
+ await this.applicationRunner.codepush(app);
3524
3176
  }
3525
3177
  async transferDatabase(app, direction, dir) {
3526
3178
  await this.applicationRunner.transferDatabase(app, direction, dir);
@@ -3558,13 +3210,13 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3558
3210
  await Promise.all(shares.map(async (share) => await share.close()));
3559
3211
  }, "Abandoning the tunnel release; the shares expire on their own.");
3560
3212
  await Promise.all(apps.map(async (app) => {
3561
- const { TunnelShare } = await import("./TunnelShare-2j6s511d.js");
3213
+ const { TunnelShare } = await import("./TunnelShare-scf4e4pd.js");
3562
3214
  const share = await TunnelShare.open(app, { workspace: app.workspace });
3563
3215
  shares.push(share);
3564
3216
  urls.set(app.name, share.url);
3565
- Logger7.rawLog(`${app.name} is shared at ${share.url}`);
3217
+ Logger6.rawLog(`${app.name} is shared at ${share.url}`);
3566
3218
  })).catch((error) => {
3567
- Logger7.rawLog(`Could not open the tunnel: ${error instanceof Error ? error.message : String(error)}`, undefined, "error");
3219
+ Logger6.rawLog(`Could not open the tunnel: ${error instanceof Error ? error.message : String(error)}`, undefined, "error");
3568
3220
  });
3569
3221
  return urls;
3570
3222
  }
@@ -3574,21 +3226,12 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
3574
3226
  }, "Abandoning the local database teardown; containers are left running.");
3575
3227
  }
3576
3228
  async#stopDatabase(workspace) {
3577
- let timer = null;
3578
- const timeout = new Promise((resolve) => {
3579
- timer = setTimeout(() => resolve("timeout"), ApplicationScript.dbShutdownTimeoutMs);
3229
+ const stopped = this.dbdown(workspace).catch(() => {
3230
+ return;
3580
3231
  });
3581
- try {
3582
- const result = await Promise.race([this.dbdown(workspace).catch(() => {
3583
- return;
3584
- }), timeout]);
3585
- if (result !== "timeout")
3586
- return;
3587
- Logger7.rawLog(`Local database did not stop within ${ApplicationScript.dbShutdownTimeoutMs}ms; run \`akan dbdown\` once Docker responds.`, undefined, "error");
3588
- } finally {
3589
- if (timer)
3590
- clearTimeout(timer);
3591
- }
3232
+ if (!await DevSupervisor.timesOut(stopped, ApplicationScript.dbShutdownTimeoutMs))
3233
+ return;
3234
+ Logger6.rawLog(`Local database did not stop within ${ApplicationScript.dbShutdownTimeoutMs}ms; run \`akan dbdown\` once Docker responds.`, undefined, "error");
3592
3235
  }
3593
3236
  }
3594
3237