@akanjs/cli 3.0.1 → 3.0.2

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 (76) hide show
  1. package/.build-stamp +1 -1
  2. package/{CodeAgent-zfab7pkn.js → CodeAgent-szbjv4gv.js} +2 -2
  3. package/{CodeTui-0zhnr0pw.js → CodeTui-5nw86ab6.js} +1 -1
  4. package/{agent.command-aja6z9mn.js → agent.command-np1dffkb.js} +5 -5
  5. package/akanCode.js +2 -2
  6. package/{application.command-049ehgx3.js → application.command-gk69v1xs.js} +8 -8
  7. package/{applicationBuildRunner-75n5rpwp.js → applicationBuildRunner-wx09n9g6.js} +3 -3
  8. package/buildBatch.proc.js +4 -4
  9. package/{cloud.command-gw4kqxt8.js → cloud.command-tw06613r.js} +10 -10
  10. package/cloud.script-64gzba8r.js +20 -0
  11. package/{code.command-x9t6z5nw.js → code.command-hmtx14b2.js} +6 -6
  12. package/{context.command-yfbe1rtd.js → context.command-6aqvdx43.js} +13 -13
  13. package/context.runner-hnkvv3z3.js +21 -0
  14. package/{guideline.command-kq9gp690.js → guideline.command-axvf68gc.js} +2 -2
  15. package/guidelines/conventions/conventions.instruction.md +89 -17
  16. package/guidelines/queryRule/queryRule.instruction.md +4 -2
  17. package/guidelines/runtimeRule/runtimeRule.instruction.md +10 -5
  18. package/guidelines/transportRule/transportRule.instruction.md +40 -4
  19. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +1 -1
  20. package/incrementalBuilder.proc.js +3 -3
  21. package/{index-66yspb67.js → index-1bjkfvm9.js} +29 -27
  22. package/{index-b95yhqjr.js → index-1gs9g12n.js} +3 -3
  23. package/{index-y7hx1ygz.js → index-3xmzr1p1.js} +2 -2
  24. package/{index-mzjb6zp4.js → index-50jjwg8y.js} +1 -1
  25. package/{index-150s07n8.js → index-50wb2a26.js} +313 -93
  26. package/{index-8b639zes.js → index-6keyf4sg.js} +4 -4
  27. package/{index-vs8mefhy.js → index-bsv901fd.js} +7 -7
  28. package/{index-5pvxf7z0.js → index-cb6yc5mb.js} +2 -2
  29. package/{index-rfcz04w9.js → index-f4e08ptp.js} +4 -4
  30. package/{index-25fvrxmy.js → index-g38nhv87.js} +1 -1
  31. package/{index-m3xsb1ms.js → index-gtjgnv36.js} +29 -11
  32. package/{index-mb59b8x0.js → index-h9ht6s60.js} +1 -1
  33. package/{index-5g4rkrvt.js → index-hp3stk1m.js} +3 -3
  34. package/{index-h54yj9wr.js → index-hxnnfy57.js} +6 -5
  35. package/{index-kn5d4jmg.js → index-j38qkvkk.js} +7 -7
  36. package/{index-y5ga5w9t.js → index-jb0hmt3k.js} +3 -3
  37. package/{index-7p4c0yer.js → index-jk9xnck6.js} +33 -11
  38. package/{index-senscydg.js → index-k9rrten6.js} +6 -1
  39. package/{index-qe71g4ze.js → index-nwd6qzvv.js} +42 -23
  40. package/{index-a37by9hn.js → index-q6ft9fkc.js} +4 -4
  41. package/{index-br8pkrk1.js → index-t91a7339.js} +5 -5
  42. package/{index-c14nsvnv.js → index-xwprn9nr.js} +1 -1
  43. package/{index-fkvb79qe.js → index-z750gk1j.js} +15 -11
  44. package/{index-5q14pwzd.js → index-zwd84m0w.js} +4 -4
  45. package/{index-8kvy8qb4.js → index-zyw622y1.js} +12 -2
  46. package/index.js +21 -21
  47. package/{library.command-keqjevpp.js → library.command-9m2rdwwz.js} +3 -3
  48. package/{localRegistry.command-pydeq5zf.js → localRegistry.command-kda81jyk.js} +9 -9
  49. package/{module.command-dkrnqx3v.js → module.command-q63dffya.js} +5 -5
  50. package/{package.command-wmc0ys5y.js → package.command-y2jh0m99.js} +3 -3
  51. package/package.json +2 -2
  52. package/{page.command-tf3erhrv.js → page.command-f3e4cwhh.js} +3 -3
  53. package/{primitive.command-7hqpegj4.js → primitive.command-r4kq75qj.js} +6 -6
  54. package/{quality.command-8122axq3.js → quality.command-f7gzh26z.js} +9 -2
  55. package/{repair.command-mcy12h0n.js → repair.command-0qmyr6qa.js} +5 -5
  56. package/{scalar.command-vvvbzttc.js → scalar.command-kddn7av4.js} +4 -4
  57. package/{subspace.command-pzvqfy5h.js → subspace.command-ft65qvc4.js} +5 -7
  58. package/templates/app/tsconfig.json.template +1 -6
  59. package/templates/app/ui/Recipe/jellyButton.ts +1 -0
  60. package/templates/facetIndex/index.ts +21 -6
  61. package/templates/lib/dict.ts +9 -1
  62. package/templates/lib/srv.ts +2 -3
  63. package/templates/libRoot/common/index.ts +2 -7
  64. package/templates/libRoot/srvkit/index.ts +2 -7
  65. package/templates/libRoot/ui/index.ts +2 -7
  66. package/templates/libRoot/webkit/index.ts +2 -7
  67. package/templates/moduleRoot/index.tsx +3 -3
  68. package/{tunnel.command-82zz5xnq.js → tunnel.command-b3ymdk4f.js} +2 -2
  69. package/{workflow.command-y8x3kgjv.js → workflow.command-z1srcdfw.js} +10 -10
  70. package/{workspace.command-jvsb7brc.js → workspace.command-vp6vmx3z.js} +21 -21
  71. package/cloud.script-c723cpcb.js +0 -20
  72. package/context.runner-erfe68j5.js +0 -21
  73. package/index-bjwxs904.js +0 -77
  74. package/templates/libRoot/common/commonLogic.ts +0 -14
  75. package/templates/libRoot/srvkit/backendLogic.ts +0 -13
  76. package/templates/libRoot/webkit/frontendLogic.ts +0 -13
@@ -517,7 +517,7 @@ import {
517
517
  stat as stat2,
518
518
  symlink
519
519
  } from "fs/promises";
520
- import path9 from "path";
520
+ import path10 from "path";
521
521
  import { pathToFileURL } from "url";
522
522
  import {
523
523
  capitalize,
@@ -1044,8 +1044,9 @@ class AkanAppConfig {
1044
1044
  "activity",
1045
1045
  "files"
1046
1046
  ],
1047
- desktop: ["indexPath", "server", "recovery", "window", "screenCapture", "entitlements"],
1047
+ desktop: ["indexPath", "server", "recovery", "window", "screenCapture", "entitlements", "dmg"],
1048
1048
  desktopServer: ["omit"],
1049
+ dmg: ["background", "background2x", "window", "iconSize", "textSize", "app", "applications"],
1049
1050
  deepLinks: ["schemes", "domains"]
1050
1051
  };
1051
1052
  static #movedKeys = {
@@ -1074,6 +1075,7 @@ class AkanAppConfig {
1074
1075
  check(settings.android, AkanAppConfig.#nativeKeys.android, `${where}.android`, "android");
1075
1076
  check(settings.desktop, AkanAppConfig.#nativeKeys.desktop, `${where}.desktop`, "desktop");
1076
1077
  check(settings.desktop?.server, AkanAppConfig.#nativeKeys.desktopServer, `${where}.desktop.server`, "desktopServer");
1078
+ check(settings.desktop?.dmg, AkanAppConfig.#nativeKeys.dmg, `${where}.desktop.dmg`, "dmg");
1077
1079
  check(settings.deepLinks, AkanAppConfig.#nativeKeys.deepLinks, `${where}.deepLinks`, "deepLinks");
1078
1080
  }
1079
1081
  static #androidFilePattern = /^(?:res\/[^/]+\/[^/]+|assets\/.+)$/;
@@ -1352,10 +1354,85 @@ var shiftBuildNum = async (app, delta) => {
1352
1354
  };
1353
1355
  var increaseBuildNum = async (app) => await shiftBuildNum(app, 1);
1354
1356
  var decreaseBuildNum = async (app) => await shiftBuildNum(app, -1);
1357
+ // pkgs/@akanjs/devkit/jsonFormatter.ts
1358
+ import path6 from "path";
1359
+
1360
+ class JsonFormatter {
1361
+ static lineWidth = 120;
1362
+ static stringify(value, filePath) {
1363
+ const json = JSON.stringify(value, null, 2);
1364
+ if (path6.basename(filePath) === "package.json")
1365
+ return `${json}
1366
+ `;
1367
+ return `${JsonFormatter.#print(JSON.parse(json), 0, { column: 0, trailing: 0 })}
1368
+ `;
1369
+ }
1370
+ static #print(value, depth, placement) {
1371
+ if (Array.isArray(value))
1372
+ return JsonFormatter.#printArray(value, depth, placement);
1373
+ if (value === null || typeof value !== "object")
1374
+ return JSON.stringify(value);
1375
+ const entries = Object.entries(value);
1376
+ if (!entries.length)
1377
+ return "{}";
1378
+ const indent = " ".repeat(depth + 1);
1379
+ const members = entries.map(([key, member], idx) => {
1380
+ const prefix = `${indent}${JSON.stringify(key)}: `;
1381
+ const trailing = idx < entries.length - 1 ? 1 : 0;
1382
+ return `${prefix}${JsonFormatter.#print(member, depth + 1, { column: Bun.stringWidth(prefix), trailing })}`;
1383
+ });
1384
+ return `{
1385
+ ${members.join(`,
1386
+ `)}
1387
+ ${" ".repeat(depth)}}`;
1388
+ }
1389
+ static #printArray(items, depth, { column, trailing }) {
1390
+ if (!items.length)
1391
+ return "[]";
1392
+ const flat = JsonFormatter.#flat(items);
1393
+ if (flat !== null && column + Bun.stringWidth(flat) + trailing <= JsonFormatter.lineWidth)
1394
+ return flat;
1395
+ const indent = " ".repeat(depth + 1);
1396
+ const isLast = (idx) => idx === items.length - 1;
1397
+ const body = items.every((item) => typeof item === "number") ? JsonFormatter.#fill(items.map((item, idx) => `${JSON.stringify(item)}${isLast(idx) ? "" : ","}`), indent) : items.map((item, idx) => {
1398
+ const placement = { column: indent.length, trailing: isLast(idx) ? 0 : 1 };
1399
+ return `${indent}${JsonFormatter.#print(item, depth + 1, placement)}`;
1400
+ }).join(`,
1401
+ `);
1402
+ return `[
1403
+ ${body}
1404
+ ${" ".repeat(depth)}]`;
1405
+ }
1406
+ static #fill(tokens, indent) {
1407
+ const lines = [];
1408
+ let line = "";
1409
+ for (const token of tokens) {
1410
+ if (line && Bun.stringWidth(line) + 1 + Bun.stringWidth(token) <= JsonFormatter.lineWidth) {
1411
+ line = `${line} ${token}`;
1412
+ continue;
1413
+ }
1414
+ if (line)
1415
+ lines.push(line);
1416
+ line = `${indent}${token}`;
1417
+ }
1418
+ return [...lines, line].join(`
1419
+ `);
1420
+ }
1421
+ static #flat(value) {
1422
+ if (Array.isArray(value)) {
1423
+ const items = value.map((item) => JsonFormatter.#flat(item));
1424
+ return items.includes(null) ? null : `[${items.join(", ")}]`;
1425
+ }
1426
+ if (value === null || typeof value !== "object")
1427
+ return JSON.stringify(value);
1428
+ return Object.keys(value).length ? null : "{}";
1429
+ }
1430
+ }
1431
+
1355
1432
  // pkgs/@akanjs/devkit/linter.ts
1356
1433
  import { spawn } from "child_process";
1357
1434
  import { existsSync, readFileSync } from "fs";
1358
- import path6 from "path";
1435
+ import path7 from "path";
1359
1436
  import chalk from "chalk";
1360
1437
  var parseBiomeReport = (output) => {
1361
1438
  for (let start = output.indexOf("{");start !== -1; start = output.indexOf("{", start + 1)) {
@@ -1421,13 +1498,13 @@ class Linter {
1421
1498
  #biomeBin;
1422
1499
  constructor(cwdPath) {
1423
1500
  this.lintRoot = this.#findBiomeRootPath(cwdPath);
1424
- this.configPath = Linter.#configPathIn(this.lintRoot) ?? path6.join(this.lintRoot, "biome.json");
1425
- const localBiomeBin = path6.join(this.lintRoot, "node_modules", ".bin", Linter.biomeBinName);
1501
+ this.configPath = Linter.#configPathIn(this.lintRoot) ?? path7.join(this.lintRoot, "biome.json");
1502
+ const localBiomeBin = path7.join(this.lintRoot, "node_modules", ".bin", Linter.biomeBinName);
1426
1503
  this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
1427
1504
  }
1428
1505
  static #configPathIn(dir) {
1429
1506
  for (const fileName of BIOME_CONFIG_FILES) {
1430
- const configPath = path6.join(dir, fileName);
1507
+ const configPath = path7.join(dir, fileName);
1431
1508
  if (existsSync(configPath))
1432
1509
  return configPath;
1433
1510
  }
@@ -1436,19 +1513,19 @@ class Linter {
1436
1513
  #findBiomeRootPath(dir) {
1437
1514
  if (Linter.#configPathIn(dir))
1438
1515
  return dir;
1439
- const parentDir = path6.dirname(dir);
1516
+ const parentDir = path7.dirname(dir);
1440
1517
  if (parentDir === dir)
1441
1518
  throw new Error(`biome.json not found from ${dir}`);
1442
1519
  return this.#findBiomeRootPath(parentDir);
1443
1520
  }
1444
1521
  #toBiomePath(filePath) {
1445
- const relativePath = path6.relative(this.lintRoot, filePath);
1446
- if (!relativePath.startsWith("..") && !path6.isAbsolute(relativePath))
1522
+ const relativePath = path7.relative(this.lintRoot, filePath);
1523
+ if (!relativePath.startsWith("..") && !path7.isAbsolute(relativePath))
1447
1524
  return relativePath;
1448
1525
  return filePath;
1449
1526
  }
1450
1527
  #resolveFilePath(filePath) {
1451
- return path6.isAbsolute(filePath) ? filePath : path6.join(this.lintRoot, filePath);
1528
+ return path7.isAbsolute(filePath) ? filePath : path7.join(this.lintRoot, filePath);
1452
1529
  }
1453
1530
  async#runBiome(args, input) {
1454
1531
  return await new Promise((resolve, reject) => {
@@ -1473,7 +1550,7 @@ class Linter {
1473
1550
  const diagnosticPath = diagnostic.location?.path;
1474
1551
  if (!diagnosticPath)
1475
1552
  return fallbackFilePath;
1476
- return path6.isAbsolute(diagnosticPath) ? diagnosticPath : path6.join(this.lintRoot, diagnosticPath);
1553
+ return path7.isAbsolute(diagnosticPath) ? diagnosticPath : path7.join(this.lintRoot, diagnosticPath);
1477
1554
  }
1478
1555
  #createLintMessage(diagnostic) {
1479
1556
  const start = diagnostic.location?.start;
@@ -1679,9 +1756,137 @@ ${errorText}, ${warningText} found`];
1679
1756
  }
1680
1757
  }
1681
1758
 
1759
+ // pkgs/@akanjs/devkit/libSource.ts
1760
+ class LibSource {
1761
+ static manifestKey = "akan";
1762
+ static unhashedDirs = ["env"];
1763
+ #lib;
1764
+ constructor(lib) {
1765
+ this.#lib = lib;
1766
+ }
1767
+ get #prefix() {
1768
+ return `libs/${this.#lib.name}/`;
1769
+ }
1770
+ #isHashed(file) {
1771
+ const relative = file.slice(this.#prefix.length);
1772
+ return !LibSource.unhashedDirs.includes(relative.split("/")[0] ?? "");
1773
+ }
1774
+ static unstamped(manifestContent) {
1775
+ const manifest = JSON.parse(manifestContent);
1776
+ delete manifest[LibSource.manifestKey];
1777
+ return JSON.stringify(manifest);
1778
+ }
1779
+ static async hashFiles(files, manifestFile, read) {
1780
+ const hasher = new Bun.CryptoHasher("sha256");
1781
+ for (const file of files) {
1782
+ const content = await read(file);
1783
+ hasher.update(file);
1784
+ hasher.update("\x00");
1785
+ hasher.update(file === manifestFile ? LibSource.unstamped(content) : content);
1786
+ hasher.update("\x00");
1787
+ }
1788
+ return hasher.digest("hex").slice(0, 32);
1789
+ }
1790
+ async computeHash() {
1791
+ const files = (await this.#lib.workspace.listGitFiles([`libs/${this.#lib.name}`], { untracked: true })).filter((file) => this.#isHashed(file));
1792
+ return await LibSource.hashFiles(files, `${this.#prefix}package.json`, (file) => this.#lib.workspace.readFile(file));
1793
+ }
1794
+ async read() {
1795
+ const manifest = await this.#lib.getPackageJson();
1796
+ const akan = manifest[LibSource.manifestKey];
1797
+ return akan?.source ?? null;
1798
+ }
1799
+ async write({ origin, sha }) {
1800
+ const [manifest, hash] = await Promise.all([this.#lib.getPackageJson(), this.computeHash()]);
1801
+ const akan = manifest[LibSource.manifestKey] ?? {};
1802
+ const stamp = { origin, sha, hash, syncedAt: new Date().toISOString() };
1803
+ await this.#lib.setPackageJson({ ...manifest, [LibSource.manifestKey]: { ...akan, source: stamp } });
1804
+ return stamp;
1805
+ }
1806
+ async syncStamp({ origin, sha }) {
1807
+ const [current, hash] = await Promise.all([this.read(), this.computeHash()]);
1808
+ if (current?.origin === origin && current.sha === sha && current.hash === hash)
1809
+ return { stamp: current, changed: false };
1810
+ return { stamp: await this.write({ origin, sha }), changed: true };
1811
+ }
1812
+ async status() {
1813
+ const [stamp, hash] = await Promise.all([this.read(), this.computeHash()]);
1814
+ const drift = !stamp ? "unstamped" : stamp.hash === hash ? "clean" : "drifted";
1815
+ return { lib: this.#lib.name, drift, stamp, hash };
1816
+ }
1817
+ }
1818
+ function formatLibStatuses(statuses) {
1819
+ const marks = { clean: "clean ", drifted: "DRIFTED ", unstamped: "unstamped" };
1820
+ const sections = [
1821
+ "Akan Library Source Status",
1822
+ "",
1823
+ ...statuses.map((status) => {
1824
+ const origin = status.stamp ? `${status.stamp.origin}@${status.stamp.sha}` : "no akan.source in package.json";
1825
+ return ` ${marks[status.drift]} libs/${status.lib} ${origin}`;
1826
+ }),
1827
+ "",
1828
+ `drifted: ${statuses.filter((status) => status.drift === "drifted").length} / ${statuses.length}`
1829
+ ];
1830
+ return sections.join(`
1831
+ `);
1832
+ }
1833
+
1834
+ // pkgs/@akanjs/devkit/manifestDependencies.ts
1835
+ class ManifestDependencies {
1836
+ #root;
1837
+ #runtime;
1838
+ #typeOnly;
1839
+ #isKept;
1840
+ constructor(root, { runtime, typeOnly }, isKept) {
1841
+ this.#root = root;
1842
+ this.#runtime = new Set(runtime);
1843
+ this.#typeOnly = new Set(typeOnly);
1844
+ this.#isKept = isKept;
1845
+ }
1846
+ static keptBy(manifest) {
1847
+ const { keepDependencies } = manifest[LibSource.manifestKey] ?? {};
1848
+ return Array.isArray(keepDependencies) ? keepDependencies.filter((dep) => typeof dep === "string") : [];
1849
+ }
1850
+ realign(manifest) {
1851
+ const removed = [];
1852
+ const unverifiable = [];
1853
+ const dependencies = {};
1854
+ for (const [dep, version] of Object.entries(manifest.dependencies ?? {})) {
1855
+ if (this.#typeOnly.has(dep))
1856
+ continue;
1857
+ const rootVersion = this.#rootVersionOf(dep);
1858
+ if (!rootVersion) {
1859
+ unverifiable.push(dep);
1860
+ dependencies[dep] = version;
1861
+ } else if (this.#runtime.has(dep) || this.#isKept(dep))
1862
+ dependencies[dep] = rootVersion;
1863
+ else
1864
+ removed.push(dep);
1865
+ }
1866
+ const runtimeOfRootDependencies = [...this.#runtime].filter((dep) => this.#root.dependencies?.[dep]);
1867
+ this.#append(dependencies, runtimeOfRootDependencies);
1868
+ const devDependencies = {};
1869
+ for (const [dep, version] of Object.entries(manifest.devDependencies ?? {}))
1870
+ if (!Object.hasOwn(dependencies, dep))
1871
+ devDependencies[dep] = this.#rootVersionOf(dep) ?? version;
1872
+ this.#append(devDependencies, [...this.#typeOnly]);
1873
+ return { dependencies, devDependencies, removed, unverifiable };
1874
+ }
1875
+ #append(map, deps) {
1876
+ for (const dep of deps.filter((dep) => !Object.hasOwn(map, dep)).sort((a, b) => a < b ? -1 : 1)) {
1877
+ const rootVersion = this.#rootVersionOf(dep);
1878
+ if (rootVersion)
1879
+ map[dep] = rootVersion;
1880
+ }
1881
+ }
1882
+ #rootVersionOf(dep) {
1883
+ return this.#root.dependencies?.[dep] ?? this.#root.devDependencies?.[dep];
1884
+ }
1885
+ }
1886
+
1682
1887
  // pkgs/@akanjs/devkit/repoIdentity.ts
1683
1888
  import { execFileSync } from "child_process";
1684
- import path7 from "path";
1889
+ import path8 from "path";
1685
1890
  var resolved = new Map;
1686
1891
  var readRemoteName = (workspaceRoot) => {
1687
1892
  try {
@@ -1699,13 +1904,13 @@ var resolveRepoName = (workspaceRoot) => {
1699
1904
  const cached = resolved.get(workspaceRoot);
1700
1905
  if (cached)
1701
1906
  return cached;
1702
- const repoName = readRemoteName(workspaceRoot) ?? path7.basename(workspaceRoot);
1907
+ const repoName = readRemoteName(workspaceRoot) ?? path8.basename(workspaceRoot);
1703
1908
  resolved.set(workspaceRoot, repoName);
1704
1909
  return repoName;
1705
1910
  };
1706
1911
 
1707
1912
  // pkgs/@akanjs/devkit/scanInfo.ts
1708
- import path8 from "path";
1913
+ import path9 from "path";
1709
1914
 
1710
1915
  // pkgs/@akanjs/devkit/workspaceLayout.ts
1711
1916
  var appRootAllowedFiles = new Set([
@@ -1778,6 +1983,14 @@ var libFacetRootAllowedFiles = new Set([
1778
1983
  ]);
1779
1984
  var libFacetRootTestPattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
1780
1985
  var isAllowedLibFacetRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || libFacetRootTestPattern.test(filename);
1986
+ var barrelFacetDirs = ["ui", "webkit", "srvkit", "common", "plugin"];
1987
+ var barrelShadowingIndexFiles = new Set(["index.tsx", "index.jsx", "index.mts"]);
1988
+ var facetIndexShadowOf = (sysRelativePath) => {
1989
+ const [facet, filename = "", ...nested] = sysRelativePath.split("/");
1990
+ if (nested.length || !barrelShadowingIndexFiles.has(filename) || !barrelFacetDirs.some((dir) => dir === facet))
1991
+ return null;
1992
+ return `shadows the generated ${facet}/index.ts: Bun loads ${filename} and TypeScript checks index.ts, so a name only ` + `the generated barrel exports typechecks and is undefined at runtime. Delete it, since the generated barrel ` + `re-exports every file and folder in ${facet}/; a namespace it builds belongs in ${facet}/<Folder>/index.tsx`;
1993
+ };
1781
1994
  var retiredAppRootEntries = new Set([
1782
1995
  "android",
1783
1996
  "ios",
@@ -1786,7 +1999,7 @@ var retiredAppRootEntries = new Set([
1786
1999
  "capacitor.config.js",
1787
2000
  "capacitor.config.json"
1788
2001
  ]);
1789
- var rootEntryHintOf = (type, name) => type === "app" && retiredAppRootEntries.has(name) ? "a Capacitor-era entry; the native runtime generates its projects under .akan/native/<target>, so delete it" : null;
2002
+ var rootEntryHintOf = (type, name) => type === "app" && retiredAppRootEntries.has(name) ? "a Capacitor-era entry; the native runtime generates its projects under dist/native/<app>/<target>, so delete it" : null;
1790
2003
  var isScannedRootEntry = (type, name) => !name.startsWith(".") || rootAllowedDirs[type].has(name);
1791
2004
 
1792
2005
  // pkgs/@akanjs/devkit/scanInfo.ts
@@ -1816,9 +2029,9 @@ var moduleUiFileTypes = {
1816
2029
  scalar: new Set(["Template", "Unit"])
1817
2030
  };
1818
2031
  var createDependencyScanner = async (exec) => (await import("./dependencyScanner-06z2dmrr.js")).TypeScriptDependencyScanner.from(exec);
1819
- var getScanPath = (exec, relativePath) => path8.posix.join(`${exec.type}s`, exec.name, relativePath.split(path8.sep).join("/"));
2032
+ var getScanPath = (exec, relativePath) => path9.posix.join(`${exec.type}s`, exec.name, relativePath.split(path9.sep).join("/"));
1820
2033
  var getModuleNameFromPath = (kind, modulePath) => {
1821
- const dirname = path8.basename(modulePath);
2034
+ const dirname = path9.basename(modulePath);
1822
2035
  return kind === "service" ? dirname.replace(/^_+/, "") : dirname;
1823
2036
  };
1824
2037
  async function assertScanConvention(exec, libRoot) {
@@ -1835,22 +2048,28 @@ async function assertScanConvention(exec, libRoot) {
1835
2048
  for (const dirname of dirs)
1836
2049
  if (!allowedRootDirs.has(dirname))
1837
2050
  addViolation(dirname, rootEntryHintOf(exec.type, dirname) ?? `unsupported ${exec.type} root folder`);
2051
+ for (const facet of barrelFacetDirs)
2052
+ for (const filename of await exec.readdir(facet)) {
2053
+ const shadow = facetIndexShadowOf(`${facet}/${filename}`);
2054
+ if (shadow)
2055
+ addViolation(path9.join(facet, filename), shadow);
2056
+ }
1838
2057
  if (exec.type === "lib")
1839
2058
  for (const { relativePath, reason } of await exec.getPageConventionViolations())
1840
2059
  addViolation(relativePath, reason);
1841
2060
  for (const filename of libRoot.files)
1842
2061
  if (!isAllowedLibFacetRootFile(filename))
1843
- addViolation(path8.join("lib", filename), "unsupported lib facet root file");
2062
+ addViolation(path9.join("lib", filename), "unsupported lib facet root file");
1844
2063
  for (const dirname of libRoot.dirs)
1845
2064
  if (dirname.startsWith("__") && !internalLibDirs.has(dirname))
1846
- addViolation(path8.join("lib", dirname), "unsupported internal lib folder");
2065
+ addViolation(path9.join("lib", dirname), "unsupported internal lib folder");
1847
2066
  const databaseDirs = libRoot.dirs.filter((dirname) => !dirname.startsWith("_"));
1848
2067
  const serviceDirs = libRoot.dirs.filter((dirname) => dirname.startsWith("_") && !dirname.startsWith("__"));
1849
2068
  const scalarDirs = await exec.readdir("lib/__scalar");
1850
2069
  await Promise.all([
1851
- ...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database", path8.join("lib", dirname))),
1852
- ...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service", path8.join("lib", dirname))),
1853
- ...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar", path8.join("lib/__scalar", dirname)))
2070
+ ...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database", path9.join("lib", dirname))),
2071
+ ...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service", path9.join("lib", dirname))),
2072
+ ...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar", path9.join("lib/__scalar", dirname)))
1854
2073
  ]);
1855
2074
  if (violations.length > 0) {
1856
2075
  throw new Error(`[scan-convention]
@@ -1862,11 +2081,11 @@ async function validateModuleFiles(exec, violations, kind, modulePath) {
1862
2081
  const { files, dirs } = await exec.getFilesAndDirs(modulePath);
1863
2082
  const moduleName = getModuleNameFromPath(kind, modulePath);
1864
2083
  dirs.forEach((dirname) => {
1865
- violations.push(`${getScanPath(exec, path8.join(modulePath, dirname))}: unsupported module folder`);
2084
+ violations.push(`${getScanPath(exec, path9.join(modulePath, dirname))}: unsupported module folder`);
1866
2085
  });
1867
2086
  const uiModuleName = moduleName[0].toUpperCase() + moduleName.slice(1);
1868
2087
  for (const filename of files) {
1869
- const scanPath = getScanPath(exec, path8.join(modulePath, filename));
2088
+ const scanPath = getScanPath(exec, path9.join(modulePath, filename));
1870
2089
  if (filename === "index.ts" || filename === "index.tsx" || /\.(test|spec)\.(ts|tsx)$/.test(filename))
1871
2090
  continue;
1872
2091
  if (filename === `${moduleName}.abstract.md`)
@@ -1939,16 +2158,16 @@ class ScanInfo {
1939
2158
  }
1940
2159
  };
1941
2160
  await Promise.all([
1942
- ...databaseDirs.map((name) => collect(path8.join("lib", name), name, "databases")),
1943
- ...serviceDirs.map((dirname) => collect(path8.join("lib", dirname), dirname.slice(1), "services")),
1944
- ...scalarDirs.map((name) => collect(path8.join("lib/__scalar", name), name, "scalars"))
2161
+ ...databaseDirs.map((name) => collect(path9.join("lib", name), name, "databases")),
2162
+ ...serviceDirs.map((dirname) => collect(path9.join("lib", dirname), dirname.slice(1), "services")),
2163
+ ...scalarDirs.map((name) => collect(path9.join("lib/__scalar", name), name, "scalars"))
1945
2164
  ]);
1946
2165
  const routes = exec.type === "lib" ? [] : await exec.getPageKeys();
1947
2166
  const common = {
1948
2167
  name: exec.name,
1949
2168
  type: exec.type,
1950
2169
  repoName: exec.workspace.repoName,
1951
- serveDomain: WorkspaceExecutor.getBaseDevEnv(path8.join(exec.workspace.workspaceRoot, ".env")).serveDomain,
2170
+ serveDomain: WorkspaceExecutor.getBaseDevEnv(path9.join(exec.workspace.workspaceRoot, ".env")).serveDomain,
1952
2171
  files,
1953
2172
  libDeps,
1954
2173
  pkgDeps,
@@ -2330,10 +2549,10 @@ class Executor {
2330
2549
  return this.#settle(proc, target, { redStderr: true }).then(({ code, signal }) => ({ code, signal }));
2331
2550
  }
2332
2551
  getPath(filePath) {
2333
- if (path9.isAbsolute(filePath))
2552
+ if (path10.isAbsolute(filePath))
2334
2553
  return filePath;
2335
2554
  if (filePath.startsWith("."))
2336
- return path9.join(this.cwdPath, filePath);
2555
+ return path10.join(this.cwdPath, filePath);
2337
2556
  const baseParts = this.cwdPath.split(/[\\/]/).filter(Boolean);
2338
2557
  const targetParts = filePath.split(/[\\/]/).filter(Boolean);
2339
2558
  let overlapLength = 0;
@@ -2347,7 +2566,7 @@ class Executor {
2347
2566
  if (isOverlap)
2348
2567
  overlapLength = i;
2349
2568
  }
2350
- return path9.join(this.cwdPath, ...targetParts.slice(overlapLength));
2569
+ return path10.join(this.cwdPath, ...targetParts.slice(overlapLength));
2351
2570
  }
2352
2571
  async mkdir(dirPath) {
2353
2572
  const writePath = this.getPath(dirPath);
@@ -2388,7 +2607,7 @@ class Executor {
2388
2607
  return this;
2389
2608
  }
2390
2609
  async removeDir(dirPath) {
2391
- const readPath = path9.join(this.getPath(dirPath), ".");
2610
+ const readPath = path10.join(this.getPath(dirPath), ".");
2392
2611
  if (await FileSys2.entryExists(readPath))
2393
2612
  await rm3(readPath, { recursive: true, force: true });
2394
2613
  this.logger.verbose(`Remove directory ${readPath}`);
@@ -2396,11 +2615,10 @@ class Executor {
2396
2615
  }
2397
2616
  async writeFile(filePath, content, { overwrite = true, silent = false } = {}) {
2398
2617
  const writePath = this.getPath(filePath);
2399
- const dir = path9.dirname(writePath);
2618
+ const dir = path10.dirname(writePath);
2400
2619
  if (!await FileSys2.dirExists(dir))
2401
2620
  await mkdir2(dir, { recursive: true });
2402
- let contentStr = typeof content === "string" ? content : `${JSON.stringify(content, null, 2)}
2403
- `;
2621
+ let contentStr = typeof content === "string" ? content : JsonFormatter.stringify(content, writePath);
2404
2622
  if (await FileSys2.fileExists(writePath)) {
2405
2623
  const currentContent = await FileSys2.readText(writePath);
2406
2624
  if (currentContent === contentStr || !overwrite) {
@@ -2422,7 +2640,7 @@ class Executor {
2422
2640
  await this.writeFile(filePath, content);
2423
2641
  }
2424
2642
  async getLocalFile(targetPath) {
2425
- const filePath = path9.isAbsolute(targetPath) ? targetPath : targetPath.replace(this.cwdPath, "");
2643
+ const filePath = path10.isAbsolute(targetPath) ? targetPath : targetPath.replace(this.cwdPath, "");
2426
2644
  const content = await this.readFile(filePath);
2427
2645
  return { filePath, content };
2428
2646
  }
@@ -2509,9 +2727,9 @@ class Executor {
2509
2727
  const result = await getContent.default(scanInfo ?? null, dict, options);
2510
2728
  if (result === null)
2511
2729
  return null;
2512
- const filename = typeof result === "object" ? result.filename : path9.basename(targetPath).replace(".js", ".ts");
2730
+ const filename = typeof result === "object" ? result.filename : path10.basename(targetPath).replace(".js", ".ts");
2513
2731
  const content = typeof result === "object" ? result.content : result;
2514
- const convertedTargetPath = convertPath(`${path9.dirname(targetPath)}/${filename}`);
2732
+ const convertedTargetPath = convertPath(`${path10.dirname(targetPath)}/${filename}`);
2515
2733
  this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
2516
2734
  return this.writeFile(convertedTargetPath, content, { overwrite });
2517
2735
  } else if (targetPath.endsWith(".template")) {
@@ -2520,10 +2738,10 @@ class Executor {
2520
2738
  const convertedContent = Object.entries(dict).reduce((data, [key, value]) => data.replace(new RegExp(`<%= ${key} %>`, "g"), value), content);
2521
2739
  this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
2522
2740
  return this.writeFile(convertedTargetPath, convertedContent, { overwrite });
2523
- } else if (staticTemplateFileExtensions.has(path9.extname(targetPath).toLowerCase())) {
2741
+ } else if (staticTemplateFileExtensions.has(path10.extname(targetPath).toLowerCase())) {
2524
2742
  const convertedTargetPath = convertPath(targetPath);
2525
2743
  const writePath = this.getPath(convertedTargetPath);
2526
- const dirname = path9.dirname(writePath);
2744
+ const dirname = path10.dirname(writePath);
2527
2745
  if (!await FileSys2.dirExists(dirname))
2528
2746
  await mkdir2(dirname, { recursive: true });
2529
2747
  await copyFile(templatePath, writePath);
@@ -2545,7 +2763,7 @@ class Executor {
2545
2763
  if ((await stat2(templatePath)).isFile()) {
2546
2764
  const fileContent = await this.#applyTemplateFile({
2547
2765
  templatePath,
2548
- targetPath: path9.join(basePath, path9.basename(templatePath)),
2766
+ targetPath: path10.join(basePath, path10.basename(templatePath)),
2549
2767
  scanInfo,
2550
2768
  overwrite
2551
2769
  }, dict, options);
@@ -2553,19 +2771,19 @@ class Executor {
2553
2771
  } else {
2554
2772
  const subdirs = await readDirEntries(templatePath);
2555
2773
  const fileContents = (await Promise.all(subdirs.map(async (subdir) => {
2556
- const subpath = path9.join(templatePath, subdir);
2774
+ const subpath = path10.join(templatePath, subdir);
2557
2775
  if ((await stat2(subpath)).isFile()) {
2558
2776
  const fileContent = await this.#applyTemplateFile({
2559
2777
  templatePath: subpath,
2560
- targetPath: path9.join(basePath, subdir),
2778
+ targetPath: path10.join(basePath, subdir),
2561
2779
  scanInfo,
2562
2780
  overwrite
2563
2781
  }, dict, options);
2564
2782
  return fileContent ? [fileContent] : [];
2565
2783
  } else
2566
2784
  return await this._applyTemplate({
2567
- basePath: path9.join(basePath, subdir),
2568
- template: path9.join(template, subdir),
2785
+ basePath: path10.join(basePath, subdir),
2786
+ template: path10.join(template, subdir),
2569
2787
  scanInfo,
2570
2788
  dict,
2571
2789
  overwrite,
@@ -2577,8 +2795,8 @@ class Executor {
2577
2795
  }
2578
2796
  async#resolveTemplateRoot() {
2579
2797
  const candidates = [
2580
- path9.resolve(getDirname2(import.meta.url), "templates"),
2581
- path9.resolve(getDirname2(import.meta.url), "../cli/templates")
2798
+ path10.resolve(getDirname2(import.meta.url), "templates"),
2799
+ path10.resolve(getDirname2(import.meta.url), "../cli/templates")
2582
2800
  ];
2583
2801
  for (const candidate of candidates) {
2584
2802
  if (await FileSys2.dirExists(candidate))
@@ -2646,11 +2864,11 @@ class Executor {
2646
2864
  async#resolveTypecheckWorkerEntry() {
2647
2865
  const dirname = getDirname2(import.meta.url);
2648
2866
  const candidates = [
2649
- path9.join(process.cwd(), "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
2650
- path9.join(process.cwd(), "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
2651
- path9.join(dirname, "typecheck/typecheck.proc.ts"),
2652
- path9.join(dirname, "typecheck.proc.js"),
2653
- path9.join(dirname, "typecheck.proc.ts")
2867
+ path10.join(process.cwd(), "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
2868
+ path10.join(process.cwd(), "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
2869
+ path10.join(dirname, "typecheck/typecheck.proc.ts"),
2870
+ path10.join(dirname, "typecheck.proc.js"),
2871
+ path10.join(dirname, "typecheck.proc.ts")
2654
2872
  ];
2655
2873
  for (const candidate of candidates)
2656
2874
  if (await Bun.file(candidate).exists())
@@ -2770,7 +2988,7 @@ class WorkspaceExecutor extends Executor {
2770
2988
  await Promise.all(dirs.map(async (dir) => {
2771
2989
  if (dir.includes("_") || AVOID_DIRS.includes(dir))
2772
2990
  return;
2773
- const dirPath = path9.join(dirname, dir);
2991
+ const dirPath = path10.join(dirname, dir);
2774
2992
  if ((await stat2(dirPath)).isDirectory()) {
2775
2993
  results.push(`${prefix}${dir}`);
2776
2994
  if (maxDepth > 0)
@@ -2807,9 +3025,9 @@ class WorkspaceExecutor extends Executor {
2807
3025
  await Promise.all(dirs.map(async (dir) => {
2808
3026
  if (AVOID_DIRS.includes(dir))
2809
3027
  return;
2810
- const dirPath = path9.join(dirname, dir);
3028
+ const dirPath = path10.join(dirname, dir);
2811
3029
  if (await FileSys2.dirExists(dirPath)) {
2812
- const hasTargetFile = await FileSys2.fileExists(path9.join(dirPath, targetFilename));
3030
+ const hasTargetFile = await FileSys2.fileExists(path10.join(dirPath, targetFilename));
2813
3031
  if (hasTargetFile)
2814
3032
  results.push(`${prefix}${dir}`);
2815
3033
  if (maxDepth > 0)
@@ -2839,7 +3057,6 @@ class WorkspaceExecutor extends Executor {
2839
3057
  return await this.#fromEverySys((sys) => sys.getViewsSourceCode());
2840
3058
  }
2841
3059
  }
2842
- var scanFacetDirs = ["ui", "webkit", "srvkit", "common", "plugin"];
2843
3060
 
2844
3061
  class SysExecutor extends Executor {
2845
3062
  workspace;
@@ -2869,7 +3086,7 @@ class SysExecutor extends Executor {
2869
3086
  return [];
2870
3087
  const violations = [];
2871
3088
  for (const entry of await this.getAllFiles("**/*", { cwd: this.getPath("page") })) {
2872
- const relativePath = entry.split(path9.sep).join("/");
3089
+ const relativePath = entry.split(path10.sep).join("/");
2873
3090
  const reason = getPageSourceFileViolation(relativePath);
2874
3091
  if (reason)
2875
3092
  violations.push({ relativePath: `page/${relativePath}`, reason });
@@ -2894,7 +3111,7 @@ class SysExecutor extends Executor {
2894
3111
  this._applyTemplate({ basePath: ".", template: "server.ts", scanInfo }),
2895
3112
  this._applyTemplate({ basePath: ".", template: "client.ts", scanInfo }),
2896
3113
  this.type === "lib" ? this._applyTemplate({ basePath: ".", template: "index.ts", scanInfo }) : null,
2897
- ...scanFacetDirs.map((facet) => this._applyTemplate({
3114
+ ...barrelFacetDirs.map((facet) => this._applyTemplate({
2898
3115
  basePath: facet,
2899
3116
  template: "facetIndex/index.ts",
2900
3117
  scanInfo,
@@ -2923,11 +3140,9 @@ class SysExecutor extends Executor {
2923
3140
  await CodegenLock.run(this.workspace.workspaceRoot, `scan:${this.name}`, async () => {
2924
3141
  await Promise.all(this.#getScanTemplateTasks(scanInfo));
2925
3142
  await this.writeJson(`akan.${this.type}.json`, scanInfo.getScanResult());
2926
- if (this.type === "lib")
2927
- this.#updateDependencies(scanInfo);
3143
+ await this.#updateDependencies(scanInfo);
2928
3144
  if (writeLib) {
2929
3145
  const libInfos = [...scanInfo.getLibInfos().values()];
2930
- await this.#updateDependencies(scanInfo);
2931
3146
  await Promise.all(libInfos.flatMap((libInfo) => libInfo.exec.#getScanTemplateTasks(libInfo)));
2932
3147
  }
2933
3148
  await this.syncAgentsIndex(scanInfo);
@@ -2946,27 +3161,27 @@ class SysExecutor extends Executor {
2946
3161
  await this.writeFile("CLAUDE.md", renderScopeClaudeMd(scope));
2947
3162
  }
2948
3163
  async#updateDependencies(scanInfo) {
2949
- const rootPackageJson = await this.workspace.getPackageJson();
2950
- const libPackageJson = await this.getPackageJson();
2951
- const dependencies = scanInfo.getScanResult().dependencies;
2952
- const devDependencies = scanInfo.getScanResult().devDependencies;
2953
- const dependencySet = new Set(dependencies);
2954
- const devDependencySet = new Set(devDependencies);
2955
- const libPkgJsonWithDeps = {
2956
- ...libPackageJson,
2957
- dependencies: {
2958
- ...Object.fromEntries(Object.entries(libPackageJson.dependencies ?? {}).filter(([dep]) => !devDependencySet.has(dep))),
2959
- ...Object.fromEntries(dependencies.filter((dep) => rootPackageJson.dependencies?.[dep]).sort().map((dep) => [dep, rootPackageJson.dependencies?.[dep]]))
2960
- },
2961
- devDependencies: {
2962
- ...Object.fromEntries(Object.entries(libPackageJson.devDependencies ?? {}).filter(([dep]) => !dependencySet.has(dep))),
2963
- ...Object.fromEntries(devDependencies.filter((dep) => rootPackageJson.dependencies?.[dep] || rootPackageJson.devDependencies?.[dep]).sort().map((dep) => [dep, rootPackageJson.devDependencies?.[dep] ?? rootPackageJson.dependencies?.[dep]]))
2964
- }
2965
- };
2966
- await this.setPackageJson(libPkgJsonWithDeps);
3164
+ const [rootPackageJson, packageJson] = await Promise.all([
3165
+ this.workspace.getPackageJson(),
3166
+ this.getPackageJson({ refresh: true })
3167
+ ]);
3168
+ const { dependencies: runtime, devDependencies: typeOnly, akanConfig } = scanInfo.getScanResult();
3169
+ const kept = new Set([
3170
+ ...ManifestDependencies.keptBy(packageJson),
3171
+ ...akanConfig.externalLibs,
3172
+ ...akanConfig.trustedDependencies
3173
+ ]);
3174
+ const isKept = (dep) => kept.has(dep) || isAkanFrameworkDependency(dep);
3175
+ const { dependencies, devDependencies, removed, unverifiable } = new ManifestDependencies(rootPackageJson, { runtime, typeOnly }, isKept).realign(packageJson);
3176
+ const manifestPath = `${this.type}s/${this.name}/package.json`;
3177
+ if (removed.length)
3178
+ this.logger.info(`Removed from ${manifestPath}, declared by the root and imported nowhere: ${removed.join(", ")} (list one in akan.keepDependencies to keep it)`);
3179
+ if (unverifiable.length)
3180
+ this.logger.warn(`${manifestPath} lists ${unverifiable.join(", ")}, which the root package.json does not declare, so sync cannot tell whether it is used; kept as is`);
3181
+ await this.setPackageJson({ ...packageJson, dependencies, devDependencies });
2967
3182
  }
2968
3183
  async getLocalFile(targetPath) {
2969
- const filePath = path9.isAbsolute(targetPath) ? targetPath : `${this.type}s/${this.name}/${targetPath}`;
3184
+ const filePath = path10.isAbsolute(targetPath) ? targetPath : `${this.type}s/${this.name}/${targetPath}`;
2970
3185
  const content = await this.workspace.readFile(filePath);
2971
3186
  return { filePath, content };
2972
3187
  }
@@ -3054,14 +3269,19 @@ class AppExecutor extends SysExecutor {
3054
3269
  static from(executor, name) {
3055
3270
  return new AppExecutor({ workspace: executor instanceof WorkspaceExecutor ? executor : executor.workspace, name });
3056
3271
  }
3057
- static #keptOnStart = [path9.join(".akan", "native"), path9.join(".akan", "cache", "bin")];
3272
+ static #keptOnStart = [path10.join(".akan", "cache", "bin")];
3273
+ static #legacyNative = path10.join(".akan", "native");
3058
3274
  async#removeDevOutput(dir = ".akan") {
3059
3275
  const entries = await readDirEntries(this.getPath(dir)).catch(() => []);
3060
3276
  await Promise.all(entries.map(async (name) => {
3061
- const entry = path9.join(dir, name);
3277
+ const entry = path10.join(dir, name);
3278
+ if (entry === AppExecutor.#legacyNative) {
3279
+ this.logger.warn(`apps/${this.name}/.akan/native holds native builds from before they moved to dist/native/${this.name}: upload any release waiting in its updates folders, then delete it.`);
3280
+ return;
3281
+ }
3062
3282
  if (AppExecutor.#keptOnStart.includes(entry))
3063
3283
  return;
3064
- if (AppExecutor.#keptOnStart.some((kept) => kept.startsWith(`${entry}${path9.sep}`)))
3284
+ if (AppExecutor.#keptOnStart.some((kept) => kept.startsWith(`${entry}${path10.sep}`)))
3065
3285
  return await this.#removeDevOutput(entry);
3066
3286
  await this.removeDir(entry);
3067
3287
  }));
@@ -3133,10 +3353,10 @@ class AppExecutor extends SysExecutor {
3133
3353
  });
3134
3354
  if (type === "build") {
3135
3355
  const buildEnv = { ...env };
3136
- delete buildEnv.AKAN_PUBLIC_CLIENT_PORT;
3137
- delete buildEnv.AKAN_PUBLIC_SERVER_PORT;
3138
- delete buildEnv.AKAN_PUBLIC_OPERATION_MODE;
3139
- delete process.env.AKAN_PUBLIC_OPERATION_MODE;
3356
+ for (const key of ["AKAN_PUBLIC_CLIENT_PORT", "AKAN_PUBLIC_SERVER_PORT", "AKAN_PUBLIC_OPERATION_MODE"]) {
3357
+ delete buildEnv[key];
3358
+ delete process.env[key];
3359
+ }
3140
3360
  Object.assign(process.env, buildEnv);
3141
3361
  }
3142
3362
  return { env };
@@ -3185,13 +3405,13 @@ class AppExecutor extends SysExecutor {
3185
3405
  absolute: false,
3186
3406
  onlyFiles: true
3187
3407
  })) {
3188
- const segments = rel.split(path9.sep);
3408
+ const segments = rel.split(path10.sep);
3189
3409
  if (segments.some((s) => s === "node_modules"))
3190
3410
  continue;
3191
3411
  const posix = `${root.keyPrefix}${segments.join("/")}`;
3192
3412
  if (!root.keyPrefix && libKeyPrefixes.some((prefix) => posix.startsWith(prefix)))
3193
3413
  continue;
3194
- const absPath = path9.join(root.dir, ...segments);
3414
+ const absPath = path10.join(root.dir, ...segments);
3195
3415
  validatePageSourceFile(posix, { filePath: absPath });
3196
3416
  if (!isRouteSourceFile(posix))
3197
3417
  continue;
@@ -3332,7 +3552,7 @@ class AppExecutor extends SysExecutor {
3332
3552
  static async#linkLibAsset(targetPath, linkPath) {
3333
3553
  const isWindows = process.platform === "win32";
3334
3554
  try {
3335
- const target = isWindows ? targetPath : path9.relative(path9.dirname(linkPath), targetPath);
3555
+ const target = isWindows ? targetPath : path10.relative(path10.dirname(linkPath), targetPath);
3336
3556
  await symlink(target, linkPath, isWindows ? "junction" : "dir");
3337
3557
  } catch (error) {
3338
3558
  if (!isWindows)
@@ -3375,7 +3595,7 @@ class AppExecutor extends SysExecutor {
3375
3595
  await this.writeFile(rel, content, opts);
3376
3596
  },
3377
3597
  readEnvClient: async () => {
3378
- const envClientPath = path9.join(this.cwdPath, "env", "env.client.ts");
3598
+ const envClientPath = path10.join(this.cwdPath, "env", "env.client.ts");
3379
3599
  if (!await FileSys2.fileExists(envClientPath))
3380
3600
  return null;
3381
3601
  try {
@@ -3469,7 +3689,7 @@ class PkgExecutor extends Executor {
3469
3689
  return overrideVersion;
3470
3690
  try {
3471
3691
  const packageJsonPath = `pkgs/${dep}/package.json`;
3472
- if (!await Bun.file(path9.join(this.workspace.workspaceRoot, packageJsonPath)).exists())
3692
+ if (!await Bun.file(path10.join(this.workspace.workspaceRoot, packageJsonPath)).exists())
3473
3693
  return;
3474
3694
  const packageJson = await this.workspace.readJson(packageJsonPath);
3475
3695
  if (packageJson.name === dep)
@@ -3562,4 +3782,4 @@ class ModuleExecutor extends Executor {
3562
3782
  }
3563
3783
  }
3564
3784
 
3565
- export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, binPlatforms, AsyncDefaultExportDetector, resolveSsrPageEntriesForApp, CodegenLock, Linter, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, rootEntryHintOf, isScannedRootEntry, AppInfo, Spinner, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
3785
+ export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, binPlatforms, AsyncDefaultExportDetector, resolveSsrPageEntriesForApp, CodegenLock, Linter, LibSource, formatLibStatuses, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, barrelFacetDirs, facetIndexShadowOf, rootEntryHintOf, isScannedRootEntry, AppInfo, Spinner, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };