akanjs 2.0.7 → 2.1.0-rc.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 (498) hide show
  1. package/README.ko.md +4 -4
  2. package/README.md +4 -4
  3. package/client/router.ts +10 -3
  4. package/document/documentSchema.ts +9 -1
  5. package/index.ts +187 -0
  6. package/package.json +6 -50
  7. package/server/akanApp.ts +2 -24
  8. package/server/akanAppHeaders.ts +30 -0
  9. package/server/di/predefinedAdaptor.ts +1 -1
  10. package/types/dictionary/base.dictionary.d.ts +1 -1
  11. package/types/dictionary/dictionary.d.ts +8 -8
  12. package/types/document/documentSchema.d.ts +33 -0
  13. package/types/document/index.d.ts +1 -1
  14. package/types/document/schema.d.ts +1 -1
  15. package/types/document/types.d.ts +1 -1
  16. package/types/{devkit/akanConfig/types.d.ts → index.d.ts} +45 -54
  17. package/types/server/akanAppHeaders.d.ts +1 -0
  18. package/types/server/di/predefinedAdaptor.d.ts +1 -1
  19. package/types/store/baseSt.d.ts +2 -2
  20. package/ui/Link/SsrLink.tsx +2 -2
  21. package/webkit/useCodepush.tsx +1 -1
  22. package/cli/application/application.command.ts +0 -224
  23. package/cli/application/application.interface.tsx +0 -225
  24. package/cli/application/application.runner.ts +0 -355
  25. package/cli/application/application.script.ts +0 -244
  26. package/cli/build.ts +0 -27
  27. package/cli/cloud/cloud.command.ts +0 -48
  28. package/cli/cloud/cloud.runner.ts +0 -157
  29. package/cli/cloud/cloud.script.ts +0 -40
  30. package/cli/guideline/guideline.command.ts +0 -31
  31. package/cli/guideline/guideline.prompt.ts +0 -212
  32. package/cli/guideline/guideline.runner.ts +0 -53
  33. package/cli/guideline/guideline.script.ts +0 -33
  34. package/cli/guidelines/___library/sharedUiStructureDescription.en.md +0 -767
  35. package/cli/guidelines/___library/utilUiStructureDescription.en.md +0 -395
  36. package/cli/guidelines/___lint/lintRuleDescription.en.md +0 -64
  37. package/cli/guidelines/___module/moduleStructureDescription.en.md +0 -80
  38. package/cli/guidelines/componentRule/componentRule.generate.json +0 -131
  39. package/cli/guidelines/componentRule/componentRule.instruction.md +0 -637
  40. package/cli/guidelines/cssRule/cssRule.generate.json +0 -93
  41. package/cli/guidelines/cssRule/cssRule.instruction.md +0 -435
  42. package/cli/guidelines/databaseModule/databaseModule.generate.json +0 -51
  43. package/cli/guidelines/databaseModule/databaseModule.instruction.md +0 -612
  44. package/cli/guidelines/docPageRule/docPageRule.generate.json +0 -72
  45. package/cli/guidelines/docPageRule/docPageRule.instruction.md +0 -389
  46. package/cli/guidelines/enumConstant/enumConstant.generate.json +0 -24
  47. package/cli/guidelines/enumConstant/enumConstant.instruction.md +0 -232
  48. package/cli/guidelines/framework/framework.generate.json +0 -119
  49. package/cli/guidelines/framework/framework.instruction.md +0 -1110
  50. package/cli/guidelines/howToUseStore/howToUseStore.generate.json +0 -0
  51. package/cli/guidelines/modelConstant/modelConstant.generate.json +0 -128
  52. package/cli/guidelines/modelConstant/modelConstant.instruction.md +0 -506
  53. package/cli/guidelines/modelDictionary/modelDictionary.generate.json +0 -108
  54. package/cli/guidelines/modelDictionary/modelDictionary.instruction.md +0 -547
  55. package/cli/guidelines/modelDocument/modelDocument.generate.json +0 -129
  56. package/cli/guidelines/modelDocument/modelDocument.instruction.md +0 -509
  57. package/cli/guidelines/modelService/modelService.generate.json +0 -135
  58. package/cli/guidelines/modelService/modelService.instruction.md +0 -708
  59. package/cli/guidelines/modelSignal/modelSignal.generate.json +0 -201
  60. package/cli/guidelines/modelSignal/modelSignal.instruction.md +0 -552
  61. package/cli/guidelines/modelStore/modelStore.generate.json +0 -130
  62. package/cli/guidelines/modelStore/modelStore.instruction.md +0 -585
  63. package/cli/guidelines/modelTemplate/modelTemplate.generate.json +0 -104
  64. package/cli/guidelines/modelTemplate/modelTemplate.instruction.md +0 -604
  65. package/cli/guidelines/modelUnit/modelUnit.generate.json +0 -92
  66. package/cli/guidelines/modelUnit/modelUnit.instruction.md +0 -541
  67. package/cli/guidelines/modelUtil/modelUtil.generate.json +0 -93
  68. package/cli/guidelines/modelUtil/modelUtil.instruction.md +0 -752
  69. package/cli/guidelines/modelView/modelView.generate.json +0 -80
  70. package/cli/guidelines/modelView/modelView.instruction.md +0 -1005
  71. package/cli/guidelines/modelZone/modelZone.generate.json +0 -126
  72. package/cli/guidelines/modelZone/modelZone.instruction.md +0 -528
  73. package/cli/guidelines/scalarConstant/scalarConstant.generate.json +0 -106
  74. package/cli/guidelines/scalarConstant/scalarConstant.instruction.md +0 -442
  75. package/cli/guidelines/scalarDictionary/scalarDictionary.generate.json +0 -83
  76. package/cli/guidelines/scalarDictionary/scalarDictionary.instruction.md +0 -273
  77. package/cli/guidelines/scalarModule/scalarModule.generate.json +0 -35
  78. package/cli/guidelines/scalarModule/scalarModule.instruction.md +0 -81
  79. package/cli/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -108
  80. package/cli/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +0 -310
  81. package/cli/guidelines/utilUiUsage/utilUiUsage.generate.json +0 -140
  82. package/cli/guidelines/utilUiUsage/utilUiUsage.instruction.md +0 -339
  83. package/cli/index.js +0 -184444
  84. package/cli/index.ts +0 -24
  85. package/cli/library/library.command.ts +0 -28
  86. package/cli/library/library.runner.ts +0 -66
  87. package/cli/library/library.script.ts +0 -39
  88. package/cli/module/module.command.ts +0 -35
  89. package/cli/module/module.prompt.ts +0 -18
  90. package/cli/module/module.request.ts +0 -319
  91. package/cli/module/module.runner.ts +0 -76
  92. package/cli/module/module.script.ts +0 -161
  93. package/cli/npmRegistry.ts +0 -13
  94. package/cli/openBrowser.ts +0 -15
  95. package/cli/package/package.command.ts +0 -32
  96. package/cli/package/package.runner.ts +0 -94
  97. package/cli/package/package.script.ts +0 -35
  98. package/cli/page/page.command.ts +0 -14
  99. package/cli/page/page.runner.ts +0 -14
  100. package/cli/page/page.script.ts +0 -12
  101. package/cli/pluralizeName.ts +0 -5
  102. package/cli/scalar/scalar.command.ts +0 -21
  103. package/cli/scalar/scalar.prompt.ts +0 -131
  104. package/cli/scalar/scalar.runner.ts +0 -38
  105. package/cli/scalar/scalar.script.ts +0 -16
  106. package/cli/semver.ts +0 -18
  107. package/cli/templates/__scalar/__model__/__model__.constant.ts +0 -15
  108. package/cli/templates/__scalar/__model__/__model__.dictionary.ts +0 -19
  109. package/cli/templates/__scalar/__model__/__model__.document.ts +0 -15
  110. package/cli/templates/app/akan.config.ts +0 -14
  111. package/cli/templates/app/env/env.client.debug.ts.template +0 -7
  112. package/cli/templates/app/env/env.client.develop.ts.template +0 -7
  113. package/cli/templates/app/env/env.client.local.ts.template +0 -7
  114. package/cli/templates/app/env/env.client.main.ts.template +0 -7
  115. package/cli/templates/app/env/env.client.testing.ts.template +0 -7
  116. package/cli/templates/app/env/env.client.ts +0 -21
  117. package/cli/templates/app/env/env.client.type.ts +0 -16
  118. package/cli/templates/app/env/env.server.debug.ts.template +0 -7
  119. package/cli/templates/app/env/env.server.develop.ts.template +0 -7
  120. package/cli/templates/app/env/env.server.local.ts.template +0 -7
  121. package/cli/templates/app/env/env.server.main.ts.template +0 -7
  122. package/cli/templates/app/env/env.server.testing.ts.template +0 -6
  123. package/cli/templates/app/env/env.server.ts +0 -20
  124. package/cli/templates/app/lib/___appName__/__appName__.dictionary.ts +0 -17
  125. package/cli/templates/app/lib/___appName__/__appName__.service.ts +0 -13
  126. package/cli/templates/app/lib/___appName__/__appName__.signal.ts +0 -17
  127. package/cli/templates/app/lib/___appName__/__appName__.store.ts +0 -15
  128. package/cli/templates/app/lib/option.ts +0 -17
  129. package/cli/templates/app/main.ts +0 -16
  130. package/cli/templates/app/package.json.template +0 -5
  131. package/cli/templates/app/page/_index.tsx +0 -296
  132. package/cli/templates/app/page/_layout.tsx +0 -31
  133. package/cli/templates/app/page/styles.css.template +0 -53
  134. package/cli/templates/app/public/favicon.ico +0 -0
  135. package/cli/templates/app/public/logo.png +0 -0
  136. package/cli/templates/app/tsconfig.json.template +0 -21
  137. package/cli/templates/client.ts +0 -46
  138. package/cli/templates/crudPages/[__model__Id]/edit/page.tsx +0 -47
  139. package/cli/templates/crudPages/[__model__Id]/page.tsx +0 -52
  140. package/cli/templates/crudPages/new/page.tsx +0 -42
  141. package/cli/templates/crudPages/page.tsx +0 -43
  142. package/cli/templates/crudSinglePage/page.tsx +0 -37
  143. package/cli/templates/env/_env.server.type.ts +0 -16
  144. package/cli/templates/facetIndex/index.ts +0 -32
  145. package/cli/templates/index.ts +0 -10
  146. package/cli/templates/lib/__lib/lib.constant.ts +0 -38
  147. package/cli/templates/lib/__lib/lib.dictionary.ts +0 -33
  148. package/cli/templates/lib/__lib/lib.document.ts +0 -35
  149. package/cli/templates/lib/__lib/lib.service.ts +0 -33
  150. package/cli/templates/lib/__lib/lib.signal.ts +0 -34
  151. package/cli/templates/lib/__lib/lib.store.ts +0 -33
  152. package/cli/templates/lib/cnst.ts +0 -29
  153. package/cli/templates/lib/db.ts +0 -32
  154. package/cli/templates/lib/dict.ts +0 -49
  155. package/cli/templates/lib/sig.ts +0 -60
  156. package/cli/templates/lib/srv.ts +0 -34
  157. package/cli/templates/lib/st.ts +0 -31
  158. package/cli/templates/lib/useClient.ts +0 -19
  159. package/cli/templates/lib/useServer.ts +0 -7
  160. package/cli/templates/libRoot/.gitignore.template +0 -16
  161. package/cli/templates/libRoot/akan.config.ts +0 -12
  162. package/cli/templates/libRoot/base/baseLogic.ts +0 -10
  163. package/cli/templates/libRoot/base/index.ts +0 -8
  164. package/cli/templates/libRoot/common/commonLogic.ts +0 -10
  165. package/cli/templates/libRoot/common/index.ts +0 -8
  166. package/cli/templates/libRoot/env/env.server.example.ts.template +0 -6
  167. package/cli/templates/libRoot/env/env.server.testing.ts.template +0 -6
  168. package/cli/templates/libRoot/lib/___libName__/__libName__.dictionary.ts +0 -15
  169. package/cli/templates/libRoot/lib/___libName__/__libName__.service.ts +0 -11
  170. package/cli/templates/libRoot/lib/___libName__/__libName__.store.ts +0 -13
  171. package/cli/templates/libRoot/lib/option.ts +0 -17
  172. package/cli/templates/libRoot/package.json.template +0 -5
  173. package/cli/templates/libRoot/srvkit/backendLogic.ts +0 -10
  174. package/cli/templates/libRoot/srvkit/index.ts +0 -8
  175. package/cli/templates/libRoot/tsconfig.json.template +0 -11
  176. package/cli/templates/libRoot/ui/index.ts +0 -7
  177. package/cli/templates/libRoot/webkit/frontendLogic.ts +0 -10
  178. package/cli/templates/libRoot/webkit/index.ts +0 -8
  179. package/cli/templates/localDev/docker-compose.yaml.template +0 -37
  180. package/cli/templates/module/__Model__.Template.tsx +0 -36
  181. package/cli/templates/module/__Model__.Unit.tsx +0 -26
  182. package/cli/templates/module/__Model__.Util.tsx +0 -30
  183. package/cli/templates/module/__Model__.View.tsx +0 -29
  184. package/cli/templates/module/__Model__.Zone.tsx +0 -43
  185. package/cli/templates/module/__model__.constant.ts +0 -24
  186. package/cli/templates/module/__model__.dictionary.ts +0 -30
  187. package/cli/templates/module/__model__.document.ts +0 -23
  188. package/cli/templates/module/__model__.service.ts +0 -16
  189. package/cli/templates/module/__model__.signal.ts +0 -27
  190. package/cli/templates/module/__model__.store.ts +0 -19
  191. package/cli/templates/moduleRoot/index.tsx +0 -31
  192. package/cli/templates/pkgRoot/tsconfig.json.template +0 -10
  193. package/cli/templates/server.ts +0 -45
  194. package/cli/templates/workspaceRoot/.env.template +0 -14
  195. package/cli/templates/workspaceRoot/.gitignore.template +0 -120
  196. package/cli/templates/workspaceRoot/.vscode/settings.json.template +0 -23
  197. package/cli/templates/workspaceRoot/biome.json.template +0 -191
  198. package/cli/templates/workspaceRoot/bunfig.toml +0 -4
  199. package/cli/templates/workspaceRoot/package.json.template +0 -7
  200. package/cli/templates/workspaceRoot/tsconfig.json.template +0 -29
  201. package/cli/testHelpers.ts +0 -171
  202. package/cli/workspace/workspace.command.ts +0 -55
  203. package/cli/workspace/workspace.runner.ts +0 -79
  204. package/cli/workspace/workspace.script.ts +0 -74
  205. package/devkit/aiEditor.ts +0 -299
  206. package/devkit/akanApp/akanApp.host.ts +0 -393
  207. package/devkit/akanApp/index.ts +0 -1
  208. package/devkit/akanConfig/akanConfig.ts +0 -360
  209. package/devkit/akanConfig/index.ts +0 -2
  210. package/devkit/akanConfig/types.ts +0 -187
  211. package/devkit/applicationBuildReporter.ts +0 -69
  212. package/devkit/applicationBuildRunner.ts +0 -302
  213. package/devkit/applicationReleasePackager.ts +0 -205
  214. package/devkit/artifact/implicitRootLayout.ts +0 -155
  215. package/devkit/artifact/index.ts +0 -1
  216. package/devkit/artifact/routeSeedIndex.ts +0 -128
  217. package/devkit/auth.ts +0 -41
  218. package/devkit/builder.ts +0 -164
  219. package/devkit/capacitor.base.config.ts +0 -88
  220. package/devkit/capacitorApp.ts +0 -443
  221. package/devkit/commandDecorators/argMeta.ts +0 -102
  222. package/devkit/commandDecorators/command.ts +0 -340
  223. package/devkit/commandDecorators/commandBuilder.ts +0 -224
  224. package/devkit/commandDecorators/commandMeta.ts +0 -6
  225. package/devkit/commandDecorators/dependencyBuilder.ts +0 -100
  226. package/devkit/commandDecorators/helpFormatter.ts +0 -220
  227. package/devkit/commandDecorators/index.ts +0 -8
  228. package/devkit/commandDecorators/targetMeta.ts +0 -31
  229. package/devkit/commandDecorators/types.ts +0 -10
  230. package/devkit/constants.ts +0 -25
  231. package/devkit/createTunnel.ts +0 -36
  232. package/devkit/dependencyScanner.ts +0 -339
  233. package/devkit/executors.ts +0 -1362
  234. package/devkit/extractDeps.ts +0 -85
  235. package/devkit/fileEditor.ts +0 -106
  236. package/devkit/fileSys.ts +0 -39
  237. package/devkit/frontendBuild/allRoutesBuilder.ts +0 -103
  238. package/devkit/frontendBuild/clientBuildTypes.ts +0 -114
  239. package/devkit/frontendBuild/clientEntriesBundler.ts +0 -300
  240. package/devkit/frontendBuild/clientEntryDiscovery.ts +0 -196
  241. package/devkit/frontendBuild/csrArtifactBuilder.ts +0 -237
  242. package/devkit/frontendBuild/cssCompiler.ts +0 -285
  243. package/devkit/frontendBuild/cssImportResolver.ts +0 -116
  244. package/devkit/frontendBuild/fontOptimizer.ts +0 -427
  245. package/devkit/frontendBuild/hmrChangeClassifier.ts +0 -28
  246. package/devkit/frontendBuild/hmrWatcher.ts +0 -101
  247. package/devkit/frontendBuild/index.ts +0 -18
  248. package/devkit/frontendBuild/pagesBundleBuilder.ts +0 -137
  249. package/devkit/frontendBuild/pagesEntrySourceGenerator.ts +0 -37
  250. package/devkit/frontendBuild/precompressArtifacts.ts +0 -59
  251. package/devkit/frontendBuild/routeClientBuilder.ts +0 -290
  252. package/devkit/frontendBuild/routesManifestArtifactSerializer.ts +0 -62
  253. package/devkit/frontendBuild/ssrBaseArtifactBuilder.ts +0 -139
  254. package/devkit/frontendBuild/vendorSpecifiers.ts +0 -16
  255. package/devkit/frontendBuild/watchRootResolver.ts +0 -28
  256. package/devkit/getCredentials.ts +0 -19
  257. package/devkit/getDirname.ts +0 -3
  258. package/devkit/getModelFileData.ts +0 -59
  259. package/devkit/getRelatedCnsts.ts +0 -300
  260. package/devkit/guideline.ts +0 -19
  261. package/devkit/incrementalBuilder/incrementalBuilder.host.ts +0 -152
  262. package/devkit/incrementalBuilder/incrementalBuilder.proc.ts +0 -331
  263. package/devkit/incrementalBuilder/index.ts +0 -1
  264. package/devkit/index.ts +0 -36
  265. package/devkit/lint/no-deep-internal-import.grit +0 -25
  266. package/devkit/lint/no-import-client-functions.grit +0 -32
  267. package/devkit/lint/no-import-external-library.grit +0 -21
  268. package/devkit/lint/no-js-private-class-method.grit +0 -42
  269. package/devkit/lint/no-use-client-in-server.grit +0 -7
  270. package/devkit/lint/non-scalar-props-restricted.grit +0 -13
  271. package/devkit/linter.ts +0 -248
  272. package/devkit/mobile/index.ts +0 -1
  273. package/devkit/mobile/mobileTarget.ts +0 -88
  274. package/devkit/prompter.ts +0 -71
  275. package/devkit/scanInfo.ts +0 -606
  276. package/devkit/selectModel.ts +0 -11
  277. package/devkit/spinner.ts +0 -54
  278. package/devkit/src/capacitorApp.ts +0 -277
  279. package/devkit/sshTunnel.ts +0 -151
  280. package/devkit/streamAi.ts +0 -45
  281. package/devkit/transforms/barrelAnalyzer.ts +0 -249
  282. package/devkit/transforms/barrelImportsPlugin.ts +0 -457
  283. package/devkit/transforms/externalizeFrameworkPlugin.ts +0 -159
  284. package/devkit/transforms/index.ts +0 -5
  285. package/devkit/transforms/rscUseClientTransform.ts +0 -52
  286. package/devkit/transforms/useClientBundlePlugin.ts +0 -47
  287. package/devkit/typeChecker.ts +0 -260
  288. package/devkit/types.ts +0 -44
  289. package/devkit/ui/MultiScrollList.tsx +0 -228
  290. package/devkit/ui/ScrollList.tsx +0 -106
  291. package/devkit/ui/index.ts +0 -2
  292. package/devkit/uploadRelease.ts +0 -95
  293. package/devkit/useStdoutDimensions.ts +0 -20
  294. package/types/cli/application/application.command.d.ts +0 -7
  295. package/types/cli/application/application.interface.d.ts +0 -40
  296. package/types/cli/application/application.runner.d.ts +0 -66
  297. package/types/cli/application/application.script.d.ts +0 -72
  298. package/types/cli/build.d.ts +0 -1
  299. package/types/cli/cloud/cloud.command.d.ts +0 -7
  300. package/types/cli/cloud/cloud.runner.d.ts +0 -13
  301. package/types/cli/cloud/cloud.script.d.ts +0 -23
  302. package/types/cli/guideline/guideline.command.d.ts +0 -7
  303. package/types/cli/guideline/guideline.prompt.d.ts +0 -29
  304. package/types/cli/guideline/guideline.runner.d.ts +0 -21
  305. package/types/cli/guideline/guideline.script.d.ts +0 -16
  306. package/types/cli/index.d.ts +0 -2
  307. package/types/cli/library/library.command.d.ts +0 -7
  308. package/types/cli/library/library.runner.d.ts +0 -11
  309. package/types/cli/library/library.script.d.ts +0 -13
  310. package/types/cli/module/module.command.d.ts +0 -7
  311. package/types/cli/module/module.prompt.d.ts +0 -13
  312. package/types/cli/module/module.request.d.ts +0 -63
  313. package/types/cli/module/module.runner.d.ts +0 -55
  314. package/types/cli/module/module.script.d.ts +0 -22
  315. package/types/cli/npmRegistry.d.ts +0 -1
  316. package/types/cli/openBrowser.d.ts +0 -1
  317. package/types/cli/package/package.command.d.ts +0 -7
  318. package/types/cli/package/package.runner.d.ts +0 -13
  319. package/types/cli/package/package.script.d.ts +0 -18
  320. package/types/cli/page/page.command.d.ts +0 -7
  321. package/types/cli/page/page.runner.d.ts +0 -10
  322. package/types/cli/page/page.script.d.ts +0 -13
  323. package/types/cli/pluralizeName.d.ts +0 -1
  324. package/types/cli/scalar/scalar.command.d.ts +0 -7
  325. package/types/cli/scalar/scalar.prompt.d.ts +0 -23
  326. package/types/cli/scalar/scalar.runner.d.ts +0 -16
  327. package/types/cli/scalar/scalar.script.d.ts +0 -11
  328. package/types/cli/semver.d.ts +0 -1
  329. package/types/cli/templates/__scalar/__model__/__model__.constant.d.ts +0 -7
  330. package/types/cli/templates/__scalar/__model__/__model__.dictionary.d.ts +0 -7
  331. package/types/cli/templates/__scalar/__model__/__model__.document.d.ts +0 -7
  332. package/types/cli/templates/app/akan.config.d.ts +0 -6
  333. package/types/cli/templates/app/env/env.client.d.ts +0 -6
  334. package/types/cli/templates/app/env/env.client.type.d.ts +0 -6
  335. package/types/cli/templates/app/env/env.server.d.ts +0 -6
  336. package/types/cli/templates/app/lib/___appName__/__appName__.dictionary.d.ts +0 -7
  337. package/types/cli/templates/app/lib/___appName__/__appName__.service.d.ts +0 -7
  338. package/types/cli/templates/app/lib/___appName__/__appName__.signal.d.ts +0 -7
  339. package/types/cli/templates/app/lib/___appName__/__appName__.store.d.ts +0 -7
  340. package/types/cli/templates/app/lib/option.d.ts +0 -6
  341. package/types/cli/templates/app/main.d.ts +0 -6
  342. package/types/cli/templates/app/page/_index.d.ts +0 -9
  343. package/types/cli/templates/app/page/_layout.d.ts +0 -11
  344. package/types/cli/templates/client.d.ts +0 -4
  345. package/types/cli/templates/crudPages/[__model__Id]/edit/page.d.ts +0 -11
  346. package/types/cli/templates/crudPages/[__model__Id]/page.d.ts +0 -11
  347. package/types/cli/templates/crudPages/new/page.d.ts +0 -11
  348. package/types/cli/templates/crudPages/page.d.ts +0 -11
  349. package/types/cli/templates/crudSinglePage/page.d.ts +0 -11
  350. package/types/cli/templates/env/_env.server.type.d.ts +0 -7
  351. package/types/cli/templates/facetIndex/index.d.ts +0 -13
  352. package/types/cli/templates/facetIndex.d.ts +0 -1
  353. package/types/cli/templates/index.d.ts +0 -6
  354. package/types/cli/templates/lib/__lib/lib.constant.d.ts +0 -4
  355. package/types/cli/templates/lib/__lib/lib.dictionary.d.ts +0 -4
  356. package/types/cli/templates/lib/__lib/lib.document.d.ts +0 -4
  357. package/types/cli/templates/lib/__lib/lib.service.d.ts +0 -4
  358. package/types/cli/templates/lib/__lib/lib.signal.d.ts +0 -4
  359. package/types/cli/templates/lib/__lib/lib.store.d.ts +0 -4
  360. package/types/cli/templates/lib/cnst.d.ts +0 -4
  361. package/types/cli/templates/lib/db.d.ts +0 -4
  362. package/types/cli/templates/lib/dict.d.ts +0 -4
  363. package/types/cli/templates/lib/sig.d.ts +0 -4
  364. package/types/cli/templates/lib/srv.d.ts +0 -4
  365. package/types/cli/templates/lib/st.d.ts +0 -4
  366. package/types/cli/templates/lib/useClient.d.ts +0 -4
  367. package/types/cli/templates/lib/useServer.d.ts +0 -4
  368. package/types/cli/templates/libRoot/akan.config.d.ts +0 -5
  369. package/types/cli/templates/libRoot/base/baseLogic.d.ts +0 -5
  370. package/types/cli/templates/libRoot/base/index.d.ts +0 -5
  371. package/types/cli/templates/libRoot/base.d.ts +0 -1
  372. package/types/cli/templates/libRoot/common/commonLogic.d.ts +0 -5
  373. package/types/cli/templates/libRoot/common/index.d.ts +0 -5
  374. package/types/cli/templates/libRoot/common.d.ts +0 -1
  375. package/types/cli/templates/libRoot/lib/___libName__/__libName__.dictionary.d.ts +0 -6
  376. package/types/cli/templates/libRoot/lib/___libName__/__libName__.service.d.ts +0 -6
  377. package/types/cli/templates/libRoot/lib/___libName__/__libName__.store.d.ts +0 -6
  378. package/types/cli/templates/libRoot/lib/option.d.ts +0 -6
  379. package/types/cli/templates/libRoot/srvkit/backendLogic.d.ts +0 -5
  380. package/types/cli/templates/libRoot/srvkit/index.d.ts +0 -5
  381. package/types/cli/templates/libRoot/srvkit.d.ts +0 -1
  382. package/types/cli/templates/libRoot/ui/index.d.ts +0 -5
  383. package/types/cli/templates/libRoot/ui.d.ts +0 -1
  384. package/types/cli/templates/libRoot/webkit/frontendLogic.d.ts +0 -5
  385. package/types/cli/templates/libRoot/webkit/index.d.ts +0 -5
  386. package/types/cli/templates/libRoot/webkit.d.ts +0 -1
  387. package/types/cli/templates/module/__Model__.Template.d.ts +0 -11
  388. package/types/cli/templates/module/__Model__.Unit.d.ts +0 -11
  389. package/types/cli/templates/module/__Model__.Util.d.ts +0 -11
  390. package/types/cli/templates/module/__Model__.View.d.ts +0 -11
  391. package/types/cli/templates/module/__Model__.Zone.d.ts +0 -11
  392. package/types/cli/templates/module/__model__.constant.d.ts +0 -8
  393. package/types/cli/templates/module/__model__.dictionary.d.ts +0 -8
  394. package/types/cli/templates/module/__model__.document.d.ts +0 -8
  395. package/types/cli/templates/module/__model__.service.d.ts +0 -8
  396. package/types/cli/templates/module/__model__.signal.d.ts +0 -9
  397. package/types/cli/templates/module/__model__.store.d.ts +0 -8
  398. package/types/cli/templates/moduleRoot/index.d.ts +0 -11
  399. package/types/cli/templates/moduleRoot.d.ts +0 -1
  400. package/types/cli/templates/server.d.ts +0 -4
  401. package/types/cli/templates.d.ts +0 -1
  402. package/types/cli/testHelpers.d.ts +0 -64
  403. package/types/cli/workspace/workspace.command.d.ts +0 -7
  404. package/types/cli/workspace/workspace.runner.d.ts +0 -14
  405. package/types/cli/workspace/workspace.script.d.ts +0 -29
  406. package/types/cli.d.ts +0 -1
  407. package/types/devkit/aiEditor.d.ts +0 -50
  408. package/types/devkit/akanApp/akanApp.host.d.ts +0 -16
  409. package/types/devkit/akanApp/index.d.ts +0 -1
  410. package/types/devkit/akanApp.d.ts +0 -1
  411. package/types/devkit/akanConfig/akanConfig.d.ts +0 -36
  412. package/types/devkit/akanConfig/index.d.ts +0 -2
  413. package/types/devkit/akanConfig.d.ts +0 -1
  414. package/types/devkit/applicationBuildReporter.d.ts +0 -25
  415. package/types/devkit/applicationBuildRunner.d.ts +0 -29
  416. package/types/devkit/applicationReleasePackager.d.ts +0 -17
  417. package/types/devkit/artifact/implicitRootLayout.d.ts +0 -17
  418. package/types/devkit/artifact/index.d.ts +0 -1
  419. package/types/devkit/artifact/routeSeedIndex.d.ts +0 -38
  420. package/types/devkit/artifact.d.ts +0 -1
  421. package/types/devkit/auth.d.ts +0 -9
  422. package/types/devkit/builder.d.ts +0 -18
  423. package/types/devkit/capacitor.base.config.d.ts +0 -3
  424. package/types/devkit/capacitorApp.d.ts +0 -58
  425. package/types/devkit/commandDecorators/argMeta.d.ts +0 -68
  426. package/types/devkit/commandDecorators/command.d.ts +0 -2
  427. package/types/devkit/commandDecorators/commandBuilder.d.ts +0 -60
  428. package/types/devkit/commandDecorators/commandMeta.d.ts +0 -2
  429. package/types/devkit/commandDecorators/dependencyBuilder.d.ts +0 -22
  430. package/types/devkit/commandDecorators/helpFormatter.d.ts +0 -3
  431. package/types/devkit/commandDecorators/index.d.ts +0 -8
  432. package/types/devkit/commandDecorators/targetMeta.d.ts +0 -21
  433. package/types/devkit/commandDecorators/types.d.ts +0 -8
  434. package/types/devkit/commandDecorators.d.ts +0 -1
  435. package/types/devkit/constants.d.ts +0 -25
  436. package/types/devkit/createTunnel.d.ts +0 -8
  437. package/types/devkit/dependencyScanner.d.ts +0 -33
  438. package/types/devkit/executors.d.ts +0 -320
  439. package/types/devkit/extractDeps.d.ts +0 -7
  440. package/types/devkit/fileEditor.d.ts +0 -16
  441. package/types/devkit/fileSys.d.ts +0 -12
  442. package/types/devkit/frontendBuild/allRoutesBuilder.d.ts +0 -18
  443. package/types/devkit/frontendBuild/clientBuildTypes.d.ts +0 -107
  444. package/types/devkit/frontendBuild/clientEntriesBundler.d.ts +0 -12
  445. package/types/devkit/frontendBuild/clientEntryDiscovery.d.ts +0 -19
  446. package/types/devkit/frontendBuild/csrArtifactBuilder.d.ts +0 -16
  447. package/types/devkit/frontendBuild/cssCompiler.d.ts +0 -25
  448. package/types/devkit/frontendBuild/cssImportResolver.d.ts +0 -9
  449. package/types/devkit/frontendBuild/fontOptimizer.d.ts +0 -14
  450. package/types/devkit/frontendBuild/hmrChangeClassifier.d.ts +0 -5
  451. package/types/devkit/frontendBuild/hmrWatcher.d.ts +0 -21
  452. package/types/devkit/frontendBuild/index.d.ts +0 -18
  453. package/types/devkit/frontendBuild/pagesBundleBuilder.d.ts +0 -28
  454. package/types/devkit/frontendBuild/pagesEntrySourceGenerator.d.ts +0 -9
  455. package/types/devkit/frontendBuild/precompressArtifacts.d.ts +0 -7
  456. package/types/devkit/frontendBuild/routeClientBuilder.d.ts +0 -50
  457. package/types/devkit/frontendBuild/routesManifestArtifactSerializer.d.ts +0 -12
  458. package/types/devkit/frontendBuild/ssrBaseArtifactBuilder.d.ts +0 -16
  459. package/types/devkit/frontendBuild/vendorSpecifiers.d.ts +0 -2
  460. package/types/devkit/frontendBuild/watchRootResolver.d.ts +0 -6
  461. package/types/devkit/frontendBuild.d.ts +0 -1
  462. package/types/devkit/getCredentials.d.ts +0 -12
  463. package/types/devkit/getDirname.d.ts +0 -1
  464. package/types/devkit/getModelFileData.d.ts +0 -16
  465. package/types/devkit/getRelatedCnsts.d.ts +0 -53
  466. package/types/devkit/guideline.d.ts +0 -19
  467. package/types/devkit/incrementalBuilder/incrementalBuilder.host.d.ts +0 -30
  468. package/types/devkit/incrementalBuilder/incrementalBuilder.proc.d.ts +0 -1
  469. package/types/devkit/incrementalBuilder/index.d.ts +0 -1
  470. package/types/devkit/incrementalBuilder.d.ts +0 -1
  471. package/types/devkit/index.d.ts +0 -36
  472. package/types/devkit/linter.d.ts +0 -108
  473. package/types/devkit/mobile/index.d.ts +0 -1
  474. package/types/devkit/mobile/mobileTarget.d.ts +0 -14
  475. package/types/devkit/mobile.d.ts +0 -1
  476. package/types/devkit/prompter.d.ts +0 -15
  477. package/types/devkit/scanInfo.d.ts +0 -82
  478. package/types/devkit/selectModel.d.ts +0 -1
  479. package/types/devkit/spinner.d.ts +0 -20
  480. package/types/devkit/src/capacitorApp.d.ts +0 -39
  481. package/types/devkit/sshTunnel.d.ts +0 -14
  482. package/types/devkit/streamAi.d.ts +0 -6
  483. package/types/devkit/transforms/barrelAnalyzer.d.ts +0 -27
  484. package/types/devkit/transforms/barrelImportsPlugin.d.ts +0 -26
  485. package/types/devkit/transforms/externalizeFrameworkPlugin.d.ts +0 -49
  486. package/types/devkit/transforms/index.d.ts +0 -5
  487. package/types/devkit/transforms/rscUseClientTransform.d.ts +0 -10
  488. package/types/devkit/transforms/useClientBundlePlugin.d.ts +0 -19
  489. package/types/devkit/transforms.d.ts +0 -1
  490. package/types/devkit/typeChecker.d.ts +0 -62
  491. package/types/devkit/types.d.ts +0 -43
  492. package/types/devkit/ui/MultiScrollList.d.ts +0 -13
  493. package/types/devkit/ui/ScrollList.d.ts +0 -7
  494. package/types/devkit/ui/index.d.ts +0 -2
  495. package/types/devkit/ui.d.ts +0 -1
  496. package/types/devkit/uploadRelease.d.ts +0 -10
  497. package/types/devkit/useStdoutDimensions.d.ts +0 -1
  498. package/types/devkit.d.ts +0 -1
@@ -1,1362 +0,0 @@
1
- import {
2
- type ChildProcess,
3
- type ExecOptions,
4
- exec,
5
- type ForkOptions,
6
- fork,
7
- type SpawnOptions,
8
- spawn,
9
- } from "node:child_process";
10
- import { readFileSync } from "node:fs";
11
- import { copyFile, mkdir, readdir as readDirEntries, stat } from "node:fs/promises";
12
- import path from "node:path";
13
- import {
14
- capitalize,
15
- isRouteSourceFile,
16
- Logger,
17
- parseRouteModuleKey,
18
- validatePageSourceFile,
19
- validateSubRoutePageKey,
20
- } from "akanjs/common";
21
- import { $ } from "bun";
22
- import chalk from "chalk";
23
- import ts from "typescript";
24
- import { AkanAppConfig, AkanLibConfig, decreaseBuildNum, increaseBuildNum } from "./akanConfig";
25
- import { FileSys } from "./fileSys";
26
- import { getDirname } from "./getDirname";
27
- import { Linter } from "./linter";
28
- import { AppInfo, LibInfo, PkgInfo, WorkspaceInfo } from "./scanInfo";
29
- import { Spinner } from "./spinner";
30
- import { TypeChecker } from "./typeChecker";
31
- import type { FileContent, PackageJson, TsConfigJson } from "./types";
32
-
33
- const staticTemplateFileExtensions = new Set([
34
- ".avif",
35
- ".bmp",
36
- ".cjs",
37
- ".css",
38
- ".eot",
39
- ".gif",
40
- ".html",
41
- ".ico",
42
- ".jpeg",
43
- ".jpg",
44
- ".js",
45
- ".json",
46
- ".map",
47
- ".md",
48
- ".mjs",
49
- ".mp3",
50
- ".mp4",
51
- ".ogg",
52
- ".otf",
53
- ".pdf",
54
- ".png",
55
- ".svg",
56
- ".ttf",
57
- ".txt",
58
- ".wasm",
59
- ".wav",
60
- ".webm",
61
- ".webp",
62
- ".woff",
63
- ".woff2",
64
- ".xml",
65
- ]);
66
-
67
- export const execEmoji = {
68
- workspace: "🏠",
69
- app: "🚀",
70
- lib: "🔧",
71
- pkg: "📦",
72
- dist: "💿",
73
- module: "⚙️",
74
- default: "✈️", // for sys executor
75
- };
76
-
77
- const parseEnvFile = (envPath: string): Record<string, string> => {
78
- const env: Record<string, string> = {};
79
- const content = (() => {
80
- try {
81
- return readFileSync(envPath, "utf8");
82
- } catch {
83
- return "";
84
- }
85
- })();
86
- for (const line of content.split(/\r?\n/)) {
87
- const trimmed = line.trim();
88
- if (!trimmed || trimmed.startsWith("#")) continue;
89
- const normalized = trimmed.startsWith("export ") ? trimmed.slice("export ".length).trim() : trimmed;
90
- const separatorIndex = normalized.indexOf("=");
91
- if (separatorIndex <= 0) continue;
92
- const key = normalized.slice(0, separatorIndex).trim();
93
- let value = normalized.slice(separatorIndex + 1).trim();
94
- if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
95
- value = value.slice(1, -1);
96
- }
97
- env[key] = value;
98
- }
99
- return env;
100
- };
101
-
102
- const PAGE_ROUTE_EXPORTS = new Set(["default", "pageConfig", "head", "generateHead", "Loading"]);
103
- const ROOT_LAYOUT_EXPORTS = new Set([
104
- "default",
105
- "head",
106
- "generateHead",
107
- "fonts",
108
- "manifest",
109
- "theme",
110
- "reconnect",
111
- "layoutStyle",
112
- "gaTrackingId",
113
- "Loading",
114
- ]);
115
- const LAYOUT_ROUTE_EXPORTS = new Set(["default", "head", "generateHead", "Loading"]);
116
-
117
- function validateRouteSourceExports(
118
- source: string,
119
- filePath: string,
120
- kind: "page" | "layout",
121
- options: { rootLayout?: boolean } = {},
122
- ) {
123
- const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
124
- const allowed =
125
- kind === "page" ? PAGE_ROUTE_EXPORTS : options.rootLayout ? ROOT_LAYOUT_EXPORTS : LAYOUT_ROUTE_EXPORTS;
126
- const exported = new Set<string>();
127
- const assertExport = (name: string) => {
128
- if (!allowed.has(name)) {
129
- throw new Error(`[route-convention] unsupported export "${name}" in ${filePath}`);
130
- }
131
- exported.add(name);
132
- };
133
-
134
- for (const statement of sourceFile.statements) {
135
- if (ts.isInterfaceDeclaration(statement) || ts.isTypeAliasDeclaration(statement)) continue;
136
- if (ts.isExportDeclaration(statement)) {
137
- if (statement.isTypeOnly) continue;
138
- const clause = statement.exportClause;
139
- if (!clause) throw new Error(`[route-convention] export * is not allowed in route modules: ${filePath}`);
140
- if (ts.isNamedExports(clause)) {
141
- for (const element of clause.elements) {
142
- if (element.isTypeOnly) continue;
143
- assertExport(element.name.text);
144
- }
145
- }
146
- continue;
147
- }
148
- const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : undefined;
149
- const isExported = modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
150
- if (!isExported) continue;
151
- const isDefault = modifiers?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword) ?? false;
152
- if (isDefault) {
153
- assertExport("default");
154
- continue;
155
- }
156
- if (ts.isVariableStatement(statement)) {
157
- for (const declaration of statement.declarationList.declarations) {
158
- if (ts.isIdentifier(declaration.name)) assertExport(declaration.name.text);
159
- }
160
- continue;
161
- }
162
- const name = (statement as unknown as { name?: ts.Node }).name;
163
- if (name && ts.isIdentifier(name)) {
164
- assertExport(name.text);
165
- }
166
- }
167
- if (exported.has("head") && exported.has("generateHead")) {
168
- throw new Error(`[route-convention] head and generateHead cannot both be exported in ${filePath}`);
169
- }
170
- }
171
-
172
- export class Executor {
173
- static verbose = false;
174
- static setVerbose(verbose: boolean) {
175
- Executor.verbose = verbose;
176
- }
177
-
178
- name: string;
179
- logger: Logger;
180
- logs: string[];
181
- cwdPath: string;
182
- emoji = execEmoji.default;
183
- typeChecker: TypeChecker | null = null;
184
- linter: Linter | null = null;
185
- constructor(name: string, cwdPath: string) {
186
- this.name = name;
187
- this.logger = new Logger(name);
188
- this.logs = [] as string[];
189
- this.cwdPath = cwdPath;
190
- }
191
- #stdout(data: Buffer) {
192
- if (Executor.verbose) Logger.raw(chalk.dim(data.toString()));
193
- }
194
- #stderr(data: Buffer) {
195
- Logger.raw(chalk.red(data.toString()));
196
- }
197
- exec(command: string, options: ExecOptions = {}) {
198
- const proc = exec(command, { cwd: this.cwdPath, ...options });
199
- proc.stdout?.on("data", (data: Buffer) => {
200
- this.#stdout(data);
201
- });
202
- proc.stderr?.on("data", (data: Buffer) => {
203
- this.#stdout(data);
204
- });
205
- return new Promise((resolve, reject) => {
206
- proc.on("exit", (code, signal) => {
207
- if (!!code || signal) reject({ code, signal });
208
- else resolve({ code, signal });
209
- });
210
- });
211
- }
212
-
213
- spawn(command: string, args: string[] = [], options: SpawnOptions = {}): Promise<string> {
214
- const proc = spawn(command, args, {
215
- cwd: this.cwdPath,
216
-
217
- ...options,
218
- });
219
- let stdout = "";
220
- let stderr = "";
221
-
222
- proc.stdout?.on("data", (data: Buffer) => {
223
- stdout += data.toString();
224
- this.logs.push(data.toString());
225
- this.#stdout(data);
226
- });
227
- proc.stderr?.on("data", (data: Buffer) => {
228
- stderr += data.toString();
229
- this.logs.push(data.toString());
230
- this.#stdout(data);
231
- });
232
- return new Promise((resolve, reject) => {
233
- proc.on("close", (code, signal) => {
234
- if (code !== 0 || signal) reject(stderr || stdout);
235
- else resolve(stdout);
236
- });
237
- });
238
- }
239
- spawnSync(command: string, args: string[] = [], options: SpawnOptions = {}): ChildProcess {
240
- const proc = spawn(command, args, {
241
- cwd: this.cwdPath,
242
-
243
- ...options,
244
- });
245
- return proc;
246
- }
247
- fork(modulePath: string, args: string[] = [], options: ForkOptions = {}) {
248
- const proc = fork(modulePath, args, {
249
- cwd: this.cwdPath,
250
-
251
- ...options,
252
- });
253
- proc.stdout?.on("data", (data: Buffer) => {
254
- this.#stdout(data);
255
- });
256
- proc.stderr?.on("data", (data: Buffer) => {
257
- this.#stderr(data);
258
- });
259
- return new Promise((resolve, reject) => {
260
- proc.on("exit", (code, signal) => {
261
- if (!!code || signal) reject({ code, signal });
262
- else resolve({ code, signal });
263
- });
264
- });
265
- }
266
- getPath(filePath: string) {
267
- if (path.isAbsolute(filePath)) return filePath;
268
- if (filePath.startsWith(".")) return path.join(this.cwdPath, filePath);
269
- const baseParts = this.cwdPath.split("/").filter(Boolean);
270
- const targetParts = filePath.split("/").filter(Boolean);
271
-
272
- let overlapLength = 0;
273
- for (let i = 1; i <= Math.min(baseParts.length, targetParts.length); i++) {
274
- let isOverlap = true;
275
- for (let j = 0; j < i; j++)
276
- if (baseParts[baseParts.length - i + j] !== targetParts[j]) {
277
- isOverlap = false;
278
- break;
279
- }
280
- if (isOverlap) overlapLength = i;
281
- }
282
- const result =
283
- overlapLength > 0
284
- ? `/${[...baseParts, ...targetParts.slice(overlapLength)].join("/")}`
285
- : `${this.cwdPath}/${filePath}`;
286
- return result.replace(/\/+/g, "/");
287
- }
288
- async mkdir(dirPath: string) {
289
- const writePath = this.getPath(dirPath);
290
- if (!(await FileSys.dirExists(writePath))) await mkdir(writePath, { recursive: true });
291
- this.logger.verbose(`Make directory ${writePath}`);
292
- return this;
293
- }
294
- async readdir(dirPath: string): Promise<string[]> {
295
- const readPath = this.getPath(dirPath);
296
- try {
297
- const glob = new Bun.Glob("*");
298
- return Array.from(glob.scanSync({ cwd: readPath, onlyFiles: false }));
299
- } catch {
300
- return [];
301
- }
302
- }
303
- async getAllFiles(pattern = "**/*", { cwd }: { cwd?: string } = {}): Promise<string[]> {
304
- const glob = new Bun.Glob(pattern);
305
- return Array.from(glob.scanSync({ cwd: cwd ?? this.cwdPath, onlyFiles: true }));
306
- }
307
- async getFilesAndDirs(dirPath: string): Promise<{ files: string[]; dirs: string[] }> {
308
- const fullDirPath = this.getPath(dirPath);
309
- const fileGlob = new Bun.Glob("*");
310
- const files = Array.from(fileGlob.scanSync({ cwd: fullDirPath, onlyFiles: true }));
311
- const dirGlob = new Bun.Glob("*");
312
- const allEntries = Array.from(dirGlob.scanSync({ cwd: fullDirPath, onlyFiles: false }));
313
- const dirs = allEntries.filter((entry) => !files.includes(entry));
314
- return { files, dirs };
315
- }
316
- async exists(filePath: string) {
317
- const readPath = this.getPath(filePath);
318
- return await FileSys.exists(readPath);
319
- }
320
- async remove(filePath: string) {
321
- const readPath = this.getPath(filePath);
322
- if (await FileSys.fileExists(readPath)) await FileSys.delete(readPath);
323
- this.logger.verbose(`Remove file ${readPath}`);
324
- return this;
325
- }
326
- async removeDir(dirPath: string) {
327
- const readPath = this.getPath(dirPath);
328
- if (await FileSys.dirExists(readPath)) await $`rm -rf ${readPath}`;
329
- this.logger.verbose(`Remove directory ${readPath}`);
330
- return this;
331
- }
332
- async writeFile(
333
- filePath: string,
334
- content: string | object,
335
- { overwrite = true }: { overwrite?: boolean } = {},
336
- ): Promise<FileContent> {
337
- const writePath = this.getPath(filePath);
338
- const dir = path.dirname(writePath);
339
- if (!(await FileSys.dirExists(dir))) await mkdir(dir, { recursive: true });
340
- let contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2);
341
-
342
- if (await FileSys.fileExists(writePath)) {
343
- const currentContent = await FileSys.readText(writePath);
344
- if (currentContent === contentStr || !overwrite) {
345
- this.logger.verbose(`File ${writePath} is unchanged`);
346
- contentStr = currentContent;
347
- } else {
348
- await FileSys.writeText(writePath, contentStr);
349
- if (Logger.isVerbose()) this.logger.rawLog(chalk.yellow(`File Update: ${filePath}`));
350
- }
351
- } else {
352
- await FileSys.writeText(writePath, contentStr);
353
- this.logger.rawLog(chalk.green(`File Create: ${filePath}`));
354
- }
355
- return { filePath: writePath, content: contentStr };
356
- }
357
- async writeJson(filePath: string, content: object) {
358
- await this.writeFile(filePath, content);
359
- }
360
- async getLocalFile(targetPath: string) {
361
- const filePath = path.isAbsolute(targetPath) ? targetPath : targetPath.replace(this.cwdPath, "");
362
- const content = await this.readFile(filePath);
363
- return { filePath, content };
364
- }
365
- async readFile(filePath: string) {
366
- const readPath = this.getPath(filePath);
367
- return await FileSys.readText(readPath);
368
- }
369
- async readJson(filePath: string) {
370
- const readPath = this.getPath(filePath);
371
- return await FileSys.readJson<object>(readPath);
372
- }
373
- async cp(srcPath: string, destPath: string) {
374
- const src = this.getPath(srcPath);
375
- const dest = this.getPath(destPath);
376
- if (!(await FileSys.exists(src))) return;
377
- const isDirectory = (await stat(src)).isDirectory();
378
- if (!(await FileSys.exists(dest)) && isDirectory) await mkdir(dest, { recursive: true });
379
- await $`cp -r ${src}${isDirectory ? "/." : ""} ${dest}`;
380
- }
381
- log(msg: string) {
382
- this.logger.info(msg);
383
- return this;
384
- }
385
- verbose(msg: string) {
386
- this.logger.verbose(msg);
387
- return this;
388
- }
389
- debug(msg: string) {
390
- this.logger.debug(msg);
391
- return this;
392
- }
393
- spinning(msg: string, { prefix = `${this.emoji}${this.name}`, indent = 0, enableSpin = !Executor.verbose } = {}) {
394
- return new Spinner(msg, { prefix, indent, enableSpin }).start();
395
- }
396
-
397
- #tsconfig: TsConfigJson | null = null;
398
- async getTsConfig(pathname = "tsconfig.json", { refresh }: { refresh?: boolean } = {}): Promise<TsConfigJson> {
399
- if (this.#tsconfig && !refresh) return this.#tsconfig;
400
- const tsconfig = (await this.readJson(pathname)) as TsConfigJson;
401
- if (tsconfig.extends) {
402
- const extendsTsconfig = await this.getTsConfig(tsconfig.extends);
403
- const result = {
404
- ...extendsTsconfig,
405
- ...tsconfig,
406
- compilerOptions: { ...extendsTsconfig.compilerOptions, ...tsconfig.compilerOptions },
407
- } as TsConfigJson;
408
- this.#tsconfig = result;
409
- return result;
410
- }
411
- this.#tsconfig = tsconfig;
412
- return tsconfig;
413
- }
414
- async setTsConfig(tsconfig: TsConfigJson) {
415
- await this.writeJson("tsconfig.json", tsconfig);
416
- this.#tsconfig = tsconfig;
417
- }
418
-
419
- #packageJson: PackageJson | null = null;
420
- async getPackageJson({ refresh }: { refresh?: boolean } = {}): Promise<PackageJson> {
421
- if (this.#packageJson && !refresh) return this.#packageJson;
422
- const packageJson = (await this.readJson("package.json")) as PackageJson;
423
- this.#packageJson = packageJson;
424
- return packageJson;
425
- }
426
- async setPackageJson(packageJson: PackageJson) {
427
- await this.writeJson("package.json", packageJson);
428
- this.#packageJson = packageJson;
429
- }
430
-
431
- #gitignorePatterns: string[] = [];
432
- async getGitignorePatterns(): Promise<string[]> {
433
- if (this.#gitignorePatterns.length) return this.#gitignorePatterns;
434
- const gitignore = await this.readFile(".gitignore");
435
- this.#gitignorePatterns = gitignore
436
- .split("\n")
437
- .map((line) => line.trim())
438
- .filter((line) => !!line && !line.startsWith("#"));
439
- return this.#gitignorePatterns;
440
- }
441
-
442
- async #applyTemplateFile(
443
- {
444
- templatePath,
445
- targetPath,
446
- scanInfo,
447
- overwrite = true,
448
- }: {
449
- templatePath: string;
450
- targetPath: string;
451
- scanInfo?: AppInfo | LibInfo | null;
452
- overwrite?: boolean;
453
- },
454
- dict: { [key: string]: string } = {},
455
- options: { [key: string]: any } = {},
456
- ): Promise<FileContent | null> {
457
- if (targetPath.endsWith(".ts") || targetPath.endsWith(".tsx")) {
458
- const getContent = (await import(templatePath)) as {
459
- default: (
460
- scanInfo: AppInfo | LibInfo | null,
461
- dict: { [key: string]: string },
462
- options?: { [key: string]: any },
463
- ) => Promise<string | null | { filename: string; content: string }>;
464
- };
465
- const result = await getContent.default(scanInfo ?? null, dict, options);
466
- if (result === null) return null;
467
- const filename = typeof result === "object" ? result.filename : path.basename(targetPath).replace(".js", ".ts");
468
- const content = typeof result === "object" ? result.content : result;
469
- const dirname = path.dirname(targetPath);
470
- const convertedTargetPath = Object.entries(dict).reduce(
471
- (path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value),
472
- `${dirname}/${filename}`,
473
- );
474
- this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
475
- return this.writeFile(convertedTargetPath, content, { overwrite });
476
- } else if (targetPath.endsWith(".template")) {
477
- const content = await FileSys.readText(templatePath);
478
- const convertedTargetPath = Object.entries(dict).reduce(
479
- (path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value),
480
- targetPath.slice(0, -9),
481
- );
482
- const convertedContent = Object.entries(dict).reduce(
483
- (data, [key, value]) => data.replace(new RegExp(`<%= ${key} %>`, "g"), value),
484
- content,
485
- );
486
- this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
487
- return this.writeFile(convertedTargetPath, convertedContent, { overwrite });
488
- } else if (staticTemplateFileExtensions.has(path.extname(targetPath).toLowerCase())) {
489
- const convertedTargetPath = Object.entries(dict).reduce(
490
- (path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value),
491
- targetPath,
492
- );
493
- const writePath = this.getPath(convertedTargetPath);
494
- const dirname = path.dirname(writePath);
495
- if (!(await FileSys.dirExists(dirname))) await mkdir(dirname, { recursive: true });
496
- await copyFile(templatePath, writePath);
497
- this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
498
- return { filePath: writePath, content: "" };
499
- } else return null;
500
- }
501
- async _applyTemplate({
502
- basePath,
503
- template,
504
- scanInfo,
505
- dict = {},
506
- options = {},
507
- overwrite = true,
508
- }: {
509
- basePath: string;
510
- template: string;
511
- scanInfo?: AppInfo | LibInfo | null;
512
- dict?: { [key: string]: string };
513
- options?: { [key: string]: any };
514
- overwrite?: boolean;
515
- }): Promise<FileContent[]> {
516
- const templateRoot = await this.#resolveTemplateRoot();
517
- const templatePath = `${templateRoot}${template ? `/${template}` : ""}`;
518
- const prefixTemplatePath = templatePath;
519
- if ((await stat(prefixTemplatePath)).isFile()) {
520
- const filename = path.basename(prefixTemplatePath);
521
- const fileContent = await this.#applyTemplateFile(
522
- { templatePath: prefixTemplatePath, targetPath: path.join(basePath, filename), scanInfo, overwrite },
523
- dict,
524
- options,
525
- );
526
- return fileContent ? [fileContent] : ([] as FileContent[]);
527
- } else {
528
- const subdirs = await readDirEntries(templatePath);
529
- const fileContents = (
530
- await Promise.all(
531
- subdirs.map(async (subdir) => {
532
- const subpath = path.join(templatePath, subdir);
533
- if ((await stat(subpath)).isFile()) {
534
- const fileContent = await this.#applyTemplateFile(
535
- { templatePath: subpath, targetPath: path.join(basePath, subdir), scanInfo, overwrite },
536
- dict,
537
- options,
538
- );
539
- return fileContent ? [fileContent] : ([] as FileContent[]);
540
- } else
541
- return await this._applyTemplate({
542
- basePath: path.join(basePath, subdir),
543
- template: path.join(template, subdir),
544
- scanInfo,
545
- dict,
546
- overwrite,
547
- options,
548
- });
549
- }),
550
- )
551
- ).flat();
552
- return fileContents;
553
- }
554
- }
555
- async #resolveTemplateRoot() {
556
- const candidates = [
557
- path.resolve(getDirname(import.meta.url), "templates"),
558
- path.resolve(getDirname(import.meta.url), "../cli/templates"),
559
- ];
560
- for (const candidate of candidates) {
561
- if (await FileSys.dirExists(candidate)) return candidate;
562
- }
563
- return candidates[0];
564
- }
565
- async applyTemplate(options: {
566
- basePath: string;
567
- template: string;
568
- dict?: { [key: string]: string };
569
- options?: { [key: string]: any };
570
- overwrite?: boolean;
571
- }): Promise<FileContent[]> {
572
- const dict = {
573
- ...(options.dict ?? {}),
574
- ...Object.fromEntries(
575
- Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]),
576
- ),
577
- };
578
- return this._applyTemplate({ ...options, dict });
579
- }
580
- getTypeChecker() {
581
- this.typeChecker ??= new TypeChecker(this);
582
- return this.typeChecker;
583
- }
584
- typeCheck(filePath: string) {
585
- const path = this.getPath(filePath);
586
- const typeChecker = this.getTypeChecker();
587
- const { fileDiagnostics, fileErrors, fileWarnings } = typeChecker.check(path);
588
- const message = typeChecker.formatDiagnostics(fileDiagnostics);
589
- return { fileDiagnostics, fileErrors, fileWarnings, message };
590
- }
591
- getLinter() {
592
- this.linter ??= new Linter(this.cwdPath);
593
- return this.linter;
594
- }
595
- async lint(
596
- filePath: string,
597
- { fix = false, dryRun = false }: { fix?: boolean; dryRun?: boolean } = {},
598
- ): Promise<{
599
- results: any[];
600
- message: string;
601
- errors: any[];
602
- warnings: any[];
603
- }> {
604
- const path = this.getPath(filePath);
605
- const linter = this.getLinter();
606
- const { results, errors, warnings } = await linter.lint(path, { fix, dryRun });
607
- const message = linter.formatLintResults(results);
608
- return { results, message, errors, warnings };
609
- }
610
- }
611
-
612
- interface ExecutorOptions {
613
- workspaceRoot: string;
614
- repoName: string;
615
- }
616
- export class WorkspaceExecutor extends Executor {
617
- workspaceRoot: string;
618
- repoName: string;
619
- override emoji = execEmoji.workspace;
620
- constructor({ workspaceRoot, repoName }: ExecutorOptions) {
621
- super("workspace", workspaceRoot);
622
- this.workspaceRoot = workspaceRoot;
623
- this.repoName = repoName;
624
- }
625
-
626
- static #execs = new Map<string, WorkspaceExecutor>();
627
- static fromRoot({
628
- workspaceRoot = process.cwd(),
629
- repoName = path.basename(process.cwd()),
630
- }: {
631
- workspaceRoot?: string;
632
- repoName?: string;
633
- } = {}) {
634
- return WorkspaceExecutor.#execs.get(repoName) ?? new WorkspaceExecutor({ workspaceRoot, repoName });
635
- }
636
- static getBaseDevEnv(envPath?: string) {
637
-
638
- const sourceEnv = envPath ? { ...process.env, ...parseEnvFile(envPath) } : process.env;
639
-
640
- const appName = sourceEnv.AKAN_PUBLIC_APP_NAME;
641
- const workspaceRoot = sourceEnv.AKAN_WORKSPACE_ROOT;
642
-
643
- const repoName = sourceEnv.AKAN_PUBLIC_REPO_NAME;
644
- if (!repoName) throw new Error("AKAN_PUBLIC_REPO_NAME is not set");
645
-
646
- const serveDomain = sourceEnv.AKAN_PUBLIC_SERVE_DOMAIN;
647
- if (!serveDomain) throw new Error("AKAN_PUBLIC_SERVE_DOMAIN is not set");
648
-
649
- const portOffset = parseInt(sourceEnv.PORT_OFFSET ?? "0");
650
-
651
- const env = (sourceEnv.AKAN_PUBLIC_ENV ?? "debug") as
652
- | "testing"
653
- | "debug"
654
- | "develop"
655
- | "main"
656
- | "local"
657
- | undefined;
658
- if (!env) throw new Error("AKAN_PUBLIC_ENV is not set");
659
- return { ...(appName ? { appName } : {}), workspaceRoot, repoName, serveDomain, env, portOffset };
660
- }
661
- async scan(): Promise<WorkspaceInfo> {
662
- return await WorkspaceInfo.fromExecutor(this);
663
- }
664
- async getApps() {
665
- if (!(await FileSys.dirExists(`${this.workspaceRoot}/apps`))) return [];
666
- return await this.#getDirHasFile(`${this.workspaceRoot}/apps`, "akan.config.ts");
667
- }
668
- async getLibs() {
669
- if (!(await FileSys.dirExists(`${this.workspaceRoot}/libs`))) return [];
670
- return await this.#getDirHasFile(`${this.workspaceRoot}/libs`, "akan.config.ts");
671
- }
672
- async getSyss() {
673
- const [appNames, libNames] = await Promise.all([this.getApps(), this.getLibs()]);
674
- return [appNames, libNames] as [string[], string[]];
675
- }
676
- async getPkgs() {
677
- if (!(await FileSys.dirExists(`${this.workspaceRoot}/pkgs`))) return [];
678
- return await this.#getDirHasFile(`${this.workspaceRoot}/pkgs`, "package.json");
679
- }
680
- async getExecs() {
681
- const [appNames, libNames, pkgNames] = await Promise.all([this.getApps(), this.getLibs(), this.getPkgs()]);
682
- return [appNames, libNames, pkgNames] as [string[], string[], string[]];
683
- }
684
- async setPkgTsPaths(name: string) {
685
- const rootTsConfig = (await this.readJson("tsconfig.json")) as TsConfigJson;
686
- rootTsConfig.compilerOptions.paths ??= {};
687
- rootTsConfig.compilerOptions.paths[name] = [`./pkgs/${name}/index.ts`];
688
- rootTsConfig.compilerOptions.paths[`${name}/*`] = [`./pkgs/${name}/*`];
689
- if (rootTsConfig.references) {
690
- if (!rootTsConfig.references.some((ref) => ref.path === `./pkgs/${name}/tsconfig.json`))
691
- rootTsConfig.references.push({ path: `./pkgs/${name}/tsconfig.json` });
692
- }
693
- await this.writeJson("tsconfig.json", rootTsConfig);
694
- return this;
695
- }
696
- async unsetPkgTsPaths(name: string) {
697
- const rootTsConfig = (await this.readJson("tsconfig.json")) as TsConfigJson;
698
- const filteredKeys = Object.keys(rootTsConfig.compilerOptions.paths ?? {}).filter(
699
- (key) => key !== name && key !== `${name}/*`,
700
- );
701
- rootTsConfig.compilerOptions.paths = Object.fromEntries(
702
- filteredKeys.map((key) => [key, rootTsConfig.compilerOptions.paths?.[key] ?? []]),
703
- );
704
- if (rootTsConfig.references) {
705
- rootTsConfig.references = rootTsConfig.references.filter(
706
- (ref) => ref.path !== `./pkgs/${name}/tsconfig.json`,
707
- ) as TsConfigJson["references"];
708
- }
709
- await this.writeJson("tsconfig.json", rootTsConfig);
710
- return this;
711
- }
712
- async getDirInModule(basePath: string, name: string) {
713
- const AVOID_DIRS = ["__lib", "__scalar", `_`, `_${name}`];
714
- const getDirs = async (dirname: string, maxDepth = 3, results: string[] = [], prefix = "") => {
715
- const dirs = await this.readdir(dirname);
716
- await Promise.all(
717
- dirs.map(async (dir) => {
718
- if (dir.includes("_") || AVOID_DIRS.includes(dir)) return;
719
- const dirPath = path.join(dirname, dir);
720
- if ((await stat(dirPath)).isDirectory()) {
721
- results.push(`${prefix}${dir}`);
722
- if (maxDepth > 0) await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
723
- }
724
- }),
725
- );
726
- return results;
727
- };
728
- return await getDirs(basePath);
729
- }
730
- async commit(message: string, { init = false, add = true }: { init?: boolean; add?: boolean } = {}) {
731
- if (init) await this.exec(`git init --quiet`);
732
- if (add) await this.exec(`git add .`);
733
- await this.exec(`git commit --quiet -m "${message}"`);
734
- }
735
- async #getDirHasFile(basePath: string, targetFilename: string) {
736
- const AVOID_DIRS = ["node_modules", "dist", "public", "webkit"];
737
- const getDirs = async (dirname: string, maxDepth = 3, results: string[] = [], prefix = "") => {
738
- const dirs = await this.readdir(dirname);
739
- await Promise.all(
740
- dirs.map(async (dir) => {
741
- if (AVOID_DIRS.includes(dir)) return;
742
- const dirPath = path.join(dirname, dir);
743
- if ((await stat(dirPath)).isDirectory()) {
744
- const hasTargetFile = await FileSys.fileExists(path.join(dirPath, targetFilename));
745
- if (hasTargetFile) results.push(`${prefix}${dir}`);
746
- if (maxDepth > 0) await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
747
- }
748
- }),
749
- );
750
- return results;
751
- };
752
- return await getDirs(basePath);
753
- }
754
-
755
- async getScalarConstantFiles() {
756
- const [appNames, libNames] = await this.getSyss();
757
- const scalarConstantExampleFiles = [
758
- ...(
759
- await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getScalarConstantFiles()))
760
- ).flat(),
761
- ...(
762
- await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getScalarConstantFiles()))
763
- ).flat(),
764
- ];
765
- return scalarConstantExampleFiles;
766
- }
767
- async getConstantFiles() {
768
- const [appNames, libNames] = await this.getSyss();
769
- const moduleConstantExampleFiles = [
770
- ...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getConstantFiles()))).flat(),
771
- ...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getConstantFiles()))).flat(),
772
- ];
773
- return moduleConstantExampleFiles;
774
- }
775
- async getDictionaryFiles() {
776
- const [appNames, libNames] = await this.getSyss();
777
- const moduleDictionaryExampleFiles = [
778
- ...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getDictionaryFiles()))).flat(),
779
- ...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getDictionaryFiles()))).flat(),
780
- ];
781
- return moduleDictionaryExampleFiles;
782
- }
783
- async getViewFiles() {
784
- const [appNames, libNames] = await this.getSyss();
785
- const viewExampleFiles = [
786
- ...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getViewsSourceCode()))).flat(),
787
- ...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getViewsSourceCode()))).flat(),
788
- ];
789
- return viewExampleFiles;
790
- }
791
- }
792
-
793
- interface SysExecutorOptions {
794
- workspace?: WorkspaceExecutor;
795
- name: string;
796
- type: "app" | "lib";
797
- }
798
-
799
- const scanFacetDirs = ["ui", "webkit", "srvkit", "common"] as const;
800
-
801
- export class SysExecutor extends Executor {
802
- workspace: WorkspaceExecutor;
803
- override name: string;
804
- type: "app" | "lib";
805
- override emoji: string;
806
- constructor({ workspace = WorkspaceExecutor.fromRoot(), name, type }: SysExecutorOptions) {
807
- super(name, `${workspace.workspaceRoot}/${type}s/${name}`);
808
- this.workspace = workspace;
809
- this.name = name;
810
- this.type = type;
811
- this.emoji = execEmoji[type];
812
- }
813
- #akanConfig: AkanAppConfig | AkanLibConfig | null = null;
814
- async getConfig({ refresh }: { refresh?: boolean } = {}) {
815
- if (this.#akanConfig && !refresh) return this.#akanConfig;
816
- this.#akanConfig =
817
- this.type === "app"
818
- ? await AkanAppConfig.from(this as unknown as AppExecutor)
819
- : await AkanLibConfig.from(this as unknown as LibExecutor);
820
- return this.#akanConfig;
821
- }
822
- async getModules() {
823
- const path = this.type === "app" ? `apps/${this.name}/lib` : `libs/${this.name}/lib`;
824
- return await this.workspace.getDirInModule(path, this.name);
825
- }
826
-
827
- #scanInfo: AppInfo | LibInfo | null = null;
828
- hasScanInfo() {
829
- return this.#scanInfo !== null;
830
- }
831
- getScanInfo<AllowEmpty extends boolean = false>({
832
- allowEmpty,
833
- }: {
834
- allowEmpty?: AllowEmpty;
835
- } = {}): AllowEmpty extends true ? AppInfo | LibInfo | null : AppInfo | LibInfo {
836
- if (!this.hasScanInfo() && !allowEmpty) throw new Error("Scan info is not available");
837
- return this.#scanInfo as AllowEmpty extends true ? AppInfo | LibInfo | null : AppInfo | LibInfo;
838
- }
839
- #getScanTemplateTasks(scanInfo: AppInfo | LibInfo): (Promise<FileContent[]> | null)[] {
840
- return [
841
- this._applyTemplate({ basePath: "env", template: "env", scanInfo }),
842
- this._applyTemplate({ basePath: "lib", template: "lib", scanInfo }),
843
- this._applyTemplate({ basePath: ".", template: "server.ts", scanInfo }),
844
- this._applyTemplate({ basePath: ".", template: "client.ts", scanInfo }),
845
- this.type === "lib" ? this._applyTemplate({ basePath: ".", template: "index.ts", scanInfo }) : null,
846
- ...scanFacetDirs.map((facet) =>
847
- this._applyTemplate({
848
- basePath: facet,
849
- template: "facetIndex/index.ts",
850
- scanInfo,
851
- options: { exec: this, facet },
852
- }),
853
- ),
854
- ...scanInfo.getDatabaseModules().map((model) =>
855
- this._applyTemplate({
856
- basePath: `lib/${model}`,
857
- template: "moduleRoot",
858
- scanInfo,
859
- dict: { model, Model: capitalize(model) },
860
- }),
861
- ),
862
- ...scanInfo.getServiceModules().map((model) =>
863
- this._applyTemplate({
864
- basePath: `lib/_${model}`,
865
- template: "moduleRoot",
866
- scanInfo,
867
- dict: { model, Model: capitalize(model) },
868
- }),
869
- ),
870
- ...scanInfo.getScalarModules().map((model) =>
871
- this._applyTemplate({
872
- basePath: `lib/__scalar/${model}`,
873
- template: "moduleRoot",
874
- scanInfo,
875
- dict: { model, Model: capitalize(model) },
876
- }),
877
- ),
878
- ];
879
- }
880
- async scan({
881
- refresh = false,
882
- write = true,
883
- writeLib = write,
884
- }: {
885
- refresh?: boolean;
886
- write?: boolean;
887
- writeLib?: boolean;
888
- } = {}): Promise<AppInfo | LibInfo> {
889
- if (this.#scanInfo && !refresh) return this.#scanInfo;
890
- const scanInfo =
891
- this.type === "app"
892
- ? await AppInfo.fromExecutor(this as unknown as AppExecutor, { refresh })
893
- : await LibInfo.fromExecutor(this as unknown as LibExecutor, { refresh });
894
- if (write) {
895
- await Promise.all(this.#getScanTemplateTasks(scanInfo));
896
- await this.writeJson(`akan.${this.type}.json`, scanInfo.getScanResult());
897
- if (this.type === "lib") this.#updateDependencies(scanInfo);
898
-
899
- if (writeLib) {
900
- const libInfos = [...scanInfo.getLibInfos().values()];
901
- await this.#updateDependencies(scanInfo);
902
- await Promise.all(libInfos.flatMap((libInfo) => libInfo.exec.#getScanTemplateTasks(libInfo)));
903
- }
904
- }
905
- this.#scanInfo = scanInfo;
906
- return scanInfo;
907
- }
908
- async #updateDependencies(scanInfo: AppInfo | LibInfo) {
909
- const rootPackageJson = await this.workspace.getPackageJson();
910
- const libPackageJson = await this.getPackageJson();
911
- const dependencies = scanInfo.getScanResult().dependencies;
912
- const devDependencies = scanInfo.getScanResult().devDependencies;
913
- const dependencySet = new Set(dependencies);
914
- const devDependencySet = new Set(devDependencies);
915
- const libPkgJsonWithDeps: PackageJson = {
916
- ...libPackageJson,
917
- dependencies: {
918
- ...Object.fromEntries(
919
- Object.entries(libPackageJson.dependencies ?? {}).filter(([dep]) => !devDependencySet.has(dep)),
920
- ),
921
- ...(Object.fromEntries(
922
- dependencies
923
- .filter((dep) => rootPackageJson.dependencies?.[dep])
924
- .sort()
925
- .map((dep) => [dep, rootPackageJson.dependencies?.[dep]]),
926
- ) as Record<string, string>),
927
- },
928
- devDependencies: {
929
- ...Object.fromEntries(
930
- Object.entries(libPackageJson.devDependencies ?? {}).filter(([dep]) => !dependencySet.has(dep)),
931
- ),
932
- ...(Object.fromEntries(
933
- devDependencies
934
- .filter((dep) => rootPackageJson.dependencies?.[dep] || rootPackageJson.devDependencies?.[dep])
935
- .sort()
936
- .map((dep) => [dep, rootPackageJson.devDependencies?.[dep] ?? rootPackageJson.dependencies?.[dep]]),
937
- ) as Record<string, string>),
938
- },
939
- };
940
- await this.setPackageJson(libPkgJsonWithDeps);
941
- }
942
- override async getLocalFile(targetPath: string) {
943
- const filePath = path.isAbsolute(targetPath) ? targetPath : `${this.type}s/${this.name}/${targetPath}`;
944
- const content = await this.workspace.readFile(filePath);
945
- return { filePath, content };
946
- }
947
-
948
- async getDatabaseModules() {
949
- const databaseModules = (await this.readdir("lib"))
950
- .filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts"))
951
- .filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.constant.ts`).exists());
952
- return databaseModules;
953
- }
954
-
955
- async getServiceModules() {
956
- const serviceModules = (await this.readdir("lib"))
957
- .filter((name) => name.startsWith("_") && !name.startsWith("__"))
958
- .filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.service.ts`).exists());
959
- return serviceModules;
960
- }
961
-
962
- async getScalarModules() {
963
- const scalarModules = (await this.readdir("lib/__scalar"))
964
- .filter((name) => !name.startsWith("_"))
965
- .filter((name) => Bun.file(`${this.cwdPath}/lib/__scalar/${name}/${name}.constant.ts`).exists());
966
- return scalarModules;
967
- }
968
-
969
- async getViewComponents() {
970
- const viewComponents = (await this.readdir("lib"))
971
- .filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts"))
972
- .filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.View.tsx`).exists());
973
- return viewComponents;
974
- }
975
-
976
- async getUnitComponents() {
977
- const unitComponents = (await this.readdir("lib"))
978
- .filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts"))
979
- .filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`).exists());
980
- return unitComponents;
981
- }
982
- async getTemplateComponents() {
983
- const templateComponents = (await this.readdir("lib"))
984
- .filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts"))
985
- .filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`).exists());
986
- return templateComponents;
987
- }
988
-
989
- async getViewsSourceCode() {
990
- const viewComponents = await this.getViewComponents();
991
- return Promise.all(
992
- viewComponents.map((viewComponent) => this.getLocalFile(`lib/${viewComponent}/${viewComponent}.View.tsx`)),
993
- );
994
- }
995
- async getUnitsSourceCode() {
996
- const unitComponents = await this.getUnitComponents();
997
- return Promise.all(
998
- unitComponents.map((unitComponent) => this.getLocalFile(`lib/${unitComponent}/${unitComponent}.Unit.tsx`)),
999
- );
1000
- }
1001
- async getTemplatesSourceCode() {
1002
- const templateComponents = await this.getTemplateComponents();
1003
- return Promise.all(
1004
- templateComponents.map((templateComponent) =>
1005
- this.getLocalFile(`lib/${templateComponent}/${templateComponent}.Template.tsx`),
1006
- ),
1007
- );
1008
- }
1009
-
1010
- async getScalarConstantFiles() {
1011
- const scalarModules = await this.getScalarModules();
1012
- return Promise.all(
1013
- scalarModules.map((scalarModule) =>
1014
- this.getLocalFile(`lib/__scalar/${scalarModule}/${scalarModule}.constant.ts`),
1015
- ),
1016
- );
1017
- }
1018
-
1019
- async getScalarDictionaryFiles() {
1020
- const scalarModules = await this.getScalarModules();
1021
- return Promise.all(
1022
- scalarModules.map((scalarModule) => this.getLocalFile(`lib/${scalarModule}/${scalarModule}.dictionary.ts`)),
1023
- );
1024
- }
1025
-
1026
- async getConstantFiles() {
1027
- const modules = await this.getModules();
1028
- return Promise.all(modules.map((module) => this.getLocalFile(`lib/${module}/${module}.constant.ts`)));
1029
- }
1030
- async getConstantFilesWithLibs() {
1031
- const scanInfo =
1032
- this.type === "app"
1033
- ? await AppInfo.fromExecutor(this as unknown as AppExecutor)
1034
- : await LibInfo.fromExecutor(this as unknown as LibExecutor);
1035
- const sysContantFiles = await this.getConstantFiles();
1036
- const sysScalarConstantFiles = await this.getScalarConstantFiles();
1037
- const libDeps = scanInfo.getLibs();
1038
- const libConstantFiles = await Promise.all(
1039
- libDeps.map(async (lib) => [
1040
- ...(await LibExecutor.from(this, lib).getConstantFiles()),
1041
- ...(await LibExecutor.from(this, lib).getScalarConstantFiles()),
1042
- ]),
1043
- );
1044
- return [...sysContantFiles, ...sysScalarConstantFiles, ...libConstantFiles.flat()];
1045
- }
1046
- async getDictionaryFiles() {
1047
- const modules = await this.getModules();
1048
- return Promise.all(modules.map((module) => this.getLocalFile(`lib/${module}/${module}.dictionary.ts`)));
1049
- }
1050
- override async applyTemplate(options: {
1051
- basePath: string;
1052
- template: string;
1053
- dict?: { [key: string]: string };
1054
- overwrite?: boolean;
1055
- }): Promise<FileContent[]> {
1056
- const dict = {
1057
- ...(options.dict ?? {}),
1058
- ...Object.fromEntries(
1059
- Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]),
1060
- ),
1061
- };
1062
- const scanInfo = await this.scan();
1063
- const fileContents = await this._applyTemplate({ ...options, scanInfo, dict });
1064
- await this.scan();
1065
- return fileContents;
1066
- }
1067
- }
1068
-
1069
- interface AppExecutorOptions {
1070
- workspace?: WorkspaceExecutor;
1071
- name: string;
1072
- }
1073
- export class AppExecutor extends SysExecutor {
1074
- dist: Executor;
1075
- override emoji = execEmoji.app;
1076
- constructor({ workspace, name }: AppExecutorOptions) {
1077
- super({ workspace, name, type: "app" });
1078
- this.dist = new Executor(`dist/${name}`, `${this.workspace.workspaceRoot}/dist/apps/${name}`);
1079
- }
1080
- static #execs = new Map<string, AppExecutor>();
1081
- static from(executor: SysExecutor | WorkspaceExecutor, name: string) {
1082
- const exec = AppExecutor.#execs.get(name);
1083
- if (exec) return exec;
1084
- else if (executor instanceof WorkspaceExecutor) return new AppExecutor({ workspace: executor, name });
1085
- else return new AppExecutor({ workspace: executor.workspace, name });
1086
- }
1087
- getEnv() {
1088
- return WorkspaceExecutor.getBaseDevEnv().env;
1089
- }
1090
- getCommandEnv(env: Record<string, string> = {}): Record<string, string> {
1091
- const basePort = 8282;
1092
- const portOffset = WorkspaceExecutor.getBaseDevEnv().portOffset;
1093
- const PORT = basePort ? (basePort + portOffset).toString() : undefined;
1094
- const AKAN_PUBLIC_SERVER_PORT = portOffset ? (8282 + portOffset).toString() : undefined;
1095
- return {
1096
- ...process.env,
1097
- AKAN_PUBLIC_APP_NAME: this.name,
1098
- AKAN_WORKSPACE_ROOT: this.workspace.workspaceRoot,
1099
- NODE_NO_WARNINGS: "1",
1100
- ...(PORT ? { PORT, AKAN_PUBLIC_CLIENT_PORT: PORT } : {}),
1101
- ...(AKAN_PUBLIC_SERVER_PORT ? { AKAN_PUBLIC_SERVER_PORT } : {}),
1102
- ...env,
1103
- };
1104
- }
1105
- async prepareCommand(type: "build" | "start") {
1106
- const akanConfig = await this.getConfig();
1107
- const databaseMode = process.env.AKAN_DATABASE_MODE ?? akanConfig.defaultDatabaseMode ?? "single";
1108
- const routeEnv = {
1109
- AKAN_PUBLIC_BASE_PATHS: [...akanConfig.basePaths].join(","),
1110
- AKAN_DATABASE_MODE: databaseMode,
1111
- };
1112
- Object.assign(process.env, routeEnv);
1113
- if (type === "build") {
1114
- if (await this.exists(this.dist.cwdPath)) await this.dist.exec(`rm -rf ${this.dist.cwdPath}`);
1115
- await Promise.all([this.dist.mkdir("private"), this.dist.mkdir("public")]);
1116
- await Promise.all([
1117
- this.cp("private", `${this.dist.cwdPath}/private`),
1118
- this.cp("public", `${this.dist.cwdPath}/public`),
1119
- ]);
1120
- } else await this.removeDir(".akan");
1121
- const env = this.getCommandEnv({ AKAN_COMMAND_TYPE: type, ...routeEnv });
1122
- return { env };
1123
- }
1124
- #publicEnv: Record<string, string> | null = null;
1125
- getPublicEnv(...patterns: string[]) {
1126
- if (this.#publicEnv) return this.#publicEnv;
1127
- const searchPatterns = [...patterns, "AKAN_PUBLIC_*"];
1128
- const regexes = searchPatterns.map((pattern) => {
1129
- let body = "";
1130
- for (const ch of pattern) {
1131
- if (ch === "*") body += ".*";
1132
- else body += ch.replace(/[.+^${}()|[\]\\?]/g, "\\$&");
1133
- }
1134
- return new RegExp(`^${body}$`);
1135
- });
1136
- const publicEnv: Record<string, string> = {};
1137
- for (const [k, v] of Object.entries(process.env)) {
1138
- if (typeof v !== "string") continue;
1139
- if (regexes.some((r) => r.test(k))) publicEnv[k] = v;
1140
- }
1141
- this.#publicEnv = publicEnv;
1142
- return publicEnv;
1143
- }
1144
-
1145
- #akanConfig: AkanAppConfig | null = null;
1146
- override async getConfig({ refresh }: { refresh?: boolean } = {}) {
1147
- if (this.#akanConfig && !refresh) return this.#akanConfig;
1148
- this.#akanConfig = await AkanAppConfig.from(this);
1149
- return this.#akanConfig;
1150
- }
1151
-
1152
- #pageKeys: string[] | null = null;
1153
- async getPageKeys({ refresh }: { refresh?: boolean } = {}): Promise<string[]> {
1154
- if (this.#pageKeys && !refresh) return this.#pageKeys;
1155
- const akanConfig = await this.getConfig();
1156
- const glob = new Bun.Glob("**/*");
1157
- const pageKeys: string[] = [];
1158
- const pageDir = `${this.cwdPath}/page`;
1159
- if (!(await FileSys.dirExists(pageDir))) {
1160
- this.#pageKeys = [];
1161
- return this.#pageKeys;
1162
- }
1163
- for await (const rel of glob.scan({ cwd: pageDir, absolute: false, onlyFiles: true })) {
1164
- const segments = rel.split(path.sep);
1165
- if (segments.some((s) => s === "node_modules")) continue;
1166
- const posix = segments.join("/");
1167
- const absPath = path.join(pageDir, posix);
1168
- validatePageSourceFile(posix, { filePath: absPath });
1169
- if (!isRouteSourceFile(posix)) continue;
1170
- const key = `./${posix}`;
1171
- validateSubRoutePageKey(key, akanConfig.basePaths, { appName: this.name, filePath: absPath });
1172
- const parsed = parseRouteModuleKey(key);
1173
- if (parsed.isInternalRootLayout) {
1174
- throw new Error(`[route-convention] __root_layout is reserved for Akan.js generated root layout: ${absPath}`);
1175
- }
1176
- const isRootLayout = parsed.kind === "layout" && parsed.moduleSegments.at(-1) === "_layout";
1177
- validateRouteSourceExports(await Bun.file(absPath).text(), absPath, parsed.kind, { rootLayout: isRootLayout });
1178
- pageKeys.push(key);
1179
- }
1180
- pageKeys.sort();
1181
- this.#pageKeys = pageKeys;
1182
- return this.#pageKeys;
1183
- }
1184
- setPageKeys(pageKeys: string[]) {
1185
- this.#pageKeys = pageKeys;
1186
- }
1187
-
1188
- async syncAssets(libDeps: string[]) {
1189
- const projectPublicPath = `${this.cwdPath}/public`;
1190
- const projectAssetsPath = `${this.cwdPath}/private`;
1191
- const projectPublicLibPath = `${projectPublicPath}/libs`;
1192
- const projectAssetsLibPath = `${projectAssetsPath}/libs`;
1193
- await Promise.all([this.removeDir(projectPublicLibPath), this.removeDir(projectAssetsLibPath)]);
1194
- const targetPublicDeps = [] as string[];
1195
- for (const dep of libDeps) {
1196
- if (await this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/public`)) targetPublicDeps.push(dep);
1197
- }
1198
- const targetAssetsDeps = [] as string[];
1199
- for (const dep of libDeps) {
1200
- if (await this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/private`)) targetAssetsDeps.push(dep);
1201
- }
1202
- await Promise.all(targetPublicDeps.map((dep) => this.mkdir(`${projectPublicLibPath}/${dep}`)));
1203
- await Promise.all(targetAssetsDeps.map((dep) => this.mkdir(`${projectAssetsLibPath}/${dep}`)));
1204
- await Promise.all([
1205
- ...targetPublicDeps.map((dep) =>
1206
- this.cp(`${this.workspace.workspaceRoot}/libs/${dep}/public`, `${projectPublicLibPath}/${dep}`),
1207
- ),
1208
- ...targetAssetsDeps.map((dep) =>
1209
- this.cp(`${this.workspace.workspaceRoot}/libs/${dep}/private`, `${projectAssetsLibPath}/${dep}`),
1210
- ),
1211
- ]);
1212
- }
1213
- async scanSync({ refresh = false, write = true }: { refresh?: boolean; write?: boolean } = {}) {
1214
- const scanInfo = (await this.scan({ refresh, write, writeLib: write })) as AppInfo;
1215
- if (write) await this.syncAssets(scanInfo.getScanResult().libDeps);
1216
- return scanInfo;
1217
- }
1218
- async increaseBuildNum() {
1219
- await increaseBuildNum(this);
1220
- }
1221
- async decreaseBuildNum() {
1222
- await decreaseBuildNum(this);
1223
- }
1224
- }
1225
- interface LibExecutorOptions {
1226
- workspace?: WorkspaceExecutor;
1227
- name: string;
1228
- }
1229
- export class LibExecutor extends SysExecutor {
1230
- dist: Executor;
1231
- override emoji = execEmoji.lib;
1232
- constructor({ workspace, name }: LibExecutorOptions) {
1233
- super({ workspace, name, type: "lib" });
1234
- this.dist = new Executor(`dist/${name}`, `${this.workspace.workspaceRoot}/dist/libs/${name}`);
1235
- }
1236
- static #execs = new Map<string, LibExecutor>();
1237
- static from(executor: SysExecutor | WorkspaceExecutor, name: string) {
1238
- const exec = LibExecutor.#execs.get(name);
1239
- if (exec) return exec;
1240
- else if (executor instanceof WorkspaceExecutor) return new LibExecutor({ workspace: executor, name });
1241
- else return new LibExecutor({ workspace: executor.workspace, name });
1242
- }
1243
-
1244
- #akanConfig: AkanLibConfig | null = null;
1245
- override async getConfig({ refresh }: { refresh?: boolean } = {}) {
1246
- if (this.#akanConfig && !refresh) return this.#akanConfig;
1247
- this.#akanConfig = await AkanLibConfig.from(this);
1248
- return this.#akanConfig;
1249
- }
1250
- }
1251
-
1252
- interface PkgExecutorOptions {
1253
- workspace?: WorkspaceExecutor;
1254
- name: string;
1255
- }
1256
- export class PkgExecutor extends Executor {
1257
- workspace: WorkspaceExecutor;
1258
- override name: string;
1259
- dist: Executor;
1260
- override emoji = execEmoji.pkg;
1261
- constructor({ workspace = WorkspaceExecutor.fromRoot(), name }: PkgExecutorOptions) {
1262
- super(name, `${workspace.workspaceRoot}/pkgs/${name}`);
1263
- this.workspace = workspace;
1264
- this.name = name;
1265
- this.dist = new Executor(`dist/${name}`, `${this.workspace.workspaceRoot}/dist/pkgs/${name}`);
1266
- }
1267
- static from(executor: SysExecutor | WorkspaceExecutor, name: string) {
1268
- if (executor instanceof WorkspaceExecutor) return new PkgExecutor({ workspace: executor, name });
1269
- return new PkgExecutor({ workspace: executor.workspace, name });
1270
- }
1271
-
1272
- #scanInfo: PkgInfo | null = null;
1273
- async scan({ refresh }: { refresh?: boolean } = {}): Promise<PkgInfo> {
1274
- if (this.#scanInfo && !refresh) return this.#scanInfo;
1275
- const scanInfo = await PkgInfo.fromExecutor(this, { refresh });
1276
-
1277
- this.#scanInfo = scanInfo;
1278
- return scanInfo;
1279
- }
1280
- #toDependencyMap(
1281
- rootPackageJson: PackageJson,
1282
- dependencies: string[] = [],
1283
- devDependencies: string[] = [],
1284
- ): Pick<PackageJson, "dependencies" | "devDependencies"> {
1285
- const rootDeps = { ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies };
1286
- const dependencyNames = [...new Set(dependencies)].sort();
1287
- const devDependencyNames = [...new Set(devDependencies)].filter((dep) => !dependencyNames.includes(dep)).sort();
1288
- const missingDeps = [...dependencyNames, ...devDependencyNames].filter((dep) => !rootDeps[dep]).sort();
1289
- if (missingDeps.length > 0)
1290
- throw new Error(`Missing dependency versions in root package.json: ${missingDeps.join(", ")}`);
1291
-
1292
- return {
1293
- dependencies: Object.fromEntries(dependencyNames.map((dep) => [dep, rootDeps[dep]])),
1294
- devDependencies: Object.fromEntries(devDependencyNames.map((dep) => [dep, rootDeps[dep]])),
1295
- };
1296
- }
1297
- async updatePackageJsonDependencies(
1298
- dependencies: string[] = [],
1299
- devDependencies: string[] = [],
1300
- ): Promise<PackageJson> {
1301
- const [rootPackageJson, pkgJson] = await Promise.all([this.workspace.getPackageJson(), this.getPackageJson()]);
1302
- const dependencyMaps = this.#toDependencyMap(rootPackageJson, dependencies, devDependencies);
1303
- const newPkgJson = {
1304
- ...pkgJson,
1305
- ...dependencyMaps,
1306
- };
1307
- await this.writeJson("package.json", newPkgJson);
1308
- return newPkgJson;
1309
- }
1310
- async generateDistPackageJson(dependencies: string[] = [], devDependencies: string[] = []): Promise<PackageJson> {
1311
- const [rootPackageJson, pkgJson] = await Promise.all([this.workspace.getPackageJson(), this.getPackageJson()]);
1312
- const dependencyMaps = this.#toDependencyMap(rootPackageJson, dependencies, devDependencies);
1313
- const distPkgJson: PackageJson = {
1314
- ...pkgJson,
1315
- type: "module",
1316
- exports: { ...pkgJson.exports, ".": { import: "./index.ts", types: "./index.ts", default: "./index.ts" } },
1317
- engines: { bun: ">=1.3.13" },
1318
- ...dependencyMaps,
1319
- };
1320
- await Promise.all([this.dist.writeJson("package.json", distPkgJson), this.writeJson("package.json", distPkgJson)]);
1321
- return distPkgJson;
1322
- }
1323
- async build(): Promise<void> {
1324
- await Bun.build({
1325
- root: this.cwdPath,
1326
- entrypoints: [`${this.cwdPath}/index.ts`],
1327
- splitting: false,
1328
- target: "bun",
1329
- });
1330
- await this.cp(`${this.cwdPath}/dist`, this.dist.cwdPath);
1331
- }
1332
- async generateTsconfigJson(): Promise<TsConfigJson> {
1333
- const [rootTsconfig, pkgTsconfig] = await Promise.all([this.workspace.getTsConfig(), this.getTsConfig()]);
1334
- const tsconfig: TsConfigJson = {
1335
- ...rootTsconfig,
1336
- ...pkgTsconfig,
1337
- compilerOptions: {
1338
- ...rootTsconfig.compilerOptions,
1339
- ...pkgTsconfig.compilerOptions,
1340
- paths: {},
1341
- },
1342
- };
1343
- await this.dist.writeJson("tsconfig.json", tsconfig);
1344
- return tsconfig;
1345
- }
1346
- }
1347
-
1348
- interface ModuleExecutorOptions {
1349
- sys: SysExecutor;
1350
- name: string;
1351
- }
1352
- export class ModuleExecutor extends Executor {
1353
- sys: SysExecutor;
1354
- override emoji = execEmoji.module;
1355
- constructor({ sys, name }: ModuleExecutorOptions) {
1356
- super(name, `${sys.workspace.workspaceRoot}/${sys.type}s/${sys.name}/lib/${name}`);
1357
- this.sys = sys;
1358
- }
1359
- static from(sysExecutor: SysExecutor, name: string) {
1360
- return new ModuleExecutor({ sys: sysExecutor, name });
1361
- }
1362
- }