@akanjs/cli 3.0.0-alpha.9 → 3.0.0-alpha.91

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 (135) 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-cefxzggj.js} +3 -5
  5. package/{agent.command-f0gqkfgz.js → agent.command-r93wmq7m.js} +11 -13
  6. package/{application.command-x903m2qq.js → application.command-5nqfqgdn.js} +62 -38
  7. package/{applicationBuildRunner-ha3y8ew8.js → applicationBuildRunner-b21m07fs.js} +23 -20
  8. package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-3wh58n2m.js} +8 -9
  9. package/buildBatch.proc.js +12 -14
  10. package/capacitorApp-gzcx6txb.js +12 -0
  11. package/{cloud.command-zs6kyf83.js → cloud.command-g0pk0k60.js} +15 -18
  12. package/commandManifest.json +1 -1
  13. package/{context.command-fmepgjzg.js → context.command-qd8kqrnh.js} +19 -23
  14. package/dependencyScanner-shs82ynp.js +8 -0
  15. package/devTui-2xf0meaq.js +552 -0
  16. package/devTuiView-7jy8f30g.js +9 -0
  17. package/getDirname-dr3jz1xg.js +7 -0
  18. package/{guideline.command-n6sw0a0c.js → guideline.command-f38x8jhw.js} +16 -18
  19. package/guidelines/agentRule/agentRule.generate.json +31 -0
  20. package/guidelines/agentRule/agentRule.instruction.md +533 -0
  21. package/guidelines/conventions/conventions.instruction.md +406 -197
  22. package/guidelines/cssRule/cssRule.instruction.md +7 -0
  23. package/guidelines/framework/framework.generate.json +3 -2
  24. package/guidelines/framework/framework.instruction.md +1 -9
  25. package/guidelines/mcpRule/mcpRule.generate.json +25 -0
  26. package/guidelines/mcpRule/mcpRule.instruction.md +217 -0
  27. package/guidelines/modelStore/modelStore.instruction.md +12 -0
  28. package/guidelines/modelTemplate/modelTemplate.instruction.md +5 -0
  29. package/guidelines/queryRule/queryRule.generate.json +31 -0
  30. package/guidelines/queryRule/queryRule.instruction.md +143 -0
  31. package/guidelines/runtimeRule/runtimeRule.generate.json +25 -0
  32. package/guidelines/runtimeRule/runtimeRule.instruction.md +213 -0
  33. package/guidelines/ssrRule/ssrRule.instruction.md +49 -5
  34. package/guidelines/transportRule/transportRule.generate.json +31 -0
  35. package/guidelines/transportRule/transportRule.instruction.md +60 -0
  36. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +51 -760
  37. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +33 -0
  38. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +402 -0
  39. package/incrementalBuilder.proc.js +26 -25
  40. package/{index-774gcx29.js → index-0emb9eat.js} +41 -34
  41. package/index-3d9y066c.js +76 -0
  42. package/{index-3vta1tqa.js → index-3vvbv974.js} +32 -32
  43. package/{index-76rn3g2c.js → index-47pj3aee.js} +4 -4
  44. package/{index-y4vkyhvv.js → index-5xdqxbn9.js} +14 -14
  45. package/{index-1577bej2.js → index-6wwzs1bc.js} +2 -2
  46. package/{index-wnp7hwq7.js → index-92zztqy1.js} +7 -7
  47. package/{index-jhpa13zj.js → index-9bwhxrqf.js} +57 -57
  48. package/{index-bjpxzr6s.js → index-9wtbw98m.js} +6 -3
  49. package/{index-fgc8r6dj.js → index-a5vmm6x4.js} +3 -1
  50. package/{index-xys926f2.js → index-by5gpp8x.js} +4 -4
  51. package/{index-kdh76j26.js → index-cezy7yb3.js} +100 -32
  52. package/{index-62955kn5.js → index-d61rcfa2.js} +758 -127
  53. package/{index-82jrh4hj.js → index-deekbtkj.js} +13 -13
  54. package/{index-rxkpk7n4.js → index-e82dyeqy.js} +4 -4
  55. package/{index-qzdjd4ct.js → index-h759vjfa.js} +18 -18
  56. package/{index-j37qq1f2.js → index-h7yw2z9n.js} +7 -7
  57. package/{index-qb61h0k7.js → index-jydtyzva.js} +1098 -1360
  58. package/{index-46tjzh6s.js → index-kcxmv48c.js} +29 -29
  59. package/{index-4m0bphac.js → index-kfnr6c19.js} +31 -30
  60. package/{index-xmmzf150.js → index-mpmyqm1y.js} +1 -1
  61. package/{index-xjd3rqzj.js → index-n68jx79w.js} +6 -15
  62. package/{index-0cj2zxbm.js → index-n85fer99.js} +12 -11
  63. package/{index-779ske1y.js → index-pgsswppj.js} +27 -27
  64. package/index-pvb4vdwr.js +159 -0
  65. package/{index-67546d0j.js → index-q0y2jq9j.js} +14 -2
  66. package/{index-z8ptfkzv.js → index-q8sn827n.js} +969 -240
  67. package/{index-5sn5w2mt.js → index-r50qen0z.js} +94 -61
  68. package/{index-eyyf2149.js → index-rntcdss1.js} +36 -37
  69. package/{index-gcv8ncfh.js → index-sjak5v5b.js} +16 -12
  70. package/{index-j9cxndc0.js → index-w8kmx1b6.js} +20 -11
  71. package/{index-jf2ya7r2.js → index-y74k5anj.js} +8 -8
  72. package/{index-d43t8af2.js → index-zkvpaggp.js} +58 -25
  73. package/index.js +22 -25
  74. package/{library.command-cv9gdbmg.js → library.command-em103wtn.js} +11 -10
  75. package/{localRegistry.command-d8fg36zc.js → localRegistry.command-gz8apn4y.js} +20 -23
  76. package/{module.command-qyr1s9cn.js → module.command-451pztkc.js} +13 -16
  77. package/{package.command-wsjx0k47.js → package.command-rfhyf38t.js} +8 -10
  78. package/package.json +5 -7
  79. package/{page.command-rdzg65rm.js → page.command-kt19da5g.js} +7 -9
  80. package/{primitive.command-89g38b53.js → primitive.command-pgy69ere.js} +13 -16
  81. package/{quality.command-0cs2z92d.js → quality.command-gpe2vqb5.js} +226 -105
  82. package/recipeScanner-fpagtgc1.js +11 -0
  83. package/{repair.command-6fphxfwj.js → repair.command-2sbrz187.js} +12 -14
  84. package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-ze6x894c.js} +0 -2
  85. package/{scalar.command-xfer69s6.js → scalar.command-jcf4e5sv.js} +11 -14
  86. package/subspace.command-kqzqtk0p.js +755 -0
  87. package/templates/app/env/env.client.debug.ts.template +1 -5
  88. package/templates/app/env/env.client.develop.ts.template +1 -5
  89. package/templates/app/env/env.client.local.ts.template +1 -5
  90. package/templates/app/env/env.client.main.ts.template +1 -5
  91. package/templates/app/env/env.client.testing.ts.template +1 -5
  92. package/templates/app/env/env.client.type.ts +2 -6
  93. package/templates/app/env/env.server.debug.ts.template +1 -5
  94. package/templates/app/env/env.server.develop.ts.template +1 -5
  95. package/templates/app/env/env.server.local.ts.template +1 -5
  96. package/templates/app/env/env.server.main.ts.template +1 -5
  97. package/templates/app/main.ts +3 -1
  98. package/templates/appSample/lib/task/task.signal.ts +11 -6
  99. package/templates/appSample/srvkit/AuthGuard.ts +9 -5
  100. package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
  101. package/templates/crudPages/[__model__Id]/edit/page.tsx +5 -5
  102. package/templates/crudPages/[__model__Id]/page.tsx +10 -13
  103. package/templates/crudPages/new/page.tsx +5 -5
  104. package/templates/crudPages/page.tsx +9 -9
  105. package/templates/crudSinglePage/page.tsx +11 -7
  106. package/templates/env/_env.server.type.ts +7 -5
  107. package/templates/lib/db.ts +1 -1
  108. package/templates/lib/dict.ts +1 -1
  109. package/templates/lib/sig.ts +1 -1
  110. package/templates/lib/srv.ts +6 -2
  111. package/templates/module/__model__.dictionary.ts +4 -1
  112. package/templates/module/__model__.signal.ts +2 -3
  113. package/templates/module/__model__.store.ts +1 -2
  114. package/templates/workspaceRoot/.gitignore.template +0 -1
  115. package/templates/workspaceRoot/.husky/pre-commit.template +16 -0
  116. package/templates/workspaceRoot/.vscode/settings.json.template +1 -1
  117. package/templates/workspaceRoot/AGENTS.md.template +4 -0
  118. package/templates/workspaceRoot/CLAUDE.md.template +19 -0
  119. package/templates/workspaceRoot/biome.json.template +2 -1
  120. package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +10 -14
  121. package/templates/workspaceRoot/docs/GENERATED.md.template +12 -10
  122. package/templates/workspaceRoot/package.json.template +2 -4
  123. package/typeChecker-3xgrzc2v.js +7 -0
  124. package/typecheck.proc.js +4 -5
  125. package/{workflow.command-2ygfqt4f.js → workflow.command-m4z25a2p.js} +22 -25
  126. package/{workspace.command-88m0zs64.js → workspace.command-dqgj9zbk.js} +96 -81
  127. package/capacitorApp-9xswcgx7.js +0 -61
  128. package/dependencyScanner-f6grrep3.js +0 -9
  129. package/getDirname-m9s0cmhq.js +0 -8
  130. package/index-mxvakhsm.js +0 -66
  131. package/index-r24hmh0q.js +0 -4
  132. package/recipeScanner-tghkzrrt.js +0 -12
  133. package/typeChecker-kravn7ns.js +0 -8
  134. /package/{index-0wae5ebk.js → index-meh558jy.js} +0 -0
  135. /package/{index-ss469dec.js → index-nz8prx9g.js} +0 -0
@@ -0,0 +1,159 @@
1
+ // @bun
2
+ import {
3
+ AppInfo
4
+ } from "./index-q8sn827n.js";
5
+
6
+ // pkgs/@akanjs/devkit/slicePlanner.ts
7
+ class SlicePlanner {
8
+ static memberDirs = ["apps", "libs", "pkgs"];
9
+ static toolchainDependencies = [
10
+ "@akanjs/cli",
11
+ "@akanjs/devkit",
12
+ "@biomejs/biome",
13
+ "@types/bun",
14
+ "akanjs",
15
+ "tailwindcss",
16
+ "typescript"
17
+ ];
18
+ static akanPackages = ["akanjs", "@akanjs/devkit", "@akanjs/cli"];
19
+ static async#frameworkPeers(workspace) {
20
+ const peers = new Set;
21
+ let found = false;
22
+ for (const akanPackage of SlicePlanner.akanPackages) {
23
+ for (const prefix of ["node_modules", "pkgs"]) {
24
+ const manifestPath = `${prefix}/${akanPackage}/package.json`;
25
+ if (!await workspace.exists(manifestPath))
26
+ continue;
27
+ const manifest = await workspace.readJson(manifestPath);
28
+ for (const peer of Object.keys(manifest.peerDependencies ?? {}))
29
+ peers.add(peer);
30
+ found = true;
31
+ break;
32
+ }
33
+ }
34
+ return found ? peers : null;
35
+ }
36
+ static typesPackageOf(dependency) {
37
+ return dependency.startsWith("@") ? `@types/${dependency.slice(1).replace("/", "__")}` : `@types/${dependency}`;
38
+ }
39
+ static async pruneDependencies(workspace, rootPackageJson, required) {
40
+ const peers = await SlicePlanner.#frameworkPeers(workspace);
41
+ const { workspaces: _workspaces, ...rest } = rootPackageJson;
42
+ if (!peers)
43
+ return {
44
+ packageJson: rest,
45
+ pruned: [],
46
+ warnings: [`dependencies carried whole \u2014 none of ${SlicePlanner.akanPackages.join(", ")} is installed`]
47
+ };
48
+ const keep = new Set([...SlicePlanner.toolchainDependencies, ...peers, ...required]);
49
+ for (const dependency of [...keep])
50
+ keep.add(SlicePlanner.typesPackageOf(dependency));
51
+ const pick = (entries) => Object.fromEntries(Object.entries(entries ?? {}).filter(([name]) => keep.has(name)));
52
+ const patched = rootPackageJson.patchedDependencies ?? {};
53
+ const packageJson = {
54
+ ...rest,
55
+ dependencies: pick(rootPackageJson.dependencies),
56
+ devDependencies: pick(rootPackageJson.devDependencies),
57
+ ...Object.keys(patched).length ? {
58
+ patchedDependencies: Object.fromEntries(Object.entries(patched).filter(([spec]) => keep.has(spec.slice(0, spec.lastIndexOf("@")))))
59
+ } : {}
60
+ };
61
+ const pruned = Object.keys({ ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies }).filter((name) => !keep.has(name)).sort();
62
+ return { packageJson, pruned, warnings: [] };
63
+ }
64
+ #app;
65
+ constructor(app) {
66
+ this.#app = app;
67
+ }
68
+ async#trackedFiles(paths) {
69
+ return await this.#app.workspace.listGitFiles(paths);
70
+ }
71
+ async#untrackedFiles(paths) {
72
+ const [tracked, all] = await Promise.all([
73
+ this.#app.workspace.listGitFiles(paths),
74
+ this.#app.workspace.listGitFiles(paths, { untracked: true })
75
+ ]);
76
+ const trackedSet = new Set(tracked);
77
+ return all.filter((file) => !trackedSet.has(file));
78
+ }
79
+ #isMemberFile(file) {
80
+ return SlicePlanner.memberDirs.includes(file.split("/")[0] ?? "");
81
+ }
82
+ static #requiredDependencies(appInfo) {
83
+ const scanResults = [
84
+ appInfo.getScanResult(),
85
+ ...[...appInfo.getLibInfos().values()].map((lib) => lib.getScanResult())
86
+ ];
87
+ return new Set([
88
+ ...scanResults.flatMap((scanResult) => [
89
+ ...scanResult.dependencies,
90
+ ...scanResult.devDependencies,
91
+ ...scanResult.pkgDeps
92
+ ])
93
+ ]);
94
+ }
95
+ async#patchWarnings(packageJson) {
96
+ const patchedDependencies = packageJson.patchedDependencies ?? {};
97
+ const missing = (await Promise.all(Object.entries(patchedDependencies).map(async ([spec, patchPath]) => await this.#app.workspace.exists(patchPath) ? null : `${spec} -> ${patchPath}`))).filter((entry) => !!entry);
98
+ return missing.length ? [`patchedDependencies references a missing patch file: ${missing.join(", ")}`] : [];
99
+ }
100
+ async plan() {
101
+ const appInfo = await AppInfo.fromExecutor(this.#app);
102
+ const libs = appInfo.getLibs();
103
+ const slicePaths = [`apps/${this.#app.name}`, ...libs.map((lib) => `libs/${lib}`)];
104
+ const [appFiles, allTracked, untracked, rootPackageJson] = await Promise.all([
105
+ this.#trackedFiles([`apps/${this.#app.name}`]),
106
+ this.#trackedFiles(["."]),
107
+ this.#untrackedFiles(slicePaths),
108
+ this.#app.workspace.getPackageJson()
109
+ ]);
110
+ const libFiles = Object.fromEntries(await Promise.all(libs.map(async (lib) => [lib, await this.#trackedFiles([`libs/${lib}`])])));
111
+ const rootFiles = allTracked.filter((file) => !this.#isMemberFile(file));
112
+ const required = SlicePlanner.#requiredDependencies(appInfo);
113
+ const {
114
+ packageJson,
115
+ pruned,
116
+ warnings: manifestWarnings
117
+ } = await SlicePlanner.pruneDependencies(this.#app.workspace, rootPackageJson, required);
118
+ const warnings = [
119
+ ...untracked.length ? [`${untracked.length} untracked file(s) under the slice paths: ${untracked.join(", ")}`] : [],
120
+ ...rootPackageJson.workspaces ? ["root `workspaces` dropped \u2014 a slice consumes akanjs from the registry"] : [],
121
+ ...manifestWarnings,
122
+ ...await this.#patchWarnings(rootPackageJson)
123
+ ];
124
+ return {
125
+ app: this.#app.name,
126
+ libs,
127
+ appFiles,
128
+ libFiles,
129
+ rootFiles,
130
+ packageJson,
131
+ requiredDependencies: [...required].sort(),
132
+ unusedDependencies: pruned,
133
+ warnings
134
+ };
135
+ }
136
+ }
137
+ var rootEntriesOf = (rootFiles) => [...new Set(rootFiles.map((file) => file.split("/")[0] ?? file))].sort();
138
+ function formatSlicePlan(plan) {
139
+ const libCounts = Object.entries(plan.libFiles).map(([lib, files]) => ` - libs/${lib}: ${files.length} files`);
140
+ const sections = [
141
+ "Akan Slice Plan",
142
+ `app: ${plan.app} (apps/${plan.app}: ${plan.appFiles.length} files)`,
143
+ `libs: ${plan.libs.length ? plan.libs.join(", ") : "(none)"}`,
144
+ ...libCounts,
145
+ `workspace shell: ${plan.rootFiles.length} files across ${rootEntriesOf(plan.rootFiles).join(", ")}`,
146
+ "",
147
+ `Root dependencies this slice does not use (${plan.unusedDependencies.length}) \u2014 pruned:`,
148
+ "",
149
+ ...plan.unusedDependencies.length ? plan.unusedDependencies.map((dep) => ` - ${dep}`) : [" (none)"],
150
+ "",
151
+ `Warnings (${plan.warnings.length}):`,
152
+ "",
153
+ ...plan.warnings.length ? plan.warnings.map((warning) => ` - ${warning}`) : [" (none)"]
154
+ ];
155
+ return sections.join(`
156
+ `);
157
+ }
158
+
159
+ export { SlicePlanner, formatSlicePlan };
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // pkgs/@akanjs/devkit/fileSys.ts
3
- import { lstat, stat } from "fs/promises";
3
+ import { lstat, rename, rm, stat } from "fs/promises";
4
4
  import { Logger } from "akanjs/common";
5
5
 
6
6
  class FileSys {
@@ -9,7 +9,7 @@ class FileSys {
9
9
  return await Bun.file(path).exists();
10
10
  }
11
11
  static async dirExists(path) {
12
- return await stat(path).then((stat2) => stat2.isDirectory()).catch(() => false);
12
+ return await stat(path).then((stat) => stat.isDirectory()).catch(() => false);
13
13
  }
14
14
  static async exists(path) {
15
15
  return await stat(path).then(() => true).catch(() => false);
@@ -34,6 +34,18 @@ class FileSys {
34
34
  static async writeText(path, content) {
35
35
  return await Bun.file(path).write(content);
36
36
  }
37
+ static async writeTextAtomic(filePath, content) {
38
+ const temp = `${filePath}.${process.pid}.${Date.now().toString(36)}.tmp`;
39
+ try {
40
+ await Bun.write(temp, content);
41
+ await rename(temp, filePath);
42
+ } catch (error) {
43
+ await rm(temp, { force: true }).catch(() => {
44
+ return;
45
+ });
46
+ throw error;
47
+ }
48
+ }
37
49
  static async writeJson(path, content) {
38
50
  return await Bun.file(path).write(`${JSON.stringify(content, null, 2)}
39
51
  `);