@akanjs/cli 3.0.0-alpha.2 → 3.0.0-alpha.21

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 (101) 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-yv00p0s0.js → agent.command-g92sg0pw.js} +8 -7
  6. package/{application.command-0qsczf4k.js → application.command-8snsrzks.js} +6 -5
  7. package/{applicationBuildRunner-ct2pxyvw.js → applicationBuildRunner-7gnfz7ww.js} +6 -7
  8. package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-93nzdfsy.js} +1 -1
  9. package/buildBatch.proc.js +5 -4
  10. package/{capacitorApp-4r9sm3qg.js → capacitorApp-hyz5hypv.js} +29 -26
  11. package/{cloud.command-dxfv18sa.js → cloud.command-27tan2c5.js} +10 -9
  12. package/{context.command-8d9e3k6b.js → context.command-x0ms4783.js} +16 -15
  13. package/{dependencyScanner-f6grrep3.js → dependencyScanner-rbs2407b.js} +1 -1
  14. package/getDirname-ka11hm7e.js +8 -0
  15. package/{guideline.command-3jbkxzh6.js → guideline.command-1vadc7m2.js} +7 -6
  16. package/guidelines/conventions/conventions.generate.json +25 -0
  17. package/guidelines/conventions/conventions.instruction.md +909 -0
  18. package/guidelines/cssRule/cssRule.instruction.md +7 -0
  19. package/guidelines/framework/framework.instruction.md +1 -0
  20. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +24 -0
  21. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +972 -0
  22. package/incrementalBuilder.proc.js +4 -3
  23. package/index-1577bej2.js +7 -0
  24. package/{index-1pvex4az.js → index-1brb6fhj.js} +13 -13
  25. package/{index-2q1f5j9k.js → index-3taw6vhk.js} +3 -3
  26. package/{index-k95xkh4p.js → index-4zbcwnr4.js} +8 -4
  27. package/{index-a00jg8x8.js → index-68ynenz3.js} +49 -32
  28. package/{index-yzmhasdb.js → index-72jn9p18.js} +8 -8
  29. package/{index-8hsbnyes.js → index-91va923f.js} +5 -3
  30. package/{index-rzwcpcc3.js → index-cfzvtfwp.js} +1 -1
  31. package/{index-7c6k4yvg.js → index-cmffkxcx.js} +15 -7
  32. package/{index-ec09pws3.js → index-cxf04znn.js} +4 -4
  33. package/{index-nm6wghb6.js → index-dc8y2vae.js} +6 -6
  34. package/{index-bbkek1bp.js → index-f8qt4sdr.js} +1 -1
  35. package/{index-hgna5rjy.js → index-gn6jc5kp.js} +141 -65
  36. package/{index-t3723f99.js → index-hbm5htq0.js} +86 -17
  37. package/{index-pyt2b4nw.js → index-hg0qvhmx.js} +152 -241
  38. package/{index-tdbas9r0.js → index-j37qq1f2.js} +1 -1
  39. package/{index-mr5s7mqd.js → index-krmp6zdm.js} +3 -3
  40. package/{index-bekddz9q.js → index-prq4dmbf.js} +4 -4
  41. package/{index-rh16j3c7.js → index-qnv0aqmm.js} +12 -8
  42. package/{index-0cj2zxbm.js → index-sh01r3pm.js} +1 -1
  43. package/{index-zasydjxd.js → index-vbvnq3cr.js} +9 -11
  44. package/{index-ej426mcr.js → index-w4gzpx6w.js} +37 -6
  45. package/{index-e16gnn26.js → index-zyk0731f.js} +12 -12
  46. package/index.js +20 -19
  47. package/{library.command-ebdj1vnm.js → library.command-eszvmj60.js} +5 -4
  48. package/{localRegistry.command-gb178ne8.js → localRegistry.command-t4yksc4z.js} +9 -8
  49. package/{module.command-9c1bnsx4.js → module.command-7nezmr8d.js} +9 -8
  50. package/{package.command-t93p4jkj.js → package.command-vtyf9kgj.js} +5 -4
  51. package/package.json +3 -4
  52. package/{page.command-k3k0meh2.js → page.command-08kg25hh.js} +5 -4
  53. package/{primitive.command-de6nktdt.js → primitive.command-er9zkjhd.js} +10 -9
  54. package/{quality.command-z5kth2wa.js → quality.command-ntyzf8vz.js} +11 -41
  55. package/{recipeScanner-tghkzrrt.js → recipeScanner-zrzev25x.js} +3 -3
  56. package/{repair.command-ehf2g112.js → repair.command-sfn4msje.js} +7 -6
  57. package/{routeSourceValidator-cncd92fv.js → routeSourceValidator-7fycdqyv.js} +3 -39
  58. package/{scalar.command-7a2jtv33.js → scalar.command-mxvqc069.js} +8 -7
  59. package/templates/app/page/styles.css.template +3 -3
  60. package/templates/appSample/srvkit/AuthGuard.ts +9 -5
  61. package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
  62. package/templates/crudPages/[__model__Id]/edit/page.tsx +1 -1
  63. package/templates/crudPages/new/page.tsx +1 -1
  64. package/templates/crudSinglePage/page.tsx +1 -1
  65. package/templates/env/_env.server.type.ts +7 -4
  66. package/templates/lib/db.ts +1 -1
  67. package/templates/lib/dict.ts +1 -1
  68. package/templates/lib/sig.ts +1 -1
  69. package/templates/lib/srv.ts +7 -3
  70. package/templates/lib/useClient.ts +9 -3
  71. package/templates/module/__Model__.Util.tsx +1 -1
  72. package/templates/module/__Model__.Zone.tsx +3 -5
  73. package/templates/workspaceRoot/AGENTS.md.template +0 -955
  74. package/templates/workspaceRoot/CLAUDE.md.template +19 -0
  75. package/templates/workspaceRoot/biome.json.template +4 -198
  76. package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +4 -1
  77. package/{typeChecker-kravn7ns.js → typeChecker-g6bh0xfv.js} +1 -1
  78. package/typecheck.proc.js +1 -1
  79. package/{workflow.command-e0tt0vk2.js → workflow.command-y7vg1hx2.js} +15 -14
  80. package/{workspace.command-fpda0evj.js → workspace.command-bjf247fv.js} +69 -51
  81. package/templates/workspaceRoot/.cursor/rules/akan-page-routing.mdc.template +0 -43
  82. package/templates/workspaceRoot/.cursor/rules/akan-sync-conventions.mdc.template +0 -33
  83. package/templates/workspaceRoot/.cursor/rules/application-test-commands.mdc.template +0 -16
  84. package/templates/workspaceRoot/.cursor/rules/change-scope.mdc.template +0 -12
  85. package/templates/workspaceRoot/.cursor/rules/client-server-boundaries.mdc.template +0 -18
  86. package/templates/workspaceRoot/.cursor/rules/coding-comments.mdc.template +0 -25
  87. package/templates/workspaceRoot/.cursor/rules/coding-style.mdc.template +0 -44
  88. package/templates/workspaceRoot/.cursor/rules/domain-module-conventions.mdc.template +0 -17
  89. package/templates/workspaceRoot/.cursor/rules/format-lint.mdc.template +0 -12
  90. package/templates/workspaceRoot/.cursor/rules/lint-enforced-rules.mdc.template +0 -18
  91. package/templates/workspaceRoot/.cursor/rules/module-file-playbook.mdc.template +0 -61
  92. package/templates/workspaceRoot/.cursor/rules/naming-conventions.mdc.template +0 -15
  93. package/templates/workspaceRoot/.cursor/rules/react-component-style.mdc.template +0 -21
  94. package/templates/workspaceRoot/.cursor/rules/repo-overview.mdc.template +0 -17
  95. package/templates/workspaceRoot/.cursor/rules/scalar-modeling.mdc.template +0 -58
  96. package/templates/workspaceRoot/.cursor/rules/secrets-and-env.mdc.template +0 -13
  97. package/templates/workspaceRoot/.cursor/rules/service-signal-conventions.mdc.template +0 -83
  98. package/templates/workspaceRoot/.cursor/rules/srvkit-adapters-and-guards.mdc.template +0 -50
  99. package/templates/workspaceRoot/.cursor/rules/ssr-first.mdc.template +0 -59
  100. package/templates/workspaceRoot/.cursor/rules/typescript-imports.mdc.template +0 -16
  101. /package/{index-r24hmh0q.js → index-yb2wsc7f.js} +0 -0
@@ -2,12 +2,15 @@
2
2
  import {
3
3
  Spinner
4
4
  } from "./index-mxvakhsm.js";
5
+ import {
6
+ getDirname
7
+ } from "./index-1577bej2.js";
5
8
  import {
6
9
  FileSys
7
10
  } from "./index-67546d0j.js";
8
11
  import {
9
12
  __require
10
- } from "./index-r24hmh0q.js";
13
+ } from "./index-yb2wsc7f.js";
11
14
 
12
15
  // pkgs/@akanjs/devkit/executors.ts
13
16
  import {
@@ -41,9 +44,24 @@ import chalk2 from "chalk";
41
44
 
42
45
  // pkgs/@akanjs/devkit/agentsIndex.ts
43
46
  var recipeScannerLoad = null;
44
- var loadRecipeScanner = () => recipeScannerLoad ??= import("./recipeScanner-tghkzrrt.js");
47
+ var loadRecipeScanner = () => recipeScannerLoad ??= import("./recipeScanner-zrzev25x.js");
45
48
  var AGENT_BLOCK_START = "<!-- akan:agent:start -->";
46
49
  var AGENT_BLOCK_END = "<!-- akan:agent:end -->";
50
+ var AGENT_VERSION_PREFIX = "<!-- akan:agent:version ";
51
+ var stampBlockVersion = (block, version) => `${AGENT_VERSION_PREFIX}${version} -->
52
+
53
+ ${block}`;
54
+ var extractBlockVersion = (content) => content.match(/<!-- akan:agent:version ([^\s]+) -->/)?.[1] ?? null;
55
+ var readDevkitVersion = async () => {
56
+ const { readFile } = await import("fs/promises");
57
+ const { getDirname: getDirname2 } = await import("./getDirname-ka11hm7e.js");
58
+ try {
59
+ const raw = await readFile(`${getDirname2(import.meta.url)}/package.json`, "utf-8");
60
+ return JSON.parse(raw).version ?? null;
61
+ } catch {
62
+ return null;
63
+ }
64
+ };
47
65
  var upsertAgentBlock = (existing, block) => {
48
66
  const managed = `${AGENT_BLOCK_START}
49
67
  ${block}
@@ -137,9 +155,29 @@ ${AGENT_BLOCK_START}
137
155
  ${block}
138
156
  ${AGENT_BLOCK_END}
139
157
  `;
158
+ var CLAUDE_COMMENT_RULE = `## Comments \u2014 Overrides Your Default
159
+
160
+ Write **no comments** unless the comment passes the test below. This is the rule agents break most often here, so it
161
+ is repeated outside the guide: a diff that adds a comment the test rejects is a diff to redo.
162
+
163
+ Before typing \`//\`, \`/*\`, or a doc block, ask \u2014 **does this sentence carry a fact that is nowhere in the code?**
164
+
165
+ - Restates the identifier, the signature, or the line under it \u2192 delete it.
166
+ - Labels a section (\`// helpers\`, \`// state\`) or narrates a step (\`// fetch the user\`, \`// then save\`) \u2192 delete it.
167
+ - JSDoc on an ordinary function, or a why/how preamble on ordinary logic \u2192 delete it.
168
+ - Explains the edit you just made, for whoever reads the diff \u2192 say it in your reply, not in the file.
169
+ - Names a vendor or protocol quirk, an infrastructure constraint, a library gotcha, security reasoning, a math
170
+ derivation, a domain field's business meaning, a state transition, or why an obvious alternative was rejected \u2192
171
+ keep it, one line.
172
+
173
+ That keep-list is exact \u2014 \`Comments\` in the guide is the full version. "It aids readability" and "this logic is
174
+ subtle" are not on it: rename or split the code instead. When you edit an existing file, match its density; if the
175
+ surrounding code carries none, your diff carries none.`;
140
176
  var renderScopeClaudeMd = (scope) => `# ${scope.name} \u2014 Claude Code Guide
141
177
 
142
178
  @AGENTS.md
179
+
180
+ ${CLAUDE_COMMENT_RULE}
143
181
  `;
144
182
 
145
183
  // pkgs/@akanjs/devkit/akanConfig/akanConfig.ts
@@ -182,8 +220,6 @@ var DEFAULT_OPTIMIZE_IMPORTS = [
182
220
  ];
183
221
  var WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"];
184
222
  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
223
  var MOBILE_RUNTIME_PACKAGES = [
188
224
  "@capacitor/cli",
189
225
  "@capacitor/core",
@@ -212,8 +248,6 @@ var DATABASE_MODE_RUNTIME_PACKAGES = {
212
248
  };
213
249
  var AKAN_RUNTIME_PACKAGES = new Set([
214
250
  ...SSR_RUNTIME_PACKAGES,
215
- ...NATIVE_RUNTIME_PACKAGES,
216
- ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
217
251
  ...MOBILE_RUNTIME_PACKAGES,
218
252
  ...Object.values(DATABASE_MODE_RUNTIME_PACKAGES).flat()
219
253
  ]);
@@ -505,13 +539,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
505
539
  return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
506
540
  }
507
541
  #getProductionRuntimePackages() {
508
- return [
509
- ...this.externalLibs,
510
- ...SSR_RUNTIME_PACKAGES,
511
- ...NATIVE_RUNTIME_PACKAGES,
512
- ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
513
- ...this.getDatabaseModeRuntimePackages()
514
- ];
542
+ return [...this.externalLibs, ...SSR_RUNTIME_PACKAGES, ...this.getDatabaseModeRuntimePackages()];
515
543
  }
516
544
  getDatabaseModeRuntimePackages(databaseMode = this.defaultDatabaseMode) {
517
545
  return [...DATABASE_MODE_RUNTIME_PACKAGES[databaseMode]];
@@ -627,42 +655,47 @@ var decreaseBuildNum = async (app) => {
627
655
  const akanConfigContent = akanConfig.replace(`buildNum: ${appConfig.mobile.buildNum}`, `buildNum: ${appConfig.mobile.buildNum - 1}`);
628
656
  fs.writeFileSync(akanConfigPath, akanConfigContent);
629
657
  };
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
658
  // pkgs/@akanjs/devkit/linter.ts
636
659
  import { spawn } from "child_process";
637
660
  import { existsSync, readFileSync } from "fs";
638
- import path3 from "path";
661
+ import path2 from "path";
639
662
  import chalk from "chalk";
663
+ var BIOME_CONFIG_FILES = ["biome.json", "biome.jsonc"];
640
664
 
641
665
  class Linter {
642
666
  lintRoot;
667
+ configPath;
643
668
  #biomeBin;
644
669
  constructor(cwdPath) {
645
670
  this.lintRoot = this.#findBiomeRootPath(cwdPath);
646
- const localBiomeBin = path3.join(this.lintRoot, "node_modules/.bin/biome");
671
+ this.configPath = Linter.#configPathIn(this.lintRoot) ?? path2.join(this.lintRoot, "biome.json");
672
+ const localBiomeBin = path2.join(this.lintRoot, "node_modules/.bin/biome");
647
673
  this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
648
674
  }
675
+ static #configPathIn(dir) {
676
+ for (const fileName of BIOME_CONFIG_FILES) {
677
+ const configPath = path2.join(dir, fileName);
678
+ if (existsSync(configPath))
679
+ return configPath;
680
+ }
681
+ return null;
682
+ }
649
683
  #findBiomeRootPath(dir) {
650
- const configPath = path3.join(dir, "biome.json");
651
- if (existsSync(configPath))
684
+ if (Linter.#configPathIn(dir))
652
685
  return dir;
653
- const parentDir = path3.dirname(dir);
686
+ const parentDir = path2.dirname(dir);
654
687
  if (parentDir === dir)
655
688
  throw new Error(`biome.json not found from ${dir}`);
656
689
  return this.#findBiomeRootPath(parentDir);
657
690
  }
658
691
  #toBiomePath(filePath) {
659
- const relativePath = path3.relative(this.lintRoot, filePath);
660
- if (!relativePath.startsWith("..") && !path3.isAbsolute(relativePath))
692
+ const relativePath = path2.relative(this.lintRoot, filePath);
693
+ if (!relativePath.startsWith("..") && !path2.isAbsolute(relativePath))
661
694
  return relativePath;
662
695
  return filePath;
663
696
  }
664
697
  #resolveFilePath(filePath) {
665
- return path3.isAbsolute(filePath) ? filePath : path3.join(this.lintRoot, filePath);
698
+ return path2.isAbsolute(filePath) ? filePath : path2.join(this.lintRoot, filePath);
666
699
  }
667
700
  async#runBiome(args, input) {
668
701
  return await new Promise((resolve, reject) => {
@@ -694,7 +727,7 @@ class Linter {
694
727
  const diagnosticPath = diagnostic.location?.path;
695
728
  if (!diagnosticPath)
696
729
  return fallbackFilePath;
697
- return path3.isAbsolute(diagnosticPath) ? diagnosticPath : path3.join(this.lintRoot, diagnosticPath);
730
+ return path2.isAbsolute(diagnosticPath) ? diagnosticPath : path2.join(this.lintRoot, diagnosticPath);
698
731
  }
699
732
  #createLintMessage(diagnostic) {
700
733
  const start = diagnostic.location?.start;
@@ -759,7 +792,7 @@ class Linter {
759
792
  "--max-diagnostics=none",
760
793
  "--no-errors-on-unmatched",
761
794
  "--config-path",
762
- path3.join(this.lintRoot, "biome.json"),
795
+ this.configPath,
763
796
  this.#toBiomePath(filePath)
764
797
  ]);
765
798
  const report = this.#parseBiomeReport(stdout || stderr);
@@ -880,14 +913,7 @@ ${errorText}, ${warningText} found`];
880
913
  if (!dryRun)
881
914
  return await this.#checkFile(resolvedFilePath, { write: true });
882
915
  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);
916
+ const { stdout } = await this.#runBiome(["check", "--write", "--config-path", this.configPath, "--stdin-file-path", this.#toBiomePath(resolvedFilePath)], source);
891
917
  const lintResult = await this.lintFile(resolvedFilePath);
892
918
  return { ...lintResult, fixed: stdout !== source, output: stdout };
893
919
  }
@@ -895,7 +921,7 @@ ${errorText}, ${warningText} found`];
895
921
  const resolvedFilePath = this.#resolveFilePath(filePath);
896
922
  if (!existsSync(resolvedFilePath))
897
923
  throw new Error(`File not found: ${filePath}`);
898
- return JSON.parse(readFileSync(path3.join(this.lintRoot, "biome.json"), "utf8"));
924
+ return JSON.parse(readFileSync(this.configPath, "utf8"));
899
925
  }
900
926
  async getProblematicRules(filePath) {
901
927
  const { results } = await this.lintFile(filePath);
@@ -910,22 +936,36 @@ ${errorText}, ${warningText} found`];
910
936
  }
911
937
  }
912
938
 
939
+ // pkgs/@akanjs/devkit/repoIdentity.ts
940
+ import { execFileSync } from "child_process";
941
+ import path3 from "path";
942
+ var resolved = new Map;
943
+ var readRemoteName = (workspaceRoot) => {
944
+ try {
945
+ const url = execFileSync("git", ["config", "--get", "remote.origin.url"], {
946
+ cwd: workspaceRoot,
947
+ encoding: "utf-8",
948
+ stdio: ["ignore", "pipe", "ignore"]
949
+ }).trim();
950
+ return url.replace(/\.git$/, "").split(/[/:]/).pop() || null;
951
+ } catch {
952
+ return null;
953
+ }
954
+ };
955
+ var resolveRepoName = (workspaceRoot) => {
956
+ const cached = resolved.get(workspaceRoot);
957
+ if (cached)
958
+ return cached;
959
+ const repoName = readRemoteName(workspaceRoot) ?? path3.basename(workspaceRoot);
960
+ resolved.set(workspaceRoot, repoName);
961
+ return repoName;
962
+ };
963
+
913
964
  // pkgs/@akanjs/devkit/scanInfo.ts
914
965
  import { rm } from "fs/promises";
915
966
  import path4 from "path";
916
- var databaseFileTypes = [
917
- "constant",
918
- "dictionary",
919
- "document",
920
- "service",
921
- "signal",
922
- "store",
923
- "template",
924
- "unit",
925
- "util",
926
- "view",
927
- "zone"
928
- ];
967
+
968
+ // pkgs/@akanjs/devkit/workspaceLayout.ts
929
969
  var appRootAllowedFiles = new Set([
930
970
  "AGENTS.md",
931
971
  "CLAUDE.md",
@@ -939,25 +979,25 @@ var appRootAllowedFiles = new Set([
939
979
  "tsconfig.json",
940
980
  "tsconfig.tsbuildinfo"
941
981
  ]);
942
- var generatedRootCapacitorConfigFiles = ["capacitor.config.js", "capacitor.config.json"];
943
982
  var appRootAllowedDirs = new Set([
944
983
  ".akan",
945
984
  "android",
985
+ "common",
946
986
  "env",
947
987
  "ios",
948
988
  "lib",
949
989
  "mobile",
950
990
  "page",
991
+ "plugin",
951
992
  "private",
952
993
  "public",
953
994
  "script",
954
- "ui",
995
+ "secrets",
955
996
  "srvkit",
956
- "webkit",
957
- "common",
958
- "secrets"
997
+ "ui",
998
+ "webkit"
959
999
  ]);
960
- var libRootAllowedFiles = new Set([
1000
+ var libFacetRootAllowedFiles = new Set([
961
1001
  "cnst.ts",
962
1002
  "db.ts",
963
1003
  "dict.ts",
@@ -968,6 +1008,23 @@ var libRootAllowedFiles = new Set([
968
1008
  "useClient.ts",
969
1009
  "useServer.ts"
970
1010
  ]);
1011
+ var isScannedAppRootEntry = (name) => !name.startsWith(".") || appRootAllowedDirs.has(name);
1012
+
1013
+ // pkgs/@akanjs/devkit/scanInfo.ts
1014
+ var databaseFileTypes = [
1015
+ "constant",
1016
+ "dictionary",
1017
+ "document",
1018
+ "service",
1019
+ "signal",
1020
+ "store",
1021
+ "template",
1022
+ "unit",
1023
+ "util",
1024
+ "view",
1025
+ "zone"
1026
+ ];
1027
+ var generatedRootCapacitorConfigFiles = ["capacitor.config.js", "capacitor.config.json"];
971
1028
  var internalLibDirs = new Set(["__lib", "__scalar"]);
972
1029
  var moduleNonUiFileTypes = {
973
1030
  database: new Set(["constant", "dictionary", "document", "service", "signal", "store"]),
@@ -981,9 +1038,9 @@ var moduleUiFileTypes = {
981
1038
  };
982
1039
  var testFilePattern = /\.(test|spec)\.(ts|tsx)$/;
983
1040
  var rootSignalTestFilePattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
984
- var createDependencyScanner = async (exec) => (await import("./dependencyScanner-f6grrep3.js")).TypeScriptDependencyScanner.from(exec);
1041
+ var createDependencyScanner = async (exec) => (await import("./dependencyScanner-rbs2407b.js")).TypeScriptDependencyScanner.from(exec);
985
1042
  var isAllowedTestFile = (filename) => testFilePattern.test(filename);
986
- var isAllowedLibRootFile = (filename) => libRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
1043
+ var isAllowedLibRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
987
1044
  var getScanPath = (exec, relativePath) => path4.posix.join(`${exec.type}s`, exec.name, relativePath.split(path4.sep).join("/"));
988
1045
  async function clearGeneratedRootCapacitorConfigs(exec) {
989
1046
  if (exec.type !== "app")
@@ -1628,7 +1685,7 @@ class Executor {
1628
1685
  }));
1629
1686
  });
1630
1687
  proc.on("exit", (code, signal) => {
1631
- if (!!code || signal)
1688
+ if (code || signal)
1632
1689
  reject(new CommandExecutionError({
1633
1690
  command,
1634
1691
  cwd,
@@ -1726,7 +1783,7 @@ class Executor {
1726
1783
  }));
1727
1784
  });
1728
1785
  proc.on("exit", (code, signal) => {
1729
- if (!!code || signal)
1786
+ if (code || signal)
1730
1787
  reject(new CommandExecutionError({
1731
1788
  command: modulePath,
1732
1789
  args,
@@ -2022,7 +2079,7 @@ class Executor {
2022
2079
  return this._applyTemplate({ ...options, dict });
2023
2080
  }
2024
2081
  async getTypeChecker() {
2025
- const { TypeChecker } = await import("./typeChecker-kravn7ns.js");
2082
+ const { TypeChecker } = await import("./typeChecker-g6bh0xfv.js");
2026
2083
  this.typeChecker ??= new TypeChecker(this);
2027
2084
  return this.typeChecker;
2028
2085
  }
@@ -2103,7 +2160,7 @@ class WorkspaceExecutor extends Executor {
2103
2160
  static #execs = new Map;
2104
2161
  static fromRoot({
2105
2162
  workspaceRoot = process.cwd(),
2106
- repoName = path5.basename(process.cwd())
2163
+ repoName = resolveRepoName(workspaceRoot)
2107
2164
  } = {}) {
2108
2165
  return WorkspaceExecutor.#execs.get(repoName) ?? new WorkspaceExecutor({ workspaceRoot, repoName });
2109
2166
  }
@@ -2475,11 +2532,12 @@ class SysExecutor extends Executor {
2475
2532
  return fileContents;
2476
2533
  }
2477
2534
  }
2535
+ var bootAppName = process.env.AKAN_PUBLIC_APP_NAME;
2478
2536
 
2479
2537
  class AppExecutor extends SysExecutor {
2480
2538
  static #routeSourceValidator = null;
2481
2539
  static async#getRouteSourceValidator() {
2482
- AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-cncd92fv.js")).RouteSourceValidator;
2540
+ AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-7fycdqyv.js")).RouteSourceValidator;
2483
2541
  return AppExecutor.#routeSourceValidator;
2484
2542
  }
2485
2543
  dist;
@@ -2527,6 +2585,22 @@ class AppExecutor extends SysExecutor {
2527
2585
  ...env
2528
2586
  };
2529
2587
  }
2588
+ static shouldRelaunchForAppEnv(appName, bootName = bootAppName, marker = process.env.AKAN_BUILD_RELAUNCHED) {
2589
+ if (marker === "1")
2590
+ return false;
2591
+ return bootName !== appName;
2592
+ }
2593
+ async relaunchWithAppEnv() {
2594
+ if (!AppExecutor.shouldRelaunchForAppEnv(this.name))
2595
+ return null;
2596
+ const child = Bun.spawn([process.execPath, ...process.argv.slice(1)], {
2597
+ env: { ...this.getCommandEnv(), AKAN_PUBLIC_APP_NAME: this.name, AKAN_BUILD_RELAUNCHED: "1" },
2598
+ stdin: "inherit",
2599
+ stdout: "inherit",
2600
+ stderr: "inherit"
2601
+ });
2602
+ return await child.exited;
2603
+ }
2530
2604
  async prepareCommand(type) {
2531
2605
  const akanConfig2 = await this.getConfig();
2532
2606
  const databaseMode = process.env.AKAN_DATABASE_MODE ?? akanConfig2.defaultDatabaseMode ?? "single";
@@ -2547,6 +2621,8 @@ class AppExecutor extends SysExecutor {
2547
2621
  ]);
2548
2622
  } else
2549
2623
  await this.removeDir(".akan");
2624
+ if (type === "start")
2625
+ process.env.NODE_ENV = "development";
2550
2626
  const devPort = type === "start" ? (await this.getDevPort()).toString() : undefined;
2551
2627
  const env = this.getCommandEnv({
2552
2628
  AKAN_COMMAND_TYPE: type,
@@ -2960,7 +3036,7 @@ class PkgExecutor extends Executor {
2960
3036
  default: "./index.ts"
2961
3037
  }
2962
3038
  },
2963
- engines: { bun: ">=1.3.13" },
3039
+ engines: { bun: ">=1.4.0" },
2964
3040
  ...dependencyMaps
2965
3041
  };
2966
3042
  await Promise.all([this.dist.writeJson("package.json", distPkgJson), this.writeJson("package.json", distPkgJson)]);
@@ -3003,4 +3079,4 @@ class ModuleExecutor extends Executor {
3003
3079
  }
3004
3080
  }
3005
3081
 
3006
- export { AGENT_BLOCK_START, AGENT_BLOCK_END, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, getDirname, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
3082
+ export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, appRootAllowedFiles, appRootAllowedDirs, libFacetRootAllowedFiles, isScannedAppRootEntry, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
@@ -5,7 +5,7 @@ import {
5
5
  } from "./index-76rn3g2c.js";
6
6
  import {
7
7
  CommandExecutionError
8
- } from "./index-hgna5rjy.js";
8
+ } from "./index-gn6jc5kp.js";
9
9
 
10
10
  // pkgs/@akanjs/devkit/capacitorApp.ts
11
11
  import { cp, mkdir, readFile, rm, writeFile } from "fs/promises";
@@ -514,6 +514,10 @@ function getAdbDeviceStateIssues(output) {
514
514
  return [];
515
515
  });
516
516
  }
517
+ function getAndroidLocalServerHost(adbDevicesOutput, fallbackHost) {
518
+ const onlineDeviceIds = adbDevicesOutput?.split(/\r?\n/).map((line) => line.trim().split(/\s+/)).filter(([id, state]) => id && state === "device").map(([id]) => id) ?? [];
519
+ return onlineDeviceIds.length === 1 && onlineDeviceIds[0]?.startsWith("emulator-") ? "10.0.2.2" : fallbackHost;
520
+ }
517
521
  var ANDROID_MIN_SDK_VERSION = 26;
518
522
  function raiseGradleMinSdkVersion(content, floor = ANDROID_MIN_SDK_VERSION) {
519
523
  const match = content.match(/minSdkVersion\s*=\s*(\d+)/);
@@ -691,7 +695,7 @@ class CapacitorApp {
691
695
  async save() {
692
696
  await this.project.commit();
693
697
  }
694
- async#prepareIos({ operation, env, regenerate = false }) {
698
+ async#prepareIos({ operation, env, regenerate = false, iosRunTargetKind }) {
695
699
  await this.init({ platform: "ios", operation, env, regenerate });
696
700
  await this.#prepareTargetAssets();
697
701
  await this.#prepareExternalFiles("ios");
@@ -700,9 +704,10 @@ class CapacitorApp {
700
704
  await this.#applyDeepLinks("ios", { operation, env });
701
705
  await this.#flushIosEntitlements();
702
706
  await this.project.commit();
707
+ await this.#setCodeSignEntitlementsInIosIfExists("App/App.entitlements");
703
708
  await this.#generateAssets({ operation, env });
704
709
  this.app.verbose(`syncing iOS`);
705
- await this.#spawnMobile("npx", ["cap", "sync", "ios"], { operation, env });
710
+ await this.#spawnMobile("npx", ["cap", "sync", "ios"], { operation, env }, { iosRunTargetKind });
706
711
  this.app.verbose(`sync completed.`);
707
712
  }
708
713
  async buildIos({ env = "debug", regenerate = false } = {}) {
@@ -721,10 +726,10 @@ class CapacitorApp {
721
726
  async runIos({ operation, env, regenerate = false, noAllowProvisioningUpdates = false, iosDeviceId }) {
722
727
  if (operation === "release")
723
728
  await this.prepareWww();
724
- await this.#prepareIos({ operation, env, regenerate });
725
729
  const runTarget = await this.#selectIosRunTarget(iosDeviceId);
730
+ await this.#prepareIos({ operation, env, regenerate, iosRunTargetKind: runTarget.kind });
726
731
  if (runTarget.kind === "simulator") {
727
- await this.#spawnMobile("npx", ["cap", "run", "ios", "--target", runTarget.id], { operation, env }, { stdio: "inherit" });
732
+ await this.#spawnMobile("npx", ["cap", "run", "ios", "--target", runTarget.id, "--no-sync"], { operation, env }, { stdio: "inherit", platform: "ios", iosRunTargetKind: runTarget.kind });
728
733
  return;
729
734
  }
730
735
  await this.#runIosPhysicalDevice({ operation, env, runTarget, noAllowProvisioningUpdates });
@@ -800,7 +805,7 @@ ${textError instanceof Error ? textError.message : ""}`);
800
805
  noAllowProvisioningUpdates
801
806
  }) {
802
807
  const mobileEnv = sanitizeIosNativeRunEnv(await this.#commandEnv(operation, env));
803
- const configContent = await this.#writeCapacitorConfig({ operation }, mobileEnv);
808
+ const configContent = await this.#writeCapacitorConfig({ operation, platform: "ios", iosRunTargetKind: runTarget.kind }, mobileEnv);
804
809
  await this.#writeRootCapacitorConfig(configContent);
805
810
  const scheme = this.#iosScheme();
806
811
  const command = buildIosNativeRunCommand({
@@ -857,6 +862,7 @@ ${error.message}`;
857
862
  await this.#applyAndroidMinSdkVersion();
858
863
  await this.#applyPermissions({ operation, env });
859
864
  await this.#applyDeepLinks("android", { operation, env });
865
+ await this.#disableNativeKeyboardResizeInAndroid();
860
866
  await this.project.commit();
861
867
  await this.#generateAssets({ operation, env });
862
868
  await this.#ensureAndroidAssetsDir();
@@ -916,6 +922,23 @@ ${error.message}`;
916
922
  async openAndroid() {
917
923
  await this.#spawnMobile("npx", ["cap", "open", "android"], { operation: "local", env: "local" });
918
924
  }
925
+ async#disableNativeKeyboardResizeInAndroid() {
926
+ const manifestPath = path.join(this.app.cwdPath, this.androidRootPath, "app/src/main/AndroidManifest.xml");
927
+ let manifest = await readFile(manifestPath, "utf8");
928
+ let changed = false;
929
+ manifest = manifest.replace(/<activity\b[^>]*android:name="\.MainActivity"[^>]*>/, (activityTag) => {
930
+ if (activityTag.includes("android:windowSoftInputMode=")) {
931
+ const nextTag = activityTag.replace(/android:windowSoftInputMode="[^"]*"/, 'android:windowSoftInputMode="adjustNothing"');
932
+ changed ||= nextTag !== activityTag;
933
+ return nextTag;
934
+ }
935
+ changed = true;
936
+ return activityTag.replace(/>$/, `
937
+ android:windowSoftInputMode="adjustNothing">`);
938
+ });
939
+ if (changed)
940
+ await writeFile(manifestPath, manifest);
941
+ }
919
942
  async#ensureAndroidAssetsDir() {
920
943
  await mkdir(path.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
921
944
  }
@@ -1005,12 +1028,16 @@ ${error.message}`;
1005
1028
  return html.replace(/<\/head\s*>/i, `${script}
1006
1029
  </head>`);
1007
1030
  }
1008
- async#writeCapacitorConfig({ operation }, commandEnv) {
1031
+ async#writeCapacitorConfig({
1032
+ operation,
1033
+ platform,
1034
+ iosRunTargetKind
1035
+ }, commandEnv) {
1009
1036
  await mkdir(this.targetRoot, { recursive: true });
1010
1037
  let localIp;
1011
1038
  if (operation === "local") {
1012
1039
  const override = commandEnv.AKAN_PUBLIC_CLIENT_HOST ?? process.env.AKAN_PUBLIC_CLIENT_HOST;
1013
- const resolution = selectLocalDevHost(os.networkInterfaces(), { override });
1040
+ const resolution = await this.#resolveLocalDevHost({ override, platform, iosRunTargetKind });
1014
1041
  localIp = resolution.host;
1015
1042
  this.#logDevHostResolution(resolution, commandEnv);
1016
1043
  }
@@ -1024,9 +1051,29 @@ ${error.message}`;
1024
1051
  await Bun.write(path.join(this.targetRoot, "capacitor.config.json"), content);
1025
1052
  return content;
1026
1053
  }
1054
+ async#resolveLocalDevHost({
1055
+ override,
1056
+ platform,
1057
+ iosRunTargetKind
1058
+ }) {
1059
+ const resolution = selectLocalDevHost(os.networkInterfaces(), { override });
1060
+ if (resolution.source === "override")
1061
+ return resolution;
1062
+ if (platform === "ios" && iosRunTargetKind === "simulator")
1063
+ return { ...resolution, host: "localhost", source: "platform" };
1064
+ if (platform === "android") {
1065
+ try {
1066
+ const host = getAndroidLocalServerHost(await this.#spawn("adb", ["devices"]), resolution.host);
1067
+ return host === resolution.host ? resolution : { ...resolution, host, source: "platform" };
1068
+ } catch {
1069
+ return resolution;
1070
+ }
1071
+ }
1072
+ return resolution;
1073
+ }
1027
1074
  #logDevHostResolution(resolution, commandEnv) {
1028
1075
  this.app.log(`Mobile live-reload server: ${this.#localCsrUrl(resolution.host, commandEnv)}`);
1029
- if (resolution.source === "override")
1076
+ if (resolution.source === "override" || resolution.source === "platform")
1030
1077
  return;
1031
1078
  const suspicious = resolution.host === "127.0.0.1" || resolution.host.startsWith("169.254.");
1032
1079
  const alternatives = resolution.candidates.filter((candidate) => candidate.address !== resolution.host);
@@ -1226,18 +1273,26 @@ ${error.message}`;
1226
1273
  return await this.app.spawn(command, args, { cwd: this.app.cwdPath, ...options });
1227
1274
  }
1228
1275
  async#spawnMobile(command, args = [], { operation, env }, options = {}) {
1276
+ const { iosRunTargetKind, platform, ...spawnOptions } = options;
1229
1277
  const mobileEnv = { ...await this.#commandEnv(operation, env), ...options.env };
1230
- const configContent = await this.#writeCapacitorConfig({ operation }, mobileEnv);
1278
+ const configContent = await this.#writeCapacitorConfig({ operation, platform: platform ?? this.#inferMobilePlatform(args), iosRunTargetKind }, mobileEnv);
1231
1279
  await this.#writeRootCapacitorConfig(configContent);
1232
1280
  try {
1233
1281
  return await this.#spawn(command, args, {
1234
- ...options,
1282
+ ...spawnOptions,
1235
1283
  env: mobileEnv
1236
1284
  });
1237
1285
  } finally {
1238
1286
  await this.#clearRootCapacitorConfigs();
1239
1287
  }
1240
1288
  }
1289
+ #inferMobilePlatform(args) {
1290
+ if (args.includes("android"))
1291
+ return "android";
1292
+ if (args.includes("ios"))
1293
+ return "ios";
1294
+ return;
1295
+ }
1241
1296
  async addCamera() {
1242
1297
  await this.#setPermissionInIos({
1243
1298
  cameraUsageDescription: "$(PRODUCT_NAME) requires access to the camera to take photos.",
@@ -1339,17 +1394,31 @@ ${error.message}`;
1339
1394
  while (end < lines.length && !/^\s*\};\s*$/.test(lines[end] ?? ""))
1340
1395
  end++;
1341
1396
  const settings = lines.slice(start, end + 1);
1342
- if (settings.some((setting) => setting.includes("CODE_SIGN_ENTITLEMENTS")))
1343
- continue;
1397
+ const configName = lines.slice(end + 1, end + 8).find((setting) => setting.includes("name = ")) ?? "";
1344
1398
  const indent = line.match(/^\s*/)?.[0] ?? "";
1345
- lines.splice(index, 0, `${indent}CODE_SIGN_ENTITLEMENTS = ${entitlementsRelPath};`);
1346
- index++;
1347
- changed = true;
1399
+ const insertSettings = [];
1400
+ if (!settings.some((setting) => setting.includes("CODE_SIGN_ENTITLEMENTS"))) {
1401
+ insertSettings.push(`${indent}CODE_SIGN_ENTITLEMENTS = ${entitlementsRelPath};`);
1402
+ }
1403
+ if (configName.includes("name = Debug;") && !settings.some((setting) => setting.includes("CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION"))) {
1404
+ insertSettings.push(`${indent}CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;`);
1405
+ }
1406
+ if (insertSettings.length > 0) {
1407
+ lines.splice(index, 0, ...insertSettings);
1408
+ index += insertSettings.length;
1409
+ changed = true;
1410
+ }
1348
1411
  }
1349
1412
  if (changed)
1350
1413
  await writeFile(pbxprojPath, lines.join(`
1351
1414
  `));
1352
1415
  }
1416
+ async#setCodeSignEntitlementsInIosIfExists(entitlementsRelPath) {
1417
+ const entitlementsPath = path.join(this.app.cwdPath, this.iosProjectPath, entitlementsRelPath);
1418
+ if (!await Bun.file(entitlementsPath).exists())
1419
+ return;
1420
+ await this.#setCodeSignEntitlementsInIos(entitlementsRelPath);
1421
+ }
1353
1422
  async#setUrlSchemesInAndroid(schemes) {
1354
1423
  const manifestPath = path.join(this.app.cwdPath, this.androidRootPath, "app/src/main/AndroidManifest.xml");
1355
1424
  let manifest = await readFile(manifestPath, "utf8");
@@ -1444,4 +1513,4 @@ ${filter}$1`);
1444
1513
  }
1445
1514
  }
1446
1515
 
1447
- export { SWIFTUICORE_MIN_IOS_MAJOR, rootCapacitorConfigFilenames, rootCapacitorConfigPaths, clearRootCapacitorConfigs, writeRootCapacitorConfig, selectLocalDevHost, parseIosRuntimeMajor, sortIosRunTargets, parseDevicectlDevices, parseSimctlDevices, buildIosNativeRunCommand, classifyIosRunFailure, formatIosRunFailureMessage, sanitizeIosNativeRunEnv, PLACEHOLDER_APP_IDS, isPlaceholderAppId, getMissingAndroidReleaseSigningKeys, formatAndroidReleaseSigningError, getAdbDeviceStateIssues, ANDROID_MIN_SDK_VERSION, raiseGradleMinSdkVersion, assertJsonSerializable, materializeCapacitorConfig, CapacitorApp };
1516
+ export { SWIFTUICORE_MIN_IOS_MAJOR, rootCapacitorConfigFilenames, rootCapacitorConfigPaths, clearRootCapacitorConfigs, writeRootCapacitorConfig, selectLocalDevHost, parseIosRuntimeMajor, sortIosRunTargets, parseDevicectlDevices, parseSimctlDevices, buildIosNativeRunCommand, classifyIosRunFailure, formatIosRunFailureMessage, sanitizeIosNativeRunEnv, PLACEHOLDER_APP_IDS, isPlaceholderAppId, getMissingAndroidReleaseSigningKeys, formatAndroidReleaseSigningError, getAdbDeviceStateIssues, getAndroidLocalServerHost, ANDROID_MIN_SDK_VERSION, raiseGradleMinSdkVersion, assertJsonSerializable, materializeCapacitorConfig, CapacitorApp };