@akanjs/cli 0.0.142 → 0.0.144

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 (349) hide show
  1. package/README.md +8 -0
  2. package/cjs/index.js +2437 -3204
  3. package/cjs/src/guidelines/___library/sharedUiStructureDescription.en.md +786 -0
  4. package/cjs/src/guidelines/___library/utilUiStructureDescription.en.md +395 -0
  5. package/cjs/src/guidelines/___lint/lintRuleDescription.en.md +64 -0
  6. package/cjs/src/guidelines/___module/moduleStructureDescription.en.md +80 -0
  7. package/cjs/src/guidelines/componentRule/componentRule.instruction.md +732 -0
  8. package/cjs/src/guidelines/databaseModule/databaseModule.instruction.md +691 -0
  9. package/cjs/src/guidelines/enumConstant/enumConstant.instruction.md +232 -0
  10. package/cjs/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +611 -0
  11. package/cjs/src/guidelines/framework/framework.instruction.md +1112 -0
  12. package/cjs/src/guidelines/modelConstant/modelConstant.instruction.md +958 -0
  13. package/cjs/src/guidelines/modelDictionary/modelDictionary.instruction.md +583 -0
  14. package/cjs/src/guidelines/modelDocument/modelDocument.instruction.md +683 -0
  15. package/cjs/src/guidelines/modelService/modelService.instruction.md +935 -0
  16. package/cjs/src/guidelines/modelSignal/modelSignal.instruction.md +588 -0
  17. package/cjs/src/guidelines/modelStore/modelStore.instruction.md +591 -0
  18. package/cjs/src/guidelines/modelTemplate/modelTemplate.instruction.md +577 -0
  19. package/cjs/src/guidelines/modelUnit/modelUnit.instruction.md +833 -0
  20. package/cjs/src/guidelines/modelUtil/modelUtil.instruction.md +752 -0
  21. package/cjs/src/guidelines/modelView/modelView.instruction.md +1005 -0
  22. package/cjs/src/guidelines/modelZone/modelZone.instruction.md +528 -0
  23. package/cjs/src/guidelines/scalarConstant/scalarConstant.instruction.md +489 -0
  24. package/cjs/src/guidelines/scalarDictionary/scalarDictionary.instruction.md +347 -0
  25. package/cjs/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +318 -0
  26. package/cjs/src/guidelines/utilUiUsage/utilUiUsage.instruction.md +339 -0
  27. package/cjs/src/templates/module/__model__.dictionary.js +4 -5
  28. package/esm/index.js +2524 -3286
  29. package/esm/src/guidelines/___library/sharedUiStructureDescription.en.md +786 -0
  30. package/esm/src/guidelines/___library/utilUiStructureDescription.en.md +395 -0
  31. package/esm/src/guidelines/___lint/lintRuleDescription.en.md +64 -0
  32. package/esm/src/guidelines/___module/moduleStructureDescription.en.md +80 -0
  33. package/esm/src/guidelines/componentRule/componentRule.instruction.md +732 -0
  34. package/esm/src/guidelines/databaseModule/databaseModule.instruction.md +691 -0
  35. package/esm/src/guidelines/enumConstant/enumConstant.instruction.md +232 -0
  36. package/esm/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +611 -0
  37. package/esm/src/guidelines/framework/framework.instruction.md +1112 -0
  38. package/esm/src/guidelines/modelConstant/modelConstant.instruction.md +958 -0
  39. package/esm/src/guidelines/modelDictionary/modelDictionary.instruction.md +583 -0
  40. package/esm/src/guidelines/modelDocument/modelDocument.instruction.md +683 -0
  41. package/esm/src/guidelines/modelService/modelService.instruction.md +935 -0
  42. package/esm/src/guidelines/modelSignal/modelSignal.instruction.md +588 -0
  43. package/esm/src/guidelines/modelStore/modelStore.instruction.md +591 -0
  44. package/esm/src/guidelines/modelTemplate/modelTemplate.instruction.md +577 -0
  45. package/esm/src/guidelines/modelUnit/modelUnit.instruction.md +833 -0
  46. package/esm/src/guidelines/modelUtil/modelUtil.instruction.md +752 -0
  47. package/esm/src/guidelines/modelView/modelView.instruction.md +1005 -0
  48. package/esm/src/guidelines/modelZone/modelZone.instruction.md +528 -0
  49. package/esm/src/guidelines/scalarConstant/scalarConstant.instruction.md +489 -0
  50. package/esm/src/guidelines/scalarDictionary/scalarDictionary.instruction.md +347 -0
  51. package/esm/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +318 -0
  52. package/esm/src/guidelines/utilUiUsage/utilUiUsage.instruction.md +339 -0
  53. package/esm/src/templates/module/__model__.dictionary.js +4 -5
  54. package/package.json +3 -1
  55. package/src/guideline/guideline.command.d.ts +7 -0
  56. package/src/guideline/guideline.prompt.d.ts +15 -0
  57. package/src/guideline/guideline.runner.d.ts +5 -0
  58. package/src/guideline/guideline.script.d.ts +6 -0
  59. package/src/guidelines/___library/sharedUiStructureDescription.en.md +786 -0
  60. package/src/guidelines/___library/utilUiStructureDescription.en.md +395 -0
  61. package/src/guidelines/___lint/lintRuleDescription.en.md +64 -0
  62. package/src/guidelines/___module/moduleStructureDescription.en.md +80 -0
  63. package/src/guidelines/componentRule/componentRule.instruction.md +732 -0
  64. package/src/guidelines/databaseModule/databaseModule.instruction.md +691 -0
  65. package/src/guidelines/enumConstant/enumConstant.instruction.md +232 -0
  66. package/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +611 -0
  67. package/src/guidelines/framework/framework.instruction.md +1112 -0
  68. package/src/guidelines/modelConstant/modelConstant.instruction.md +958 -0
  69. package/src/guidelines/modelDictionary/modelDictionary.instruction.md +583 -0
  70. package/src/guidelines/modelDocument/modelDocument.instruction.md +683 -0
  71. package/src/guidelines/modelService/modelService.instruction.md +935 -0
  72. package/src/guidelines/modelSignal/modelSignal.instruction.md +588 -0
  73. package/src/guidelines/modelStore/modelStore.instruction.md +591 -0
  74. package/src/guidelines/modelTemplate/modelTemplate.instruction.md +577 -0
  75. package/src/guidelines/modelUnit/modelUnit.instruction.md +833 -0
  76. package/src/guidelines/modelUtil/modelUtil.instruction.md +752 -0
  77. package/src/guidelines/modelView/modelView.instruction.md +1005 -0
  78. package/src/guidelines/modelZone/modelZone.instruction.md +528 -0
  79. package/src/guidelines/scalarConstant/scalarConstant.instruction.md +489 -0
  80. package/src/guidelines/scalarDictionary/scalarDictionary.instruction.md +347 -0
  81. package/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +318 -0
  82. package/src/guidelines/utilUiUsage/utilUiUsage.instruction.md +339 -0
  83. package/src/module/module.command.d.ts +6 -8
  84. package/src/module/module.prompt.d.ts +2 -15
  85. package/src/module/module.request.d.ts +22 -18
  86. package/src/module/module.runner.d.ts +4 -20
  87. package/src/module/module.script.d.ts +6 -7
  88. package/src/scalar/scalar.command.d.ts +7 -0
  89. package/src/scalar/scalar.prompt.d.ts +23 -0
  90. package/src/scalar/scalar.runner.d.ts +13 -0
  91. package/src/scalar/scalar.script.d.ts +6 -0
  92. package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/forgotpassword/page.js +0 -47
  93. package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/page.js +0 -128
  94. package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/privacy/page.js +0 -42
  95. package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/signin/page.js +0 -50
  96. package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/termsofservice/page.js +0 -41
  97. package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/unknown/page.js +0 -51
  98. package/cjs/src/templates/app/app/[lang]/(__appName__)/(user)/layout.js +0 -43
  99. package/cjs/src/templates/app/app/[lang]/(__appName__)/(user)/self/page.js +0 -60
  100. package/cjs/src/templates/app/app/[lang]/(__appName__)/layout.js +0 -54
  101. package/cjs/src/templates/app/app/[lang]/(__appName__)/styles.css.template +0 -19
  102. package/cjs/src/templates/app/app/[lang]/admin/layout.js +0 -54
  103. package/cjs/src/templates/app/app/[lang]/admin/page.js +0 -63
  104. package/cjs/src/templates/app/app/csr.js +0 -34
  105. package/cjs/src/templates/app/app/index.html.template +0 -13
  106. package/cjs/src/templates/app/app/layout.js +0 -38
  107. package/cjs/src/templates/app/capacitor.config.ts.template +0 -8
  108. package/cjs/src/templates/app/env/env.client.debug.ts.template +0 -7
  109. package/cjs/src/templates/app/env/env.client.develop.ts.template +0 -7
  110. package/cjs/src/templates/app/env/env.client.local.ts.template +0 -7
  111. package/cjs/src/templates/app/env/env.client.main.ts.template +0 -7
  112. package/cjs/src/templates/app/env/env.client.testing.ts.template +0 -7
  113. package/cjs/src/templates/app/env/env.server.debug.ts.template +0 -15
  114. package/cjs/src/templates/app/env/env.server.develop.ts.template +0 -15
  115. package/cjs/src/templates/app/env/env.server.local.ts.template +0 -15
  116. package/cjs/src/templates/app/env/env.server.main.ts.template +0 -15
  117. package/cjs/src/templates/app/env/env.server.testing.ts.template +0 -7
  118. package/cjs/src/templates/app/lib/setting/Setting.Template.js +0 -57
  119. package/cjs/src/templates/app/lib/setting/Setting.Unit.js +0 -38
  120. package/cjs/src/templates/app/lib/setting/Setting.Util.js +0 -34
  121. package/cjs/src/templates/app/lib/setting/Setting.View.js +0 -51
  122. package/cjs/src/templates/app/lib/setting/Setting.Zone.js +0 -80
  123. package/cjs/src/templates/app/lib/setting/index.js +0 -61
  124. package/cjs/src/templates/app/lib/summary/Summary.Template.js +0 -43
  125. package/cjs/src/templates/app/lib/summary/Summary.Unit.js +0 -38
  126. package/cjs/src/templates/app/lib/summary/Summary.Util.js +0 -33
  127. package/cjs/src/templates/app/lib/summary/Summary.View.js +0 -51
  128. package/cjs/src/templates/app/lib/summary/Summary.Zone.js +0 -62
  129. package/cjs/src/templates/app/lib/summary/index.js +0 -67
  130. package/cjs/src/templates/app/lib/user/User.Template.js +0 -65
  131. package/cjs/src/templates/app/lib/user/User.Unit.js +0 -38
  132. package/cjs/src/templates/app/lib/user/User.Util.js +0 -94
  133. package/cjs/src/templates/app/lib/user/User.View.js +0 -66
  134. package/cjs/src/templates/app/lib/user/User.Zone.js +0 -74
  135. package/cjs/src/templates/app/lib/user/index.js +0 -61
  136. package/cjs/src/templates/app/page.test.ts.template +0 -10
  137. package/cjs/src/templates/app/playwright.config.ts.template +0 -6
  138. package/cjs/src/templates/app/postcss.config.js.template +0 -10
  139. package/cjs/src/templates/app/public/manifest.json.template +0 -67
  140. package/cjs/src/templates/app/tsconfig.json.template +0 -22
  141. package/cjs/src/templates/app/tsconfig.spec.json.template +0 -7
  142. package/cjs/src/templates/app/ui/Footer.js +0 -67
  143. package/cjs/src/templates/app/ui/MainHeader.js +0 -131
  144. package/cjs/src/templates/crudPages/[__model__Id]/edit/page.js +0 -73
  145. package/cjs/src/templates/crudPages/[__model__Id]/page.js +0 -83
  146. package/cjs/src/templates/crudPages/new/page.js +0 -70
  147. package/cjs/src/templates/crudPages/page.js +0 -71
  148. package/cjs/src/templates/libRoot/.gitignore.template +0 -15
  149. package/cjs/src/templates/libRoot/env/env.server.example.ts.template +0 -7
  150. package/cjs/src/templates/libRoot/env/env.server.testing.ts.template +0 -7
  151. package/cjs/src/templates/libRoot/lib/setting/Setting.Template.js +0 -57
  152. package/cjs/src/templates/libRoot/lib/setting/Setting.Unit.js +0 -38
  153. package/cjs/src/templates/libRoot/lib/setting/Setting.Util.js +0 -34
  154. package/cjs/src/templates/libRoot/lib/setting/Setting.View.js +0 -51
  155. package/cjs/src/templates/libRoot/lib/setting/Setting.Zone.js +0 -80
  156. package/cjs/src/templates/libRoot/lib/setting/index.js +0 -61
  157. package/cjs/src/templates/libRoot/lib/summary/Summary.Template.js +0 -43
  158. package/cjs/src/templates/libRoot/lib/summary/Summary.Unit.js +0 -38
  159. package/cjs/src/templates/libRoot/lib/summary/Summary.Util.js +0 -33
  160. package/cjs/src/templates/libRoot/lib/summary/Summary.View.js +0 -51
  161. package/cjs/src/templates/libRoot/lib/summary/Summary.Zone.js +0 -62
  162. package/cjs/src/templates/libRoot/lib/summary/index.js +0 -67
  163. package/cjs/src/templates/libRoot/lib/user/User.Template.js +0 -65
  164. package/cjs/src/templates/libRoot/lib/user/User.Unit.js +0 -38
  165. package/cjs/src/templates/libRoot/lib/user/User.Util.js +0 -94
  166. package/cjs/src/templates/libRoot/lib/user/User.View.js +0 -66
  167. package/cjs/src/templates/libRoot/lib/user/User.Zone.js +0 -74
  168. package/cjs/src/templates/libRoot/lib/user/index.js +0 -61
  169. package/cjs/src/templates/libRoot/package.json.template +0 -4
  170. package/cjs/src/templates/libRoot/tsconfig.json.template +0 -13
  171. package/cjs/src/templates/libRoot/tsconfig.spec.json.template +0 -7
  172. package/cjs/src/templates/localDev/docker-compose.yaml.template +0 -36
  173. package/cjs/src/templates/module/__Model__.Template.js +0 -54
  174. package/cjs/src/templates/module/__Model__.Unit.js +0 -42
  175. package/cjs/src/templates/module/__Model__.Util.js +0 -70
  176. package/cjs/src/templates/module/__Model__.View.js +0 -48
  177. package/cjs/src/templates/module/__Model__.Zone.js +0 -83
  178. package/cjs/src/templates/module/index.js +0 -61
  179. package/cjs/src/templates/pkgRoot/tsconfig.json.template +0 -15
  180. package/cjs/src/templates/workspaceRoot/.env.template +0 -20
  181. package/cjs/src/templates/workspaceRoot/.gitignore.template +0 -118
  182. package/cjs/src/templates/workspaceRoot/.prettierignore.template +0 -10
  183. package/cjs/src/templates/workspaceRoot/.prettierrc.json.template +0 -6
  184. package/cjs/src/templates/workspaceRoot/.swcrc.template +0 -9
  185. package/cjs/src/templates/workspaceRoot/.vscode/settings.json.template +0 -13
  186. package/cjs/src/templates/workspaceRoot/README.md.template +0 -37
  187. package/cjs/src/templates/workspaceRoot/eslint.config.ts.template +0 -3
  188. package/cjs/src/templates/workspaceRoot/package.json.template +0 -43
  189. package/cjs/src/templates/workspaceRoot/tsconfig.json.template +0 -29
  190. package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/forgotpassword/page.js +0 -27
  191. package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/page.js +0 -108
  192. package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/privacy/page.js +0 -22
  193. package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/signin/page.js +0 -30
  194. package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/termsofservice/page.js +0 -21
  195. package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/unknown/page.js +0 -31
  196. package/esm/src/templates/app/app/[lang]/(__appName__)/(user)/layout.js +0 -23
  197. package/esm/src/templates/app/app/[lang]/(__appName__)/(user)/self/page.js +0 -40
  198. package/esm/src/templates/app/app/[lang]/(__appName__)/layout.js +0 -34
  199. package/esm/src/templates/app/app/[lang]/(__appName__)/styles.css.template +0 -19
  200. package/esm/src/templates/app/app/[lang]/admin/layout.js +0 -34
  201. package/esm/src/templates/app/app/[lang]/admin/page.js +0 -43
  202. package/esm/src/templates/app/app/csr.js +0 -14
  203. package/esm/src/templates/app/app/index.html.template +0 -13
  204. package/esm/src/templates/app/app/layout.js +0 -18
  205. package/esm/src/templates/app/capacitor.config.ts.template +0 -8
  206. package/esm/src/templates/app/env/env.client.debug.ts.template +0 -7
  207. package/esm/src/templates/app/env/env.client.develop.ts.template +0 -7
  208. package/esm/src/templates/app/env/env.client.local.ts.template +0 -7
  209. package/esm/src/templates/app/env/env.client.main.ts.template +0 -7
  210. package/esm/src/templates/app/env/env.client.testing.ts.template +0 -7
  211. package/esm/src/templates/app/env/env.server.debug.ts.template +0 -15
  212. package/esm/src/templates/app/env/env.server.develop.ts.template +0 -15
  213. package/esm/src/templates/app/env/env.server.local.ts.template +0 -15
  214. package/esm/src/templates/app/env/env.server.main.ts.template +0 -15
  215. package/esm/src/templates/app/env/env.server.testing.ts.template +0 -7
  216. package/esm/src/templates/app/lib/setting/Setting.Template.js +0 -37
  217. package/esm/src/templates/app/lib/setting/Setting.Unit.js +0 -18
  218. package/esm/src/templates/app/lib/setting/Setting.Util.js +0 -14
  219. package/esm/src/templates/app/lib/setting/Setting.View.js +0 -31
  220. package/esm/src/templates/app/lib/setting/Setting.Zone.js +0 -60
  221. package/esm/src/templates/app/lib/setting/index.js +0 -41
  222. package/esm/src/templates/app/lib/summary/Summary.Template.js +0 -23
  223. package/esm/src/templates/app/lib/summary/Summary.Unit.js +0 -18
  224. package/esm/src/templates/app/lib/summary/Summary.Util.js +0 -13
  225. package/esm/src/templates/app/lib/summary/Summary.View.js +0 -31
  226. package/esm/src/templates/app/lib/summary/Summary.Zone.js +0 -42
  227. package/esm/src/templates/app/lib/summary/index.js +0 -47
  228. package/esm/src/templates/app/lib/user/User.Template.js +0 -45
  229. package/esm/src/templates/app/lib/user/User.Unit.js +0 -18
  230. package/esm/src/templates/app/lib/user/User.Util.js +0 -74
  231. package/esm/src/templates/app/lib/user/User.View.js +0 -46
  232. package/esm/src/templates/app/lib/user/User.Zone.js +0 -54
  233. package/esm/src/templates/app/lib/user/index.js +0 -41
  234. package/esm/src/templates/app/page.test.ts.template +0 -10
  235. package/esm/src/templates/app/playwright.config.ts.template +0 -6
  236. package/esm/src/templates/app/postcss.config.js.template +0 -10
  237. package/esm/src/templates/app/public/manifest.json.template +0 -67
  238. package/esm/src/templates/app/tsconfig.json.template +0 -22
  239. package/esm/src/templates/app/tsconfig.spec.json.template +0 -7
  240. package/esm/src/templates/app/ui/Footer.js +0 -47
  241. package/esm/src/templates/app/ui/MainHeader.js +0 -111
  242. package/esm/src/templates/crudPages/[__model__Id]/edit/page.js +0 -53
  243. package/esm/src/templates/crudPages/[__model__Id]/page.js +0 -63
  244. package/esm/src/templates/crudPages/new/page.js +0 -50
  245. package/esm/src/templates/crudPages/page.js +0 -51
  246. package/esm/src/templates/libRoot/.gitignore.template +0 -15
  247. package/esm/src/templates/libRoot/env/env.server.example.ts.template +0 -7
  248. package/esm/src/templates/libRoot/env/env.server.testing.ts.template +0 -7
  249. package/esm/src/templates/libRoot/lib/setting/Setting.Template.js +0 -37
  250. package/esm/src/templates/libRoot/lib/setting/Setting.Unit.js +0 -18
  251. package/esm/src/templates/libRoot/lib/setting/Setting.Util.js +0 -14
  252. package/esm/src/templates/libRoot/lib/setting/Setting.View.js +0 -31
  253. package/esm/src/templates/libRoot/lib/setting/Setting.Zone.js +0 -60
  254. package/esm/src/templates/libRoot/lib/setting/index.js +0 -41
  255. package/esm/src/templates/libRoot/lib/summary/Summary.Template.js +0 -23
  256. package/esm/src/templates/libRoot/lib/summary/Summary.Unit.js +0 -18
  257. package/esm/src/templates/libRoot/lib/summary/Summary.Util.js +0 -13
  258. package/esm/src/templates/libRoot/lib/summary/Summary.View.js +0 -31
  259. package/esm/src/templates/libRoot/lib/summary/Summary.Zone.js +0 -42
  260. package/esm/src/templates/libRoot/lib/summary/index.js +0 -47
  261. package/esm/src/templates/libRoot/lib/user/User.Template.js +0 -45
  262. package/esm/src/templates/libRoot/lib/user/User.Unit.js +0 -18
  263. package/esm/src/templates/libRoot/lib/user/User.Util.js +0 -74
  264. package/esm/src/templates/libRoot/lib/user/User.View.js +0 -46
  265. package/esm/src/templates/libRoot/lib/user/User.Zone.js +0 -54
  266. package/esm/src/templates/libRoot/lib/user/index.js +0 -41
  267. package/esm/src/templates/libRoot/package.json.template +0 -4
  268. package/esm/src/templates/libRoot/tsconfig.json.template +0 -13
  269. package/esm/src/templates/libRoot/tsconfig.spec.json.template +0 -7
  270. package/esm/src/templates/localDev/docker-compose.yaml.template +0 -36
  271. package/esm/src/templates/module/__Model__.Template.js +0 -34
  272. package/esm/src/templates/module/__Model__.Unit.js +0 -22
  273. package/esm/src/templates/module/__Model__.Util.js +0 -50
  274. package/esm/src/templates/module/__Model__.View.js +0 -28
  275. package/esm/src/templates/module/__Model__.Zone.js +0 -63
  276. package/esm/src/templates/module/index.js +0 -41
  277. package/esm/src/templates/pkgRoot/tsconfig.json.template +0 -15
  278. package/esm/src/templates/workspaceRoot/.env.template +0 -20
  279. package/esm/src/templates/workspaceRoot/.gitignore.template +0 -118
  280. package/esm/src/templates/workspaceRoot/.prettierignore.template +0 -10
  281. package/esm/src/templates/workspaceRoot/.prettierrc.json.template +0 -6
  282. package/esm/src/templates/workspaceRoot/.swcrc.template +0 -9
  283. package/esm/src/templates/workspaceRoot/.vscode/settings.json.template +0 -13
  284. package/esm/src/templates/workspaceRoot/README.md.template +0 -37
  285. package/esm/src/templates/workspaceRoot/eslint.config.ts.template +0 -3
  286. package/esm/src/templates/workspaceRoot/package.json.template +0 -43
  287. package/esm/src/templates/workspaceRoot/tsconfig.json.template +0 -29
  288. package/src/application/application.prompt.d.ts +0 -2
  289. package/src/templates/app/app/[lang]/(__appName__)/(public)/forgotpassword/page.d.ts +0 -9
  290. package/src/templates/app/app/[lang]/(__appName__)/(public)/page.d.ts +0 -9
  291. package/src/templates/app/app/[lang]/(__appName__)/(public)/privacy/page.d.ts +0 -9
  292. package/src/templates/app/app/[lang]/(__appName__)/(public)/signin/page.d.ts +0 -9
  293. package/src/templates/app/app/[lang]/(__appName__)/(public)/termsofservice/page.d.ts +0 -10
  294. package/src/templates/app/app/[lang]/(__appName__)/(public)/unknown/page.d.ts +0 -9
  295. package/src/templates/app/app/[lang]/(__appName__)/(user)/layout.d.ts +0 -9
  296. package/src/templates/app/app/[lang]/(__appName__)/(user)/self/page.d.ts +0 -9
  297. package/src/templates/app/app/[lang]/(__appName__)/layout.d.ts +0 -9
  298. package/src/templates/app/app/[lang]/admin/layout.d.ts +0 -9
  299. package/src/templates/app/app/[lang]/admin/page.d.ts +0 -9
  300. package/src/templates/app/app/csr.d.ts +0 -9
  301. package/src/templates/app/app/layout.d.ts +0 -9
  302. package/src/templates/app/lib/setting/Setting.Template.d.ts +0 -9
  303. package/src/templates/app/lib/setting/Setting.Unit.d.ts +0 -9
  304. package/src/templates/app/lib/setting/Setting.Util.d.ts +0 -9
  305. package/src/templates/app/lib/setting/Setting.View.d.ts +0 -9
  306. package/src/templates/app/lib/setting/Setting.Zone.d.ts +0 -9
  307. package/src/templates/app/lib/setting/index.d.ts +0 -9
  308. package/src/templates/app/lib/summary/Summary.Template.d.ts +0 -9
  309. package/src/templates/app/lib/summary/Summary.Unit.d.ts +0 -9
  310. package/src/templates/app/lib/summary/Summary.Util.d.ts +0 -9
  311. package/src/templates/app/lib/summary/Summary.View.d.ts +0 -9
  312. package/src/templates/app/lib/summary/Summary.Zone.d.ts +0 -9
  313. package/src/templates/app/lib/summary/index.d.ts +0 -9
  314. package/src/templates/app/lib/user/User.Template.d.ts +0 -9
  315. package/src/templates/app/lib/user/User.Unit.d.ts +0 -9
  316. package/src/templates/app/lib/user/User.Util.d.ts +0 -9
  317. package/src/templates/app/lib/user/User.View.d.ts +0 -9
  318. package/src/templates/app/lib/user/User.Zone.d.ts +0 -9
  319. package/src/templates/app/lib/user/index.d.ts +0 -9
  320. package/src/templates/app/ui/Footer.d.ts +0 -9
  321. package/src/templates/app/ui/MainHeader.d.ts +0 -10
  322. package/src/templates/crudPages/[__model__Id]/edit/page.d.ts +0 -11
  323. package/src/templates/crudPages/[__model__Id]/page.d.ts +0 -11
  324. package/src/templates/crudPages/new/page.d.ts +0 -11
  325. package/src/templates/crudPages/page.d.ts +0 -11
  326. package/src/templates/libRoot/lib/setting/Setting.Template.d.ts +0 -9
  327. package/src/templates/libRoot/lib/setting/Setting.Unit.d.ts +0 -9
  328. package/src/templates/libRoot/lib/setting/Setting.Util.d.ts +0 -9
  329. package/src/templates/libRoot/lib/setting/Setting.View.d.ts +0 -9
  330. package/src/templates/libRoot/lib/setting/Setting.Zone.d.ts +0 -9
  331. package/src/templates/libRoot/lib/setting/index.d.ts +0 -9
  332. package/src/templates/libRoot/lib/summary/Summary.Template.d.ts +0 -9
  333. package/src/templates/libRoot/lib/summary/Summary.Unit.d.ts +0 -9
  334. package/src/templates/libRoot/lib/summary/Summary.Util.d.ts +0 -9
  335. package/src/templates/libRoot/lib/summary/Summary.View.d.ts +0 -9
  336. package/src/templates/libRoot/lib/summary/Summary.Zone.d.ts +0 -9
  337. package/src/templates/libRoot/lib/summary/index.d.ts +0 -9
  338. package/src/templates/libRoot/lib/user/User.Template.d.ts +0 -9
  339. package/src/templates/libRoot/lib/user/User.Unit.d.ts +0 -9
  340. package/src/templates/libRoot/lib/user/User.Util.d.ts +0 -9
  341. package/src/templates/libRoot/lib/user/User.View.d.ts +0 -9
  342. package/src/templates/libRoot/lib/user/User.Zone.d.ts +0 -9
  343. package/src/templates/libRoot/lib/user/index.d.ts +0 -9
  344. package/src/templates/module/__Model__.Template.d.ts +0 -11
  345. package/src/templates/module/__Model__.Unit.d.ts +0 -11
  346. package/src/templates/module/__Model__.Util.d.ts +0 -11
  347. package/src/templates/module/__Model__.View.d.ts +0 -11
  348. package/src/templates/module/__Model__.Zone.d.ts +0 -11
  349. package/src/templates/module/index.d.ts +0 -11
@@ -0,0 +1,935 @@
1
+ # Akan.js Model Service Implementation Guide
2
+
3
+ ## Purpose and Role of model.service.ts Files
4
+
5
+ In the Akan.js framework, `model.service.ts` files are central components that implement business logic and manage interactions with data models. These services serve multiple critical purposes:
6
+
7
+ 1. **Business Logic Layer** - Encapsulate domain-specific operations and rules
8
+ 2. **Data Orchestration** - Coordinate operations between different models and external systems
9
+ 3. **Transaction Management** - Handle complex multi-step operations that may involve multiple models
10
+ 4. **Lifecycle Management** - Initialize resources and clean up when the application starts or stops
11
+ 5. **Scheduled Tasks** - Execute recurring operations using cron jobs and intervals
12
+ 6. **Security** - Implement authorization and permission checks
13
+ 7. **Integration** - Connect with external APIs, message queues, and other services
14
+
15
+ Services in Akan.js follow a stateless design pattern, where any persistent state should be managed through MongoDB and Redis, not within the service instance itself.
16
+
17
+ ## Service Structure and Inheritance
18
+
19
+ Akan.js services typically extend base service classes provided by the framework:
20
+
21
+ ### DbService
22
+
23
+ Most services extend `DbService` to work with MongoDB models:
24
+
25
+ ```typescript
26
+ @Service("ProductService")
27
+ export class ProductService extends DbService(db.productDb) {
28
+ // Service methods here
29
+ }
30
+ ```
31
+
32
+ The `DbService` function automatically injects the database model and provides numerous convenience methods for CRUD operations.
33
+
34
+ ### LogService
35
+
36
+ For utility services that don't directly work with a database model:
37
+
38
+ ```typescript
39
+ @Service("SecurityService")
40
+ export class SecurityService extends LogService("SecurityService") {
41
+ // Utility methods here
42
+ }
43
+ ```
44
+
45
+ ### Custom Service Base Classes
46
+
47
+ For specific domain services with shared functionality:
48
+
49
+ ```typescript
50
+ // In _libName/libName.service.ts
51
+ export const LibService = MixSrvs(SharedService, PlatformService, SocialService);
52
+
53
+ // In another service
54
+ @Service("CustomService")
55
+ export class CustomService extends LibService {
56
+ // Custom methods here
57
+ }
58
+ ```
59
+
60
+ ## Core Decorators
61
+
62
+ ### @Service Decorator
63
+
64
+ Declares a class as an injectable NestJS service with additional configuration options:
65
+
66
+ ```typescript
67
+ @Service("UserService", {
68
+ enabled: true, // Enable/disable service dynamically
69
+ serverMode: "federation", // "federation", "batch", or not specified
70
+ })
71
+ export class UserService extends DbService(db.userDb) {
72
+ // Service implementation
73
+ }
74
+ ```
75
+
76
+ Options:
77
+
78
+ - `enabled`: Boolean flag to conditionally disable a service (default: true)
79
+ - `serverMode`: Restricts the service to run only in specific server modes:
80
+ - `"federation"`: For API/GraphQL servers
81
+ - `"batch"`: For background processing servers
82
+ - Not specified: Runs in all modes
83
+
84
+ ### @Srv Decorator
85
+
86
+ Injects another service by name:
87
+
88
+ ```typescript
89
+ @Srv()
90
+ protected readonly userService: UserService; // Injects using capitalized property name
91
+
92
+ @Srv("CustomName")
93
+ protected readonly customService: SomeService; // Injects using specified name
94
+ ```
95
+
96
+ The `@Srv` decorator automatically capitalizes the property name if no explicit name is provided. For example, `@Srv() userService` will look for a service named "UserService".
97
+
98
+ ### @Use Decorator
99
+
100
+ Injects non-service dependencies like APIs, configurations, or utilities:
101
+
102
+ ```typescript
103
+ @Use()
104
+ protected readonly emailApi: EmailApi; // Injects using capitalized property name
105
+
106
+ @Use("CustomKey")
107
+ protected readonly customConfig: SomeConfig; // Injects using specified name
108
+ ```
109
+
110
+ Similar to `@Srv`, the `@Use` decorator capitalizes property names by default.
111
+
112
+ ### @Db Decorator
113
+
114
+ Injects a specific database model directly (rarely needed since `DbService` already provides this):
115
+
116
+ ```typescript
117
+ @Db("User")
118
+ protected readonly userModel: UserModel;
119
+ ```
120
+
121
+ ### @Queue Decorator
122
+
123
+ Injects a Bull queue for background processing:
124
+
125
+ ```typescript
126
+ @Queue()
127
+ protected readonly userQueue: Queue<UserSignal>;
128
+ ```
129
+
130
+ ### @Websocket Decorator
131
+
132
+ Injects a websocket server instance for real-time communication:
133
+
134
+ ```typescript
135
+ @Websocket()
136
+ protected readonly websocket: Websocket<ChatSignal>;
137
+ ```
138
+
139
+ ## Lifecycle Methods
140
+
141
+ Akan.js services can implement lifecycle hooks that are called by the NestJS framework.
142
+
143
+ ### onModuleInit()
144
+
145
+ Called once the module has been initialized by NestJS. Use this for setup operations:
146
+
147
+ ```typescript
148
+ async onModuleInit() {
149
+ // Initialize service resources
150
+ await this.loadInitialData();
151
+ this.setupEventListeners();
152
+ this.logger.log('Service initialized successfully');
153
+ }
154
+ ```
155
+
156
+ Common use cases:
157
+
158
+ - Initializing in-memory cache
159
+ - Setting up event listeners
160
+ - Loading configuration data
161
+ - Establishing connections to external services
162
+
163
+ ### onModuleDestroy()
164
+
165
+ Called just before the application shuts down. Use this for cleanup operations:
166
+
167
+ ```typescript
168
+ async onModuleDestroy() {
169
+ // Clean up resources
170
+ await Promise.all(this.connections.map(conn => conn.close()));
171
+ this.clearTimers();
172
+ this.logger.log('Service resources released');
173
+ }
174
+ ```
175
+
176
+ Common use cases:
177
+
178
+ - Closing database connections
179
+ - Releasing external resources
180
+ - Clearing timers and intervals
181
+ - Unregistering event listeners
182
+
183
+ ## Scheduled Tasks
184
+
185
+ Akan.js provides decorators for scheduling recurring tasks.
186
+
187
+ ### @Cron Decorator
188
+
189
+ Executes methods on a cron schedule:
190
+
191
+ ```typescript
192
+ @Cron("0 0 * * *") // Run at midnight every day
193
+ async dailyCleanup() {
194
+ await this.cleanupExpiredRecords();
195
+ this.logger.log('Daily cleanup completed');
196
+ }
197
+
198
+ @Cron("*/5 * * * *", { serverMode: "batch" }) // Run every 5 minutes, only in batch mode
199
+ async periodicSync() {
200
+ await this.syncExternalData();
201
+ }
202
+ ```
203
+
204
+ The first parameter uses standard cron syntax:
205
+
206
+ - `* * * * *` = minute hour day-of-month month day-of-week
207
+ - Special patterns like `@daily`, `@hourly` are also supported
208
+
209
+ Options include:
210
+
211
+ - `serverMode`: Restrict to a specific server mode (e.g., "batch")
212
+ - `name`: Assign a name to the scheduled job
213
+ - `timeZone`: Specify the timezone for the schedule
214
+
215
+ ### @Interval Decorator
216
+
217
+ Executes methods at fixed time intervals in milliseconds:
218
+
219
+ ```typescript
220
+ @Interval(60000) // Run every minute (60,000 ms)
221
+ async checkStatus() {
222
+ await this.monitorSystemHealth();
223
+ }
224
+ ```
225
+
226
+ Options:
227
+
228
+ - `name`: Assign a name to the interval
229
+
230
+ ## Database Operations
231
+
232
+ When extending `DbService`, your service automatically inherits numerous methods for working with the database model.
233
+
234
+ ### Basic CRUD Operations
235
+
236
+ ```typescript
237
+ // Create
238
+ const newProduct = await this.createProduct(productData);
239
+
240
+ // Read
241
+ const product = await this.getProduct(productId); // Throws if not found
242
+ const maybeProduct = await this.loadProduct(productId); // Returns null if not found
243
+ const products = await this.loadProductMany([id1, id2, id3]); // Load multiple by IDs
244
+
245
+ // Update
246
+ const updatedProduct = await this.updateProduct(productId, updateData);
247
+
248
+ // Delete (soft delete)
249
+ const removedProduct = await this.removeProduct(productId);
250
+ ```
251
+
252
+ ### Query Operations
253
+
254
+ ```typescript
255
+ // List with filtering, sorting, and pagination
256
+ const products = await this.listActiveProducts(categoryId, {
257
+ skip: 0,
258
+ limit: 10,
259
+ sort: "priceAsc",
260
+ });
261
+
262
+ // Get IDs only
263
+ const productIds = await this.listIdsActiveProducts(categoryId);
264
+
265
+ // Find a single item (returns null if not found)
266
+ const product = await this.findActiveProduct(categoryId);
267
+
268
+ // Pick a single item (throws if not found)
269
+ const product = await this.pickActiveProduct(categoryId);
270
+
271
+ // Check existence
272
+ const exists = await this.existsActiveProduct(categoryId);
273
+
274
+ // Count
275
+ const count = await this.countActiveProducts(categoryId);
276
+
277
+ // Insight (aggregate statistics)
278
+ const stats = await this.insightActiveProducts(categoryId);
279
+ ```
280
+
281
+ ### Search Operations (with Meilisearch)
282
+
283
+ ```typescript
284
+ // Full-text search with pagination
285
+ const { docs, count } = await this.searchProduct("wireless headphones", {
286
+ skip: 0,
287
+ limit: 10,
288
+ });
289
+
290
+ // Just get documents
291
+ const products = await this.searchDocsProduct("wireless headphones");
292
+
293
+ // Just get count
294
+ const total = await this.searchCountProduct("wireless headphones");
295
+ ```
296
+
297
+ ## Customizing Database Operations
298
+
299
+ `DbService` provides hooks for customizing database operations:
300
+
301
+ ```typescript
302
+ // Called before document creation
303
+ async _preCreate(data: ProductInput): Promise<ProductInput> {
304
+ // Validate or transform input data
305
+ if (!data.slug && data.name) {
306
+ data.slug = this.generateSlug(data.name);
307
+ }
308
+ return data;
309
+ }
310
+
311
+ // Called after document creation
312
+ async _postCreate(doc: Product): Promise<Product> {
313
+ // Perform additional actions after creation
314
+ await this.notificationService.notifyNewProduct(doc);
315
+ return doc;
316
+ }
317
+
318
+ // Called before document update
319
+ async _preUpdate(id: string, data: Partial<Product>): Promise<Partial<Product>> {
320
+ // Validate update data
321
+ const product = await this.getProduct(id);
322
+ if (product.status === 'published' && data.status === 'draft') {
323
+ throw new Error('Cannot revert published product to draft');
324
+ }
325
+ return data;
326
+ }
327
+
328
+ // Called after document update
329
+ async _postUpdate(doc: Product): Promise<Product> {
330
+ // Perform additional actions after update
331
+ await this.cacheService.invalidateProduct(doc.id);
332
+ return doc;
333
+ }
334
+
335
+ // Called before document removal
336
+ async _preRemove(id: string): Promise<void> {
337
+ // Validate removal
338
+ const product = await this.getProduct(id);
339
+ if (product.hasActiveOrders) {
340
+ throw new Error('Cannot remove product with active orders');
341
+ }
342
+ }
343
+
344
+ // Called after document removal
345
+ async _postRemove(doc: Product): Promise<Product> {
346
+ // Perform additional actions after removal
347
+ await this.searchService.removeProductFromIndex(doc.id);
348
+ return doc;
349
+ }
350
+ ```
351
+
352
+ ## Working with Other Services
353
+
354
+ Services often work together to implement complex operations:
355
+
356
+ ```typescript
357
+ @Service("OrderService")
358
+ export class OrderService extends DbService(db.orderDb) {
359
+ @Srv() productService: ProductService;
360
+ @Srv() userService: UserService;
361
+ @Srv() paymentService: PaymentService;
362
+ @Use() emailApi: EmailApi;
363
+
364
+ async createOrder(userId: string, items: OrderItemInput[]): Promise<Order> {
365
+ // Get user information
366
+ const user = await this.userService.getUser(userId);
367
+
368
+ // Verify product availability and calculate total
369
+ let total = 0;
370
+ const orderItems = [];
371
+
372
+ for (const item of items) {
373
+ const product = await this.productService.getProduct(item.productId);
374
+
375
+ if (product.stock < item.quantity) {
376
+ throw new Error(`Not enough stock for ${product.name}`);
377
+ }
378
+
379
+ const itemTotal = product.price * item.quantity;
380
+ total += itemTotal;
381
+
382
+ orderItems.push({
383
+ product: product.id,
384
+ quantity: item.quantity,
385
+ price: product.price,
386
+ total: itemTotal,
387
+ });
388
+
389
+ // Update product stock
390
+ await this.productService.updateProduct(product.id, {
391
+ stock: product.stock - item.quantity,
392
+ });
393
+ }
394
+
395
+ // Create order
396
+ const order = await this.createOrder({
397
+ user: user.id,
398
+ items: orderItems,
399
+ total,
400
+ status: "pending",
401
+ });
402
+
403
+ // Send confirmation email
404
+ await this.emailApi.sendOrderConfirmation(user.email, order);
405
+
406
+ return order;
407
+ }
408
+ }
409
+ ```
410
+
411
+ ## Websocket Integration
412
+
413
+ For real-time features:
414
+
415
+ ```typescript
416
+ @Service("ChatService")
417
+ export class ChatService extends DbService(db.chatDb) {
418
+ @Websocket()
419
+ websocket: Websocket<ChatSignal>;
420
+
421
+ async sendMessage(roomId: string, userId: string, content: string) {
422
+ // Create message in database
423
+ const message = await this.createMessage({
424
+ room: roomId,
425
+ sender: userId,
426
+ content,
427
+ sentAt: new Date(),
428
+ });
429
+
430
+ // Broadcast to room subscribers
431
+ this.websocket.pubsubNewMessage(roomId, {
432
+ id: message.id,
433
+ sender: message.sender,
434
+ content: message.content,
435
+ sentAt: message.sentAt,
436
+ });
437
+
438
+ return message;
439
+ }
440
+ }
441
+ ```
442
+
443
+ ## Queue Integration
444
+
445
+ For background processing:
446
+
447
+ ```typescript
448
+ @Service("EmailService")
449
+ export class EmailService extends LogService("EmailService") {
450
+ @Queue()
451
+ emailQueue: Queue<EmailSignal>;
452
+ @Use()
453
+ emailApi: EmailApi;
454
+
455
+ async sendWelcomeEmail(userId: string, email: string) {
456
+ // Add to background queue
457
+ await this.emailQueue.add("sendWelcomeEmail", { userId, email });
458
+ }
459
+
460
+ // Process queue job
461
+ async processSendWelcomeEmail(userId: string, email: string) {
462
+ const template = await this.getWelcomeTemplate();
463
+ await this.emailApi.send(email, "Welcome!", template);
464
+ await this.userService.updateUser(userId, { emailSent: true });
465
+ }
466
+ }
467
+ ```
468
+
469
+ ## Error Handling
470
+
471
+ Akan.js services should implement proper error handling:
472
+
473
+ ```typescript
474
+ async transferFunds(fromAccountId: string, toAccountId: string, amount: number) {
475
+ try {
476
+ // Validate accounts
477
+ const [fromAccount, toAccount] = await Promise.all([
478
+ this.getAccount(fromAccountId),
479
+ this.getAccount(toAccountId)
480
+ ]);
481
+
482
+ // Check balance
483
+ if (fromAccount.balance < amount) {
484
+ throw new InsufficientFundsError(
485
+ `Account ${fromAccountId} has insufficient funds: ${fromAccount.balance} < ${amount}`
486
+ );
487
+ }
488
+
489
+ // Perform transfer
490
+ await Promise.all([
491
+ this.updateAccount(fromAccountId, { balance: fromAccount.balance - amount }),
492
+ this.updateAccount(toAccountId, { balance: toAccount.balance + amount })
493
+ ]);
494
+
495
+ // Log transaction
496
+ await this.createTransaction({
497
+ from: fromAccountId,
498
+ to: toAccountId,
499
+ amount,
500
+ status: 'completed'
501
+ });
502
+
503
+ return true;
504
+ } catch (error) {
505
+ // Log error
506
+ this.logger.error(`Transfer failed: ${error.message}`, error.stack);
507
+
508
+ // Create failed transaction record
509
+ await this.createTransaction({
510
+ from: fromAccountId,
511
+ to: toAccountId,
512
+ amount,
513
+ status: 'failed',
514
+ error: error.message
515
+ });
516
+
517
+ // Rethrow domain-specific errors, wrap others
518
+ if (error instanceof DomainError) {
519
+ throw error;
520
+ }
521
+
522
+ throw new TransferFailedError(`Transfer failed: ${error.message}`, { cause: error });
523
+ }
524
+ }
525
+ ```
526
+
527
+ ## Best Practices
528
+
529
+ ### 1. Stateless Design
530
+
531
+ Services should not maintain internal state between requests:
532
+
533
+ ```typescript
534
+ // BAD - maintains state in the service
535
+ @Service("CounterService")
536
+ class CounterService {
537
+ private count = 0; // This state is lost on server restart
538
+
539
+ increment() {
540
+ this.count++;
541
+ }
542
+ getCount() {
543
+ return this.count;
544
+ }
545
+ }
546
+
547
+ // GOOD - uses database for state
548
+ @Service("CounterService")
549
+ class CounterService extends DbService(db.counterDb) {
550
+ async increment(counterId: string) {
551
+ const counter = await this.getCounter(counterId);
552
+ return await counter.set({ count: counter.count + 1 }).save();
553
+ }
554
+
555
+ async getCount(counterId: string) {
556
+ const counter = await this.getCounter(counterId);
557
+ return counter.count;
558
+ }
559
+ }
560
+ ```
561
+
562
+ ### 2. Single Responsibility
563
+
564
+ Each service should focus on a specific domain:
565
+
566
+ ```typescript
567
+ // BAD - mixing concerns
568
+ @Service("UserService")
569
+ class UserService extends DbService(db.userDb) {
570
+ async createUser(data) {
571
+ // User creation logic
572
+ }
573
+
574
+ async sendEmail(userId, subject, content) {
575
+ // Email sending logic
576
+ }
577
+
578
+ async processPayment(userId, amount) {
579
+ // Payment processing logic
580
+ }
581
+ }
582
+
583
+ // GOOD - separate services
584
+ @Service("UserService")
585
+ class UserService extends DbService(db.userDb) {
586
+ @Srv() emailService: EmailService;
587
+ @Srv() paymentService: PaymentService;
588
+
589
+ async createUser(data) {
590
+ // User creation logic
591
+ }
592
+ }
593
+
594
+ @Service("EmailService")
595
+ class EmailService extends LogService("EmailService") {
596
+ async sendEmail(userId, subject, content) {
597
+ // Email sending logic
598
+ }
599
+ }
600
+
601
+ @Service("PaymentService")
602
+ class PaymentService extends DbService(db.paymentDb) {
603
+ async processPayment(userId, amount) {
604
+ // Payment processing logic
605
+ }
606
+ }
607
+ ```
608
+
609
+ ### 3. Proper Resource Management
610
+
611
+ Clean up resources in lifecycle hooks:
612
+
613
+ ```typescript
614
+ @Service("ExternalApiService")
615
+ class ExternalApiService extends LogService("ExternalApiService") {
616
+ private client: ApiClient;
617
+ private timers: NodeJS.Timeout[] = [];
618
+
619
+ async onModuleInit() {
620
+ this.client = new ApiClient();
621
+ await this.client.connect();
622
+
623
+ this.timers.push(setInterval(() => this.refreshToken(), 3600000));
624
+ }
625
+
626
+ async onModuleDestroy() {
627
+ // Clean up resources
628
+ await this.client.disconnect();
629
+
630
+ for (const timer of this.timers) {
631
+ clearInterval(timer);
632
+ }
633
+ }
634
+ }
635
+ ```
636
+
637
+ ### 4. Transaction Safety
638
+
639
+ Use hooks for validating operations:
640
+
641
+ ```typescript
642
+ async _preUpdate(id: string, data: Partial<Product>) {
643
+ // Validate that product exists
644
+ const product = await this.getProduct(id);
645
+
646
+ // Check authorization
647
+ if (product.owner !== this.currentUser.id) {
648
+ throw new UnauthorizedError('You do not own this product');
649
+ }
650
+
651
+ // Validate business rules
652
+ if (product.status === 'published' && data.price < product.price) {
653
+ throw new ValidationError('Cannot reduce price of published product');
654
+ }
655
+
656
+ return data;
657
+ }
658
+ ```
659
+
660
+ ### 5. Service Dependency Injection
661
+
662
+ Inject other services using decorators, not direct imports:
663
+
664
+ ```typescript
665
+ // BAD - direct import
666
+ import { UserService } from "../user/user.service";
667
+
668
+ @Service("OrderService")
669
+ class OrderService extends DbService(db.orderDb) {
670
+ private userService = new UserService(); // Hard-coded dependency
671
+ }
672
+
673
+ // GOOD - dependency injection
674
+ @Service("OrderService")
675
+ class OrderService extends DbService(db.orderDb) {
676
+ @Srv() userService: UserService; // Injected dependency
677
+ }
678
+ ```
679
+
680
+ ### 6. Logging
681
+
682
+ Use the built-in logger for consistent logging:
683
+
684
+ ```typescript
685
+ @Service("PaymentService")
686
+ class PaymentService extends DbService(db.paymentDb) {
687
+ async processPayment(orderId: string, amount: number) {
688
+ this.logger.log(`Processing payment of ${amount} for order ${orderId}`);
689
+
690
+ try {
691
+ // Payment processing logic
692
+ this.logger.debug("Payment gateway response", response);
693
+
694
+ return result;
695
+ } catch (error) {
696
+ this.logger.error(`Payment failed for order ${orderId}: ${error.message}`, error.stack);
697
+ throw error;
698
+ }
699
+ }
700
+ }
701
+ ```
702
+
703
+ ## Integration with NestJS
704
+
705
+ Akan.js services are built on top of NestJS's dependency injection system. The `@Service` decorator builds on top of NestJS's `@Injectable()`:
706
+
707
+ ```typescript
708
+ // Behind the scenes, @Service does this:
709
+ @Injectable()
710
+ export class UserService {
711
+ // ...
712
+ }
713
+ ```
714
+
715
+ This allows Akan.js services to be used within NestJS modules, controllers, and resolvers.
716
+
717
+ ## Complete Example
718
+
719
+ Here's a complete example of a service implementation:
720
+
721
+ ```typescript
722
+ import { Dayjs } from "@akanjs/base";
723
+ import { Cron } from "@akanjs/nest";
724
+ import { DbService, Service, Srv, Use } from "@akanjs/service";
725
+ import type { EmailApi } from "@util/nest";
726
+
727
+ import { cnst } from "../cnst";
728
+ import * as db from "../db";
729
+ import { Revert } from "../dict";
730
+ import type * as srv from "../srv";
731
+
732
+ @Service("OrderService")
733
+ export class OrderService extends DbService(db.orderDb) {
734
+ @Srv() userService: srv.UserService;
735
+ @Srv() productService: srv.ProductService;
736
+ @Srv() paymentService: srv.PaymentService;
737
+ @Use() emailApi: EmailApi;
738
+
739
+ async onModuleInit() {
740
+ await this.syncPendingOrders();
741
+ this.logger.log("Order service initialized");
742
+ }
743
+
744
+ // Custom business logic
745
+ async createOrder(userId: string, items: OrderItemInput[]): Promise<Order> {
746
+ const user = await this.userService.getUser(userId);
747
+
748
+ // Calculate total and check stock
749
+ let total = 0;
750
+ const orderItems = [];
751
+
752
+ for (const item of items) {
753
+ const product = await this.productService.getProduct(item.productId);
754
+
755
+ if (product.stock < item.quantity) {
756
+ throw new Revert("order.insufficientStock", { product: product.name });
757
+ }
758
+
759
+ const itemTotal = product.price * item.quantity;
760
+ total += itemTotal;
761
+
762
+ orderItems.push({
763
+ product: product.id,
764
+ name: product.name,
765
+ quantity: item.quantity,
766
+ price: product.price,
767
+ total: itemTotal,
768
+ });
769
+
770
+ // Update product stock
771
+ await this.productService.updateProduct(product.id, {
772
+ stock: product.stock - item.quantity,
773
+ });
774
+ }
775
+
776
+ // Create order
777
+ const order = await this.createOrder({
778
+ user: user.id,
779
+ items: orderItems,
780
+ total,
781
+ status: "pending",
782
+ });
783
+
784
+ // Send confirmation email
785
+ await this.emailApi.sendOrderConfirmation(user.email, {
786
+ orderId: order.id,
787
+ items: orderItems,
788
+ total,
789
+ });
790
+
791
+ return order;
792
+ }
793
+
794
+ async cancelOrder(orderId: string) {
795
+ const order = await this.getOrder(orderId);
796
+
797
+ if (order.status !== "pending") {
798
+ throw new Revert("order.cannotCancelProcessedOrder");
799
+ }
800
+
801
+ // Return stock to inventory
802
+ for (const item of order.items) {
803
+ await this.productService.updateProduct(item.product, {
804
+ $inc: { stock: item.quantity },
805
+ });
806
+ }
807
+
808
+ return await order.set({ status: "cancelled" }).save();
809
+ }
810
+
811
+ // Lifecycle hooks
812
+ async _preUpdate(id: string, data: Partial<db.Order>) {
813
+ const order = await this.getOrder(id);
814
+
815
+ if (order.status === "completed" && data.status === "pending") {
816
+ throw new Revert("order.cannotRevertCompletedOrder");
817
+ }
818
+
819
+ return data;
820
+ }
821
+
822
+ // Scheduled task
823
+ @Cron("0 0 * * *", { serverMode: "batch" })
824
+ async cleanupAbandonedOrders() {
825
+ const cutoffDate = dayjs().subtract(7, "days");
826
+ const orders = await this.listPendingOrders(cutoffDate);
827
+
828
+ for (const order of orders) {
829
+ await this.cancelOrder(order.id);
830
+ this.logger.log(`Cancelled abandoned order: ${order.id}`);
831
+ }
832
+ }
833
+
834
+ // Summary method
835
+ async summarize(): Promise<cnst.OrderSummary> {
836
+ return {
837
+ ...(await this.orderModel.getSummary()),
838
+ };
839
+ }
840
+ }
841
+ ```
842
+
843
+ ## Troubleshooting
844
+
845
+ ### Service Not Being Injected
846
+
847
+ If a service isn't being injected correctly:
848
+
849
+ 1. Ensure the service name matches:
850
+
851
+ ```typescript
852
+ @Service("UserService") // This name must match
853
+ export class UserService extends DbService(db.userDb) {}
854
+
855
+ @Srv("UserService") // Or this must match if using explicit name
856
+ userService: UserService;
857
+ ```
858
+
859
+ 2. Check if the service is enabled in the current environment:
860
+
861
+ ```typescript
862
+ @Service("UserService", { enabled: process.env.ENABLE_USER_SERVICE === 'true' })
863
+ ```
864
+
865
+ 3. Verify server mode restrictions:
866
+ ```typescript
867
+ @Service("CleanupService", { serverMode: "batch" }) // Only runs in batch mode
868
+ ```
869
+
870
+ ### Database Operations Failing
871
+
872
+ 1. Check model definition and schema:
873
+
874
+ ```typescript
875
+ // Is the schema defined correctly?
876
+ console.log(db.userDb);
877
+ ```
878
+
879
+ 2. Verify input data format:
880
+
881
+ ```typescript
882
+ this.logger.debug("Creating user with data:", userData);
883
+ ```
884
+
885
+ 3. Check for middleware or hook errors:
886
+ ```typescript
887
+ async _preCreate(data) {
888
+ try {
889
+ return await validateUser(data); // This might be throwing
890
+ } catch (error) {
891
+ this.logger.error('Validation error:', error);
892
+ throw error;
893
+ }
894
+ }
895
+ ```
896
+
897
+ ### Scheduled Tasks Not Running
898
+
899
+ 1. Verify cron syntax:
900
+
901
+ ```typescript
902
+ // Correct syntax
903
+ @Cron("0 * * * *") // Every hour at minute 0
904
+
905
+ // Incorrect syntax
906
+ @Cron("0 * * *") // Missing day-of-week field
907
+ ```
908
+
909
+ 2. Check server mode restrictions:
910
+
911
+ ```typescript
912
+ // Only runs in batch mode
913
+ @Cron("0 * * * *", { serverMode: "batch" })
914
+ ```
915
+
916
+ 3. Ensure the service is properly initialized:
917
+ ```typescript
918
+ onModuleInit() {
919
+ this.logger.log('Service initialized'); // Is this being logged?
920
+ }
921
+ ```
922
+
923
+ ## Summary
924
+
925
+ Model services in Akan.js are powerful components that encapsulate business logic and data operations. By following the patterns and best practices outlined in this guide, you can create maintainable, scalable services that effectively implement your application's domain logic while maintaining clean separation of concerns.
926
+
927
+ Key takeaways:
928
+
929
+ - Services should be stateless, with persistent state managed in the database
930
+ - Use the appropriate decorator (@Service, @Srv, @Use, etc.) for dependency injection
931
+ - Implement lifecycle hooks for proper resource management
932
+ - Use scheduled tasks for recurring operations
933
+ - Follow single responsibility principle
934
+ - Use proper error handling and logging
935
+ - Leverage the built-in database operations from DbService