@akanjs/cli 3.0.0-beta.9 → 3.0.0

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 (224) hide show
  1. package/.build-stamp +1 -1
  2. package/CodeAgent-2vmp9qe0.js +9 -0
  3. package/CodeAgentRpcHost-p7h6n2hp.js +7 -0
  4. package/CodeAgentRpcListener-7p7z5dd7.js +97 -0
  5. package/CodeTui-5ed6bg2a.js +1457 -0
  6. package/README.ko.md +83 -28
  7. package/README.md +70 -27
  8. package/TunnelShare-cwh9ezsm.js +9 -0
  9. package/{agent.command-0q17pnrs.js → agent.command-gn73rhe7.js} +8 -9
  10. package/akanCode.js +102 -0
  11. package/application.command-e968t0hw.js +246 -0
  12. package/{applicationBuildRunner-kxwbssgn.js → applicationBuildRunner-64taxseg.js} +121 -77
  13. package/buildBatch.proc.js +120 -32
  14. package/cloud.command-0jm301rr.js +95 -0
  15. package/cloud.script-nemnzjpv.js +20 -0
  16. package/code.command-18kcm7hq.js +154 -0
  17. package/commandManifest.json +1 -1
  18. package/consoleToStderr-h5bryj94.js +7 -0
  19. package/context.command-trd9bn18.js +48 -0
  20. package/context.runner-y5hwh673.js +21 -0
  21. package/{dependencyScanner-shs82ynp.js → dependencyScanner-06z2dmrr.js} +2 -2
  22. package/{devTui-m1atgkc9.js → devTui-q7k7bakd.js} +122 -40
  23. package/fileSys-wzzrntkw.js +9 -0
  24. package/guideline.command-bdmdn2de.js +42 -0
  25. package/guidelines/agentRule/agentRule.instruction.md +154 -26
  26. package/guidelines/conventions/conventions.instruction.md +134 -48
  27. package/guidelines/mcpRule/mcpRule.instruction.md +7 -5
  28. package/guidelines/queryRule/queryRule.instruction.md +21 -7
  29. package/guidelines/runtimeRule/runtimeRule.instruction.md +291 -6
  30. package/guidelines/ssrRule/ssrRule.instruction.md +4 -2
  31. package/guidelines/transportRule/transportRule.instruction.md +10 -8
  32. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +20 -0
  33. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +66 -3
  34. package/incrementalBuilder.proc.js +564 -109
  35. package/index-0wpybxtr.js +2729 -0
  36. package/{index-kcxmv48c.js → index-2ahj896a.js} +45 -79
  37. package/index-2wc41k5w.js +49 -0
  38. package/index-3hx1z96c.js +87 -0
  39. package/{index-2tv3fdx4.js → index-3w94e7n3.js} +1228 -1458
  40. package/{index-hwkygn9s.js → index-48k96p55.js} +325 -36
  41. package/index-4npz05nm.js +187 -0
  42. package/{index-q0y2jq9j.js → index-52w0fvh8.js} +21 -4
  43. package/index-6he6gvfg.js +4300 -0
  44. package/index-7md2g9vw.js +6 -0
  45. package/{index-04bk599g.js → index-93j60em0.js} +10 -17
  46. package/index-94s080qm.js +266 -0
  47. package/index-9dp031by.js +12 -0
  48. package/{index-ktb5njgy.js → index-9z771ptz.js} +49 -99
  49. package/{index-y6n8nmny.js → index-abxpehf8.js} +75 -203
  50. package/{index-3d9y066c.js → index-bjwxs904.js} +9 -8
  51. package/{index-9077wzd2.js → index-by9pxkr0.js} +43 -26
  52. package/index-c6eggbee.js +123 -0
  53. package/index-d2242ksy.js +99 -0
  54. package/index-drehwpdt.js +1119 -0
  55. package/{index-92zztqy1.js → index-dy0jx9ay.js} +2 -17
  56. package/{index-ffvk10zz.js → index-f3c78nd6.js} +107 -241
  57. package/index-gbggbqcp.js +1058 -0
  58. package/{index-by5gpp8x.js → index-hj6w4ka1.js} +2 -1
  59. package/index-hsmtysz4.js +53 -0
  60. package/{index-j9yhg404.js → index-jmrn54tt.js} +4 -7
  61. package/{index-a64esmtb.js → index-kcdj1z5v.js} +523 -1022
  62. package/{index-d43r08tf.js → index-kqabytj7.js} +77 -150
  63. package/{index-vyvre9en.js → index-mbxbhay5.js} +6 -2
  64. package/{index-vxtad5bd.js → index-mgxpx3f2.js} +5 -8
  65. package/index-p6pbz9n5.js +25 -0
  66. package/{index-sj5vxr8f.js → index-p993efkq.js} +981 -897
  67. package/{index-2xp0kfkt.js → index-pmhqttv3.js} +37 -25
  68. package/index-tqm7jjcn.js +700 -0
  69. package/{index-0g7r8xz3.js → index-vpj42xwt.js} +114 -232
  70. package/index-wa5jbxj1.js +760 -0
  71. package/{index-k2j1hc4r.js → index-wprnsjms.js} +12 -12
  72. package/{index-gyd220p2.js → index-y3mphr1m.js} +554 -577
  73. package/index-yg7jhz8x.js +69 -0
  74. package/{index-h7yw2z9n.js → index-zzvvc845.js} +8 -14
  75. package/index.js +23 -22
  76. package/{library.command-qzzbj6d8.js → library.command-9h749a1x.js} +4 -5
  77. package/{localRegistry.command-vyrgg4xw.js → localRegistry.command-2bqqhxyz.js} +23 -43
  78. package/{module.command-rq5hq3ax.js → module.command-nv8nzgft.js} +8 -12
  79. package/{package.command-d9hd6v9n.js → package.command-mq4bggp6.js} +6 -7
  80. package/package.json +15 -7
  81. package/{page.command-126d56te.js → page.command-j639n707.js} +4 -5
  82. package/{primitive.command-taxd1538.js → primitive.command-kz6849th.js} +9 -23
  83. package/prompter-76k56b37.js +8 -0
  84. package/{quality.command-6gsna0a3.js → quality.command-4hyabwkb.js} +205 -377
  85. package/{recipeScanner-fpagtgc1.js → recipeScanner-4b69ybe0.js} +1 -1
  86. package/{repair.command-tq2dgy72.js → repair.command-a9awpbqr.js} +11 -35
  87. package/{routeSourceValidator-apyqw7wk.js → routeSourceValidator-7ycnfz0e.js} +0 -6
  88. package/{scalar.command-3bcmrrkv.js → scalar.command-ma4fpm9m.js} +7 -11
  89. package/skills/akan-code/SKILL.md +130 -0
  90. package/skills/akan-debug/SKILL.md +42 -0
  91. package/skills/akan-deps/SKILL.md +50 -0
  92. package/skills/akan-err/SKILL.md +39 -0
  93. package/skills/akan-module/SKILL.md +45 -0
  94. package/skills/akan-scaffold/SKILL.md +76 -0
  95. package/skills/akan-scalar/SKILL.md +52 -0
  96. package/skills/akan-service/SKILL.md +34 -0
  97. package/skills/akan-store/SKILL.md +67 -0
  98. package/skills/akan-ui/SKILL.md +63 -0
  99. package/skills/akan-validate/SKILL.md +44 -0
  100. package/{subspace.command-eddzqpx3.js → subspace.command-3k2pmrs4.js} +53 -62
  101. package/templates/__scalar/__model__/__model__.abstract.md.template +8 -0
  102. package/templates/app/page/_index.tsx +257 -258
  103. package/templates/app/page/_layout.tsx +5 -1
  104. package/templates/app/page/_overrides.tsx +12 -0
  105. package/templates/app/page/styles.css.template +316 -14
  106. package/templates/app/public/apple-touch-icon.png +0 -0
  107. package/templates/app/public/favicon.ico +0 -0
  108. package/templates/app/public/jelly/cloud.webp +0 -0
  109. package/templates/app/public/jelly/comet.webp +0 -0
  110. package/templates/app/public/jelly/moon.webp +0 -0
  111. package/templates/app/public/jelly/planet.webp +0 -0
  112. package/templates/app/public/jelly/rocket.webp +0 -0
  113. package/templates/app/public/jelly/star.webp +0 -0
  114. package/templates/app/public/jelly/sugar.webp +0 -0
  115. package/templates/app/public/logo.png +0 -0
  116. package/templates/app/ui/Recipe/index.ts +9 -0
  117. package/templates/app/ui/Recipe/jellyButton.ts +63 -0
  118. package/templates/appSample/lib/__scalar/workHistory/workHistory.abstract.ts +8 -39
  119. package/templates/appSample/lib/_noti/noti.abstract.ts +6 -29
  120. package/templates/appSample/lib/task/Task.Unit.tsx +1 -1
  121. package/templates/appSample/lib/task/Task.Util.tsx +10 -13
  122. package/templates/appSample/lib/task/Task.View.tsx +2 -2
  123. package/templates/appSample/lib/task/Task.Zone.tsx +5 -2
  124. package/templates/appSample/lib/task/task.abstract.ts +12 -32
  125. package/templates/appSample/lib/task/task.signal.spec.ts +1 -15
  126. package/templates/appSample/lib/task/task.signal.test.ts +15 -1
  127. package/templates/appSample/lib/task/task.signal.ts +10 -8
  128. package/templates/appSample/page/task/[taskId]/_index.tsx +6 -6
  129. package/templates/appSample/page/task/[taskId]/edit.tsx +5 -4
  130. package/templates/appSample/page/task/_index.tsx +4 -3
  131. package/templates/appSample/page/task/_layout.tsx +1 -1
  132. package/templates/appSample/page/task/new.tsx +5 -4
  133. package/templates/appSample/srvkit/{AuthGuard.ts → guards.ts} +7 -4
  134. package/templates/appSample/srvkit/{SessionInternalArg.ts → internalArgs.ts} +6 -4
  135. package/templates/appSample/ui/GlobalLoading.tsx +2 -1
  136. package/templates/appSample/ui/QuantityControl.tsx +3 -3
  137. package/templates/client.ts +7 -30
  138. package/templates/crudPages/[__model__Id]/edit/page.tsx +2 -1
  139. package/templates/crudPages/[__model__Id]/page.tsx +2 -1
  140. package/templates/crudPages/new/page.tsx +2 -1
  141. package/templates/crudPages/page.tsx +2 -1
  142. package/templates/crudSinglePage/page.tsx +2 -1
  143. package/templates/lib/__lib/lib.dictionary.ts +0 -2
  144. package/templates/lib/__lib/lib.document.ts +0 -2
  145. package/templates/lib/sig.ts +8 -30
  146. package/templates/localDev/docker-compose.yaml.template +3 -14
  147. package/templates/module/__model__.signal.ts +12 -4
  148. package/templates/pkgRoot/tsconfig.json.template +2 -7
  149. package/templates/server.ts +1 -3
  150. package/templates/service/__model__.abstract.md.template +8 -0
  151. package/templates/workspaceRoot/.gitignore.template +0 -1
  152. package/templates/workspaceRoot/AGENTS.md.template +6 -0
  153. package/templates/workspaceRoot/package.json.template +1 -3
  154. package/tunnel.command-xwr46b66.js +129 -0
  155. package/{typeChecker-3xgrzc2v.js → typeChecker-px49mezc.js} +1 -1
  156. package/typecheck.proc.js +1 -1
  157. package/workflow.command-t7wqe4h7.js +79 -0
  158. package/{workspace.command-06wvstgr.js → workspace.command-4derhzrh.js} +79 -109
  159. package/abstractCompactor-gmkc0z8j.js +0 -102
  160. package/application.command-18y0s485.js +0 -204
  161. package/applicationReleasePackager-4yasxwv9.js +0 -244
  162. package/capacitorApp-36rbr858.js +0 -12
  163. package/cloud.command-av97ndh6.js +0 -94
  164. package/cloud.script-cm11xjdz.js +0 -20
  165. package/context.command-5v37ef3n.js +0 -81
  166. package/devTuiView-0hc2emhe.js +0 -9
  167. package/getDirname-dr3jz1xg.js +0 -7
  168. package/guideline.command-4pz9g1rt.js +0 -360
  169. package/guidelines/agentRule/agentRule.generate.json +0 -31
  170. package/guidelines/componentRule/componentRule.generate.json +0 -31
  171. package/guidelines/conventions/conventions.generate.json +0 -25
  172. package/guidelines/cssRule/cssRule.generate.json +0 -31
  173. package/guidelines/docPageRule/docPageRule.generate.json +0 -31
  174. package/guidelines/docPageRule/docPageRule.instruction.md +0 -25
  175. package/guidelines/docSyncRule/docSyncRule.generate.json +0 -31
  176. package/guidelines/docSyncRule/docSyncRule.instruction.md +0 -25
  177. package/guidelines/enumConstant/enumConstant.generate.json +0 -31
  178. package/guidelines/enumConstant/enumConstant.instruction.md +0 -28
  179. package/guidelines/fieldRule/fieldRule.generate.json +0 -31
  180. package/guidelines/framework/framework.generate.json +0 -32
  181. package/guidelines/mcpRule/mcpRule.generate.json +0 -35
  182. package/guidelines/modelConstant/modelConstant.generate.json +0 -32
  183. package/guidelines/modelDictionary/modelDictionary.generate.json +0 -32
  184. package/guidelines/modelDocument/modelDocument.generate.json +0 -31
  185. package/guidelines/modelService/modelService.generate.json +0 -31
  186. package/guidelines/modelSignal/modelSignal.generate.json +0 -31
  187. package/guidelines/modelStore/modelStore.generate.json +0 -31
  188. package/guidelines/modelTemplate/modelTemplate.generate.json +0 -31
  189. package/guidelines/modelUnit/modelUnit.generate.json +0 -31
  190. package/guidelines/modelUtil/modelUtil.generate.json +0 -31
  191. package/guidelines/modelView/modelView.generate.json +0 -31
  192. package/guidelines/modelZone/modelZone.generate.json +0 -31
  193. package/guidelines/moduleCodegen/moduleCodegen.generate.json +0 -31
  194. package/guidelines/moduleCodegen/moduleCodegen.instruction.md +0 -28
  195. package/guidelines/moduleOverview/moduleOverview.generate.json +0 -31
  196. package/guidelines/queryRule/queryRule.generate.json +0 -31
  197. package/guidelines/recipeRule/recipeRule.generate.json +0 -31
  198. package/guidelines/runtimeRule/runtimeRule.generate.json +0 -25
  199. package/guidelines/scalarConstant/scalarConstant.generate.json +0 -32
  200. package/guidelines/scalarDictionary/scalarDictionary.generate.json +0 -32
  201. package/guidelines/scalarModule/scalarModule.generate.json +0 -31
  202. package/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -31
  203. package/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +0 -25
  204. package/guidelines/ssrRule/ssrRule.generate.json +0 -31
  205. package/guidelines/transportRule/transportRule.generate.json +0 -31
  206. package/guidelines/utilUiUsage/utilUiUsage.generate.json +0 -31
  207. package/guidelines/utilUiUsage/utilUiUsage.instruction.md +0 -25
  208. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +0 -24
  209. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +0 -33
  210. package/index-47pj3aee.js +0 -76
  211. package/index-5ystnsd5.js +0 -841
  212. package/index-6wwzs1bc.js +0 -7
  213. package/index-a17x49vg.js +0 -229
  214. package/index-m0xccmmm.js +0 -228
  215. package/index-meh558jy.js +0 -65
  216. package/index-rtxxan88.js +0 -471
  217. package/index-te54x9zm.js +0 -338
  218. package/index-w8kmx1b6.js +0 -2176
  219. package/index-wt7qrtd4.js +0 -1516
  220. package/templates/__scalar/__model__/__model__.abstract.md +0 -28
  221. package/templates/module/__model__.abstract.md +0 -28
  222. package/templates/service/__model__.abstract.md +0 -28
  223. package/templates/workspaceRoot/patches/react-dom@19.2.7.patch.template +0 -62
  224. package/workflow.command-gtdnzvbz.js +0 -108
@@ -0,0 +1,187 @@
1
+ // @bun
2
+ import {
3
+ runner,
4
+ script
5
+ } from "./index-vpj42xwt.js";
6
+ import {
7
+ ModuleExecutor
8
+ } from "./index-3w94e7n3.js";
9
+ import {
10
+ sourceFile,
11
+ moduleSourcePaths,
12
+ generatedFilesForSync,
13
+ createPassedPrimitiveReport,
14
+ bilingualLabelForField,
15
+ bilingualDescriptionForField
16
+ } from "./index-y3mphr1m.js";
17
+ import {
18
+ PageScript
19
+ } from "./index-mbxbhay5.js";
20
+ import {
21
+ pluralizeName
22
+ } from "./index-nz8prx9g.js";
23
+
24
+ // pkgs/@akanjs/cli/module/module.script.ts
25
+ import { capitalize as capitalize2 } from "akanjs/common";
26
+
27
+ // pkgs/@akanjs/cli/module/module.runner.ts
28
+ import { capitalize } from "akanjs/common";
29
+ var purposeByModule = {
30
+ budget: "Budget represents planned or actual money allocated inside the app.",
31
+ project: "Project represents a project workspace or business initiative managed by the app.",
32
+ task: "Task represents work items that move through the app workflow."
33
+ };
34
+ var moduleAbstractContent = (moduleName, sharedGuards) => {
35
+ const title = capitalize(moduleName);
36
+ const noun = bilingualLabelForField(moduleName).en.toLowerCase();
37
+ const purpose = purposeByModule[moduleName] ?? `${title} represents ${noun} records managed by the app.`;
38
+ const writeRule = sharedGuards ? `Anyone may read a ${noun}; only an admin creates, updates or removes one.` : `Anyone may read a ${noun}; nobody creates, updates or removes one until the slice names a guard.`;
39
+ return `# ${moduleName} Abstract
40
+ ${purpose}
41
+
42
+ ## Rules
43
+ - ${writeRule}
44
+ - Removal is soft: a removed ${noun} keeps its row with \`removedAt\` set.
45
+ `;
46
+ };
47
+ var moduleFileKeys = [
48
+ "abstract",
49
+ "constant",
50
+ "dictionary",
51
+ "service",
52
+ "store",
53
+ "signal",
54
+ "unit",
55
+ "view",
56
+ "template",
57
+ "zone",
58
+ "util"
59
+ ];
60
+
61
+ class ModuleRunner extends runner("module") {
62
+ async createService(module) {
63
+ const serviceName = module.name.replace(/^_+/, "");
64
+ await module.applyTemplate({
65
+ basePath: `.`,
66
+ template: "service",
67
+ dict: { model: serviceName, sysName: module.sys.name }
68
+ });
69
+ return await this.#readFiles(module, {
70
+ abstract: `${serviceName}.abstract.md`,
71
+ dictionary: `${serviceName}.dictionary.ts`,
72
+ service: `${serviceName}.service.ts`,
73
+ signal: `${serviceName}.signal.ts`,
74
+ store: `${serviceName}.store.ts`
75
+ });
76
+ }
77
+ async#readFiles(module, filenames) {
78
+ const files = await Promise.all(Object.entries(filenames).map(async ([key, filename]) => [
79
+ key,
80
+ { filename, content: await module.readFile(filename) }
81
+ ]));
82
+ return Object.fromEntries(files);
83
+ }
84
+ async removeModule(module) {
85
+ await module.sys.removeDir(`lib/${module.name}`);
86
+ }
87
+ async#hasSharedGuards(module) {
88
+ const { sys } = module;
89
+ if (sys.type === "lib" && sys.name === "shared")
90
+ return true;
91
+ if (!await sys.exists("lib/srv.ts"))
92
+ return false;
93
+ return (await sys.readFile("lib/srv.ts")).includes('"@libs/shared/lib/srv"');
94
+ }
95
+ async createComponentTemplate(module, type) {
96
+ await module.sys.applyTemplate({
97
+ basePath: `./lib/${module.name}`,
98
+ template: `module/__Model__.${capitalize(type)}.tsx`,
99
+ dict: { model: module.name, sysName: module.sys.name, sysType: module.sys.type }
100
+ });
101
+ return {
102
+ component: {
103
+ filename: `${capitalize(module.name)}.${capitalize(type)}.tsx`,
104
+ content: await module.sys.readFile(`lib/${module.name}/${capitalize(module.name)}.${capitalize(type)}.tsx`)
105
+ }
106
+ };
107
+ }
108
+ async createModuleTemplate(module) {
109
+ const names = pluralizeName(module.name);
110
+ const modelLabel = bilingualLabelForField(module.name);
111
+ const modelDescription = bilingualDescriptionForField(module.name);
112
+ const paths = moduleSourcePaths(module.name);
113
+ const filenames = Object.fromEntries(moduleFileKeys.map((key) => [key, paths[key].replace(`lib/${module.name}/`, "")]));
114
+ const sharedGuards = await this.#hasSharedGuards(module);
115
+ await module.applyTemplate({
116
+ basePath: `.`,
117
+ template: "module",
118
+ options: { sharedGuards },
119
+ dict: {
120
+ model: module.name,
121
+ models: names,
122
+ sysName: module.sys.name,
123
+ sysType: module.sys.type,
124
+ modelLabelEn: modelLabel.en,
125
+ modelLabelKo: modelLabel.ko,
126
+ modelDescEn: modelDescription.en,
127
+ modelDescKo: modelDescription.ko
128
+ }
129
+ });
130
+ await module.writeFile(filenames.abstract, moduleAbstractContent(module.name, sharedGuards));
131
+ return await this.#readFiles(module, filenames);
132
+ }
133
+ }
134
+
135
+ // pkgs/@akanjs/cli/module/module.script.ts
136
+ var moduleChangedFiles = (sys, moduleName, files) => Object.values(files).map((file) => sourceFile(sys, `lib/${moduleName}/${file.filename}`, "create", "Module source file was created."));
137
+
138
+ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
139
+ async createModuleTemplate(sys, name, { page = false } = {}) {
140
+ const mod = ModuleExecutor.from(sys, name);
141
+ const files = await this.moduleRunner.createModuleTemplate(mod);
142
+ if (page && sys.type === "app")
143
+ await this.pageScript.createCrudPage(mod, { app: sys, basePath: null, single: false });
144
+ await sys.scan();
145
+ return createPassedPrimitiveReport({
146
+ command: "create-module",
147
+ changedFiles: moduleChangedFiles(sys, name, files),
148
+ generatedFiles: generatedFilesForSync(sys, "Generated files were refreshed after module creation."),
149
+ target: sys.name
150
+ });
151
+ }
152
+ async removeModule(mod) {
153
+ await this.moduleRunner.removeModule(mod);
154
+ }
155
+ async createService(sys, name) {
156
+ const service = ModuleExecutor.from(sys, `_${name}`);
157
+ const files = await this.moduleRunner.createService(service);
158
+ await sys.scan();
159
+ return createPassedPrimitiveReport({
160
+ command: "create-service",
161
+ changedFiles: moduleChangedFiles(sys, `_${name}`, files),
162
+ generatedFiles: generatedFilesForSync(sys, "Generated files were refreshed after service creation."),
163
+ target: sys.name
164
+ });
165
+ }
166
+ async createTemplate(mod) {
167
+ return await this.#createComponent(mod, "template");
168
+ }
169
+ async createUnit(mod) {
170
+ return await this.#createComponent(mod, "unit");
171
+ }
172
+ async createView(mod) {
173
+ return await this.#createComponent(mod, "view");
174
+ }
175
+ async#createComponent(mod, type) {
176
+ const { component } = await this.moduleRunner.createComponentTemplate(mod, type);
177
+ return createPassedPrimitiveReport({
178
+ command: `create-${type}`,
179
+ changedFiles: [
180
+ sourceFile(mod.sys, `lib/${mod.name}/${component.filename}`, "create", `${capitalize2(type)} UI source was created.`)
181
+ ],
182
+ target: mod.sys.name
183
+ });
184
+ }
185
+ }
186
+
187
+ export { ModuleScript };
@@ -1,9 +1,12 @@
1
1
  // @bun
2
2
  // pkgs/@akanjs/devkit/fileSys.ts
3
3
  import { lstat, rename, rm, stat } from "fs/promises";
4
+ import nodePath from "path";
5
+ import { fileURLToPath } from "url";
4
6
  import { Logger } from "akanjs/common";
7
+ var getDirname2 = (url) => nodePath.dirname(fileURLToPath(url));
5
8
 
6
- class FileSys {
9
+ class FileSys2 {
7
10
  static logger = new Logger("FileSys");
8
11
  static async fileExists(path) {
9
12
  return await Bun.file(path).exists();
@@ -24,7 +27,7 @@ class FileSys {
24
27
  try {
25
28
  return await Bun.file(path).json();
26
29
  } catch (error) {
27
- FileSys.logger.error(`Failed to read JSON file: ${path}`);
30
+ FileSys2.logger.error(`Failed to read JSON file: ${path}`);
28
31
  throw error;
29
32
  }
30
33
  }
@@ -38,7 +41,7 @@ class FileSys {
38
41
  const temp = `${filePath}.${process.pid}.${Date.now().toString(36)}.tmp`;
39
42
  try {
40
43
  await Bun.write(temp, content);
41
- await rename(temp, filePath);
44
+ await FileSys2.replace(temp, filePath);
42
45
  } catch (error) {
43
46
  await rm(temp, { force: true }).catch(() => {
44
47
  return;
@@ -46,10 +49,24 @@ class FileSys {
46
49
  throw error;
47
50
  }
48
51
  }
52
+ static #replaceAttempts = 100;
53
+ static async replace(temp, target) {
54
+ for (let attempt = 1;; attempt++) {
55
+ try {
56
+ return await rename(temp, target);
57
+ } catch (error) {
58
+ const code = error.code;
59
+ const busy = process.platform === "win32" && (code === "EPERM" || code === "EACCES" || code === "EBUSY");
60
+ if (!busy || attempt >= FileSys2.#replaceAttempts)
61
+ throw error;
62
+ await Bun.sleep(Math.min(10 * attempt, 50));
63
+ }
64
+ }
65
+ }
49
66
  static async writeJson(path, content) {
50
67
  return await Bun.file(path).write(`${JSON.stringify(content, null, 2)}
51
68
  `);
52
69
  }
53
70
  }
54
71
 
55
- export { FileSys };
72
+ export { getDirname2, FileSys2 };