@akanjs/cli 2.4.1-rc.3 → 2.4.1-rc.4

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 (44) hide show
  1. package/.build-stamp +1 -0
  2. package/{agent.command-h4afc69n.js → agent.command-t4346579.js} +6 -6
  3. package/{application.command-jkmbsd1x.js → application.command-zkmeemdt.js} +5 -4
  4. package/{applicationBuildRunner-ny84tjhc.js → applicationBuildRunner-5w8j9yp7.js} +2 -1
  5. package/buildBatch.proc.js +3 -2
  6. package/{capacitorApp-y0h6cgft.js → capacitorApp-wnxzrppx.js} +2 -2
  7. package/{cloud.command-53j76grx.js → cloud.command-5ztqxppm.js} +8 -7
  8. package/{context.command-ds3mka9p.js → context.command-smwxwgwf.js} +13 -13
  9. package/{guideline.command-ya0dh44f.js → guideline.command-1r0esdjs.js} +3 -3
  10. package/incrementalBuilder.proc.js +36 -13
  11. package/index-0fn1r7gg.js +466 -0
  12. package/{index-1fpjvqhs.js → index-0jwvs8vp.js} +11 -11
  13. package/{index-a6sbyy0b.js → index-0t7pwff2.js} +3 -0
  14. package/{index-h6ca6qg0.js → index-2v10yr8g.js} +1 -1
  15. package/{index-m9pca6jv.js → index-2v6a4wd5.js} +4 -4
  16. package/{index-45aj5ry0.js → index-3sd2vape.js} +3 -3
  17. package/{index-gb26e7z0.js → index-ahpcr9ss.js} +3 -3
  18. package/{index-8rc0bm04.js → index-eay4t1te.js} +2 -2
  19. package/{index-qaq13qk3.js → index-eqxmxan6.js} +1 -1
  20. package/{index-pmm9e2jf.js → index-fh990y67.js} +2 -2
  21. package/{index-dynknvzd.js → index-gr4cjv99.js} +3 -3
  22. package/{index-1xdrsbry.js → index-hk58kr1m.js} +1 -1
  23. package/{index-85msc0wg.js → index-jbtn8h1y.js} +3 -3
  24. package/{index-q7zcac6n.js → index-khzzttv1.js} +108 -191
  25. package/{index-rgfxj6qc.js → index-n5y2gbf2.js} +307 -15
  26. package/{index-n6h3482q.js → index-nv7et4t3.js} +2 -2
  27. package/{index-hwzpw9c1.js → index-pya1h7wx.js} +3 -3
  28. package/{index-hdqztm58.js → index-qpz4csbs.js} +1 -1
  29. package/{index-0hjg9qs5.js → index-s9yajzkj.js} +5 -5
  30. package/{index-fmky5k3p.js → index-wh201a76.js} +5 -5
  31. package/{index-swf4bmbg.js → index-y4kg682s.js} +1 -1
  32. package/index.js +18 -18
  33. package/{library.command-r15zdqvp.js → library.command-jrew04m6.js} +3 -3
  34. package/{localRegistry.command-25sv5hmt.js → localRegistry.command-m08dkm1b.js} +7 -6
  35. package/{module.command-tnj2bzst.js → module.command-p98t7522.js} +6 -6
  36. package/{package.command-5x5m0ej1.js → package.command-57dyrfmn.js} +3 -3
  37. package/package.json +2 -2
  38. package/{page.command-c6xdx0xm.js → page.command-tas6f3na.js} +3 -3
  39. package/{primitive.command-q1ycj5vr.js → primitive.command-bjrbsakw.js} +7 -7
  40. package/{quality.command-es67wvdp.js → quality.command-zavaafbw.js} +2 -2
  41. package/{repair.command-677675vw.js → repair.command-je57wx67.js} +5 -5
  42. package/{scalar.command-bmrmp8n4.js → scalar.command-gqqyy1kr.js} +5 -5
  43. package/{workflow.command-64550hka.js → workflow.command-d6mrc47s.js} +10 -10
  44. package/{workspace.command-pmfxxfew.js → workspace.command-bbg96z8k.js} +20 -19
@@ -0,0 +1,466 @@
1
+ // @bun
2
+ // pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
3
+ import fs from "fs";
4
+ import path3 from "path";
5
+
6
+ // pkgs/@akanjs/devkit/frontendBuild/hmrChangeClassifier.ts
7
+ import path from "path";
8
+ var SOURCE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
9
+ var CSS_EXTS = new Set([".css"]);
10
+ var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
11
+
12
+ class HmrChangeClassifier {
13
+ classify(abs) {
14
+ if (this.#isUninteresting(abs))
15
+ return "ignore";
16
+ const base = path.basename(abs);
17
+ if (CONFIG_BASENAMES.has(base))
18
+ return "config";
19
+ const ext = path.extname(abs).toLowerCase();
20
+ if (CSS_EXTS.has(ext))
21
+ return "css";
22
+ if (SOURCE_EXTS.has(ext))
23
+ return "code";
24
+ return "ignore";
25
+ }
26
+ #isUninteresting(abs) {
27
+ const base = path.basename(abs);
28
+ if (!base)
29
+ return true;
30
+ if (base.startsWith("."))
31
+ return true;
32
+ if (base.endsWith("~") || base.endsWith(".swp") || base.endsWith(".swx") || base.endsWith(".tmp"))
33
+ return true;
34
+ if (abs.includes(`${path.sep}node_modules${path.sep}`))
35
+ return true;
36
+ if (abs.includes(`${path.sep}.akan${path.sep}`))
37
+ return true;
38
+ return false;
39
+ }
40
+ }
41
+
42
+ // pkgs/@akanjs/devkit/frontendBuild/sourceMtimeIndex.ts
43
+ import { readdir, stat } from "fs/promises";
44
+ import path2 from "path";
45
+ var UNREADABLE = Number.NaN;
46
+
47
+ class SourceMtimeIndex {
48
+ #roots;
49
+ #classifier;
50
+ #files = new Map;
51
+ #dirs = new Map;
52
+ #unreadable = new Map;
53
+ #primed = false;
54
+ #queue = Promise.resolve();
55
+ constructor({ roots, classifier }) {
56
+ this.#roots = SourceMtimeIndex.#pruneNestedRoots(roots);
57
+ this.#classifier = classifier ?? new HmrChangeClassifier;
58
+ }
59
+ get primed() {
60
+ return this.#primed;
61
+ }
62
+ get trackedFileCount() {
63
+ return this.#files.size;
64
+ }
65
+ get coverageGaps() {
66
+ return [...this.#unreadable].map(([file, code]) => ({ path: file, code }));
67
+ }
68
+ async prime() {
69
+ await this.#serialize(async () => {
70
+ this.#files.clear();
71
+ this.#dirs.clear();
72
+ this.#unreadable.clear();
73
+ await Promise.all(this.#roots.map((root) => this.#walk(root, null)));
74
+ this.#primed = true;
75
+ });
76
+ }
77
+ async collectChanges() {
78
+ return this.#serialize(async () => {
79
+ if (!this.#primed)
80
+ return [];
81
+ const changed = new Set;
82
+ await this.#collectFileChanges(changed);
83
+ await this.#collectDirChanges(changed);
84
+ return [...changed];
85
+ });
86
+ }
87
+ async#serialize(work) {
88
+ const run = this.#queue.then(work, work);
89
+ this.#queue = run.catch(() => {
90
+ return;
91
+ });
92
+ return run;
93
+ }
94
+ async absorb(paths) {
95
+ await this.#serialize(async () => {
96
+ if (!this.#primed)
97
+ return;
98
+ await Promise.all(paths.map(async (file) => {
99
+ const abs = path2.resolve(file);
100
+ const stats = await stat(abs).catch(() => null);
101
+ if (!stats?.isFile()) {
102
+ this.#files.delete(abs);
103
+ return;
104
+ }
105
+ this.#files.set(abs, { mtimeMs: stats.mtimeMs, size: stats.size });
106
+ }));
107
+ });
108
+ }
109
+ async#collectFileChanges(changed) {
110
+ await Promise.all([...this.#files.keys()].map(async (abs) => {
111
+ const { stats, err } = await SourceMtimeIndex.#statPath(abs);
112
+ if (!stats) {
113
+ if (err && !SourceMtimeIndex.#isMissing(err)) {
114
+ this.#unreadable.set(abs, err.code ?? "EUNKNOWN");
115
+ return;
116
+ }
117
+ this.#files.delete(abs);
118
+ this.#unreadable.delete(abs);
119
+ changed.add(abs);
120
+ return;
121
+ }
122
+ this.#unreadable.delete(abs);
123
+ if (!stats.isFile()) {
124
+ this.#files.delete(abs);
125
+ changed.add(abs);
126
+ return;
127
+ }
128
+ const known = this.#files.get(abs);
129
+ if (known && known.mtimeMs === stats.mtimeMs && known.size === stats.size)
130
+ return;
131
+ this.#files.set(abs, { mtimeMs: stats.mtimeMs, size: stats.size });
132
+ changed.add(abs);
133
+ }));
134
+ }
135
+ async#collectDirChanges(changed) {
136
+ const moved = [];
137
+ const gone = [];
138
+ await Promise.all([...this.#dirs.entries()].map(async ([dir, mtimeMs]) => {
139
+ const { stats, err } = await SourceMtimeIndex.#statPath(dir);
140
+ if (!stats?.isDirectory()) {
141
+ if (err && !SourceMtimeIndex.#isMissing(err)) {
142
+ this.#markUnreadable(dir, err);
143
+ return;
144
+ }
145
+ gone.push(dir);
146
+ return;
147
+ }
148
+ if (stats.mtimeMs !== mtimeMs)
149
+ moved.push(dir);
150
+ }));
151
+ for (const dir of gone)
152
+ this.#forget(dir);
153
+ for (const dir of moved)
154
+ await this.#walk(dir, changed);
155
+ }
156
+ async#walk(dir, changed) {
157
+ const [listing, dirStat] = await Promise.all([SourceMtimeIndex.#readdirPath(dir), SourceMtimeIndex.#statPath(dir)]);
158
+ const entries = listing.entries;
159
+ const dirStats = dirStat.stats;
160
+ if (!entries || !dirStats?.isDirectory()) {
161
+ const err = listing.err ?? dirStat.err;
162
+ if (err && !SourceMtimeIndex.#isMissing(err)) {
163
+ this.#markUnreadable(dir, err);
164
+ return;
165
+ }
166
+ this.#forget(dir);
167
+ return;
168
+ }
169
+ const known = this.#dirs.has(dir);
170
+ this.#dirs.set(dir, dirStats.mtimeMs);
171
+ this.#unreadable.delete(dir);
172
+ const descend = [];
173
+ const present = new Set;
174
+ let blind = false;
175
+ for (const entry of entries) {
176
+ if (SourceMtimeIndex.#skipDirent(entry.name))
177
+ continue;
178
+ const abs = path2.join(dir, entry.name);
179
+ if (entry.isDirectory()) {
180
+ descend.push(abs);
181
+ continue;
182
+ }
183
+ if (!entry.isFile())
184
+ continue;
185
+ if (this.#classifier.classify(abs) === "ignore")
186
+ continue;
187
+ present.add(abs);
188
+ const { stats, err } = await SourceMtimeIndex.#statPath(abs);
189
+ if (!stats?.isFile()) {
190
+ if (err && !SourceMtimeIndex.#isMissing(err)) {
191
+ this.#unreadable.set(abs, err.code ?? "EUNKNOWN");
192
+ blind = true;
193
+ }
194
+ continue;
195
+ }
196
+ this.#unreadable.delete(abs);
197
+ const previous = this.#files.get(abs);
198
+ if (previous && previous.mtimeMs === stats.mtimeMs && previous.size === stats.size)
199
+ continue;
200
+ this.#files.set(abs, { mtimeMs: stats.mtimeMs, size: stats.size });
201
+ changed?.add(abs);
202
+ }
203
+ if (known) {
204
+ for (const abs of [...this.#files.keys()]) {
205
+ if (present.has(abs) || path2.dirname(abs) !== dir)
206
+ continue;
207
+ this.#files.delete(abs);
208
+ changed?.add(abs);
209
+ }
210
+ }
211
+ if (blind)
212
+ this.#dirs.set(dir, UNREADABLE);
213
+ await Promise.all(descend.filter((sub) => !this.#dirs.has(sub)).map((sub) => this.#walk(sub, changed)));
214
+ }
215
+ #markUnreadable(dir, err) {
216
+ this.#dirs.set(dir, UNREADABLE);
217
+ this.#unreadable.set(dir, err.code ?? "EUNKNOWN");
218
+ }
219
+ #forget(dir) {
220
+ const prefix = `${dir}${path2.sep}`;
221
+ this.#dirs.delete(dir);
222
+ this.#unreadable.delete(dir);
223
+ for (const known of [...this.#dirs.keys()])
224
+ if (known.startsWith(prefix))
225
+ this.#dirs.delete(known);
226
+ for (const known of [...this.#unreadable.keys()])
227
+ if (known.startsWith(prefix))
228
+ this.#unreadable.delete(known);
229
+ }
230
+ static async#statPath(abs) {
231
+ try {
232
+ return { stats: await stat(abs), err: null };
233
+ } catch (err) {
234
+ return { stats: null, err };
235
+ }
236
+ }
237
+ static async#readdirPath(dir) {
238
+ try {
239
+ return { entries: await readdir(dir, { withFileTypes: true }), err: null };
240
+ } catch (err) {
241
+ return { entries: null, err };
242
+ }
243
+ }
244
+ static #isMissing(err) {
245
+ return err.code === "ENOENT" || err.code === "ENOTDIR";
246
+ }
247
+ static #skipDirent(name) {
248
+ return !name || name.startsWith(".") || name === "node_modules";
249
+ }
250
+ static #pruneNestedRoots(roots) {
251
+ const resolved = [...new Set(roots.map((root) => path2.resolve(root)))].sort();
252
+ return resolved.filter((root) => !resolved.some((other) => other !== root && root.startsWith(`${other}${path2.sep}`)));
253
+ }
254
+ }
255
+
256
+ // pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
257
+ class HmrWatcher {
258
+ #roots;
259
+ #debounceMs;
260
+ #verifyDelayMs;
261
+ #onBatch;
262
+ #logger;
263
+ #watchers = [];
264
+ #pending = new Map;
265
+ #hinted = new Set;
266
+ #classifier = new HmrChangeClassifier;
267
+ #index;
268
+ #timer = null;
269
+ #verifyTimer = null;
270
+ #stopped = false;
271
+ #flushing = false;
272
+ #unreportedChanges = 0;
273
+ #reportedCompensating = false;
274
+ #reportedGaps = "";
275
+ constructor(opts) {
276
+ this.#roots = [...new Set(opts.roots.map((r) => path3.resolve(r)))];
277
+ this.#debounceMs = opts.debounceMs ?? 80;
278
+ this.#verifyDelayMs = opts.verifyDelayMs ?? 250;
279
+ this.#onBatch = opts.onBatch;
280
+ this.#logger = opts.logger;
281
+ this.#index = new SourceMtimeIndex({ roots: this.#roots, classifier: this.#classifier });
282
+ }
283
+ get unreportedChanges() {
284
+ return this.#unreportedChanges;
285
+ }
286
+ async start() {
287
+ for (const root of this.#roots) {
288
+ try {
289
+ const w = fs.watch(root, { recursive: true, persistent: false }, (_event, filename) => {
290
+ if (!filename)
291
+ return;
292
+ const abs = path3.resolve(root, filename.toString());
293
+ this.#queue(abs);
294
+ });
295
+ this.#watchers.push(w);
296
+ this.#logger.verbose(`[hmr] watching ${root}`);
297
+ } catch (err) {
298
+ this.#logger.error(`[hmr] failed to watch ${root}: ${err.message}`);
299
+ }
300
+ }
301
+ try {
302
+ await this.#index.prime();
303
+ this.#reportCoverageGaps();
304
+ this.#logger.verbose(`[hmr] tracking ${this.#index.trackedFileCount} source files for change verification`);
305
+ } catch (err) {
306
+ this.#logger.error(`[hmr] mtime index unavailable; falling back to watcher events alone, which drop concurrent saves: ${err.message}`);
307
+ }
308
+ }
309
+ stop() {
310
+ this.#stopped = true;
311
+ if (this.#timer)
312
+ clearTimeout(this.#timer);
313
+ if (this.#verifyTimer)
314
+ clearTimeout(this.#verifyTimer);
315
+ for (const w of this.#watchers) {
316
+ try {
317
+ w.close();
318
+ } catch {}
319
+ }
320
+ }
321
+ async absorb(paths) {
322
+ if (paths.length === 0)
323
+ return;
324
+ await this.#index.absorb(paths);
325
+ }
326
+ #queue(abs) {
327
+ const kind = this.#classifier.classify(abs);
328
+ if (!this.#index.primed) {
329
+ if (kind === "ignore")
330
+ return;
331
+ this.#pending.set(abs, kind);
332
+ this.#scheduleFlush();
333
+ return;
334
+ }
335
+ if (kind === "ignore") {
336
+ this.#scheduleVerify();
337
+ return;
338
+ }
339
+ this.#hinted.add(abs);
340
+ this.#scheduleFlush();
341
+ }
342
+ #scheduleFlush() {
343
+ if (this.#flushing)
344
+ return;
345
+ if (this.#timer)
346
+ clearTimeout(this.#timer);
347
+ this.#timer = setTimeout(() => this.#flush(), this.#debounceMs);
348
+ }
349
+ #flush() {
350
+ this.#timer = null;
351
+ if (this.#stopped || this.#flushing)
352
+ return;
353
+ this.#drain();
354
+ }
355
+ async#drain() {
356
+ this.#flushing = true;
357
+ try {
358
+ while (!this.#stopped) {
359
+ await this.#mergeDetectedChanges();
360
+ if (this.#pending.size === 0)
361
+ break;
362
+ const files = Array.from(this.#pending.keys());
363
+ const kinds = new Set(this.#pending.values());
364
+ this.#pending.clear();
365
+ this.#hinted.clear();
366
+ try {
367
+ await this.#onBatch({ files, kinds });
368
+ } catch (e) {
369
+ this.#logger.error(`[hmr] onBatch error: ${e.message}`);
370
+ }
371
+ }
372
+ } finally {
373
+ this.#flushing = false;
374
+ if (!this.#stopped && this.#pending.size > 0)
375
+ this.#timer = setTimeout(() => this.#flush(), this.#debounceMs);
376
+ else
377
+ this.#scheduleVerify();
378
+ }
379
+ }
380
+ async#mergeDetectedChanges() {
381
+ const detected = await this.#index.collectChanges().catch((err) => {
382
+ this.#logger.error(`[hmr] mtime scan failed: ${err.message}`);
383
+ return [];
384
+ });
385
+ this.#reportCoverageGaps();
386
+ let unreported = 0;
387
+ for (const abs of detected) {
388
+ const kind = this.#classifier.classify(abs);
389
+ if (kind === "ignore")
390
+ continue;
391
+ if (!this.#hinted.has(abs))
392
+ unreported += 1;
393
+ this.#pending.set(abs, kind);
394
+ }
395
+ if (unreported === 0)
396
+ return;
397
+ this.#unreportedChanges += unreported;
398
+ if (!this.#reportedCompensating) {
399
+ this.#reportedCompensating = true;
400
+ this.#logger.info(`[hmr] recovered ${unreported} change(s) that fs.watch did not report; Bun coalesces concurrent saves and drops all but one, so changes are resolved by mtime`);
401
+ }
402
+ this.#logger.verbose(`[hmr] mtime scan found ${unreported} change(s) fs.watch never reported (${this.#unreportedChanges} total)`);
403
+ }
404
+ #reportCoverageGaps() {
405
+ const gaps = this.#index.coverageGaps;
406
+ const key = gaps.map((gap) => `${gap.code}:${gap.path}`).sort().join("|");
407
+ if (key === this.#reportedGaps)
408
+ return;
409
+ this.#reportedGaps = key;
410
+ if (gaps.length === 0) {
411
+ this.#logger.info("[hmr] all watch roots readable again; change detection is complete");
412
+ return;
413
+ }
414
+ const shown = gaps.slice(0, 3).map((gap) => `${gap.path} (${gap.code})`).join(", ");
415
+ const rest = gaps.length > 3 ? ` and ${gaps.length - 3} more` : "";
416
+ this.#logger.warn(`[hmr] cannot read ${gaps.length} path(s), so edits underneath them will not rebuild: ${shown}${rest}`);
417
+ }
418
+ #scheduleVerify() {
419
+ if (this.#stopped || this.#verifyDelayMs <= 0)
420
+ return;
421
+ if (this.#verifyTimer)
422
+ clearTimeout(this.#verifyTimer);
423
+ this.#verifyTimer = setTimeout(() => {
424
+ this.#verifyTimer = null;
425
+ this.#verify();
426
+ }, this.#verifyDelayMs);
427
+ }
428
+ async#verify() {
429
+ if (this.#stopped || this.#flushing)
430
+ return;
431
+ await this.#mergeDetectedChanges();
432
+ if (this.#pending.size > 0)
433
+ await this.#drain();
434
+ }
435
+ }
436
+
437
+ // pkgs/@akanjs/devkit/frontendBuild/watchRootResolver.ts
438
+ import fs2 from "fs";
439
+ import path4 from "path";
440
+
441
+ class WatchRootResolver {
442
+ #app;
443
+ constructor(app) {
444
+ this.#app = app;
445
+ }
446
+ async resolve() {
447
+ const tsconfig = await this.#app.getTsConfig();
448
+ const set = new Set;
449
+ set.add(path4.resolve(`${this.#app.cwdPath}/page`));
450
+ for (const targets of Object.values(tsconfig.compilerOptions.paths ?? {})) {
451
+ for (const target of targets) {
452
+ if (!target)
453
+ continue;
454
+ if (path4.isAbsolute(target))
455
+ continue;
456
+ const cleaned = target.replace(/\/?\*+.*$/, "").replace(/\/[^/]+\.[^/]+$/, "");
457
+ const resolved = path4.resolve(this.#app.workspace.workspaceRoot, cleaned);
458
+ if (fs2.existsSync(resolved))
459
+ set.add(resolved);
460
+ }
461
+ }
462
+ return [...set];
463
+ }
464
+ }
465
+
466
+ export { HmrWatcher, WatchRootResolver };
@@ -1,22 +1,22 @@
1
1
  // @bun
2
2
  import {
3
3
  RepairRunner
4
- } from "./index-85msc0wg.js";
4
+ } from "./index-jbtn8h1y.js";
5
5
  import {
6
6
  WorkflowRunner
7
- } from "./index-45aj5ry0.js";
7
+ } from "./index-3sd2vape.js";
8
8
  import {
9
9
  ScalarScript
10
- } from "./index-gb26e7z0.js";
10
+ } from "./index-ahpcr9ss.js";
11
11
  import {
12
12
  PrimitiveScript
13
- } from "./index-m9pca6jv.js";
13
+ } from "./index-2v6a4wd5.js";
14
14
  import {
15
15
  ModuleScript
16
- } from "./index-fmky5k3p.js";
16
+ } from "./index-wh201a76.js";
17
17
  import {
18
18
  isPlaceholderAppId
19
- } from "./index-1xdrsbry.js";
19
+ } from "./index-hk58kr1m.js";
20
20
  import {
21
21
  AkanContextAnalyzer,
22
22
  akanMcpInstallConfigPaths,
@@ -27,17 +27,17 @@ import {
27
27
  renderDoctorText,
28
28
  resourceList,
29
29
  upsertCodexMcpServerBlock
30
- } from "./index-8rc0bm04.js";
30
+ } from "./index-eay4t1te.js";
31
31
  import {
32
32
  buildAkanModuleContextIndex,
33
33
  createWorkflowBaselineSummary,
34
34
  createWorkflowStepRegistry,
35
35
  jsonText,
36
36
  toolingRolloutGate
37
- } from "./index-h6ca6qg0.js";
37
+ } from "./index-2v10yr8g.js";
38
38
  import {
39
39
  Prompter
40
- } from "./index-qaq13qk3.js";
40
+ } from "./index-eqxmxan6.js";
41
41
  import {
42
42
  getMobileTargets
43
43
  } from "./index-76rn3g2c.js";
@@ -45,10 +45,10 @@ import {
45
45
  CommandContainer,
46
46
  runner,
47
47
  script
48
- } from "./index-hdqztm58.js";
48
+ } from "./index-qpz4csbs.js";
49
49
  import {
50
50
  AppExecutor
51
- } from "./index-a6sbyy0b.js";
51
+ } from "./index-0t7pwff2.js";
52
52
 
53
53
  // pkgs/@akanjs/cli/context/context.script.ts
54
54
  import { Logger } from "akanjs/common";
@@ -2369,6 +2369,9 @@ class AppExecutor extends SysExecutor {
2369
2369
  return WorkspaceExecutor.getBaseDevEnv().env;
2370
2370
  }
2371
2371
  async getDevPort() {
2372
+ const pinned = Number(process.env.AKAN_DEV_PORT);
2373
+ if (Number.isInteger(pinned) && pinned > 0 && pinned <= 65535)
2374
+ return pinned;
2372
2375
  const basePort = 8282;
2373
2376
  const appNames = (await this.workspace.getApps()).sort((a, b) => a.localeCompare(b));
2374
2377
  const appIndex = Math.max(appNames.indexOf(this.name), 0);
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  AppExecutor,
4
4
  LibExecutor
5
- } from "./index-a6sbyy0b.js";
5
+ } from "./index-0t7pwff2.js";
6
6
 
7
7
  // pkgs/@akanjs/devkit/workflow/utils.ts
8
8
  var jsonText = (value, { trailingNewline = true } = {}) => `${JSON.stringify(value, null, 2)}${trailingNewline ? `
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  ModuleScript
4
- } from "./index-fmky5k3p.js";
4
+ } from "./index-wh201a76.js";
5
5
  import {
6
6
  addFieldUiPolicyForType,
7
7
  coerceFieldDefault,
@@ -34,15 +34,15 @@ import {
34
34
  sourceFile,
35
35
  validationCommandsForTarget,
36
36
  viaBuilderParameterName
37
- } from "./index-h6ca6qg0.js";
37
+ } from "./index-2v10yr8g.js";
38
38
  import {
39
39
  script
40
- } from "./index-hdqztm58.js";
40
+ } from "./index-qpz4csbs.js";
41
41
  import {
42
42
  AppExecutor,
43
43
  LibExecutor,
44
44
  ModuleExecutor
45
- } from "./index-a6sbyy0b.js";
45
+ } from "./index-0t7pwff2.js";
46
46
 
47
47
  // pkgs/@akanjs/cli/primitive/primitive.script.ts
48
48
  import { capitalize } from "akanjs/common";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  AkanContextAnalyzer
4
- } from "./index-8rc0bm04.js";
4
+ } from "./index-eay4t1te.js";
5
5
  import {
6
6
  WorkflowExecutor,
7
7
  compactWorkflowInputs,
@@ -23,10 +23,10 @@ import {
23
23
  workflowCommandsForPlan,
24
24
  workflowPlanApproval,
25
25
  writeWorkflowRunArtifact
26
- } from "./index-h6ca6qg0.js";
26
+ } from "./index-2v10yr8g.js";
27
27
  import {
28
28
  runner
29
- } from "./index-hdqztm58.js";
29
+ } from "./index-qpz4csbs.js";
30
30
 
31
31
  // pkgs/@akanjs/cli/workflow/workflow.runner.ts
32
32
  import { mkdir, readFile, writeFile } from "fs/promises";
@@ -6,17 +6,17 @@ import {
6
6
  createPassedPrimitiveReport,
7
7
  generatedFilesForSync,
8
8
  scalarChangedFiles
9
- } from "./index-h6ca6qg0.js";
9
+ } from "./index-2v10yr8g.js";
10
10
  import {
11
11
  Prompter
12
- } from "./index-qaq13qk3.js";
12
+ } from "./index-eqxmxan6.js";
13
13
  import {
14
14
  AiSession
15
15
  } from "./index-5vvwc0cz.js";
16
16
  import {
17
17
  runner,
18
18
  script
19
- } from "./index-hdqztm58.js";
19
+ } from "./index-qpz4csbs.js";
20
20
 
21
21
  // pkgs/@akanjs/cli/scalar/scalar.prompt.ts
22
22
  import { input } from "@inquirer/prompts";
@@ -2,11 +2,11 @@
2
2
  import {
3
3
  workflowRunArtifactPath,
4
4
  workflowSyncDir
5
- } from "./index-h6ca6qg0.js";
5
+ } from "./index-2v10yr8g.js";
6
6
  import {
7
7
  AppExecutor,
8
8
  LibExecutor
9
- } from "./index-a6sbyy0b.js";
9
+ } from "./index-0t7pwff2.js";
10
10
  import {
11
11
  FileSys
12
12
  } from "./index-61keag0s.js";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  getDirname
4
- } from "./index-a6sbyy0b.js";
4
+ } from "./index-0t7pwff2.js";
5
5
 
6
6
  // pkgs/@akanjs/devkit/prompter.ts
7
7
  import fsPromise from "fs/promises";
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-hdqztm58.js";
5
+ } from "./index-qpz4csbs.js";
6
6
  import {
7
7
  LibExecutor
8
- } from "./index-a6sbyy0b.js";
8
+ } from "./index-0t7pwff2.js";
9
9
 
10
10
  // pkgs/@akanjs/cli/semver.ts
11
11
  function parseVersion(version) {
@@ -7,14 +7,14 @@ import {
7
7
  } from "./index-5vvwc0cz.js";
8
8
  import {
9
9
  openBrowser
10
- } from "./index-rgfxj6qc.js";
10
+ } from "./index-n5y2gbf2.js";
11
11
  import {
12
12
  runner
13
- } from "./index-hdqztm58.js";
13
+ } from "./index-qpz4csbs.js";
14
14
  import {
15
15
  AppExecutor,
16
16
  WorkspaceExecutor
17
- } from "./index-a6sbyy0b.js";
17
+ } from "./index-0t7pwff2.js";
18
18
 
19
19
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
20
20
  import path from "path";
@@ -5,7 +5,7 @@ import {
5
5
  } from "./index-76rn3g2c.js";
6
6
  import {
7
7
  CommandExecutionError
8
- } from "./index-a6sbyy0b.js";
8
+ } from "./index-0t7pwff2.js";
9
9
 
10
10
  // pkgs/@akanjs/devkit/capacitorApp.ts
11
11
  import { cp, mkdir, readFile, rm, writeFile } from "fs/promises";