@akanjs/cli 3.0.0-alpha.7 → 3.0.0-alpha.71

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 (129) hide show
  1. package/.build-stamp +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +1 -1
  4. package/{abstractCompactor-e5yq60qz.js → abstractCompactor-20e0cwbs.js} +2 -2
  5. package/{agent.command-pggr92jj.js → agent.command-xdvw642m.js} +9 -7
  6. package/{application.command-692yap1d.js → application.command-g3f7xj25.js} +31 -6
  7. package/{applicationBuildRunner-ha3y8ew8.js → applicationBuildRunner-af0wtspv.js} +19 -14
  8. package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-93nzdfsy.js} +1 -1
  9. package/buildBatch.proc.js +7 -5
  10. package/{capacitorApp-p0z5yab2.js → capacitorApp-b0ppke3m.js} +29 -27
  11. package/{cloud.command-wqfsyzv2.js → cloud.command-0hmsv44q.js} +12 -10
  12. package/commandManifest.json +1 -1
  13. package/{context.command-9bxtdn0w.js → context.command-x92afrnf.js} +17 -15
  14. package/{dependencyScanner-f6grrep3.js → dependencyScanner-rbs2407b.js} +1 -1
  15. package/getDirname-ka11hm7e.js +8 -0
  16. package/{guideline.command-nfqahxex.js → guideline.command-hpq08q66.js} +8 -6
  17. package/guidelines/agentRule/agentRule.generate.json +31 -0
  18. package/guidelines/agentRule/agentRule.instruction.md +525 -0
  19. package/guidelines/conventions/conventions.generate.json +25 -0
  20. package/guidelines/conventions/conventions.instruction.md +839 -0
  21. package/guidelines/cssRule/cssRule.instruction.md +7 -0
  22. package/guidelines/framework/framework.generate.json +3 -2
  23. package/guidelines/framework/framework.instruction.md +1 -9
  24. package/guidelines/mcpRule/mcpRule.generate.json +25 -0
  25. package/guidelines/mcpRule/mcpRule.instruction.md +217 -0
  26. package/guidelines/queryRule/queryRule.generate.json +31 -0
  27. package/guidelines/queryRule/queryRule.instruction.md +143 -0
  28. package/guidelines/runtimeRule/runtimeRule.generate.json +25 -0
  29. package/guidelines/runtimeRule/runtimeRule.instruction.md +176 -0
  30. package/guidelines/transportRule/transportRule.generate.json +31 -0
  31. package/guidelines/transportRule/transportRule.instruction.md +60 -0
  32. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +24 -0
  33. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +263 -0
  34. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +33 -0
  35. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +402 -0
  36. package/incrementalBuilder.proc.js +8 -6
  37. package/index-1577bej2.js +7 -0
  38. package/{index-vg0sj9nc.js → index-5f4gnt4c.js} +258 -97
  39. package/{index-bjpxzr6s.js → index-5vy2jzar.js} +1 -1
  40. package/{index-mssqn2sq.js → index-6d5r8q6k.js} +54 -15
  41. package/{index-p3f4q532.js → index-737aj4fm.js} +14 -13
  42. package/{index-2c3e2xh8.js → index-8besc14m.js} +1 -1
  43. package/{index-qb61h0k7.js → index-abyjt72y.js} +333 -540
  44. package/{index-xhgtkekh.js → index-cbfp5wyp.js} +1 -1
  45. package/{index-5dw57f0d.js → index-cp00yns2.js} +80 -14
  46. package/{index-ztpw544k.js → index-ety6takb.js} +3 -3
  47. package/index-f39512t6.js +255 -0
  48. package/{index-6rhabeev.js → index-gvq17wqn.js} +5 -3
  49. package/{index-js368gk9.js → index-hs70d8ed.js} +6 -6
  50. package/{index-7myvn0f0.js → index-j37qq1f2.js} +1 -1
  51. package/{index-azv0xjb5.js → index-jybbmwed.js} +8 -4
  52. package/{index-4hek879p.js → index-m5gfc86a.js} +1 -1
  53. package/{index-w6wbb612.js → index-nq3avsf6.js} +13 -13
  54. package/{index-vtj3zps1.js → index-p27h7535.js} +8 -8
  55. package/{index-5pmx7bkg.js → index-pehn44hr.js} +3 -3
  56. package/{index-j9cxndc0.js → index-qnv0aqmm.js} +9 -6
  57. package/{index-gmy45vz2.js → index-r691v756.js} +4 -4
  58. package/{index-0cj2zxbm.js → index-sh01r3pm.js} +1 -1
  59. package/{index-a1e0j63x.js → index-sqsfv8wg.js} +15 -7
  60. package/{index-gex7c8kd.js → index-wbbswwqt.js} +51 -24
  61. package/{index-bz2sfzzt.js → index-wybbcgxn.js} +4 -4
  62. package/index.js +21 -19
  63. package/{library.command-md9715jz.js → library.command-8vgrdtwy.js} +6 -4
  64. package/{localRegistry.command-exkbamyj.js → localRegistry.command-0gtqj0r0.js} +11 -9
  65. package/{module.command-w5aaddxk.js → module.command-rama4zya.js} +10 -8
  66. package/{package.command-yfkrcy0z.js → package.command-6jxapdsg.js} +6 -4
  67. package/package.json +4 -5
  68. package/{page.command-echbavp4.js → page.command-hxy7x525.js} +6 -4
  69. package/{primitive.command-9fbhspw2.js → primitive.command-4bf6xcc3.js} +11 -9
  70. package/{quality.command-3pnt9yep.js → quality.command-h5edwegz.js} +192 -97
  71. package/{recipeScanner-tghkzrrt.js → recipeScanner-zrzev25x.js} +3 -3
  72. package/{repair.command-carj4vax.js → repair.command-rgqf6px6.js} +8 -6
  73. package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-7fycdqyv.js} +1 -1
  74. package/{scalar.command-51ryzypc.js → scalar.command-6krkz6tw.js} +9 -7
  75. package/templates/app/env/env.client.debug.ts.template +1 -5
  76. package/templates/app/env/env.client.develop.ts.template +1 -5
  77. package/templates/app/env/env.client.local.ts.template +1 -5
  78. package/templates/app/env/env.client.main.ts.template +1 -5
  79. package/templates/app/env/env.client.testing.ts.template +1 -5
  80. package/templates/app/env/env.client.type.ts +2 -6
  81. package/templates/app/env/env.server.debug.ts.template +1 -5
  82. package/templates/app/env/env.server.develop.ts.template +1 -5
  83. package/templates/app/env/env.server.local.ts.template +1 -5
  84. package/templates/app/env/env.server.main.ts.template +1 -5
  85. package/templates/app/main.ts +3 -1
  86. package/templates/app/page/styles.css.template +3 -3
  87. package/templates/appSample/srvkit/AuthGuard.ts +9 -5
  88. package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
  89. package/templates/crudPages/[__model__Id]/edit/page.tsx +1 -1
  90. package/templates/crudPages/new/page.tsx +1 -1
  91. package/templates/crudSinglePage/page.tsx +1 -1
  92. package/templates/env/_env.server.type.ts +7 -5
  93. package/templates/lib/db.ts +1 -1
  94. package/templates/lib/dict.ts +1 -1
  95. package/templates/lib/sig.ts +1 -1
  96. package/templates/lib/srv.ts +6 -2
  97. package/templates/module/__Model__.Util.tsx +1 -1
  98. package/templates/module/__Model__.Zone.tsx +3 -5
  99. package/templates/workspaceRoot/AGENTS.md.template +4 -972
  100. package/templates/workspaceRoot/CLAUDE.md.template +19 -0
  101. package/templates/workspaceRoot/biome.json.template +4 -244
  102. package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +10 -14
  103. package/templates/workspaceRoot/docs/GENERATED.md.template +12 -10
  104. package/templates/workspaceRoot/package.json.template +1 -1
  105. package/{typeChecker-kravn7ns.js → typeChecker-g6bh0xfv.js} +1 -1
  106. package/typecheck.proc.js +1 -1
  107. package/{workflow.command-91wmvm8k.js → workflow.command-dwhwrqhd.js} +16 -14
  108. package/{workspace.command-wa10mfd9.js → workspace.command-f5h11gjn.js} +71 -52
  109. package/templates/workspaceRoot/.cursor/rules/akan-page-routing.mdc.template +0 -43
  110. package/templates/workspaceRoot/.cursor/rules/akan-sync-conventions.mdc.template +0 -34
  111. package/templates/workspaceRoot/.cursor/rules/application-test-commands.mdc.template +0 -16
  112. package/templates/workspaceRoot/.cursor/rules/change-scope.mdc.template +0 -12
  113. package/templates/workspaceRoot/.cursor/rules/client-server-boundaries.mdc.template +0 -18
  114. package/templates/workspaceRoot/.cursor/rules/coding-comments.mdc.template +0 -25
  115. package/templates/workspaceRoot/.cursor/rules/coding-style.mdc.template +0 -44
  116. package/templates/workspaceRoot/.cursor/rules/domain-module-conventions.mdc.template +0 -17
  117. package/templates/workspaceRoot/.cursor/rules/format-lint.mdc.template +0 -12
  118. package/templates/workspaceRoot/.cursor/rules/lint-enforced-rules.mdc.template +0 -19
  119. package/templates/workspaceRoot/.cursor/rules/module-file-playbook.mdc.template +0 -62
  120. package/templates/workspaceRoot/.cursor/rules/naming-conventions.mdc.template +0 -15
  121. package/templates/workspaceRoot/.cursor/rules/react-component-style.mdc.template +0 -21
  122. package/templates/workspaceRoot/.cursor/rules/repo-overview.mdc.template +0 -17
  123. package/templates/workspaceRoot/.cursor/rules/scalar-modeling.mdc.template +0 -99
  124. package/templates/workspaceRoot/.cursor/rules/secrets-and-env.mdc.template +0 -13
  125. package/templates/workspaceRoot/.cursor/rules/service-signal-conventions.mdc.template +0 -83
  126. package/templates/workspaceRoot/.cursor/rules/srvkit-adapters-and-guards.mdc.template +0 -50
  127. package/templates/workspaceRoot/.cursor/rules/ssr-first.mdc.template +0 -59
  128. package/templates/workspaceRoot/.cursor/rules/typescript-imports.mdc.template +0 -16
  129. /package/{index-r24hmh0q.js → index-yb2wsc7f.js} +0 -0
@@ -1,13 +1,20 @@
1
1
  // @bun
2
+ import {
3
+ getRootBoundarySegments,
4
+ isRootBoundarySegments
5
+ } from "./index-f39512t6.js";
2
6
  import {
3
7
  Spinner
4
8
  } from "./index-mxvakhsm.js";
9
+ import {
10
+ getDirname
11
+ } from "./index-1577bej2.js";
5
12
  import {
6
13
  FileSys
7
14
  } from "./index-67546d0j.js";
8
15
  import {
9
16
  __require
10
- } from "./index-r24hmh0q.js";
17
+ } from "./index-yb2wsc7f.js";
11
18
 
12
19
  // pkgs/@akanjs/devkit/executors.ts
13
20
  import {
@@ -30,6 +37,7 @@ import path5 from "path";
30
37
  import { pathToFileURL } from "url";
31
38
  import {
32
39
  capitalize,
40
+ getPageSourceFileViolation,
33
41
  isRouteSourceFile,
34
42
  Logger,
35
43
  parseRouteModuleKey,
@@ -41,9 +49,24 @@ import chalk2 from "chalk";
41
49
 
42
50
  // pkgs/@akanjs/devkit/agentsIndex.ts
43
51
  var recipeScannerLoad = null;
44
- var loadRecipeScanner = () => recipeScannerLoad ??= import("./recipeScanner-tghkzrrt.js");
52
+ var loadRecipeScanner = () => recipeScannerLoad ??= import("./recipeScanner-zrzev25x.js");
45
53
  var AGENT_BLOCK_START = "<!-- akan:agent:start -->";
46
54
  var AGENT_BLOCK_END = "<!-- akan:agent:end -->";
55
+ var AGENT_VERSION_PREFIX = "<!-- akan:agent:version ";
56
+ var stampBlockVersion = (block, version) => `${AGENT_VERSION_PREFIX}${version} -->
57
+
58
+ ${block}`;
59
+ var extractBlockVersion = (content) => content.match(/<!-- akan:agent:version ([^\s]+) -->/)?.[1] ?? null;
60
+ var readDevkitVersion = async () => {
61
+ const { readFile } = await import("fs/promises");
62
+ const { getDirname: getDirname2 } = await import("./getDirname-ka11hm7e.js");
63
+ try {
64
+ const raw = await readFile(`${getDirname2(import.meta.url)}/package.json`, "utf-8");
65
+ return JSON.parse(raw).version ?? null;
66
+ } catch {
67
+ return null;
68
+ }
69
+ };
47
70
  var upsertAgentBlock = (existing, block) => {
48
71
  const managed = `${AGENT_BLOCK_START}
49
72
  ${block}
@@ -137,9 +160,29 @@ ${AGENT_BLOCK_START}
137
160
  ${block}
138
161
  ${AGENT_BLOCK_END}
139
162
  `;
163
+ var CLAUDE_COMMENT_RULE = `## Comments \u2014 Overrides Your Default
164
+
165
+ Write **no comments** unless the comment passes the test below. This is the rule agents break most often here, so it
166
+ is repeated outside the guide: a diff that adds a comment the test rejects is a diff to redo.
167
+
168
+ Before typing \`//\`, \`/*\`, or a doc block, ask \u2014 **does this sentence carry a fact that is nowhere in the code?**
169
+
170
+ - Restates the identifier, the signature, or the line under it \u2192 delete it.
171
+ - Labels a section (\`// helpers\`, \`// state\`) or narrates a step (\`// fetch the user\`, \`// then save\`) \u2192 delete it.
172
+ - JSDoc on an ordinary function, or a why/how preamble on ordinary logic \u2192 delete it.
173
+ - Explains the edit you just made, for whoever reads the diff \u2192 say it in your reply, not in the file.
174
+ - Names a vendor or protocol quirk, an infrastructure constraint, a library gotcha, security reasoning, a math
175
+ derivation, a domain field's business meaning, a state transition, or why an obvious alternative was rejected \u2192
176
+ keep it, one line.
177
+
178
+ That keep-list is exact \u2014 \`Comments\` in the guide is the full version. "It aids readability" and "this logic is
179
+ subtle" are not on it: rename or split the code instead. When you edit an existing file, match its density; if the
180
+ surrounding code carries none, your diff carries none.`;
140
181
  var renderScopeClaudeMd = (scope) => `# ${scope.name} \u2014 Claude Code Guide
141
182
 
142
183
  @AGENTS.md
184
+
185
+ ${CLAUDE_COMMENT_RULE}
143
186
  `;
144
187
 
145
188
  // pkgs/@akanjs/devkit/akanConfig/akanConfig.ts
@@ -181,9 +224,8 @@ var DEFAULT_OPTIMIZE_IMPORTS = [
181
224
  "react-icons/*"
182
225
  ];
183
226
  var WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"];
227
+ var DEFAULT_DOCKER_IMAGE = "oven/bun:1-slim";
184
228
  var SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"];
185
- var NATIVE_RUNTIME_PACKAGES = ["sharp"];
186
- var DEFAULT_BACKEND_RUNTIME_PACKAGES = ["croner"];
187
229
  var MOBILE_RUNTIME_PACKAGES = [
188
230
  "@capacitor/cli",
189
231
  "@capacitor/core",
@@ -212,8 +254,6 @@ var DATABASE_MODE_RUNTIME_PACKAGES = {
212
254
  };
213
255
  var AKAN_RUNTIME_PACKAGES = new Set([
214
256
  ...SSR_RUNTIME_PACKAGES,
215
- ...NATIVE_RUNTIME_PACKAGES,
216
- ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
217
257
  ...MOBILE_RUNTIME_PACKAGES,
218
258
  ...Object.values(DATABASE_MODE_RUNTIME_PACKAGES).flat()
219
259
  ]);
@@ -228,7 +268,8 @@ var DEFAULT_AKAN_IMAGE_CONFIG = {
228
268
  dangerouslyAllowSVG: false,
229
269
  maximumRedirects: 3,
230
270
  fetchTimeoutMs: 7000,
231
- maxRemoteBytes: 25 * 1024 * 1024
271
+ maxRemoteBytes: 25 * 1024 * 1024,
272
+ maxConcurrency: 0
232
273
  };
233
274
  var normalizeIndexPath = (indexPath) => {
234
275
  const normalized = indexPath?.trim();
@@ -275,12 +316,28 @@ var normalizeDeepLinks = (deepLinks) => {
275
316
  ...sha256CertFingerprints ? { android: { sha256CertFingerprints } } : {}
276
317
  };
277
318
  };
319
+ var emptyLibContributions = () => ({
320
+ externalLibs: [],
321
+ docker: { preRuns: [], postRuns: [] },
322
+ keepFonts: []
323
+ });
324
+ var normalizeKeepFonts = (keepFonts) => [
325
+ ...new Set((keepFonts ?? []).map((glob) => glob.trim().replace(/^\/+/, "")).filter(Boolean))
326
+ ];
327
+ var dedupeDockerRuns = (runs) => {
328
+ const byKey = new Map;
329
+ for (const run of runs)
330
+ byKey.set(typeof run === "string" ? run : JSON.stringify(run), run);
331
+ return [...byKey.values()];
332
+ };
278
333
 
279
334
  class AkanAppConfig {
280
335
  app;
281
336
  rootPackageJson;
282
337
  docker;
338
+ dockerfile;
283
339
  defaultDatabaseMode;
340
+ web;
284
341
  externalLibs;
285
342
  barrelImports;
286
343
  optimizeImports;
@@ -290,6 +347,7 @@ class AkanAppConfig {
290
347
  mobile;
291
348
  hasMobileConfig;
292
349
  secrets;
350
+ assets;
293
351
  syncPageLibs;
294
352
  baseDevEnv;
295
353
  libs;
@@ -298,7 +356,7 @@ class AkanAppConfig {
298
356
  subRoutes = new Map;
299
357
  basePaths = new Set;
300
358
  branches = new Set(["debug", "develop", "main"]);
301
- constructor(app, libs, rootPackageJson, config, baseDevEnv, plugins = []) {
359
+ constructor(app, libs, rootPackageJson, config, baseDevEnv, plugins = [], libContributions = emptyLibContributions()) {
302
360
  this.app = app;
303
361
  this.rootPackageJson = rootPackageJson;
304
362
  this.libs = libs;
@@ -306,7 +364,7 @@ class AkanAppConfig {
306
364
  this.plugins = plugins;
307
365
  this.#applyRoutes(config?.routes);
308
366
  this.defaultDatabaseMode = config?.defaultDatabaseMode ?? "single";
309
- this.externalLibs = config?.externalLibs ?? [];
367
+ this.externalLibs = [...new Set([...config?.externalLibs ?? [], ...libContributions.externalLibs])];
310
368
  this.barrelImports = [
311
369
  ...DEFAULT_BARREL_IMPORTS,
312
370
  ...WORKSPACE_BARREL_FACETS.map((facet) => `@apps/${app.name}/${facet}`),
@@ -320,10 +378,25 @@ class AkanAppConfig {
320
378
  process.env.AKAN_PUBLIC_LOCALES = this.i18n.locales.join(",");
321
379
  this.publicEnv = config?.publicEnv ?? [];
322
380
  this.secrets = config?.secrets ?? [];
381
+ this.assets = {
382
+ pruneFonts: config?.assets?.pruneFonts ?? true,
383
+ keepFonts: [
384
+ ...normalizeKeepFonts(config?.assets?.keepFonts),
385
+ ...libContributions.keepFonts ?? []
386
+ ]
387
+ };
323
388
  this.syncPageLibs = config?.syncPageLibs ?? false;
324
389
  this.hasMobileConfig = Boolean(config.mobile);
325
390
  this.mobile = this.#resolveMobileConfig(config.mobile);
326
- this.docker = this.#makeDockerContent(config?.docker ?? {});
391
+ this.web = this.#resolveWebConfig(config.web);
392
+ this.docker = AkanAppConfig.#resolveDocker(config.docker, libContributions.docker);
393
+ this.dockerfile = this.#makeDockerfile();
394
+ }
395
+ #resolveWebConfig(web) {
396
+ const resolved = typeof web === "object" ? { ssr: true, csr: web.csr } : { ssr: web ?? true, csr: web ?? true };
397
+ if (!resolved.csr && this.hasMobileConfig)
398
+ throw new Error(`apps/${this.app.name}/akan.config.ts turns the CSR bundle off but declares mobile targets; the Capacitor build ships that bundle. Drop the mobile section or leave CSR on.`);
399
+ return resolved;
327
400
  }
328
401
  #resolveMobileConfig(mobile) {
329
402
  const {
@@ -433,23 +506,31 @@ class AkanAppConfig {
433
506
  return archs.map((arch) => `FROM ${image[arch] ?? defaultImage} AS ${arch}`).join(`
434
507
  `);
435
508
  }
436
- #makeDockerContent(docker) {
437
- if (docker.content)
438
- return {
439
- content: docker.content,
440
- image: {},
441
- preRuns: [],
442
- postRuns: [],
443
- command: []
444
- };
445
- const preRunScripts = this.#getDockerRunScripts(docker.preRuns ?? []);
446
- const postRunScripts = this.#getDockerRunScripts(docker.postRuns ?? []);
447
- const imageScript = docker.image ? this.#getDockerImageScript(docker.image, "oven/bun:1-slim") : "FROM oven/bun:1-slim";
448
- const command = docker.command ?? ["bun", "main.js"];
449
- const content = `${imageScript}
509
+ static #resolveDocker(docker, libDocker) {
510
+ if (typeof docker === "string")
511
+ return docker;
512
+ return {
513
+ image: docker?.image ?? DEFAULT_DOCKER_IMAGE,
514
+ preRuns: dedupeDockerRuns([...libDocker.preRuns, ...docker?.preRuns ?? []]),
515
+ postRuns: dedupeDockerRuns([...libDocker.postRuns, ...docker?.postRuns ?? []]),
516
+ command: docker?.command ?? ["bun", "main.js"]
517
+ };
518
+ }
519
+ #makeDockerfile() {
520
+ if (typeof this.docker === "string")
521
+ return this.docker;
522
+ const { image, preRuns, postRuns, command } = this.docker;
523
+ const preRunScripts = this.#getDockerRunScripts(preRuns);
524
+ const postRunScripts = this.#getDockerRunScripts(postRuns);
525
+ const imageScript = this.#getDockerImageScript(image, DEFAULT_DOCKER_IMAGE);
526
+ const webEnvLines = [
527
+ ...this.web.ssr ? [] : ["ENV AKAN_SSR=false"],
528
+ ...this.web.csr ? [] : ["ENV AKAN_CSR=false"]
529
+ ].join(`
530
+ `);
531
+ return `${imageScript}
532
+ RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends ca-certificates tzdata && rm -rf /var/lib/apt/lists/*
450
533
  RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
451
- RUN apt-get update && apt-get upgrade -y
452
- RUN apt-get install -y --no-install-recommends git redis build-essential python3 ca-certificates fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils udev ffmpeg
453
534
  ARG TARGETARCH
454
535
  ${preRunScripts.join(`
455
536
  `)}
@@ -470,15 +551,9 @@ ${this.basePaths.size ? `ENV AKAN_PUBLIC_BASE_PATHS=${[...this.basePaths].join("
470
551
  ENV AKAN_PUBLIC_DEFAULT_LOCALE=${this.i18n.defaultLocale}
471
552
  ENV AKAN_PUBLIC_LOCALES=${this.i18n.locales.join(",")}
472
553
  ENV AKAN_PUBLIC_OPERATION_MODE=cloud
473
-
554
+ ENV AKAN_LOG_TO_FILE=0
555
+ ${webEnvLines}
474
556
  CMD [${command.map((c) => `"${c}"`).join(",")}]`;
475
- return {
476
- content,
477
- image: imageScript,
478
- preRuns: docker.preRuns ?? [],
479
- postRuns: docker.postRuns ?? [],
480
- command
481
- };
482
557
  }
483
558
  static #importGeneration = 0;
484
559
  static async importConfigModule(cwdPath, { bustImportCache = false } = {}) {
@@ -495,7 +570,22 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
495
570
  ]);
496
571
  const resolved = typeof configImp === "function" ? configImp(app) : configImp;
497
572
  const { plugins, ...config } = resolved ?? {};
498
- return new AkanAppConfig(app, libs, rootPackageJson, config, baseDevEnv, plugins ?? []);
573
+ const libContributions = await AkanAppConfig.#collectLibContributions(app, libs, bustImportCache);
574
+ return new AkanAppConfig(app, libs, rootPackageJson, config, baseDevEnv, plugins ?? [], libContributions);
575
+ }
576
+ static async#collectLibContributions(app, libs, bustImportCache) {
577
+ const libConfigs = await Promise.all(libs.map(async (libName) => LibExecutor.from(app, libName).getConfig({ refresh: bustImportCache }).catch((error) => {
578
+ app.logger.warn(`Skipped libs/${libName}/akan.config.ts contributions: ${String(error)}`);
579
+ return null;
580
+ })));
581
+ return {
582
+ externalLibs: libConfigs.flatMap((libConfig) => libConfig?.externalLibs ?? []),
583
+ docker: {
584
+ preRuns: libConfigs.flatMap((libConfig) => libConfig?.docker.preRuns ?? []),
585
+ postRuns: libConfigs.flatMap((libConfig) => libConfig?.docker.postRuns ?? [])
586
+ },
587
+ keepFonts: libConfigs.flatMap((libConfig) => (libConfig?.assets.keepFonts ?? []).map((glob) => `libs/${libConfig?.lib.name}/${glob}`))
588
+ };
499
589
  }
500
590
  #resolveProductionDependencyVersion(lib) {
501
591
  const rootVersion = this.rootPackageJson.dependencies?.[lib] ?? this.rootPackageJson.devDependencies?.[lib];
@@ -505,13 +595,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
505
595
  return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
506
596
  }
507
597
  #getProductionRuntimePackages() {
508
- return [
509
- ...this.externalLibs,
510
- ...SSR_RUNTIME_PACKAGES,
511
- ...NATIVE_RUNTIME_PACKAGES,
512
- ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
513
- ...this.getDatabaseModeRuntimePackages()
514
- ];
598
+ return [...this.externalLibs, ...SSR_RUNTIME_PACKAGES, ...this.getDatabaseModeRuntimePackages()];
515
599
  }
516
600
  getDatabaseModeRuntimePackages(databaseMode = this.defaultDatabaseMode) {
517
601
  return [...DATABASE_MODE_RUNTIME_PACKAGES[databaseMode]];
@@ -599,14 +683,18 @@ function mergeImageConfig(config = {}) {
599
683
  class AkanLibConfig {
600
684
  lib;
601
685
  externalLibs;
686
+ docker;
687
+ assets;
602
688
  plugins;
603
689
  constructor(lib, config, plugins = []) {
604
690
  this.lib = lib;
605
691
  this.externalLibs = config?.externalLibs ?? [];
692
+ this.docker = { preRuns: config?.docker?.preRuns ?? [], postRuns: config?.docker?.postRuns ?? [] };
693
+ this.assets = { keepFonts: normalizeKeepFonts(config?.assets?.keepFonts) };
606
694
  this.plugins = plugins;
607
695
  }
608
- static async from(lib) {
609
- const [configImp] = await Promise.all([import(`${lib.cwdPath}/akan.config.ts`).then((mod) => mod.default)]);
696
+ static async from(lib, { bustImportCache = false } = {}) {
697
+ const configImp = await AkanAppConfig.importConfigModule(lib.cwdPath, { bustImportCache });
610
698
  const resolved = typeof configImp === "function" ? configImp(lib) : configImp;
611
699
  const { plugins, ...config } = resolved ?? {};
612
700
  return new AkanLibConfig(lib, config, plugins ?? []);
@@ -627,42 +715,47 @@ var decreaseBuildNum = async (app) => {
627
715
  const akanConfigContent = akanConfig.replace(`buildNum: ${appConfig.mobile.buildNum}`, `buildNum: ${appConfig.mobile.buildNum - 1}`);
628
716
  fs.writeFileSync(akanConfigPath, akanConfigContent);
629
717
  };
630
- // pkgs/@akanjs/devkit/getDirname.ts
631
- import path2 from "path";
632
- import { fileURLToPath as fileURLToPath2 } from "url";
633
- var getDirname = (url) => path2.dirname(fileURLToPath2(url));
634
-
635
718
  // pkgs/@akanjs/devkit/linter.ts
636
719
  import { spawn } from "child_process";
637
720
  import { existsSync, readFileSync } from "fs";
638
- import path3 from "path";
721
+ import path2 from "path";
639
722
  import chalk from "chalk";
723
+ var BIOME_CONFIG_FILES = ["biome.json", "biome.jsonc"];
640
724
 
641
725
  class Linter {
642
726
  lintRoot;
727
+ configPath;
643
728
  #biomeBin;
644
729
  constructor(cwdPath) {
645
730
  this.lintRoot = this.#findBiomeRootPath(cwdPath);
646
- const localBiomeBin = path3.join(this.lintRoot, "node_modules/.bin/biome");
731
+ this.configPath = Linter.#configPathIn(this.lintRoot) ?? path2.join(this.lintRoot, "biome.json");
732
+ const localBiomeBin = path2.join(this.lintRoot, "node_modules/.bin/biome");
647
733
  this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
648
734
  }
735
+ static #configPathIn(dir) {
736
+ for (const fileName of BIOME_CONFIG_FILES) {
737
+ const configPath = path2.join(dir, fileName);
738
+ if (existsSync(configPath))
739
+ return configPath;
740
+ }
741
+ return null;
742
+ }
649
743
  #findBiomeRootPath(dir) {
650
- const configPath = path3.join(dir, "biome.json");
651
- if (existsSync(configPath))
744
+ if (Linter.#configPathIn(dir))
652
745
  return dir;
653
- const parentDir = path3.dirname(dir);
746
+ const parentDir = path2.dirname(dir);
654
747
  if (parentDir === dir)
655
748
  throw new Error(`biome.json not found from ${dir}`);
656
749
  return this.#findBiomeRootPath(parentDir);
657
750
  }
658
751
  #toBiomePath(filePath) {
659
- const relativePath = path3.relative(this.lintRoot, filePath);
660
- if (!relativePath.startsWith("..") && !path3.isAbsolute(relativePath))
752
+ const relativePath = path2.relative(this.lintRoot, filePath);
753
+ if (!relativePath.startsWith("..") && !path2.isAbsolute(relativePath))
661
754
  return relativePath;
662
755
  return filePath;
663
756
  }
664
757
  #resolveFilePath(filePath) {
665
- return path3.isAbsolute(filePath) ? filePath : path3.join(this.lintRoot, filePath);
758
+ return path2.isAbsolute(filePath) ? filePath : path2.join(this.lintRoot, filePath);
666
759
  }
667
760
  async#runBiome(args, input) {
668
761
  return await new Promise((resolve, reject) => {
@@ -694,7 +787,7 @@ class Linter {
694
787
  const diagnosticPath = diagnostic.location?.path;
695
788
  if (!diagnosticPath)
696
789
  return fallbackFilePath;
697
- return path3.isAbsolute(diagnosticPath) ? diagnosticPath : path3.join(this.lintRoot, diagnosticPath);
790
+ return path2.isAbsolute(diagnosticPath) ? diagnosticPath : path2.join(this.lintRoot, diagnosticPath);
698
791
  }
699
792
  #createLintMessage(diagnostic) {
700
793
  const start = diagnostic.location?.start;
@@ -759,7 +852,7 @@ class Linter {
759
852
  "--max-diagnostics=none",
760
853
  "--no-errors-on-unmatched",
761
854
  "--config-path",
762
- path3.join(this.lintRoot, "biome.json"),
855
+ this.configPath,
763
856
  this.#toBiomePath(filePath)
764
857
  ]);
765
858
  const report = this.#parseBiomeReport(stdout || stderr);
@@ -880,14 +973,7 @@ ${errorText}, ${warningText} found`];
880
973
  if (!dryRun)
881
974
  return await this.#checkFile(resolvedFilePath, { write: true });
882
975
  const source = readFileSync(resolvedFilePath, "utf8");
883
- const { stdout } = await this.#runBiome([
884
- "check",
885
- "--write",
886
- "--config-path",
887
- path3.join(this.lintRoot, "biome.json"),
888
- "--stdin-file-path",
889
- this.#toBiomePath(resolvedFilePath)
890
- ], source);
976
+ const { stdout } = await this.#runBiome(["check", "--write", "--config-path", this.configPath, "--stdin-file-path", this.#toBiomePath(resolvedFilePath)], source);
891
977
  const lintResult = await this.lintFile(resolvedFilePath);
892
978
  return { ...lintResult, fixed: stdout !== source, output: stdout };
893
979
  }
@@ -895,7 +981,7 @@ ${errorText}, ${warningText} found`];
895
981
  const resolvedFilePath = this.#resolveFilePath(filePath);
896
982
  if (!existsSync(resolvedFilePath))
897
983
  throw new Error(`File not found: ${filePath}`);
898
- return JSON.parse(readFileSync(path3.join(this.lintRoot, "biome.json"), "utf8"));
984
+ return JSON.parse(readFileSync(this.configPath, "utf8"));
899
985
  }
900
986
  async getProblematicRules(filePath) {
901
987
  const { results } = await this.lintFile(filePath);
@@ -910,6 +996,31 @@ ${errorText}, ${warningText} found`];
910
996
  }
911
997
  }
912
998
 
999
+ // pkgs/@akanjs/devkit/repoIdentity.ts
1000
+ import { execFileSync } from "child_process";
1001
+ import path3 from "path";
1002
+ var resolved = new Map;
1003
+ var readRemoteName = (workspaceRoot) => {
1004
+ try {
1005
+ const url = execFileSync("git", ["config", "--get", "remote.origin.url"], {
1006
+ cwd: workspaceRoot,
1007
+ encoding: "utf-8",
1008
+ stdio: ["ignore", "pipe", "ignore"]
1009
+ }).trim();
1010
+ return url.replace(/\.git$/, "").split(/[/:]/).pop() || null;
1011
+ } catch {
1012
+ return null;
1013
+ }
1014
+ };
1015
+ var resolveRepoName = (workspaceRoot) => {
1016
+ const cached = resolved.get(workspaceRoot);
1017
+ if (cached)
1018
+ return cached;
1019
+ const repoName = readRemoteName(workspaceRoot) ?? path3.basename(workspaceRoot);
1020
+ resolved.set(workspaceRoot, repoName);
1021
+ return repoName;
1022
+ };
1023
+
913
1024
  // pkgs/@akanjs/devkit/scanInfo.ts
914
1025
  import { rm } from "fs/promises";
915
1026
  import path4 from "path";
@@ -946,6 +1057,34 @@ var appRootAllowedDirs = new Set([
946
1057
  "ui",
947
1058
  "webkit"
948
1059
  ]);
1060
+ var libRootAllowedFiles = new Set([
1061
+ "AGENTS.md",
1062
+ "CLAUDE.md",
1063
+ "README.md",
1064
+ "akan.config.ts",
1065
+ "akan.lib.json",
1066
+ "client.ts",
1067
+ "index.ts",
1068
+ "package.json",
1069
+ "server.ts",
1070
+ "tsconfig.json",
1071
+ "tsconfig.spec.json",
1072
+ "tsconfig.tsbuildinfo"
1073
+ ]);
1074
+ var libRootAllowedDirs = new Set([
1075
+ "common",
1076
+ "env",
1077
+ "lib",
1078
+ "page",
1079
+ "plugin",
1080
+ "private",
1081
+ "public",
1082
+ "srvkit",
1083
+ "ui",
1084
+ "webkit"
1085
+ ]);
1086
+ var rootAllowedFiles = { app: appRootAllowedFiles, lib: libRootAllowedFiles };
1087
+ var rootAllowedDirs = { app: appRootAllowedDirs, lib: libRootAllowedDirs };
949
1088
  var libFacetRootAllowedFiles = new Set([
950
1089
  "cnst.ts",
951
1090
  "db.ts",
@@ -957,7 +1096,9 @@ var libFacetRootAllowedFiles = new Set([
957
1096
  "useClient.ts",
958
1097
  "useServer.ts"
959
1098
  ]);
960
- var isScannedAppRootEntry = (name) => !name.startsWith(".") || appRootAllowedDirs.has(name);
1099
+ var libFacetRootTestPattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
1100
+ var isAllowedLibFacetRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || libFacetRootTestPattern.test(filename);
1101
+ var isScannedRootEntry = (type, name) => !name.startsWith(".") || rootAllowedDirs[type].has(name);
961
1102
 
962
1103
  // pkgs/@akanjs/devkit/scanInfo.ts
963
1104
  var databaseFileTypes = [
@@ -986,10 +1127,8 @@ var moduleUiFileTypes = {
986
1127
  scalar: new Set(["Template", "Unit"])
987
1128
  };
988
1129
  var testFilePattern = /\.(test|spec)\.(ts|tsx)$/;
989
- var rootSignalTestFilePattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
990
- var createDependencyScanner = async (exec) => (await import("./dependencyScanner-f6grrep3.js")).TypeScriptDependencyScanner.from(exec);
1130
+ var createDependencyScanner = async (exec) => (await import("./dependencyScanner-rbs2407b.js")).TypeScriptDependencyScanner.from(exec);
991
1131
  var isAllowedTestFile = (filename) => testFilePattern.test(filename);
992
- var isAllowedLibRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
993
1132
  var getScanPath = (exec, relativePath) => path4.posix.join(`${exec.type}s`, exec.name, relativePath.split(path4.sep).join("/"));
994
1133
  async function clearGeneratedRootCapacitorConfigs(exec) {
995
1134
  if (exec.type !== "app")
@@ -1006,17 +1145,20 @@ async function assertScanConvention(exec, libRoot) {
1006
1145
  const addViolation = (relativePath, reason) => {
1007
1146
  violations.push(`${getScanPath(exec, relativePath)}: ${reason}`);
1008
1147
  };
1009
- if (exec.type === "app") {
1010
- const { files, dirs } = await exec.getFilesAndDirs(".");
1011
- files.filter((filename) => !appRootAllowedFiles.has(filename)).forEach((filename) => {
1012
- addViolation(filename, "unsupported app root file");
1013
- });
1014
- dirs.filter((dirname) => !appRootAllowedDirs.has(dirname)).forEach((dirname) => {
1015
- addViolation(dirname, "unsupported app root folder");
1016
- });
1017
- }
1018
- libRoot.files.filter((filename) => !isAllowedLibRootFile(filename)).forEach((filename) => {
1019
- addViolation(path4.join("lib", filename), "unsupported lib root file");
1148
+ const allowedRootFiles = rootAllowedFiles[exec.type];
1149
+ const allowedRootDirs = rootAllowedDirs[exec.type];
1150
+ const { files, dirs } = await exec.getFilesAndDirs(".");
1151
+ files.filter((filename) => !allowedRootFiles.has(filename)).forEach((filename) => {
1152
+ addViolation(filename, `unsupported ${exec.type} root file`);
1153
+ });
1154
+ dirs.filter((dirname) => !allowedRootDirs.has(dirname)).forEach((dirname) => {
1155
+ addViolation(dirname, `unsupported ${exec.type} root folder`);
1156
+ });
1157
+ if (exec.type === "lib")
1158
+ for (const { relativePath, reason } of await exec.getPageConventionViolations())
1159
+ addViolation(relativePath, reason);
1160
+ libRoot.files.filter((filename) => !isAllowedLibFacetRootFile(filename)).forEach((filename) => {
1161
+ addViolation(path4.join("lib", filename), "unsupported lib facet root file");
1020
1162
  });
1021
1163
  libRoot.dirs.filter((dirname) => dirname.startsWith("__") && !internalLibDirs.has(dirname)).forEach((dirname) => {
1022
1164
  addViolation(path4.join("lib", dirname), "unsupported internal lib folder");
@@ -1196,12 +1338,11 @@ class ScanInfo {
1196
1338
  })
1197
1339
  ]);
1198
1340
  const routes = exec.type === "lib" ? [] : await exec.getPageKeys();
1199
- const scanResult = {
1341
+ const common = {
1200
1342
  name: exec.name,
1201
1343
  type: exec.type,
1202
1344
  repoName: exec.workspace.repoName,
1203
1345
  serveDomain: WorkspaceExecutor.getBaseDevEnv(path4.join(exec.workspace.workspaceRoot, ".env")).serveDomain,
1204
- akanConfig: akanConfig2,
1205
1346
  files,
1206
1347
  libDeps,
1207
1348
  pkgDeps,
@@ -1209,6 +1350,7 @@ class ScanInfo {
1209
1350
  devDependencies: npmDevDeps.filter((dep) => !isAkanFrameworkDependency(dep)),
1210
1351
  routes
1211
1352
  };
1353
+ const scanResult = akanConfig2 instanceof AkanAppConfig ? { ...common, akanConfig: akanConfig2 } : { ...common, akanConfig: akanConfig2 };
1212
1354
  return scanResult;
1213
1355
  }
1214
1356
  constructor(scanResult) {
@@ -1634,7 +1776,7 @@ class Executor {
1634
1776
  }));
1635
1777
  });
1636
1778
  proc.on("exit", (code, signal) => {
1637
- if (!!code || signal)
1779
+ if (code || signal)
1638
1780
  reject(new CommandExecutionError({
1639
1781
  command,
1640
1782
  cwd,
@@ -1732,7 +1874,7 @@ class Executor {
1732
1874
  }));
1733
1875
  });
1734
1876
  proc.on("exit", (code, signal) => {
1735
- if (!!code || signal)
1877
+ if (code || signal)
1736
1878
  reject(new CommandExecutionError({
1737
1879
  command: modulePath,
1738
1880
  args,
@@ -1819,7 +1961,8 @@ class Executor {
1819
1961
  const dir = path5.dirname(writePath);
1820
1962
  if (!await FileSys.dirExists(dir))
1821
1963
  await mkdir(dir, { recursive: true });
1822
- let contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2);
1964
+ let contentStr = typeof content === "string" ? content : `${JSON.stringify(content, null, 2)}
1965
+ `;
1823
1966
  if (await FileSys.fileExists(writePath)) {
1824
1967
  const currentContent = await FileSys.readText(writePath);
1825
1968
  if (currentContent === contentStr || !overwrite) {
@@ -2028,7 +2171,7 @@ class Executor {
2028
2171
  return this._applyTemplate({ ...options, dict });
2029
2172
  }
2030
2173
  async getTypeChecker() {
2031
- const { TypeChecker } = await import("./typeChecker-kravn7ns.js");
2174
+ const { TypeChecker } = await import("./typeChecker-g6bh0xfv.js");
2032
2175
  this.typeChecker ??= new TypeChecker(this);
2033
2176
  return this.typeChecker;
2034
2177
  }
@@ -2109,7 +2252,7 @@ class WorkspaceExecutor extends Executor {
2109
2252
  static #execs = new Map;
2110
2253
  static fromRoot({
2111
2254
  workspaceRoot = process.cwd(),
2112
- repoName = path5.basename(process.cwd())
2255
+ repoName = resolveRepoName(workspaceRoot)
2113
2256
  } = {}) {
2114
2257
  return WorkspaceExecutor.#execs.get(repoName) ?? new WorkspaceExecutor({ workspaceRoot, repoName });
2115
2258
  }
@@ -2297,6 +2440,18 @@ class SysExecutor extends Executor {
2297
2440
  const path6 = this.type === "app" ? `apps/${this.name}/lib` : `libs/${this.name}/lib`;
2298
2441
  return await this.workspace.getDirInModule(path6, this.name);
2299
2442
  }
2443
+ async getPageConventionViolations() {
2444
+ if (!await this.exists("page"))
2445
+ return [];
2446
+ const violations = [];
2447
+ for (const entry of await this.getAllFiles("**/*", { cwd: this.getPath("page") })) {
2448
+ const relativePath = entry.split(path5.sep).join("/");
2449
+ const reason = getPageSourceFileViolation(relativePath);
2450
+ if (reason)
2451
+ violations.push({ relativePath: `page/${relativePath}`, reason });
2452
+ }
2453
+ return violations;
2454
+ }
2300
2455
  #scanInfo = null;
2301
2456
  hasScanInfo() {
2302
2457
  return this.#scanInfo !== null;
@@ -2485,7 +2640,7 @@ class SysExecutor extends Executor {
2485
2640
  class AppExecutor extends SysExecutor {
2486
2641
  static #routeSourceValidator = null;
2487
2642
  static async#getRouteSourceValidator() {
2488
- AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-e4jmbfcx.js")).RouteSourceValidator;
2643
+ AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-7fycdqyv.js")).RouteSourceValidator;
2489
2644
  return AppExecutor.#routeSourceValidator;
2490
2645
  }
2491
2646
  dist;
@@ -2549,10 +2704,15 @@ class AppExecutor extends SysExecutor {
2549
2704
  await Promise.all([this.dist.mkdir("private"), this.dist.mkdir("public")]);
2550
2705
  await Promise.all([
2551
2706
  this.cp("private", `${this.dist.cwdPath}/private`, { dereference: true }),
2552
- this.cp("public", `${this.dist.cwdPath}/public`, { dereference: true })
2707
+ ...akanConfig2.web.ssr ? [this.cp("public", `${this.dist.cwdPath}/public`, { dereference: true })] : []
2553
2708
  ]);
2554
- } else
2709
+ } else {
2555
2710
  await this.removeDir(".akan");
2711
+ if (!akanConfig2.web.ssr || !akanConfig2.web.csr)
2712
+ this.logger.verbose(`akan.config.ts disables web.${!akanConfig2.web.ssr ? "ssr" : "csr"}; \`akan start\` still serves it, \`akan build\` will not`);
2713
+ }
2714
+ if (type === "start")
2715
+ process.env.NODE_ENV = "development";
2556
2716
  const devPort = type === "start" ? (await this.getDevPort()).toString() : undefined;
2557
2717
  const env = this.getCommandEnv({
2558
2718
  AKAN_COMMAND_TYPE: type,
@@ -2641,7 +2801,8 @@ class AppExecutor extends SysExecutor {
2641
2801
  }
2642
2802
  if (!owner)
2643
2803
  owners.set(routeId, { absPath, fromLib });
2644
- const isRootLayout = parsed.kind === "layout" && parsed.moduleSegments.at(-1) === "_layout";
2804
+ const layoutSegments = getRootBoundarySegments(key);
2805
+ const isRootLayout = layoutSegments !== null && isRootBoundarySegments(layoutSegments, akanConfig2.basePaths);
2645
2806
  const routeSource = await Bun.file(absPath).text();
2646
2807
  const validator = await AppExecutor.#getRouteSourceValidator();
2647
2808
  if (parsed.kind === "overrides")
@@ -2869,7 +3030,7 @@ class LibExecutor extends SysExecutor {
2869
3030
  async getConfig({ refresh } = {}) {
2870
3031
  if (this.#akanConfig && !refresh)
2871
3032
  return this.#akanConfig;
2872
- this.#akanConfig = await AkanLibConfig.from(this);
3033
+ this.#akanConfig = await AkanLibConfig.from(this, { bustImportCache: refresh });
2873
3034
  return this.#akanConfig;
2874
3035
  }
2875
3036
  }
@@ -2966,7 +3127,7 @@ class PkgExecutor extends Executor {
2966
3127
  default: "./index.ts"
2967
3128
  }
2968
3129
  },
2969
- engines: { bun: ">=1.3.13" },
3130
+ engines: { bun: ">=1.4.0" },
2970
3131
  ...dependencyMaps
2971
3132
  };
2972
3133
  await Promise.all([this.dist.writeJson("package.json", distPkgJson), this.writeJson("package.json", distPkgJson)]);
@@ -3009,4 +3170,4 @@ class ModuleExecutor extends Executor {
3009
3170
  }
3010
3171
  }
3011
3172
 
3012
- export { AGENT_BLOCK_START, AGENT_BLOCK_END, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, getDirname, appRootAllowedFiles, appRootAllowedDirs, libFacetRootAllowedFiles, isScannedAppRootEntry, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
3173
+ export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, isScannedRootEntry, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };