@tailor-platform/erp-kit 0.2.2 → 0.4.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 (639) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +193 -69
  3. package/dist/cli.mjs +1038 -398
  4. package/package.json +7 -5
  5. package/skills/erp-kit-app-1-requirements/SKILL.md +27 -17
  6. package/skills/erp-kit-app-2-requirements-review/SKILL.md +5 -4
  7. package/skills/erp-kit-app-2-requirements-review/references/best-practices-check.md +10 -1
  8. package/skills/erp-kit-app-2-requirements-review/references/boundary-consistency-check.md +10 -1
  9. package/skills/erp-kit-app-3-plan/SKILL.md +31 -34
  10. package/skills/erp-kit-app-3-plan/references/resolver-extraction.md +22 -36
  11. package/skills/erp-kit-app-3-plan/references/screen-extraction.md +15 -1
  12. package/skills/erp-kit-app-3-plan/references/story-extraction.md +8 -2
  13. package/skills/erp-kit-app-4-plan-review/SKILL.md +1 -10
  14. package/skills/erp-kit-app-5-impl-backend/SKILL.md +10 -19
  15. package/skills/erp-kit-app-5-impl-backend/references/app-config.md +1 -22
  16. package/skills/erp-kit-app-5-impl-backend/references/module-wiring.md +0 -1
  17. package/skills/erp-kit-app-5-impl-backend/references/resolver-patterns.md +13 -4
  18. package/skills/erp-kit-app-6-impl-frontend/SKILL.md +5 -0
  19. package/skills/erp-kit-app-6-impl-frontend/references/pages.md +16 -46
  20. package/skills/erp-kit-app-7-impl-review/SKILL.md +13 -11
  21. package/skills/erp-kit-app-7-impl-review/references/resolver-doc-code-parity.md +16 -17
  22. package/skills/erp-kit-app-shared/SKILL.md +15 -0
  23. package/skills/erp-kit-app-shared/references/link-format-reference.md +13 -0
  24. package/skills/erp-kit-app-shared/references/naming-conventions.md +21 -0
  25. package/skills/erp-kit-app-shared/references/resolver-classification.md +23 -0
  26. package/skills/erp-kit-app-shared/references/schema-constraints.md +25 -0
  27. package/skills/erp-kit-module-1-requirements/SKILL.md +7 -13
  28. package/skills/erp-kit-module-1-requirements/references/feature-doc.md +1 -1
  29. package/skills/erp-kit-module-2-requirements-review/SKILL.md +21 -5
  30. package/skills/erp-kit-module-2-requirements-review/references/requirements-report-format.md +19 -0
  31. package/skills/erp-kit-module-3-plan/SKILL.md +6 -8
  32. package/skills/erp-kit-module-3-plan/references/naming.md +15 -1
  33. package/skills/erp-kit-module-4-plan-review/SKILL.md +21 -5
  34. package/skills/erp-kit-module-4-plan-review/references/parity-report-format.md +15 -0
  35. package/skills/erp-kit-module-5-impl/SKILL.md +12 -10
  36. package/skills/erp-kit-module-5-impl/references/generated-code.md +2 -2
  37. package/skills/erp-kit-module-6-impl-review/SKILL.md +21 -7
  38. package/skills/erp-kit-module-6-impl-review/references/error-implementation-parity.md +1 -1
  39. package/skills/erp-kit-module-6-impl-review/references/errors.md +1 -1
  40. package/skills/erp-kit-module-6-impl-review/references/impl-parity-report-format.md +15 -0
  41. package/skills/erp-kit-module-shared/SKILL.md +4 -0
  42. package/skills/erp-kit-module-shared/references/errors.md +1 -1
  43. package/skills/erp-kit-module-shared/references/queries.md +1 -1
  44. package/skills/erp-kit-module-shared/references/structure.md +1 -1
  45. package/skills/erp-kit-update/SKILL.md +2 -2
  46. package/src/commands/app/index.ts +75 -31
  47. package/src/commands/check.test.ts +1 -1
  48. package/src/commands/check.ts +2 -35
  49. package/src/commands/doc/index.ts +83 -0
  50. package/src/commands/doc/module.test.ts +119 -0
  51. package/src/commands/doc/module.ts +114 -0
  52. package/src/commands/doc/modules.test.ts +103 -0
  53. package/src/commands/doc/modules.ts +98 -0
  54. package/src/commands/doc/search.test.ts +94 -0
  55. package/src/commands/doc/search.ts +111 -0
  56. package/src/commands/generate-doc.test.ts +63 -0
  57. package/src/commands/generate-doc.ts +105 -0
  58. package/src/commands/index.ts +20 -8
  59. package/src/commands/init-module.test.ts +43 -0
  60. package/src/commands/init-module.ts +74 -0
  61. package/src/commands/lib/command-result.ts +30 -0
  62. package/src/commands/lib/discovery.test.ts +74 -0
  63. package/src/commands/lib/discovery.ts +106 -0
  64. package/src/commands/lib/paths.ts +22 -0
  65. package/src/commands/lib/sync-check-source.test.ts +197 -0
  66. package/src/commands/lib/sync-check-source.ts +100 -0
  67. package/src/commands/lib/sync-check-tests.test.ts +178 -0
  68. package/src/commands/lib/sync-check-tests.ts +69 -0
  69. package/src/commands/mock/index.ts +11 -6
  70. package/src/commands/module/generate.ts +39 -14
  71. package/src/commands/module/index.ts +31 -45
  72. package/src/commands/parse-doc-test-cases.ts +13 -2
  73. package/src/commands/sync-check.test.ts +6 -364
  74. package/src/commands/sync-check.ts +7 -251
  75. package/src/generator/generate-app-code.test.ts +121 -0
  76. package/src/generator/generate-app-code.ts +51 -0
  77. package/src/{commands/scaffold.test.ts → generator/generate-code-boilerplate.test.ts} +19 -89
  78. package/src/generator/generate-code.test.ts +57 -6
  79. package/src/generator/generate-code.ts +40 -157
  80. package/src/generator/generate-errors.ts +34 -0
  81. package/src/generator/generate-permissions.ts +12 -0
  82. package/src/generator/generate-shells.ts +28 -0
  83. package/src/generator/generate-stubs.ts +31 -0
  84. package/src/generator/parse-resolver-doc.test.ts +89 -0
  85. package/src/generator/parse-resolver-doc.ts +125 -0
  86. package/src/generator/scaffold.ts +57 -0
  87. package/src/generator/stub-templates.test.ts +55 -0
  88. package/src/generator/stub-templates.ts +145 -0
  89. package/src/integration.test.ts +2 -2
  90. package/src/modules/audit/README.md +46 -0
  91. package/src/modules/audit/command/activateAuditPolicy.generated.ts +6 -0
  92. package/src/modules/audit/command/activateAuditPolicy.test.ts +186 -0
  93. package/src/modules/audit/command/activateAuditPolicy.ts +97 -0
  94. package/src/modules/audit/command/createAuditPolicy.generated.ts +6 -0
  95. package/src/modules/audit/command/createAuditPolicy.test.ts +395 -0
  96. package/src/modules/audit/command/createAuditPolicy.ts +131 -0
  97. package/src/modules/audit/command/deactivateAuditPolicy.generated.ts +6 -0
  98. package/src/modules/audit/command/deactivateAuditPolicy.test.ts +138 -0
  99. package/src/modules/audit/command/deactivateAuditPolicy.ts +58 -0
  100. package/src/modules/audit/command/deleteAuditPolicy.generated.ts +6 -0
  101. package/src/modules/audit/command/deleteAuditPolicy.test.ts +121 -0
  102. package/src/modules/audit/command/deleteAuditPolicy.ts +52 -0
  103. package/src/modules/audit/command/logAuditEvent.generated.ts +6 -0
  104. package/src/modules/audit/command/logAuditEvent.test.ts +991 -0
  105. package/src/modules/audit/command/logAuditEvent.ts +357 -0
  106. package/src/modules/audit/command/reactivateAuditPolicy.generated.ts +6 -0
  107. package/src/modules/audit/command/reactivateAuditPolicy.test.ts +143 -0
  108. package/src/modules/audit/command/reactivateAuditPolicy.ts +79 -0
  109. package/src/modules/audit/command/registerAuditableEntity.generated.ts +6 -0
  110. package/src/modules/audit/command/registerAuditableEntity.test.ts +268 -0
  111. package/src/modules/audit/command/registerAuditableEntity.ts +94 -0
  112. package/src/modules/audit/command/replaceAuditPolicy.generated.ts +6 -0
  113. package/src/modules/audit/command/replaceAuditPolicy.test.ts +242 -0
  114. package/src/modules/audit/command/replaceAuditPolicy.ts +91 -0
  115. package/src/modules/audit/command/updateAuditPolicy.generated.ts +6 -0
  116. package/src/modules/audit/command/updateAuditPolicy.test.ts +284 -0
  117. package/src/modules/audit/command/updateAuditPolicy.ts +151 -0
  118. package/src/modules/audit/db/auditEntry.ts +47 -0
  119. package/src/modules/audit/db/auditPolicy.ts +33 -0
  120. package/src/modules/audit/db/auditableEntity.ts +22 -0
  121. package/src/modules/audit/db/changeDetail.ts +28 -0
  122. package/src/modules/audit/db/policyFieldRule.ts +23 -0
  123. package/src/modules/audit/docs/commands/ActivateAuditPolicy.md +69 -0
  124. package/src/modules/audit/docs/commands/CreateAuditPolicy.md +79 -0
  125. package/src/modules/audit/docs/commands/DeactivateAuditPolicy.md +55 -0
  126. package/src/modules/audit/docs/commands/DeleteAuditPolicy.md +55 -0
  127. package/src/modules/audit/docs/commands/LogAuditEvent.md +137 -0
  128. package/src/modules/audit/docs/commands/ReactivateAuditPolicy.md +58 -0
  129. package/src/modules/audit/docs/commands/RegisterAuditableEntity.md +62 -0
  130. package/src/modules/audit/docs/commands/ReplaceAuditPolicy.md +72 -0
  131. package/src/modules/audit/docs/commands/UpdateAuditPolicy.md +77 -0
  132. package/src/modules/audit/docs/features/audit-event-logging.md +126 -0
  133. package/src/modules/audit/docs/features/audit-policy-configuration.md +135 -0
  134. package/src/modules/audit/docs/features/field-level-change-tracking.md +95 -0
  135. package/src/modules/audit/docs/models/AuditEntry.md +55 -0
  136. package/src/modules/audit/docs/models/AuditPolicy.md +79 -0
  137. package/src/modules/audit/docs/models/AuditableEntity.md +38 -0
  138. package/src/modules/audit/docs/models/ChangeDetail.md +55 -0
  139. package/src/modules/audit/docs/models/PolicyFieldRule.md +45 -0
  140. package/src/modules/audit/docs/queries/GetAuditEntry.md +49 -0
  141. package/src/modules/audit/docs/queries/GetAuditPolicy.md +54 -0
  142. package/src/modules/audit/docs/queries/GetAuditSummary.md +84 -0
  143. package/src/modules/audit/docs/queries/GetChangeDetails.md +56 -0
  144. package/src/modules/audit/docs/queries/ListAuditPolicies.md +58 -0
  145. package/src/modules/audit/docs/queries/SearchAuditEntries.md +91 -0
  146. package/src/modules/audit/generated/kysely-tailordb.ts +92 -0
  147. package/src/modules/audit/index.ts +2 -0
  148. package/src/modules/audit/lib/_db_deps.ts +13 -0
  149. package/src/modules/audit/lib/errors.generated.ts +120 -0
  150. package/src/modules/audit/lib/permissions.generated.ts +14 -0
  151. package/src/modules/audit/lib/types.ts +28 -0
  152. package/src/modules/audit/module.ts +57 -0
  153. package/src/modules/audit/permissions.ts +39 -0
  154. package/src/modules/audit/query/getAuditEntry.generated.ts +5 -0
  155. package/src/modules/audit/query/getAuditEntry.test.ts +123 -0
  156. package/src/modules/audit/query/getAuditEntry.ts +36 -0
  157. package/src/modules/audit/query/getAuditPolicy.generated.ts +5 -0
  158. package/src/modules/audit/query/getAuditPolicy.test.ts +169 -0
  159. package/src/modules/audit/query/getAuditPolicy.ts +42 -0
  160. package/src/modules/audit/query/getAuditSummary.generated.ts +5 -0
  161. package/src/modules/audit/query/getAuditSummary.test.ts +632 -0
  162. package/src/modules/audit/query/getAuditSummary.ts +164 -0
  163. package/src/modules/audit/query/getChangeDetails.generated.ts +5 -0
  164. package/src/modules/audit/query/getChangeDetails.test.ts +195 -0
  165. package/src/modules/audit/query/getChangeDetails.ts +42 -0
  166. package/src/modules/audit/query/listAuditPolicies.generated.ts +5 -0
  167. package/src/modules/audit/query/listAuditPolicies.test.ts +239 -0
  168. package/src/modules/audit/query/listAuditPolicies.ts +100 -0
  169. package/src/modules/audit/query/searchAuditEntries.generated.ts +5 -0
  170. package/src/modules/audit/query/searchAuditEntries.test.ts +424 -0
  171. package/src/modules/audit/query/searchAuditEntries.ts +121 -0
  172. package/src/modules/audit/tailor.config.ts +13 -0
  173. package/src/modules/audit/tailor.d.ts +13 -0
  174. package/src/modules/audit/testing/fixtures.ts +215 -0
  175. package/src/modules/business-partner/README.md +60 -0
  176. package/src/modules/business-partner/command/.gitkeep +0 -0
  177. package/src/modules/business-partner/command/activatePartner.generated.ts +6 -0
  178. package/src/modules/business-partner/command/activatePartner.test.ts +59 -0
  179. package/src/modules/business-partner/command/activatePartner.ts +45 -0
  180. package/src/modules/business-partner/command/assignRoleToPartner.generated.ts +6 -0
  181. package/src/modules/business-partner/command/assignRoleToPartner.test.ts +113 -0
  182. package/src/modules/business-partner/command/assignRoleToPartner.ts +72 -0
  183. package/src/modules/business-partner/command/createContactPerson.generated.ts +6 -0
  184. package/src/modules/business-partner/command/createContactPerson.test.ts +193 -0
  185. package/src/modules/business-partner/command/createContactPerson.ts +98 -0
  186. package/src/modules/business-partner/command/createPartner.generated.ts +6 -0
  187. package/src/modules/business-partner/command/createPartner.test.ts +179 -0
  188. package/src/modules/business-partner/command/createPartner.ts +83 -0
  189. package/src/modules/business-partner/command/createPartnerAddress.generated.ts +6 -0
  190. package/src/modules/business-partner/command/createPartnerAddress.test.ts +195 -0
  191. package/src/modules/business-partner/command/createPartnerAddress.ts +119 -0
  192. package/src/modules/business-partner/command/createPartnerBankAccount.generated.ts +6 -0
  193. package/src/modules/business-partner/command/createPartnerBankAccount.test.ts +297 -0
  194. package/src/modules/business-partner/command/createPartnerBankAccount.ts +114 -0
  195. package/src/modules/business-partner/command/createPartnerIdentification.generated.ts +6 -0
  196. package/src/modules/business-partner/command/createPartnerIdentification.test.ts +255 -0
  197. package/src/modules/business-partner/command/createPartnerIdentification.ts +97 -0
  198. package/src/modules/business-partner/command/deactivateContactPerson.generated.ts +6 -0
  199. package/src/modules/business-partner/command/deactivateContactPerson.test.ts +70 -0
  200. package/src/modules/business-partner/command/deactivateContactPerson.ts +54 -0
  201. package/src/modules/business-partner/command/deactivatePartner.generated.ts +6 -0
  202. package/src/modules/business-partner/command/deactivatePartner.test.ts +59 -0
  203. package/src/modules/business-partner/command/deactivatePartner.ts +46 -0
  204. package/src/modules/business-partner/command/deleteContactPerson.generated.ts +6 -0
  205. package/src/modules/business-partner/command/deleteContactPerson.test.ts +61 -0
  206. package/src/modules/business-partner/command/deleteContactPerson.ts +48 -0
  207. package/src/modules/business-partner/command/deletePartner.generated.ts +6 -0
  208. package/src/modules/business-partner/command/deletePartner.test.ts +58 -0
  209. package/src/modules/business-partner/command/deletePartner.ts +46 -0
  210. package/src/modules/business-partner/command/deletePartnerAddress.generated.ts +6 -0
  211. package/src/modules/business-partner/command/deletePartnerAddress.test.ts +74 -0
  212. package/src/modules/business-partner/command/deletePartnerAddress.ts +52 -0
  213. package/src/modules/business-partner/command/deletePartnerBankAccount.generated.ts +6 -0
  214. package/src/modules/business-partner/command/deletePartnerBankAccount.test.ts +55 -0
  215. package/src/modules/business-partner/command/deletePartnerBankAccount.ts +36 -0
  216. package/src/modules/business-partner/command/deletePartnerIdentification.generated.ts +6 -0
  217. package/src/modules/business-partner/command/deletePartnerIdentification.test.ts +47 -0
  218. package/src/modules/business-partner/command/deletePartnerIdentification.ts +37 -0
  219. package/src/modules/business-partner/command/reactivateContactPerson.generated.ts +6 -0
  220. package/src/modules/business-partner/command/reactivateContactPerson.test.ts +48 -0
  221. package/src/modules/business-partner/command/reactivateContactPerson.ts +48 -0
  222. package/src/modules/business-partner/command/reactivatePartner.generated.ts +6 -0
  223. package/src/modules/business-partner/command/reactivatePartner.test.ts +59 -0
  224. package/src/modules/business-partner/command/reactivatePartner.ts +46 -0
  225. package/src/modules/business-partner/command/removeRoleFromPartner.generated.ts +6 -0
  226. package/src/modules/business-partner/command/removeRoleFromPartner.test.ts +82 -0
  227. package/src/modules/business-partner/command/removeRoleFromPartner.ts +73 -0
  228. package/src/modules/business-partner/command/setDefaultPartnerAddress.generated.ts +6 -0
  229. package/src/modules/business-partner/command/setDefaultPartnerAddress.test.ts +60 -0
  230. package/src/modules/business-partner/command/setDefaultPartnerAddress.ts +48 -0
  231. package/src/modules/business-partner/command/setDefaultPartnerBankAccount.generated.ts +6 -0
  232. package/src/modules/business-partner/command/setDefaultPartnerBankAccount.test.ts +56 -0
  233. package/src/modules/business-partner/command/setDefaultPartnerBankAccount.ts +51 -0
  234. package/src/modules/business-partner/command/setPrimaryContactPerson.generated.ts +6 -0
  235. package/src/modules/business-partner/command/setPrimaryContactPerson.test.ts +63 -0
  236. package/src/modules/business-partner/command/setPrimaryContactPerson.ts +55 -0
  237. package/src/modules/business-partner/command/updateContactPerson.generated.ts +6 -0
  238. package/src/modules/business-partner/command/updateContactPerson.test.ts +193 -0
  239. package/src/modules/business-partner/command/updateContactPerson.ts +92 -0
  240. package/src/modules/business-partner/command/updatePartner.generated.ts +6 -0
  241. package/src/modules/business-partner/command/updatePartner.test.ts +101 -0
  242. package/src/modules/business-partner/command/updatePartner.ts +76 -0
  243. package/src/modules/business-partner/command/updatePartnerAddress.generated.ts +6 -0
  244. package/src/modules/business-partner/command/updatePartnerAddress.test.ts +148 -0
  245. package/src/modules/business-partner/command/updatePartnerAddress.ts +64 -0
  246. package/src/modules/business-partner/command/updatePartnerBankAccount.generated.ts +6 -0
  247. package/src/modules/business-partner/command/updatePartnerBankAccount.test.ts +249 -0
  248. package/src/modules/business-partner/command/updatePartnerBankAccount.ts +109 -0
  249. package/src/modules/business-partner/command/updatePartnerIdentification.generated.ts +6 -0
  250. package/src/modules/business-partner/command/updatePartnerIdentification.test.ts +162 -0
  251. package/src/modules/business-partner/command/updatePartnerIdentification.ts +105 -0
  252. package/src/modules/business-partner/db/.gitkeep +0 -0
  253. package/src/modules/business-partner/db/businessPartner.ts +59 -0
  254. package/src/modules/business-partner/db/contactPerson.ts +49 -0
  255. package/src/modules/business-partner/db/partnerAddress.ts +45 -0
  256. package/src/modules/business-partner/db/partnerBankAccount.ts +53 -0
  257. package/src/modules/business-partner/db/partnerIdentification.ts +53 -0
  258. package/src/modules/business-partner/db/partnerRole.ts +43 -0
  259. package/src/modules/business-partner/docs/commands/ActivatePartner.md +39 -0
  260. package/src/modules/business-partner/docs/commands/AssignRoleToPartner.md +49 -0
  261. package/src/modules/business-partner/docs/commands/CreateContactPerson.md +59 -0
  262. package/src/modules/business-partner/docs/commands/CreatePartner.md +54 -0
  263. package/src/modules/business-partner/docs/commands/CreatePartnerAddress.md +60 -0
  264. package/src/modules/business-partner/docs/commands/CreatePartnerBankAccount.md +68 -0
  265. package/src/modules/business-partner/docs/commands/CreatePartnerIdentification.md +59 -0
  266. package/src/modules/business-partner/docs/commands/DeactivateContactPerson.md +42 -0
  267. package/src/modules/business-partner/docs/commands/DeactivatePartner.md +39 -0
  268. package/src/modules/business-partner/docs/commands/DeleteContactPerson.md +43 -0
  269. package/src/modules/business-partner/docs/commands/DeletePartner.md +40 -0
  270. package/src/modules/business-partner/docs/commands/DeletePartnerAddress.md +40 -0
  271. package/src/modules/business-partner/docs/commands/DeletePartnerBankAccount.md +35 -0
  272. package/src/modules/business-partner/docs/commands/DeletePartnerIdentification.md +33 -0
  273. package/src/modules/business-partner/docs/commands/ReactivateContactPerson.md +38 -0
  274. package/src/modules/business-partner/docs/commands/ReactivatePartner.md +39 -0
  275. package/src/modules/business-partner/docs/commands/RemoveRoleFromPartner.md +46 -0
  276. package/src/modules/business-partner/docs/commands/SetDefaultPartnerAddress.md +38 -0
  277. package/src/modules/business-partner/docs/commands/SetDefaultPartnerBankAccount.md +38 -0
  278. package/src/modules/business-partner/docs/commands/SetPrimaryContactPerson.md +43 -0
  279. package/src/modules/business-partner/docs/commands/UpdateContactPerson.md +66 -0
  280. package/src/modules/business-partner/docs/commands/UpdatePartner.md +48 -0
  281. package/src/modules/business-partner/docs/commands/UpdatePartnerAddress.md +46 -0
  282. package/src/modules/business-partner/docs/commands/UpdatePartnerBankAccount.md +64 -0
  283. package/src/modules/business-partner/docs/commands/UpdatePartnerIdentification.md +52 -0
  284. package/src/modules/business-partner/docs/features/contact-person-management.md +70 -0
  285. package/src/modules/business-partner/docs/features/partner-address-management.md +96 -0
  286. package/src/modules/business-partner/docs/features/partner-bank-account.md +70 -0
  287. package/src/modules/business-partner/docs/features/partner-identification.md +76 -0
  288. package/src/modules/business-partner/docs/features/partner-lifecycle.md +59 -0
  289. package/src/modules/business-partner/docs/features/partner-role-classification.md +73 -0
  290. package/src/modules/business-partner/docs/models/BusinessPartner.md +64 -0
  291. package/src/modules/business-partner/docs/models/ContactPerson.md +62 -0
  292. package/src/modules/business-partner/docs/models/PartnerAddress.md +52 -0
  293. package/src/modules/business-partner/docs/models/PartnerBankAccount.md +50 -0
  294. package/src/modules/business-partner/docs/models/PartnerIdentification.md +46 -0
  295. package/src/modules/business-partner/docs/models/PartnerRole.md +42 -0
  296. package/src/modules/business-partner/docs/queries/GetContactPerson.md +34 -0
  297. package/src/modules/business-partner/docs/queries/GetDefaultPartnerAddress.md +40 -0
  298. package/src/modules/business-partner/docs/queries/GetDefaultPartnerBankAccount.md +36 -0
  299. package/src/modules/business-partner/docs/queries/GetPartner.md +35 -0
  300. package/src/modules/business-partner/docs/queries/GetPartnerAddress.md +34 -0
  301. package/src/modules/business-partner/docs/queries/GetPartnerBankAccount.md +34 -0
  302. package/src/modules/business-partner/docs/queries/GetPartnerIdentification.md +34 -0
  303. package/src/modules/business-partner/docs/queries/GetPartnerRole.md +34 -0
  304. package/src/modules/business-partner/docs/queries/GetPrimaryContactPerson.md +36 -0
  305. package/src/modules/business-partner/docs/queries/ListContactPersonsByPartner.md +39 -0
  306. package/src/modules/business-partner/docs/queries/ListPartnerAddressesByPartner.md +41 -0
  307. package/src/modules/business-partner/docs/queries/ListPartnerBankAccountsByPartner.md +39 -0
  308. package/src/modules/business-partner/docs/queries/ListPartnerIdentificationsByPartner.md +41 -0
  309. package/src/modules/business-partner/docs/queries/ListPartnersByRole.md +47 -0
  310. package/src/modules/business-partner/executor/.gitkeep +0 -0
  311. package/src/modules/business-partner/generated/.gitkeep +0 -0
  312. package/src/modules/business-partner/generated/enums.ts +60 -0
  313. package/src/modules/business-partner/generated/kysely-tailordb.ts +114 -0
  314. package/src/modules/business-partner/index.ts +2 -0
  315. package/src/modules/business-partner/lib/_db_deps.ts +17 -0
  316. package/src/modules/business-partner/lib/errors.generated.ts +172 -0
  317. package/src/modules/business-partner/lib/errors.ts +2 -0
  318. package/src/modules/business-partner/lib/permissions.generated.ts +30 -0
  319. package/src/modules/business-partner/lib/types.ts +53 -0
  320. package/src/modules/business-partner/module.ts +181 -0
  321. package/src/modules/business-partner/permissions.ts +3 -0
  322. package/src/modules/business-partner/query/.gitkeep +0 -0
  323. package/src/modules/business-partner/query/getContactPerson.generated.ts +5 -0
  324. package/src/modules/business-partner/query/getContactPerson.test.ts +31 -0
  325. package/src/modules/business-partner/query/getContactPerson.ts +16 -0
  326. package/src/modules/business-partner/query/getDefaultPartnerAddress.generated.ts +5 -0
  327. package/src/modules/business-partner/query/getDefaultPartnerAddress.test.ts +45 -0
  328. package/src/modules/business-partner/query/getDefaultPartnerAddress.ts +30 -0
  329. package/src/modules/business-partner/query/getDefaultPartnerBankAccount.generated.ts +5 -0
  330. package/src/modules/business-partner/query/getDefaultPartnerBankAccount.test.ts +43 -0
  331. package/src/modules/business-partner/query/getDefaultPartnerBankAccount.ts +17 -0
  332. package/src/modules/business-partner/query/getPartner.generated.ts +5 -0
  333. package/src/modules/business-partner/query/getPartner.test.ts +31 -0
  334. package/src/modules/business-partner/query/getPartner.ts +16 -0
  335. package/src/modules/business-partner/query/getPartnerAddress.generated.ts +5 -0
  336. package/src/modules/business-partner/query/getPartnerAddress.test.ts +31 -0
  337. package/src/modules/business-partner/query/getPartnerAddress.ts +16 -0
  338. package/src/modules/business-partner/query/getPartnerBankAccount.generated.ts +5 -0
  339. package/src/modules/business-partner/query/getPartnerBankAccount.test.ts +31 -0
  340. package/src/modules/business-partner/query/getPartnerBankAccount.ts +16 -0
  341. package/src/modules/business-partner/query/getPartnerIdentification.generated.ts +5 -0
  342. package/src/modules/business-partner/query/getPartnerIdentification.test.ts +31 -0
  343. package/src/modules/business-partner/query/getPartnerIdentification.ts +16 -0
  344. package/src/modules/business-partner/query/getPartnerRole.generated.ts +5 -0
  345. package/src/modules/business-partner/query/getPartnerRole.test.ts +31 -0
  346. package/src/modules/business-partner/query/getPartnerRole.ts +19 -0
  347. package/src/modules/business-partner/query/getPrimaryContactPerson.generated.ts +5 -0
  348. package/src/modules/business-partner/query/getPrimaryContactPerson.test.ts +43 -0
  349. package/src/modules/business-partner/query/getPrimaryContactPerson.ts +17 -0
  350. package/src/modules/business-partner/query/listContactPersonsByPartner.generated.ts +5 -0
  351. package/src/modules/business-partner/query/listContactPersonsByPartner.test.ts +77 -0
  352. package/src/modules/business-partner/query/listContactPersonsByPartner.ts +32 -0
  353. package/src/modules/business-partner/query/listPartnerAddressesByPartner.generated.ts +5 -0
  354. package/src/modules/business-partner/query/listPartnerAddressesByPartner.test.ts +71 -0
  355. package/src/modules/business-partner/query/listPartnerAddressesByPartner.ts +37 -0
  356. package/src/modules/business-partner/query/listPartnerBankAccountsByPartner.generated.ts +5 -0
  357. package/src/modules/business-partner/query/listPartnerBankAccountsByPartner.test.ts +59 -0
  358. package/src/modules/business-partner/query/listPartnerBankAccountsByPartner.ts +32 -0
  359. package/src/modules/business-partner/query/listPartnerIdentificationsByPartner.generated.ts +5 -0
  360. package/src/modules/business-partner/query/listPartnerIdentificationsByPartner.test.ts +72 -0
  361. package/src/modules/business-partner/query/listPartnerIdentificationsByPartner.ts +40 -0
  362. package/src/modules/business-partner/query/listPartnersByRole.generated.ts +5 -0
  363. package/src/modules/business-partner/query/listPartnersByRole.test.ts +103 -0
  364. package/src/modules/business-partner/query/listPartnersByRole.ts +47 -0
  365. package/src/modules/business-partner/tailor.config.ts +13 -0
  366. package/src/modules/business-partner/tailor.d.ts +13 -0
  367. package/src/modules/business-partner/testing/fixtures.ts +204 -0
  368. package/src/modules/coa-management/README.md +61 -0
  369. package/src/modules/coa-management/command/.gitkeep +0 -0
  370. package/src/modules/coa-management/command/activateAccount.generated.ts +6 -0
  371. package/src/modules/coa-management/command/activateAccount.test.ts +125 -0
  372. package/src/modules/coa-management/command/activateAccount.ts +105 -0
  373. package/src/modules/coa-management/command/activateChartOfAccounts.generated.ts +6 -0
  374. package/src/modules/coa-management/command/activateChartOfAccounts.test.ts +113 -0
  375. package/src/modules/coa-management/command/activateChartOfAccounts.ts +104 -0
  376. package/src/modules/coa-management/command/createAccount.generated.ts +6 -0
  377. package/src/modules/coa-management/command/createAccount.test.ts +767 -0
  378. package/src/modules/coa-management/command/createAccount.ts +247 -0
  379. package/src/modules/coa-management/command/createAccountGroup.generated.ts +6 -0
  380. package/src/modules/coa-management/command/createAccountGroup.test.ts +494 -0
  381. package/src/modules/coa-management/command/createAccountGroup.ts +207 -0
  382. package/src/modules/coa-management/command/createChartOfAccounts.generated.ts +6 -0
  383. package/src/modules/coa-management/command/createChartOfAccounts.test.ts +502 -0
  384. package/src/modules/coa-management/command/createChartOfAccounts.ts +267 -0
  385. package/src/modules/coa-management/command/deactivateAccount.generated.ts +6 -0
  386. package/src/modules/coa-management/command/deactivateAccount.test.ts +199 -0
  387. package/src/modules/coa-management/command/deactivateAccount.ts +142 -0
  388. package/src/modules/coa-management/command/deactivateChartOfAccounts.generated.ts +6 -0
  389. package/src/modules/coa-management/command/deactivateChartOfAccounts.test.ts +91 -0
  390. package/src/modules/coa-management/command/deactivateChartOfAccounts.ts +88 -0
  391. package/src/modules/coa-management/command/deleteAccount.generated.ts +6 -0
  392. package/src/modules/coa-management/command/deleteAccount.test.ts +122 -0
  393. package/src/modules/coa-management/command/deleteAccount.ts +103 -0
  394. package/src/modules/coa-management/command/deleteAccountGroup.generated.ts +6 -0
  395. package/src/modules/coa-management/command/deleteAccountGroup.test.ts +120 -0
  396. package/src/modules/coa-management/command/deleteAccountGroup.ts +113 -0
  397. package/src/modules/coa-management/command/deleteChartOfAccounts.generated.ts +6 -0
  398. package/src/modules/coa-management/command/deleteChartOfAccounts.test.ts +154 -0
  399. package/src/modules/coa-management/command/deleteChartOfAccounts.ts +133 -0
  400. package/src/modules/coa-management/command/moveAccountGroup.generated.ts +6 -0
  401. package/src/modules/coa-management/command/moveAccountGroup.test.ts +199 -0
  402. package/src/modules/coa-management/command/moveAccountGroup.ts +145 -0
  403. package/src/modules/coa-management/command/reactivateAccount.generated.ts +6 -0
  404. package/src/modules/coa-management/command/reactivateAccount.test.ts +126 -0
  405. package/src/modules/coa-management/command/reactivateAccount.ts +123 -0
  406. package/src/modules/coa-management/command/updateAccount.generated.ts +6 -0
  407. package/src/modules/coa-management/command/updateAccount.test.ts +669 -0
  408. package/src/modules/coa-management/command/updateAccount.ts +370 -0
  409. package/src/modules/coa-management/command/updateAccountGroup.generated.ts +6 -0
  410. package/src/modules/coa-management/command/updateAccountGroup.test.ts +253 -0
  411. package/src/modules/coa-management/command/updateAccountGroup.ts +191 -0
  412. package/src/modules/coa-management/command/updateChartOfAccounts.generated.ts +6 -0
  413. package/src/modules/coa-management/command/updateChartOfAccounts.test.ts +153 -0
  414. package/src/modules/coa-management/command/updateChartOfAccounts.ts +133 -0
  415. package/src/modules/coa-management/db/.gitkeep +0 -0
  416. package/src/modules/coa-management/db/account.ts +119 -0
  417. package/src/modules/coa-management/db/accountGroup.ts +57 -0
  418. package/src/modules/coa-management/db/chartOfAccounts.ts +55 -0
  419. package/src/modules/coa-management/docs/commands/ActivateAccount.md +49 -0
  420. package/src/modules/coa-management/docs/commands/ActivateChartOfAccounts.md +47 -0
  421. package/src/modules/coa-management/docs/commands/CreateAccount.md +94 -0
  422. package/src/modules/coa-management/docs/commands/CreateAccountGroup.md +70 -0
  423. package/src/modules/coa-management/docs/commands/CreateChartOfAccounts.md +72 -0
  424. package/src/modules/coa-management/docs/commands/DeactivateAccount.md +65 -0
  425. package/src/modules/coa-management/docs/commands/DeactivateChartOfAccounts.md +44 -0
  426. package/src/modules/coa-management/docs/commands/DeleteAccount.md +52 -0
  427. package/src/modules/coa-management/docs/commands/DeleteAccountGroup.md +50 -0
  428. package/src/modules/coa-management/docs/commands/DeleteChartOfAccounts.md +48 -0
  429. package/src/modules/coa-management/docs/commands/MoveAccountGroup.md +57 -0
  430. package/src/modules/coa-management/docs/commands/ReactivateAccount.md +50 -0
  431. package/src/modules/coa-management/docs/commands/UpdateAccount.md +102 -0
  432. package/src/modules/coa-management/docs/commands/UpdateAccountGroup.md +62 -0
  433. package/src/modules/coa-management/docs/commands/UpdateChartOfAccounts.md +49 -0
  434. package/src/modules/coa-management/docs/features/account-group-hierarchy.md +81 -0
  435. package/src/modules/coa-management/docs/features/account-lifecycle.md +80 -0
  436. package/src/modules/coa-management/docs/features/account-management.md +114 -0
  437. package/src/modules/coa-management/docs/features/chart-of-accounts-setup.md +86 -0
  438. package/src/modules/coa-management/docs/models/Account.md +84 -0
  439. package/src/modules/coa-management/docs/models/AccountGroup.md +55 -0
  440. package/src/modules/coa-management/docs/models/ChartOfAccounts.md +65 -0
  441. package/src/modules/coa-management/docs/queries/DetectCircularReference.md +52 -0
  442. package/src/modules/coa-management/docs/queries/GetAccount.md +42 -0
  443. package/src/modules/coa-management/docs/queries/GetAccountGroup.md +42 -0
  444. package/src/modules/coa-management/docs/queries/GetChartOfAccounts.md +48 -0
  445. package/src/modules/coa-management/docs/queries/ListAccountGroups.md +42 -0
  446. package/src/modules/coa-management/docs/queries/ListAccounts.md +54 -0
  447. package/src/modules/coa-management/docs/queries/ListUnassignedAccounts.md +40 -0
  448. package/src/modules/coa-management/executor/.gitkeep +0 -0
  449. package/src/modules/coa-management/generated/.gitkeep +0 -0
  450. package/src/modules/coa-management/generated/enums.ts +45 -0
  451. package/src/modules/coa-management/generated/kysely-tailordb.ts +81 -0
  452. package/src/modules/coa-management/index.ts +2 -0
  453. package/src/modules/coa-management/lib/_db_deps.ts +17 -0
  454. package/src/modules/coa-management/lib/errors.generated.ts +162 -0
  455. package/src/modules/coa-management/lib/errors.ts +0 -0
  456. package/src/modules/coa-management/lib/permissions.generated.ts +20 -0
  457. package/src/modules/coa-management/lib/types.ts +22 -0
  458. package/src/modules/coa-management/module.ts +136 -0
  459. package/src/modules/coa-management/permissions.ts +3 -0
  460. package/src/modules/coa-management/query/.gitkeep +0 -0
  461. package/src/modules/coa-management/query/detectCircularReference.generated.ts +5 -0
  462. package/src/modules/coa-management/query/detectCircularReference.test.ts +88 -0
  463. package/src/modules/coa-management/query/detectCircularReference.ts +46 -0
  464. package/src/modules/coa-management/query/getAccount.generated.ts +5 -0
  465. package/src/modules/coa-management/query/getAccount.test.ts +55 -0
  466. package/src/modules/coa-management/query/getAccount.ts +25 -0
  467. package/src/modules/coa-management/query/getAccountGroup.generated.ts +5 -0
  468. package/src/modules/coa-management/query/getAccountGroup.test.ts +55 -0
  469. package/src/modules/coa-management/query/getAccountGroup.ts +25 -0
  470. package/src/modules/coa-management/query/getChartOfAccounts.generated.ts +5 -0
  471. package/src/modules/coa-management/query/getChartOfAccounts.test.ts +79 -0
  472. package/src/modules/coa-management/query/getChartOfAccounts.ts +28 -0
  473. package/src/modules/coa-management/query/listAccountGroups.generated.ts +5 -0
  474. package/src/modules/coa-management/query/listAccountGroups.test.ts +72 -0
  475. package/src/modules/coa-management/query/listAccountGroups.ts +49 -0
  476. package/src/modules/coa-management/query/listAccounts.generated.ts +5 -0
  477. package/src/modules/coa-management/query/listAccounts.test.ts +136 -0
  478. package/src/modules/coa-management/query/listAccounts.ts +82 -0
  479. package/src/modules/coa-management/query/listUnassignedAccounts.generated.ts +5 -0
  480. package/src/modules/coa-management/query/listUnassignedAccounts.test.ts +96 -0
  481. package/src/modules/coa-management/query/listUnassignedAccounts.ts +39 -0
  482. package/src/modules/coa-management/tailor.config.ts +13 -0
  483. package/src/modules/coa-management/tailor.d.ts +13 -0
  484. package/src/modules/coa-management/testing/fixtures.ts +201 -0
  485. package/src/modules/item-management/README.md +1 -1
  486. package/src/modules/organization/README.md +57 -0
  487. package/src/modules/organization/command/.gitkeep +0 -0
  488. package/src/modules/organization/command/activateCompany.generated.ts +6 -0
  489. package/src/modules/organization/command/activateCompany.test.ts +184 -0
  490. package/src/modules/organization/command/activateCompany.ts +92 -0
  491. package/src/modules/organization/command/createCompany.generated.ts +6 -0
  492. package/src/modules/organization/command/createCompany.test.ts +156 -0
  493. package/src/modules/organization/command/createCompany.ts +80 -0
  494. package/src/modules/organization/command/createDepartment.generated.ts +6 -0
  495. package/src/modules/organization/command/createDepartment.test.ts +239 -0
  496. package/src/modules/organization/command/createDepartment.ts +98 -0
  497. package/src/modules/organization/command/createSite.generated.ts +6 -0
  498. package/src/modules/organization/command/createSite.test.ts +262 -0
  499. package/src/modules/organization/command/createSite.ts +155 -0
  500. package/src/modules/organization/command/deactivateCompany.generated.ts +6 -0
  501. package/src/modules/organization/command/deactivateCompany.test.ts +58 -0
  502. package/src/modules/organization/command/deactivateCompany.ts +47 -0
  503. package/src/modules/organization/command/deactivateDepartment.generated.ts +6 -0
  504. package/src/modules/organization/command/deactivateDepartment.test.ts +115 -0
  505. package/src/modules/organization/command/deactivateDepartment.ts +63 -0
  506. package/src/modules/organization/command/deactivateSite.generated.ts +6 -0
  507. package/src/modules/organization/command/deactivateSite.test.ts +53 -0
  508. package/src/modules/organization/command/deactivateSite.ts +47 -0
  509. package/src/modules/organization/command/deleteCompany.generated.ts +6 -0
  510. package/src/modules/organization/command/deleteCompany.test.ts +99 -0
  511. package/src/modules/organization/command/deleteCompany.ts +66 -0
  512. package/src/modules/organization/command/reactivateCompany.generated.ts +6 -0
  513. package/src/modules/organization/command/reactivateCompany.test.ts +58 -0
  514. package/src/modules/organization/command/reactivateCompany.ts +47 -0
  515. package/src/modules/organization/command/reactivateDepartment.generated.ts +6 -0
  516. package/src/modules/organization/command/reactivateDepartment.test.ts +59 -0
  517. package/src/modules/organization/command/reactivateDepartment.ts +47 -0
  518. package/src/modules/organization/command/reactivateSite.generated.ts +6 -0
  519. package/src/modules/organization/command/reactivateSite.test.ts +53 -0
  520. package/src/modules/organization/command/reactivateSite.ts +47 -0
  521. package/src/modules/organization/command/updateCompany.generated.ts +6 -0
  522. package/src/modules/organization/command/updateCompany.test.ts +239 -0
  523. package/src/modules/organization/command/updateCompany.ts +127 -0
  524. package/src/modules/organization/command/updateDepartment.generated.ts +6 -0
  525. package/src/modules/organization/command/updateDepartment.test.ts +232 -0
  526. package/src/modules/organization/command/updateDepartment.ts +120 -0
  527. package/src/modules/organization/command/updateSite.generated.ts +6 -0
  528. package/src/modules/organization/command/updateSite.test.ts +274 -0
  529. package/src/modules/organization/command/updateSite.ts +176 -0
  530. package/src/modules/organization/db/.gitkeep +0 -0
  531. package/src/modules/organization/db/company.ts +44 -0
  532. package/src/modules/organization/db/department.ts +46 -0
  533. package/src/modules/organization/db/site.ts +44 -0
  534. package/src/modules/organization/docs/commands/ActivateCompany.md +62 -0
  535. package/src/modules/organization/docs/commands/CreateCompany.md +49 -0
  536. package/src/modules/organization/docs/commands/CreateDepartment.md +62 -0
  537. package/src/modules/organization/docs/commands/CreateSite.md +74 -0
  538. package/src/modules/organization/docs/commands/DeactivateCompany.md +40 -0
  539. package/src/modules/organization/docs/commands/DeactivateDepartment.md +44 -0
  540. package/src/modules/organization/docs/commands/DeactivateSite.md +38 -0
  541. package/src/modules/organization/docs/commands/DeleteCompany.md +50 -0
  542. package/src/modules/organization/docs/commands/ReactivateCompany.md +39 -0
  543. package/src/modules/organization/docs/commands/ReactivateDepartment.md +37 -0
  544. package/src/modules/organization/docs/commands/ReactivateSite.md +37 -0
  545. package/src/modules/organization/docs/commands/UpdateCompany.md +58 -0
  546. package/src/modules/organization/docs/commands/UpdateDepartment.md +64 -0
  547. package/src/modules/organization/docs/commands/UpdateSite.md +80 -0
  548. package/src/modules/organization/docs/features/company-lifecycle.md +76 -0
  549. package/src/modules/organization/docs/features/department-management.md +66 -0
  550. package/src/modules/organization/docs/features/site-management.md +86 -0
  551. package/src/modules/organization/docs/models/Company.md +60 -0
  552. package/src/modules/organization/docs/models/Department.md +57 -0
  553. package/src/modules/organization/docs/models/Site.md +57 -0
  554. package/src/modules/organization/docs/queries/DetectDepartmentCircularReference.md +50 -0
  555. package/src/modules/organization/docs/queries/GetCompany.md +40 -0
  556. package/src/modules/organization/docs/queries/GetDepartment.md +44 -0
  557. package/src/modules/organization/docs/queries/GetDepartmentChildren.md +40 -0
  558. package/src/modules/organization/docs/queries/GetSite.md +37 -0
  559. package/src/modules/organization/docs/queries/ListDepartmentsByCompany.md +54 -0
  560. package/src/modules/organization/docs/queries/ListSitesByCompany.md +54 -0
  561. package/src/modules/organization/executor/.gitkeep +0 -0
  562. package/src/modules/organization/generated/.gitkeep +0 -0
  563. package/src/modules/organization/generated/kysely-tailordb.ts +77 -0
  564. package/src/modules/organization/index.ts +2 -0
  565. package/src/modules/organization/lib/_db_deps.ts +10 -0
  566. package/src/modules/organization/lib/errors.generated.ts +117 -0
  567. package/src/modules/organization/lib/errors.ts +1 -0
  568. package/src/modules/organization/lib/permissions.generated.ts +19 -0
  569. package/src/modules/organization/lib/types.ts +16 -0
  570. package/src/modules/organization/module.ts +89 -0
  571. package/src/modules/organization/permissions.ts +3 -0
  572. package/src/modules/organization/query/.gitkeep +0 -0
  573. package/src/modules/organization/query/detectDepartmentCircularReference.generated.ts +5 -0
  574. package/src/modules/organization/query/detectDepartmentCircularReference.test.ts +102 -0
  575. package/src/modules/organization/query/detectDepartmentCircularReference.ts +27 -0
  576. package/src/modules/organization/query/getCompany.generated.ts +5 -0
  577. package/src/modules/organization/query/getCompany.test.ts +70 -0
  578. package/src/modules/organization/query/getCompany.ts +16 -0
  579. package/src/modules/organization/query/getDepartment.generated.ts +5 -0
  580. package/src/modules/organization/query/getDepartment.test.ts +85 -0
  581. package/src/modules/organization/query/getDepartment.ts +17 -0
  582. package/src/modules/organization/query/getDepartmentChildren.generated.ts +5 -0
  583. package/src/modules/organization/query/getDepartmentChildren.test.ts +75 -0
  584. package/src/modules/organization/query/getDepartmentChildren.ts +21 -0
  585. package/src/modules/organization/query/getSite.generated.ts +5 -0
  586. package/src/modules/organization/query/getSite.test.ts +55 -0
  587. package/src/modules/organization/query/getSite.ts +16 -0
  588. package/src/modules/organization/query/listDepartmentsByCompany.generated.ts +5 -0
  589. package/src/modules/organization/query/listDepartmentsByCompany.test.ts +124 -0
  590. package/src/modules/organization/query/listDepartmentsByCompany.ts +43 -0
  591. package/src/modules/organization/query/listSitesByCompany.generated.ts +5 -0
  592. package/src/modules/organization/query/listSitesByCompany.test.ts +126 -0
  593. package/src/modules/organization/query/listSitesByCompany.ts +41 -0
  594. package/src/modules/organization/tailor.config.ts +13 -0
  595. package/src/modules/organization/tailor.d.ts +13 -0
  596. package/src/modules/organization/testing/fixtures.ts +155 -0
  597. package/src/modules/primitives/README.md +1 -1
  598. package/src/modules/primitives/command/setBaseCurrency.test.ts +8 -64
  599. package/src/modules/primitives/command/setBaseCurrency.ts +6 -64
  600. package/src/modules/primitives/docs/commands/ActivateCategory.md +1 -1
  601. package/src/modules/primitives/docs/commands/ActivateCurrency.md +1 -1
  602. package/src/modules/primitives/docs/commands/ActivateUnit.md +1 -1
  603. package/src/modules/primitives/docs/commands/CreateExchangeRate.md +2 -2
  604. package/src/modules/primitives/docs/commands/CreateUnit.md +1 -1
  605. package/src/modules/primitives/docs/commands/DeactivateCategory.md +1 -1
  606. package/src/modules/primitives/docs/commands/DeactivateCurrency.md +1 -1
  607. package/src/modules/primitives/docs/commands/DeactivateUnit.md +1 -1
  608. package/src/modules/primitives/docs/commands/SetBaseCurrency.md +13 -23
  609. package/src/modules/primitives/docs/commands/SetReferenceUnit.md +1 -1
  610. package/src/modules/primitives/docs/features/currency-definitions.md +13 -14
  611. package/src/modules/primitives/docs/models/Currency.md +3 -4
  612. package/src/modules/primitives/docs/queries/ConvertAmount.md +2 -2
  613. package/src/modules/primitives/docs/queries/ConvertQuantity.md +2 -2
  614. package/src/modules/primitives/lib/errors.generated.ts +5 -0
  615. package/src/modules/product-management/README.md +1 -1
  616. package/src/modules/user-management/docs/commands/CreatePermission.md +3 -3
  617. package/src/modules/user-management/docs/commands/CreateRole.md +1 -1
  618. package/src/modules/user-management/docs/queries/ListRolePermissionsByRole.md +39 -0
  619. package/src/modules/user-management/docs/queries/ListUserRolesByUser.md +39 -0
  620. package/src/modules/user-management/generated/enums.ts +0 -15
  621. package/src/modules/user-management/generated/kysely-tailordb.ts +0 -11
  622. package/src/shared/createContext.ts +2 -1
  623. package/src/shared/defineQuery.ts +36 -1
  624. package/src/shared/requirePermission.ts +3 -3
  625. package/src/shared/types.ts +3 -0
  626. package/templates/scaffold/app/backend/package.json +8 -7
  627. package/templates/scaffold/app/frontend/eslint.config.js +12 -0
  628. package/templates/scaffold/app/frontend/package.json +19 -16
  629. package/templates/scaffold/app/frontend/src/hooks/use-toast.ts +30 -0
  630. package/templates/scaffold/app/frontend/src/pages/user-management/user/create/components/create-user-form.tsx +3 -2
  631. package/templates/scaffold/app/frontend/vite.config.ts +5 -5
  632. package/templates/workflows/erp-kit-check.yml +2 -2
  633. package/src/commands/module/list.test.ts +0 -57
  634. package/src/commands/module/list.ts +0 -64
  635. package/src/commands/scaffold.ts +0 -176
  636. /package/src/modules/{accounting → audit/db}/.gitkeep +0 -0
  637. /package/src/modules/audit/{.gitkeep → executor/.gitkeep} +0 -0
  638. /package/src/modules/{coa-management/.gitkeep → audit/lib/errors.ts} +0 -0
  639. /package/src/modules/{supplier-management → business-partner}/.gitkeep +0 -0
package/dist/cli.mjs CHANGED
@@ -362,22 +362,85 @@ const ALL_SCHEMAS = {
362
362
  ...APP_COMPOSE_SCHEMAS
363
363
  };
364
364
  //#endregion
365
- //#region src/commands/check.ts
365
+ //#region src/commands/lib/paths.ts
366
+ const MODULE_PATHS = {
367
+ commands: "command",
368
+ db: "db",
369
+ queries: "query",
370
+ docs: {
371
+ commands: "docs/commands",
372
+ models: "docs/models",
373
+ queries: "docs/queries",
374
+ features: "docs/features"
375
+ }
376
+ };
377
+ const APP_PATHS = {
378
+ storySegment: "story",
379
+ docs: {
380
+ resolver: "docs/resolver",
381
+ actors: "docs/actors",
382
+ businessFlow: "docs/business-flow",
383
+ screen: "docs/screen"
384
+ }
385
+ };
386
+ //#endregion
387
+ //#region src/commands/lib/discovery.ts
388
+ function moduleCategories(root) {
389
+ return [
390
+ {
391
+ name: "command",
392
+ sourcePattern: `${root}/*/${MODULE_PATHS.commands}/*.ts`,
393
+ docPattern: `${root}/*/${MODULE_PATHS.docs.commands}/*.md`,
394
+ exclusions: [/\.test\.ts$/, /\.generated\.ts$/]
395
+ },
396
+ {
397
+ name: "model",
398
+ sourcePattern: `${root}/*/${MODULE_PATHS.db}/*.ts`,
399
+ docPattern: `${root}/*/${MODULE_PATHS.docs.models}/*.md`,
400
+ exclusions: [/\.test\.ts$/, /^index\.ts$/]
401
+ },
402
+ {
403
+ name: "query",
404
+ sourcePattern: `${root}/*/${MODULE_PATHS.queries}/*.ts`,
405
+ docPattern: `${root}/*/${MODULE_PATHS.docs.queries}/*.md`,
406
+ exclusions: [/\.test\.ts$/]
407
+ }
408
+ ];
409
+ }
410
+ function appComposeCategories(root) {
411
+ return [{
412
+ name: "resolver",
413
+ sourcePattern: `${root}/*/backend/src/resolvers/*.ts`,
414
+ docPattern: `${root}/*/${APP_PATHS.docs.resolver}/*.md`,
415
+ exclusions: [/\.test\.ts$/, /^index\.ts$/]
416
+ }];
417
+ }
418
+ function testCaseCategories(root) {
419
+ return [{
420
+ name: "command-test-case",
421
+ docPattern: `${root}/*/${MODULE_PATHS.docs.commands}/*.md`,
422
+ testDir: MODULE_PATHS.commands
423
+ }, {
424
+ name: "query-test-case",
425
+ docPattern: `${root}/*/${MODULE_PATHS.docs.queries}/*.md`,
426
+ testDir: MODULE_PATHS.queries
427
+ }];
428
+ }
366
429
  function buildCheckTargets(config) {
367
430
  const targets = [];
368
431
  if (config.modulesRoot) {
369
432
  const m = config.modulesRoot;
370
433
  targets.push({
371
- glob: `${m}/[a-zA-Z]*/docs/features/*.md`,
434
+ glob: `${m}/[a-zA-Z]*/${MODULE_PATHS.docs.features}/*.md`,
372
435
  schemaKey: "feature"
373
436
  }, {
374
- glob: `${m}/[a-zA-Z]*/docs/commands/*.md`,
437
+ glob: `${m}/[a-zA-Z]*/${MODULE_PATHS.docs.commands}/*.md`,
375
438
  schemaKey: "command"
376
439
  }, {
377
- glob: `${m}/[a-zA-Z]*/docs/models/*.md`,
440
+ glob: `${m}/[a-zA-Z]*/${MODULE_PATHS.docs.models}/*.md`,
378
441
  schemaKey: "model"
379
442
  }, {
380
- glob: `${m}/[a-zA-Z]*/docs/queries/*.md`,
443
+ glob: `${m}/[a-zA-Z]*/${MODULE_PATHS.docs.queries}/*.md`,
381
444
  schemaKey: "query"
382
445
  }, {
383
446
  glob: `${m}/[a-zA-Z]*/README.md`,
@@ -390,24 +453,26 @@ function buildCheckTargets(config) {
390
453
  glob: `${a}/[a-zA-Z]*/README.md`,
391
454
  schemaKey: "app"
392
455
  }, {
393
- glob: `${a}/[a-zA-Z]*/docs/actors/*.md`,
456
+ glob: `${a}/[a-zA-Z]*/${APP_PATHS.docs.actors}/*.md`,
394
457
  schemaKey: "actors"
395
458
  }, {
396
- glob: `${a}/[a-zA-Z]*/docs/business-flow/*/README.md`,
459
+ glob: `${a}/[a-zA-Z]*/${APP_PATHS.docs.businessFlow}/*/README.md`,
397
460
  schemaKey: "business-flow"
398
461
  }, {
399
- glob: `${a}/[a-zA-Z]*/docs/business-flow/*/story/*.md`,
462
+ glob: `${a}/[a-zA-Z]*/${APP_PATHS.docs.businessFlow}/*/${APP_PATHS.storySegment}/*.md`,
400
463
  schemaKey: "story"
401
464
  }, {
402
- glob: `${a}/[a-zA-Z]*/docs/screen/*.md`,
465
+ glob: `${a}/[a-zA-Z]*/${APP_PATHS.docs.screen}/*.md`,
403
466
  schemaKey: "screen"
404
467
  }, {
405
- glob: `${a}/[a-zA-Z]*/docs/resolver/*.md`,
468
+ glob: `${a}/[a-zA-Z]*/${APP_PATHS.docs.resolver}/*.md`,
406
469
  schemaKey: "resolver"
407
470
  });
408
471
  }
409
472
  return targets;
410
473
  }
474
+ //#endregion
475
+ //#region src/commands/check.ts
411
476
  async function runCheck(config, cwd) {
412
477
  const targets = buildCheckTargets(config);
413
478
  const results = await Promise.all(targets.map(async (target) => {
@@ -430,83 +495,85 @@ async function runCheck(config, cwd) {
430
495
  return results.some((code) => code !== 0) ? 1 : 0;
431
496
  }
432
497
  //#endregion
433
- //#region src/commands/parse-doc-test-cases.ts
434
- function isHeading$1(node) {
435
- return node.type === "heading";
498
+ //#region src/commands/init-module.ts
499
+ function runInitModule(name, dir) {
500
+ const moduleDir = path.resolve(dir, name);
501
+ if (fs.existsSync(moduleDir)) {
502
+ console.error(`Directory already exists: ${moduleDir}`);
503
+ return 1;
504
+ }
505
+ fs.mkdirSync(moduleDir, { recursive: true });
506
+ return 0;
436
507
  }
437
- function isList$1(node) {
438
- return node.type === "list";
508
+ async function runInitModuleWithReadme(name, dir, cwd) {
509
+ const initResult = runInitModule(name, dir);
510
+ if (initResult !== 0) return initResult;
511
+ const moduleDir = path.resolve(cwd, dir, name);
512
+ const readmePath = path.join(moduleDir, "README.md");
513
+ const schemaPath = MODULE_SCHEMAS.module;
514
+ const { exitCode, stdout, stderr } = await runMdschema([
515
+ "generate",
516
+ "--schema",
517
+ schemaPath,
518
+ "--output",
519
+ readmePath
520
+ ], cwd);
521
+ if (stdout.trim()) console.log(stdout);
522
+ if (stderr.trim()) console.error(stderr);
523
+ return exitCode;
439
524
  }
440
- /**
441
- * Parse test case descriptions from the `## Test Cases` section of a Markdown doc.
442
- * Uses mdast to traverse the AST instead of string matching.
443
- */
444
- function parseTestCasesFromDoc(markdown) {
445
- const tree = fromMarkdown(markdown);
446
- const cases = [];
447
- let collecting = false;
448
- for (const node of tree.children) {
449
- if (isHeading$1(node)) {
450
- if (collecting) break;
451
- if (node.depth === 2 && toString(node) === "Test Cases") {
452
- collecting = true;
453
- continue;
454
- }
455
- }
456
- if (collecting && isList$1(node)) for (const item of node.children) {
457
- const text = toString(item).trim();
458
- if (text) cases.push(text);
459
- }
525
+ function runInitApp(name, dir) {
526
+ const appDir = path.resolve(dir, name);
527
+ if (fs.existsSync(appDir)) {
528
+ console.error(`Directory already exists: ${appDir}`);
529
+ return 1;
460
530
  }
461
- return cases;
531
+ fs.mkdirSync(appDir, { recursive: true });
532
+ return 0;
462
533
  }
463
- /**
464
- * Parse `it("...")` descriptions from a test file using regex.
465
- * Test files are not Markdown, so regex is appropriate here.
466
- */
467
- function parseItDescriptionsFromTest(content) {
468
- const descriptions = [];
469
- const regex = /\bit\(\s*["'`]([^"'`]+)["'`]/g;
470
- let match;
471
- while ((match = regex.exec(content)) !== null) descriptions.push(match[1]);
472
- return descriptions;
534
+ async function runInitAppWithReadme(name, dir, cwd) {
535
+ const initResult = runInitApp(name, dir);
536
+ if (initResult !== 0) return initResult;
537
+ const appDir = path.resolve(cwd, dir, name);
538
+ const readmePath = path.join(appDir, "README.md");
539
+ const schemaPath = APP_COMPOSE_SCHEMAS.app;
540
+ const { exitCode, stdout, stderr } = await runMdschema([
541
+ "generate",
542
+ "--schema",
543
+ schemaPath,
544
+ "--output",
545
+ readmePath
546
+ ], cwd);
547
+ if (stdout.trim()) console.log(stdout);
548
+ if (stderr.trim()) console.error(stderr);
549
+ return exitCode;
473
550
  }
474
551
  //#endregion
475
- //#region src/commands/sync-check.ts
476
- function moduleCategories(root) {
477
- return [
478
- {
479
- name: "command",
480
- sourcePattern: `${root}/*/command/*.ts`,
481
- docPattern: `${root}/*/docs/commands/*.md`,
482
- exclusions: [/\.test\.ts$/, /\.generated\.ts$/]
483
- },
484
- {
485
- name: "model",
486
- sourcePattern: `${root}/*/db/*.ts`,
487
- docPattern: `${root}/*/docs/models/*.md`,
488
- exclusions: [/\.test\.ts$/, /^index\.ts$/]
489
- },
490
- {
491
- name: "query",
492
- sourcePattern: `${root}/*/query/*.ts`,
493
- docPattern: `${root}/*/docs/queries/*.md`,
494
- exclusions: [/\.test\.ts$/]
495
- }
496
- ];
552
+ //#region src/commands/lib/command-result.ts
553
+ function success() {
554
+ return { exitCode: 0 };
497
555
  }
498
- function appComposeCategories(root) {
499
- return [{
500
- name: "resolver",
501
- sourcePattern: `${root}/*/backend/src/modules/**/resolvers/*.ts`,
502
- docPattern: `${root}/*/docs/resolver/*.md`,
503
- exclusions: [/\.test\.ts$/, /^index\.ts$/]
504
- }];
556
+ function silentFailure(exitCode = 1) {
557
+ return {
558
+ exitCode,
559
+ message: ""
560
+ };
561
+ }
562
+ async function runCommand(fn) {
563
+ const result = await fn();
564
+ if (result.exitCode !== 0 && "message" in result && result.message) console.error(result.message);
565
+ return result;
505
566
  }
567
+ async function executeCommand(fn) {
568
+ const result = await runCommand(fn);
569
+ process.exit(result.exitCode);
570
+ }
571
+ //#endregion
572
+ //#region src/commands/lib/sync-check-source.ts
506
573
  function shouldExclude(fileName, exclusions) {
507
574
  return exclusions.some((pattern) => pattern.test(fileName));
508
575
  }
509
- async function runSyncCheck(config, cwd) {
576
+ async function runSourceSyncCheck(config, cwd) {
510
577
  const errors = [];
511
578
  let totalSources = 0;
512
579
  let totalDocs = 0;
@@ -543,10 +610,6 @@ async function runSyncCheck(config, cwd) {
543
610
  totalSources += sourceBasenames.size;
544
611
  totalDocs += docBasenames.size;
545
612
  }
546
- if (config.modulesRoot) {
547
- const testCaseErrors = await runTestCaseSyncCheck(config.modulesRoot, cwd);
548
- errors.push(...testCaseErrors);
549
- }
550
613
  return {
551
614
  exitCode: errors.length > 0 ? 1 : 0,
552
615
  errors,
@@ -557,17 +620,56 @@ async function runSyncCheck(config, cwd) {
557
620
  }
558
621
  };
559
622
  }
560
- function testCaseCategories(root) {
561
- return [{
562
- name: "command-test-case",
563
- docPattern: `${root}/*/docs/commands/*.md`,
564
- testDir: "command"
565
- }, {
566
- name: "query-test-case",
567
- docPattern: `${root}/*/docs/queries/*.md`,
568
- testDir: "query"
569
- }];
623
+ //#endregion
624
+ //#region src/commands/parse-doc-test-cases.ts
625
+ function isHeading$2(node) {
626
+ return node.type === "heading";
627
+ }
628
+ function isList$1(node) {
629
+ return node.type === "list";
630
+ }
631
+ /**
632
+ * Parse test case descriptions from the `## Test Cases` section of a Markdown doc.
633
+ * Uses mdast to traverse the AST instead of string matching.
634
+ */
635
+ function parseTestCasesFromDoc(markdown) {
636
+ const tree = fromMarkdown(markdown);
637
+ const cases = [];
638
+ let collecting = false;
639
+ for (const node of tree.children) {
640
+ if (isHeading$2(node)) {
641
+ if (collecting) break;
642
+ if (node.depth === 2 && toString(node) === "Test Cases") {
643
+ collecting = true;
644
+ continue;
645
+ }
646
+ }
647
+ if (collecting && isList$1(node)) for (const item of node.children) {
648
+ const text = toString(item).trim();
649
+ if (text) cases.push(text);
650
+ }
651
+ }
652
+ return cases;
653
+ }
654
+ /**
655
+ * Parse `it("...")` descriptions from a test file using regex.
656
+ * Test files are not Markdown, so regex is appropriate here.
657
+ * Uses separate patterns per quote type so that e.g. an apostrophe
658
+ * inside a double-quoted string does not end the match early.
659
+ */
660
+ function parseItDescriptionsFromTest(content) {
661
+ const descriptions = [];
662
+ const regex = /\bit\(\s*"([^"]+)"/gs;
663
+ let match;
664
+ while ((match = regex.exec(content)) !== null) descriptions.push(match[1].replace(/\s+/g, " ").trim());
665
+ const singleQuoteRegex = /\bit\(\s*'([^']+)'/gs;
666
+ while ((match = singleQuoteRegex.exec(content)) !== null) descriptions.push(match[1].replace(/\s+/g, " ").trim());
667
+ const backtickRegex = /\bit\(\s*`([^`]+)`/gs;
668
+ while ((match = backtickRegex.exec(content)) !== null) descriptions.push(match[1].replace(/\s+/g, " ").trim());
669
+ return descriptions;
570
670
  }
671
+ //#endregion
672
+ //#region src/commands/lib/sync-check-tests.ts
571
673
  function toCamelCase(pascalCase) {
572
674
  return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1);
573
675
  }
@@ -609,6 +711,17 @@ async function runTestCaseSyncCheck(root, cwd) {
609
711
  }
610
712
  return errors;
611
713
  }
714
+ //#endregion
715
+ //#region src/commands/sync-check.ts
716
+ async function runSyncCheck(config, cwd) {
717
+ const sourceResult = await runSourceSyncCheck(config, cwd);
718
+ if (config.modulesRoot) {
719
+ const testCaseErrors = await runTestCaseSyncCheck(config.modulesRoot, cwd);
720
+ sourceResult.errors.push(...testCaseErrors);
721
+ sourceResult.exitCode = sourceResult.errors.length > 0 ? 1 : 0;
722
+ }
723
+ return sourceResult;
724
+ }
612
725
  function formatSyncCheckReport(result) {
613
726
  const lines = [];
614
727
  lines.push(chalk.bold("docs-sync-check: Checking source-documentation correspondence...\n"));
@@ -655,158 +768,6 @@ function formatSyncCheckReport(result) {
655
768
  return lines.join("\n");
656
769
  }
657
770
  //#endregion
658
- //#region src/commands/scaffold.ts
659
- const MODULE_TYPES = [
660
- "module",
661
- "feature",
662
- "command",
663
- "model",
664
- "query"
665
- ];
666
- const APP_TYPES = [
667
- "app",
668
- "actors",
669
- "business-flow",
670
- "story",
671
- "screen",
672
- "resolver"
673
- ];
674
- [...MODULE_TYPES, ...APP_TYPES];
675
- const MODULE_DIR_MAP = {
676
- feature: "docs/features",
677
- command: "docs/commands",
678
- model: "docs/models",
679
- query: "docs/queries"
680
- };
681
- const APP_DIR_MAP = {
682
- actors: "docs/actors",
683
- "business-flow": "docs/business-flow",
684
- screen: "docs/screen",
685
- resolver: "docs/resolver"
686
- };
687
- function resolveScaffoldPath(type, parentName, name, root) {
688
- if (type === "module" || type === "app") return path.join(root, parentName, "README.md");
689
- if (!name) throw new Error(`Name is required for scaffold type "${type}"`);
690
- if (type === "business-flow") return path.join(root, parentName, "docs/business-flow", name, "README.md");
691
- if (type === "story") {
692
- const parts = name.split("/");
693
- if (parts.length !== 2) throw new Error(`Story name must be "<flow>/<story>" (e.g., "onboarding/admin--create-user")`);
694
- return path.join(root, parentName, "docs/business-flow", parts[0], "story", `${parts[1]}.md`);
695
- }
696
- if (MODULE_DIR_MAP[type]) return path.join(root, parentName, MODULE_DIR_MAP[type], `${name}.md`);
697
- if (APP_DIR_MAP[type]) return path.join(root, parentName, APP_DIR_MAP[type], `${name}.md`);
698
- throw new Error(`Unknown scaffold type: ${type}`);
699
- }
700
- async function runScaffold(type, parentName, name, root, cwd) {
701
- const outputPath = resolveScaffoldPath(type, parentName, name, root);
702
- const absoluteOutput = path.resolve(cwd, outputPath);
703
- if (fs.existsSync(absoluteOutput)) {
704
- console.error(`File already exists: ${outputPath}`);
705
- return 1;
706
- }
707
- const schemaPath = ALL_SCHEMAS[type];
708
- if (!schemaPath) {
709
- console.error(`No schema found for type: ${type}`);
710
- return 2;
711
- }
712
- try {
713
- fs.mkdirSync(path.dirname(absoluteOutput), { recursive: true });
714
- } catch (err) {
715
- console.error(`Failed to create directory: ${err instanceof Error ? err.message : String(err)}`);
716
- return 1;
717
- }
718
- const { exitCode, stdout, stderr } = await runMdschema([
719
- "generate",
720
- "--schema",
721
- schemaPath,
722
- "--output",
723
- absoluteOutput
724
- ], cwd);
725
- if (stdout.trim()) console.log(stdout);
726
- if (stderr.trim()) console.error(stderr);
727
- if (exitCode !== 0) return exitCode;
728
- if (type === "module") scaffoldModuleSrc(path.dirname(absoluteOutput), parentName);
729
- if (type === "app") scaffoldAppSrc(path.dirname(absoluteOutput), parentName);
730
- return exitCode;
731
- }
732
- function copyTemplateDir(srcDir, destDir, replacements, placeholderFiles) {
733
- for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
734
- const srcPath = path.join(srcDir, entry.name);
735
- const destName = entry.name === "__dot__gitignore" ? ".gitignore" : entry.name;
736
- const destPath = path.join(destDir, destName);
737
- if (entry.isDirectory()) {
738
- fs.mkdirSync(destPath, { recursive: true });
739
- copyTemplateDir(srcPath, destPath, replacements, placeholderFiles);
740
- } else {
741
- fs.mkdirSync(path.dirname(destPath), { recursive: true });
742
- if (placeholderFiles.has(entry.name)) {
743
- let content = fs.readFileSync(srcPath, "utf-8");
744
- for (const [from, to] of Object.entries(replacements)) content = content.replaceAll(from, to);
745
- fs.writeFileSync(destPath, content);
746
- } else fs.copyFileSync(srcPath, destPath);
747
- }
748
- }
749
- }
750
- function scaffoldModuleSrc(moduleDir, moduleName) {
751
- copyTemplateDir(path.join(PACKAGE_ROOT, "templates", "scaffold", "module"), moduleDir, { "template-module": moduleName }, new Set(["permissions.ts", "tailor.config.ts"]));
752
- }
753
- function scaffoldAppSrc(appDir, appName) {
754
- const templateDir = path.join(PACKAGE_ROOT, "templates", "scaffold", "app");
755
- const erpKitVersion = readErpKitVersion();
756
- copyTemplateDir(templateDir, appDir, {
757
- "template-app-frontend": `${appName}-frontend`,
758
- "template-app-backend": appName,
759
- "template-app": appName,
760
- "\"workspace:*\"": `"${erpKitVersion}"`
761
- }, new Set([
762
- "package.json",
763
- "tailor.config.ts",
764
- "index.html"
765
- ]));
766
- }
767
- //#endregion
768
- //#region src/commands/module/list.ts
769
- const MODULES_DIR = join(PACKAGE_ROOT, "src", "modules");
770
- const EXCLUDED_DIRS = new Set(["shared", "testing"]);
771
- function countFiles(dir, pattern, exclusions) {
772
- if (!existsSync(dir)) return 0;
773
- return readdirSync(dir).filter((f) => pattern.test(f) && !exclusions.some((p) => p.test(f))).length;
774
- }
775
- function listModules() {
776
- if (!existsSync(MODULES_DIR)) return [];
777
- return readdirSync(MODULES_DIR, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DIRS.has(d.name)).map((d) => {
778
- const modDir = join(MODULES_DIR, d.name);
779
- return {
780
- name: d.name,
781
- commands: countFiles(join(modDir, "command"), /\.ts$/, [/\.test\.ts$/]),
782
- models: countFiles(join(modDir, "db"), /\.ts$/, [/\.test\.ts$/, /^index\.ts$/]),
783
- features: countFiles(join(modDir, "docs", "features"), /\.md$/, [])
784
- };
785
- }).sort((a, b) => a.name.localeCompare(b.name));
786
- }
787
- function formatModuleList(modules) {
788
- if (modules.length === 0) return "No modules found.";
789
- const lines = [];
790
- lines.push(chalk.bold("Modules:\n"));
791
- const nameWidth = Math.max(...modules.map((m) => m.name.length), 4);
792
- for (const mod of modules) {
793
- const counts = [
794
- `${mod.commands} commands`,
795
- `${mod.models} models`,
796
- `${mod.features} features`
797
- ].join(", ");
798
- lines.push(` ${mod.name.padEnd(nameWidth)} ${counts}`);
799
- }
800
- lines.push("");
801
- lines.push(`${modules.length} modules`);
802
- return lines.join("\n");
803
- }
804
- function runModuleList() {
805
- const modules = listModules();
806
- console.log(formatModuleList(modules));
807
- return 0;
808
- }
809
- //#endregion
810
771
  //#region src/generator/parse-command-doc.ts
811
772
  function parseCommandDoc(fileName, markdown) {
812
773
  const commandName = fileName.charAt(0).toLowerCase() + fileName.slice(1);
@@ -820,17 +781,17 @@ function parseCommandDoc(fileName, markdown) {
820
781
  function errorCodeToClassName(code) {
821
782
  return code.toLowerCase().split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("") + "Error";
822
783
  }
823
- function isHeading(node) {
784
+ function isHeading$1(node) {
824
785
  return node.type === "heading";
825
786
  }
826
787
  function isList(node) {
827
788
  return node.type === "list";
828
789
  }
829
- function getNodesUnderHeading(tree, headingText) {
790
+ function getNodesUnderHeading$1(tree, headingText) {
830
791
  const nodes = [];
831
792
  let collecting = false;
832
793
  for (const node of tree.children) {
833
- if (isHeading(node)) {
794
+ if (isHeading$1(node)) {
834
795
  if (collecting) break;
835
796
  if (node.depth === 2 && toString(node) === headingText) {
836
797
  collecting = true;
@@ -843,7 +804,7 @@ function getNodesUnderHeading(tree, headingText) {
843
804
  }
844
805
  const ERROR_PATTERN = /^([A-Z_]+):\s*(.+)$/;
845
806
  function parseErrorScenarios(tree) {
846
- const nodes = getNodesUnderHeading(tree, "Error Scenarios");
807
+ const nodes = getNodesUnderHeading$1(tree, "Error Scenarios");
847
808
  const errors = [];
848
809
  for (const node of nodes) {
849
810
  if (!isList(node)) continue;
@@ -860,7 +821,7 @@ function parseErrorScenarios(tree) {
860
821
  }
861
822
  const DEPENDENCY_PATTERN = /^([^:]+)::(.+)$/;
862
823
  function parseExternalDependencies(tree) {
863
- const nodes = getNodesUnderHeading(tree, "External Dependencies");
824
+ const nodes = getNodesUnderHeading$1(tree, "External Dependencies");
864
825
  const deps = [];
865
826
  for (const node of nodes) {
866
827
  if (!isList(node)) continue;
@@ -880,7 +841,7 @@ function parseExternalDependencies(tree) {
880
841
  return deps;
881
842
  }
882
843
  //#endregion
883
- //#region src/generator/generate-code.ts
844
+ //#region src/generator/generate-errors.ts
884
845
  function moduleNameToPrefix(moduleName) {
885
846
  return moduleName.toUpperCase().replace(/-/g, "_");
886
847
  }
@@ -906,9 +867,49 @@ import { createDomainError } from "../../../shared";
906
867
 
907
868
  ${lines.join("\n")}`;
908
869
  }
909
- function generateCommandStub(doc) {
910
- const inputType = `${doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1)}Input`;
911
- return `import { ok, type CommandContext } from "../../../shared";
870
+ //#endregion
871
+ //#region src/generator/generate-permissions.ts
872
+ function generatePermissions(moduleName, commandNames) {
873
+ return `// @generated — do not edit
874
+ import { definePermissions } from "../../../shared";
875
+
876
+ export const { permissions, own, all } = definePermissions("${moduleName}", [
877
+ ${[...commandNames].sort().map((name) => ` "${name}",`).join("\n")}
878
+ ] as const);
879
+ `;
880
+ }
881
+ //#endregion
882
+ //#region src/generator/generate-shells.ts
883
+ function generateCommandShell(doc) {
884
+ return [
885
+ `// @generated — do not edit`,
886
+ `import { defineCommand } from "../../../shared";`,
887
+ `import { permissions } from "../lib/permissions.generated";`,
888
+ `import { run } from "./${doc.commandName}";`,
889
+ ``,
890
+ `export const ${doc.commandName} = defineCommand(permissions.${doc.commandName}, run);`,
891
+ ``
892
+ ].join("\n");
893
+ }
894
+ function generateQueryShell(doc) {
895
+ return [
896
+ `// @generated — do not edit`,
897
+ `import { defineQuery } from "../../../shared";`,
898
+ `import { run } from "./${doc.commandName}";`,
899
+ ``,
900
+ `export const ${doc.commandName} = defineQuery(run);`,
901
+ ``
902
+ ].join("\n");
903
+ }
904
+ //#endregion
905
+ //#region src/generator/stub-templates.ts
906
+ function toPascal(name) {
907
+ return name.charAt(0).toUpperCase() + name.slice(1);
908
+ }
909
+ const templates = {
910
+ command: { render: (name) => {
911
+ const inputType = `${toPascal(name)}Input`;
912
+ return `import { ok, type CommandContext } from "../../../shared";
912
913
  import type { Transaction } from "../generated/kysely-tailordb";
913
914
 
914
915
  export interface ${inputType} {
@@ -920,19 +921,19 @@ export async function run(db: Transaction, input: ${inputType}, ctx: CommandCont
920
921
  return ok({});
921
922
  }
922
923
  `;
923
- }
924
- function generateTestStub(doc) {
925
- const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
926
- return `import { describe, expect, it } from "vitest";
924
+ } },
925
+ commandTest: { render: (name) => {
926
+ const pascal = toPascal(name);
927
+ return `import { describe, expect, it } from "vitest";
927
928
  import { createMockDb } from "../../../testing/index";
928
929
  import type { CommandContext } from "../../../shared";
929
930
  import type { Transaction } from "../generated/kysely-tailordb";
930
- import { run, ${pascal}Input } from "./${doc.commandName}";
931
+ import { run, ${pascal}Input } from "./${name}";
931
932
 
932
- describe("${doc.commandName} - test scenario", () => {
933
+ describe("${name} - test scenario", () => {
933
934
  const ctx: CommandContext = {
934
935
  actorId: "test-actor",
935
- permissions: ["TODO:${doc.commandName}"],
936
+ permissions: ["TODO:${name}"],
936
937
  };
937
938
 
938
939
  it("should be implemented", async () => {
@@ -942,31 +943,10 @@ describe("${doc.commandName} - test scenario", () => {
942
943
  });
943
944
  });
944
945
  `;
945
- }
946
- function generateCommandShell(doc) {
947
- return [
948
- `// @generated do not edit`,
949
- `import { defineCommand } from "../../../shared";`,
950
- `import { permissions } from "../lib/permissions.generated";`,
951
- `import { run } from "./${doc.commandName}";`,
952
- ``,
953
- `export const ${doc.commandName} = defineCommand(permissions.${doc.commandName}, run);`,
954
- ``
955
- ].join("\n");
956
- }
957
- function generateQueryShell(doc) {
958
- return [
959
- `// @generated — do not edit`,
960
- `import { defineQuery } from "../../../shared";`,
961
- `import { run } from "./${doc.commandName}";`,
962
- ``,
963
- `export const ${doc.commandName} = defineQuery(run);`,
964
- ``
965
- ].join("\n");
966
- }
967
- function generateQueryStub(doc) {
968
- const inputType = `${doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1)}Input`;
969
- return `import type { ReadonlyDB } from "../../../shared";
946
+ } },
947
+ query: { render: (name) => {
948
+ const inputType = `${toPascal(name)}Input`;
949
+ return `import type { ReadonlyDB } from "../../../shared";
970
950
  import type { DB } from "../generated/kysely-tailordb";
971
951
 
972
952
  export interface ${inputType} {
@@ -978,15 +958,15 @@ export async function run(db: ReadonlyDB<DB>, input: ${inputType}) {
978
958
  return {};
979
959
  }
980
960
  `;
981
- }
982
- function generateQueryTestStub(doc) {
983
- const inputType = `${doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1)}Input`;
984
- return `import { describe, expect, it } from "vitest";
961
+ } },
962
+ queryTest: { render: (name) => {
963
+ const inputType = `${toPascal(name)}Input`;
964
+ return `import { describe, expect, it } from "vitest";
985
965
  import { createMockDb } from "../../../testing/index";
986
966
  import type { DB } from "../generated/kysely-tailordb";
987
- import { run, type ${inputType} } from "./${doc.commandName}";
967
+ import { run, type ${inputType} } from "./${name}";
988
968
 
989
- describe("${doc.commandName}", () => {
969
+ describe("${name}", () => {
990
970
  it("should be implemented", async () => {
991
971
  const { db } = createMockDb<DB>();
992
972
  const result = await run(db, {} as ${inputType});
@@ -994,28 +974,140 @@ describe("${doc.commandName}", () => {
994
974
  });
995
975
  });
996
976
  `;
997
- }
998
- function generatePermissions(moduleName, commandNames) {
999
- return `// @generated do not edit
1000
- import { definePermissions } from "../../../shared";
977
+ } },
978
+ db: { render: (name) => {
979
+ return `import { db, unsafeAllowAllGqlPermission, unsafeAllowAllTypePermission } from "@tailor-platform/sdk";
1001
980
 
1002
- export const { permissions, own, all } = definePermissions("${moduleName}", [
1003
- ${[...commandNames].sort().map((name) => ` "${name}",`).join("\n")}
1004
- ] as const);
981
+ export const ${name} = db
982
+ .type("${toPascal(name)}", {
983
+ // TODO: define fields
984
+ ...db.fields.timestamps(),
985
+ })
986
+ .permission(unsafeAllowAllTypePermission)
987
+ .gqlPermission(unsafeAllowAllGqlPermission);
988
+ `;
989
+ } },
990
+ resolver: { render: (name) => {
991
+ return `import { createResolver, t } from "@tailor-platform/sdk";
992
+ import { createContext } from "@tailor-platform/erp-kit/app";
993
+ import { getDB } from "@/generated/kysely-tailordb";
994
+
995
+ export default createResolver({
996
+ name: "${name}",
997
+ operation: "mutation",
998
+ input: {
999
+ // TODO: define input fields
1000
+ },
1001
+ body: async (context) => {
1002
+ const db = getDB("main-db");
1003
+ return db.transaction().execute(async (trx) => {
1004
+ // TODO: implement
1005
+ return {};
1006
+ });
1007
+ },
1008
+ output: t
1009
+ .object({
1010
+ // TODO: define output fields
1011
+ })
1012
+ .description("${toPascal(name)} response"),
1013
+ });
1014
+ `;
1015
+ } },
1016
+ resolverTest: { render: (name) => {
1017
+ return `import { describe, expect, it } from "vitest";
1018
+
1019
+ describe("${name}", () => {
1020
+ it("should be implemented", async () => {
1021
+ const resolver = await import("./${name}");
1022
+ expect(resolver.default).toBeDefined();
1023
+ expect(resolver.default.name).toBe("${name}");
1024
+ });
1025
+ });
1005
1026
  `;
1027
+ } }
1028
+ };
1029
+ function renderStub(type, name) {
1030
+ return templates[type].render(name);
1031
+ }
1032
+ //#endregion
1033
+ //#region src/generator/generate-stubs.ts
1034
+ function generateCommandStub(doc) {
1035
+ return renderStub("command", doc.commandName);
1036
+ }
1037
+ function generateTestStub(doc) {
1038
+ return renderStub("commandTest", doc.commandName);
1039
+ }
1040
+ function generateQueryStub(doc) {
1041
+ return renderStub("query", doc.commandName);
1042
+ }
1043
+ function generateQueryTestStub(doc) {
1044
+ return renderStub("queryTest", doc.commandName);
1045
+ }
1046
+ function generateDbStub(modelName) {
1047
+ return renderStub("db", modelName);
1006
1048
  }
1049
+ function generateResolverStub(resolverName) {
1050
+ return renderStub("resolver", resolverName);
1051
+ }
1052
+ function generateResolverTestStub(resolverName) {
1053
+ return renderStub("resolverTest", resolverName);
1054
+ }
1055
+ //#endregion
1056
+ //#region src/generator/scaffold.ts
1057
+ function copyTemplateDir(srcDir, destDir, replacements, placeholderFiles) {
1058
+ for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
1059
+ const srcPath = path.join(srcDir, entry.name);
1060
+ const destName = entry.name === "__dot__gitignore" ? ".gitignore" : entry.name;
1061
+ const destPath = path.join(destDir, destName);
1062
+ if (entry.name === "node_modules") continue;
1063
+ if (entry.isDirectory()) {
1064
+ fs.mkdirSync(destPath, { recursive: true });
1065
+ copyTemplateDir(srcPath, destPath, replacements, placeholderFiles);
1066
+ } else {
1067
+ if (fs.existsSync(destPath)) continue;
1068
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
1069
+ if (placeholderFiles.has(entry.name)) {
1070
+ let content = fs.readFileSync(srcPath, "utf-8");
1071
+ for (const [from, to] of Object.entries(replacements)) content = content.replaceAll(from, to);
1072
+ fs.writeFileSync(destPath, content);
1073
+ } else fs.copyFileSync(srcPath, destPath);
1074
+ }
1075
+ }
1076
+ }
1077
+ function scaffoldModuleBoilerplate(moduleDir, moduleName) {
1078
+ copyTemplateDir(path.join(PACKAGE_ROOT, "templates", "scaffold", "module"), moduleDir, { "template-module": moduleName }, new Set(["permissions.ts", "tailor.config.ts"]));
1079
+ }
1080
+ function scaffoldAppBoilerplate(appDir, appName) {
1081
+ const templateDir = path.join(PACKAGE_ROOT, "templates", "scaffold", "app");
1082
+ const erpKitVersion = readErpKitVersion();
1083
+ copyTemplateDir(templateDir, appDir, {
1084
+ "template-app-frontend": `${appName}-frontend`,
1085
+ "template-app-backend": appName,
1086
+ "template-app": appName,
1087
+ "\"workspace:*\"": `"${erpKitVersion}"`
1088
+ }, new Set([
1089
+ "package.json",
1090
+ "tailor.config.ts",
1091
+ "index.html"
1092
+ ]));
1093
+ }
1094
+ //#endregion
1095
+ //#region src/generator/generate-code.ts
1007
1096
  function runGenerateCode(modulePath, moduleName) {
1097
+ scaffoldModuleBoilerplate(modulePath, moduleName);
1008
1098
  const docsDir = path.join(modulePath, "docs", "commands");
1009
1099
  const libDir = path.join(modulePath, "lib");
1010
1100
  const commandDir = path.join(modulePath, "command");
1011
1101
  if (!fs.existsSync(docsDir)) {
1012
- console.error(`No docs/commands/ directory found at ${docsDir}`);
1013
- return 1;
1102
+ console.log(`No docs/commands/ directory found skipping code generation`);
1103
+ console.log(`Generated boilerplate for ${moduleName}`);
1104
+ return 0;
1014
1105
  }
1015
1106
  const mdFiles = fs.readdirSync(docsDir).filter((f) => f.endsWith(".md"));
1016
1107
  if (mdFiles.length === 0) {
1017
- console.error(`No command docs found in ${docsDir}`);
1018
- return 1;
1108
+ console.log(`No command docs found skipping code generation`);
1109
+ console.log(`Generated boilerplate for ${moduleName}`);
1110
+ return 0;
1019
1111
  }
1020
1112
  const parsedDocs = [];
1021
1113
  for (const file of mdFiles) {
@@ -1090,149 +1182,404 @@ function runGenerateCode(modulePath, moduleName) {
1090
1182
  }
1091
1183
  }
1092
1184
  }
1185
+ const modelDocsDir = path.join(modulePath, "docs", "models");
1186
+ if (fs.existsSync(modelDocsDir)) {
1187
+ const modelFiles = fs.readdirSync(modelDocsDir).filter((f) => f.endsWith(".md"));
1188
+ if (modelFiles.length > 0) {
1189
+ const dbDir = path.join(modulePath, "db");
1190
+ fs.mkdirSync(dbDir, { recursive: true });
1191
+ for (const file of modelFiles) {
1192
+ const modelName = path.basename(file, ".md");
1193
+ const camelName = modelName.charAt(0).toLowerCase() + modelName.slice(1);
1194
+ const dbFile = path.join(dbDir, `${camelName}.ts`);
1195
+ if (!fs.existsSync(dbFile)) {
1196
+ fs.writeFileSync(dbFile, generateDbStub(camelName));
1197
+ console.log(` scaffolded ${path.relative(modulePath, dbFile)}`);
1198
+ }
1199
+ }
1200
+ }
1201
+ }
1093
1202
  console.log(`Generated ${generated} file(s) for ${moduleName}`);
1094
1203
  return 0;
1095
1204
  }
1096
1205
  //#endregion
1206
+ //#region src/commands/generate-doc.ts
1207
+ const MODULE_DOC_TYPES = [
1208
+ "feature",
1209
+ "command",
1210
+ "model",
1211
+ "query"
1212
+ ];
1213
+ const APP_DOC_TYPES = [
1214
+ "actors",
1215
+ "business-flow",
1216
+ "story",
1217
+ "screen",
1218
+ "resolver"
1219
+ ];
1220
+ [...MODULE_DOC_TYPES, ...APP_DOC_TYPES];
1221
+ const MODULE_DIR_MAP = {
1222
+ feature: MODULE_PATHS.docs.features,
1223
+ command: MODULE_PATHS.docs.commands,
1224
+ model: MODULE_PATHS.docs.models,
1225
+ query: MODULE_PATHS.docs.queries
1226
+ };
1227
+ const APP_DIR_MAP = {
1228
+ actors: APP_PATHS.docs.actors,
1229
+ "business-flow": APP_PATHS.docs.businessFlow,
1230
+ screen: APP_PATHS.docs.screen,
1231
+ resolver: APP_PATHS.docs.resolver
1232
+ };
1233
+ function resolveDocPath(type, name, modulePath) {
1234
+ if (!name) throw new Error(`Name is required for doc type "${type}"`);
1235
+ if (type === "business-flow") return path.join(modulePath, APP_PATHS.docs.businessFlow, name, "README.md");
1236
+ if (type === "story") {
1237
+ const parts = name.split("/");
1238
+ if (parts.length !== 2) throw new Error(`Story name must be "<flow>/<story>" (e.g., "onboarding/admin--create-user")`);
1239
+ return path.join(modulePath, APP_PATHS.docs.businessFlow, parts[0], APP_PATHS.storySegment, `${parts[1]}.md`);
1240
+ }
1241
+ if (MODULE_DIR_MAP[type]) return path.join(modulePath, MODULE_DIR_MAP[type], `${name}.md`);
1242
+ if (APP_DIR_MAP[type]) return path.join(modulePath, APP_DIR_MAP[type], `${name}.md`);
1243
+ throw new Error(`Unknown doc type: ${type}`);
1244
+ }
1245
+ async function runGenerateDoc(type, name, modulePath, cwd) {
1246
+ const outputPath = resolveDocPath(type, name, modulePath);
1247
+ const absoluteOutput = path.resolve(cwd, outputPath);
1248
+ if (fs.existsSync(absoluteOutput)) {
1249
+ console.error(`File already exists: ${outputPath}`);
1250
+ return 1;
1251
+ }
1252
+ const schemaPath = ALL_SCHEMAS[type];
1253
+ if (!schemaPath) {
1254
+ console.error(`No schema found for type: ${type}`);
1255
+ return 2;
1256
+ }
1257
+ try {
1258
+ fs.mkdirSync(path.dirname(absoluteOutput), { recursive: true });
1259
+ } catch (err) {
1260
+ console.error(`Failed to create directory: ${err instanceof Error ? err.message : String(err)}`);
1261
+ return 1;
1262
+ }
1263
+ const { exitCode, stdout, stderr } = await runMdschema([
1264
+ "generate",
1265
+ "--schema",
1266
+ schemaPath,
1267
+ "--output",
1268
+ absoluteOutput
1269
+ ], cwd);
1270
+ if (stdout.trim()) console.log(stdout);
1271
+ if (stderr.trim()) console.error(stderr);
1272
+ return exitCode;
1273
+ }
1274
+ //#endregion
1097
1275
  //#region src/commands/module/generate.ts
1098
1276
  const cwd$3 = process.cwd();
1099
- const generateCommand = defineCommand({
1277
+ const pathArgs$2 = z.object({ path: arg(z.string(), {
1278
+ alias: "p",
1279
+ description: "Path to the module directory"
1280
+ }) });
1281
+ const generateCommand$1 = defineCommand({
1100
1282
  name: "generate",
1101
- description: "Generate code from model definitions and docs",
1102
- subCommands: { code: defineCommand({
1103
- name: "code",
1104
- description: "Generate errors, permissions, command shells, and query shells from docs",
1105
- args: z.object({
1106
- root: arg(z.string(), {
1107
- alias: "r",
1108
- description: "Path to modules directory"
1283
+ description: "Generate docs and code for a module",
1284
+ subCommands: {
1285
+ doc: defineCommand({
1286
+ name: "doc",
1287
+ description: "Create a documentation file from a schema template",
1288
+ args: pathArgs$2.extend({
1289
+ type: arg(z.enum(MODULE_DOC_TYPES), {
1290
+ positional: true,
1291
+ description: `Doc type (${MODULE_DOC_TYPES.join(", ")})`
1292
+ }),
1293
+ name: arg(z.string().optional(), {
1294
+ positional: true,
1295
+ description: "Item name (required for all types)"
1296
+ })
1109
1297
  }),
1110
- module: arg(z.string(), {
1111
- positional: true,
1112
- description: "Module name (e.g., primitives, item-management)"
1113
- })
1298
+ run: (args) => {
1299
+ return executeCommand(async () => {
1300
+ const exitCode = await runGenerateDoc(args.type, args.name, args.path, cwd$3);
1301
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1302
+ });
1303
+ }
1114
1304
  }),
1115
- run: (args) => {
1116
- const modulePath = path.resolve(cwd$3, args.root, args.module);
1117
- console.log(`Generating code for ${args.module}...`);
1118
- const exitCode = runGenerateCode(modulePath, args.module);
1119
- process.exit(exitCode);
1120
- }
1121
- }) }
1305
+ code: defineCommand({
1306
+ name: "code",
1307
+ description: "Generate boilerplate, implementation stubs, and generated code from docs",
1308
+ args: pathArgs$2,
1309
+ run: (args) => {
1310
+ return executeCommand(() => {
1311
+ const modulePath = path.resolve(cwd$3, args.path);
1312
+ const moduleName = path.basename(modulePath);
1313
+ console.log(`Generating code for ${moduleName}...`);
1314
+ const exitCode = runGenerateCode(modulePath, moduleName);
1315
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1316
+ });
1317
+ }
1318
+ })
1319
+ }
1122
1320
  });
1123
1321
  //#endregion
1124
1322
  //#region src/commands/module/index.ts
1125
1323
  const cwd$2 = process.cwd();
1126
- const rootArgs$1 = z.object({ root: arg(z.string(), {
1127
- alias: "r",
1324
+ const pathArgs$1 = z.object({ path: arg(z.string(), {
1325
+ alias: "p",
1128
1326
  description: "Path to modules directory"
1129
1327
  }) });
1130
- const listCommand = defineCommand({
1131
- name: "list",
1132
- description: "List available modules",
1133
- run: () => {
1134
- const exitCode = runModuleList();
1135
- process.exit(exitCode);
1136
- }
1137
- });
1138
1328
  const checkCommand$1 = defineCommand({
1139
1329
  name: "check",
1140
1330
  description: "Validate module docs against schemas",
1141
- args: rootArgs$1,
1142
- run: async (args) => {
1143
- const exitCode = await runCheck({ modulesRoot: args.root }, cwd$2);
1144
- process.exit(exitCode);
1331
+ args: pathArgs$1,
1332
+ run: (args) => {
1333
+ return executeCommand(async () => {
1334
+ const exitCode = await runCheck({ modulesRoot: args.path }, cwd$2);
1335
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1336
+ });
1145
1337
  }
1146
1338
  });
1147
1339
  const syncCheckCommand$1 = defineCommand({
1148
1340
  name: "sync-check",
1149
1341
  description: "Validate source <-> doc correspondence",
1150
- args: rootArgs$1,
1151
- run: async (args) => {
1152
- const result = await runSyncCheck({ modulesRoot: args.root }, cwd$2);
1153
- console.log(formatSyncCheckReport(result));
1154
- process.exit(result.exitCode);
1342
+ args: pathArgs$1,
1343
+ run: (args) => {
1344
+ return executeCommand(async () => {
1345
+ const result = await runSyncCheck({ modulesRoot: args.path }, cwd$2);
1346
+ console.log(formatSyncCheckReport(result));
1347
+ return result.exitCode === 0 ? success() : silentFailure(result.exitCode);
1348
+ });
1155
1349
  }
1156
1350
  });
1157
- const scaffoldCommand$1 = defineCommand({
1158
- name: "scaffold",
1159
- description: "Generate module doc from schema template",
1160
- args: rootArgs$1.extend({
1161
- type: arg(z.enum(MODULE_TYPES), {
1162
- positional: true,
1163
- description: `Scaffold type (${MODULE_TYPES.join(", ")})`
1164
- }),
1165
- parent: arg(z.string(), {
1351
+ const initCommand$2 = defineCommand({
1352
+ name: "init",
1353
+ description: "Bootstrap a new module with directory structure and README",
1354
+ args: z.object({
1355
+ name: arg(z.string(), {
1166
1356
  positional: true,
1167
1357
  description: "Module name"
1168
1358
  }),
1169
- name: arg(z.string().optional(), {
1359
+ dir: arg(z.string(), {
1170
1360
  positional: true,
1171
- description: "Item name (required for feature, command, model)"
1361
+ description: "Parent directory where the module will be created"
1172
1362
  })
1173
1363
  }),
1174
- run: async (args) => {
1175
- const exitCode = await runScaffold(args.type, args.parent, args.name, args.root, cwd$2);
1176
- process.exit(exitCode);
1364
+ run: (args) => {
1365
+ return executeCommand(async () => {
1366
+ const exitCode = await runInitModuleWithReadme(args.name, args.dir, cwd$2);
1367
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1368
+ });
1177
1369
  }
1178
1370
  });
1179
- const moduleCommand = defineCommand({
1371
+ const moduleCommand$1 = defineCommand({
1180
1372
  name: "module",
1181
1373
  description: "Module management",
1182
1374
  subCommands: {
1183
- list: listCommand,
1184
1375
  check: checkCommand$1,
1185
1376
  "sync-check": syncCheckCommand$1,
1186
- scaffold: scaffoldCommand$1,
1187
- generate: generateCommand
1377
+ init: initCommand$2,
1378
+ generate: generateCommand$1
1188
1379
  }
1189
1380
  });
1190
1381
  //#endregion
1382
+ //#region src/generator/parse-resolver-doc.ts
1383
+ const MODULE_COMMAND_PATTERN = /([a-z][\w-]*)\.(\w+)/;
1384
+ const TABLE_ROW_PATTERN = /^\|(.+)\|(.+)\|$/;
1385
+ function parseResolverDoc(fileName, markdown) {
1386
+ return {
1387
+ resolverName: fileName.charAt(0).toLowerCase() + fileName.slice(1),
1388
+ moduleCommands: parseModuleCommands(fromMarkdown(markdown)),
1389
+ errors: parseExceptionHandlingFromRaw(markdown)
1390
+ };
1391
+ }
1392
+ function isHeading(node) {
1393
+ return node.type === "heading";
1394
+ }
1395
+ function getNodesUnderHeading(tree, headingText) {
1396
+ const nodes = [];
1397
+ let collecting = false;
1398
+ for (const node of tree.children) {
1399
+ if (isHeading(node)) {
1400
+ if (collecting) break;
1401
+ if (node.depth === 2 && toString(node) === headingText) {
1402
+ collecting = true;
1403
+ continue;
1404
+ }
1405
+ }
1406
+ if (collecting) nodes.push(node);
1407
+ }
1408
+ return nodes;
1409
+ }
1410
+ function parseModuleCommands(tree) {
1411
+ const nodes = getNodesUnderHeading(tree, "Modules Commands Used");
1412
+ const commands = [];
1413
+ for (const node of nodes) {
1414
+ if (node.type !== "list") continue;
1415
+ for (const item of node.children) {
1416
+ const text = toString(item);
1417
+ const match = MODULE_COMMAND_PATTERN.exec(text);
1418
+ if (match) commands.push({
1419
+ module: match[1],
1420
+ command: match[2]
1421
+ });
1422
+ }
1423
+ }
1424
+ return commands;
1425
+ }
1426
+ function parseExceptionHandlingFromRaw(markdown) {
1427
+ const lines = markdown.split("\n");
1428
+ const errors = [];
1429
+ let inSection = false;
1430
+ let headerSkipped = false;
1431
+ let separatorSkipped = false;
1432
+ for (const line of lines) {
1433
+ const trimmed = line.trim();
1434
+ if (trimmed.startsWith("## Exception Handling")) {
1435
+ inSection = true;
1436
+ continue;
1437
+ }
1438
+ if (!inSection) continue;
1439
+ if (trimmed.startsWith("#")) break;
1440
+ if (!trimmed) continue;
1441
+ const match = TABLE_ROW_PATTERN.exec(trimmed);
1442
+ if (!match) continue;
1443
+ if (!headerSkipped) {
1444
+ headerSkipped = true;
1445
+ continue;
1446
+ }
1447
+ if (!separatorSkipped) {
1448
+ separatorSkipped = true;
1449
+ continue;
1450
+ }
1451
+ const code = match[1].trim();
1452
+ const description = match[2].trim();
1453
+ if (code) errors.push({
1454
+ code,
1455
+ description
1456
+ });
1457
+ }
1458
+ return errors;
1459
+ }
1460
+ //#endregion
1461
+ //#region src/generator/generate-app-code.ts
1462
+ function runGenerateAppCode(appPath) {
1463
+ const appName = path.basename(appPath);
1464
+ scaffoldAppBoilerplate(appPath, appName);
1465
+ const docsDir = path.join(appPath, "docs", "resolver");
1466
+ const resolverDir = path.join(appPath, "backend", "src", "resolvers");
1467
+ if (!fs.existsSync(docsDir)) {
1468
+ console.log(`No docs/resolver/ directory found — skipping resolver generation`);
1469
+ console.log(`Generated boilerplate for ${appName}`);
1470
+ return 0;
1471
+ }
1472
+ const mdFiles = fs.readdirSync(docsDir).filter((f) => f.endsWith(".md"));
1473
+ if (mdFiles.length === 0) {
1474
+ console.log(`No resolver docs found — skipping resolver generation`);
1475
+ console.log(`Generated boilerplate for ${appName}`);
1476
+ return 0;
1477
+ }
1478
+ fs.mkdirSync(resolverDir, { recursive: true });
1479
+ let generated = 0;
1480
+ for (const file of mdFiles) {
1481
+ const content = fs.readFileSync(path.join(docsDir, file), "utf-8");
1482
+ const doc = parseResolverDoc(path.basename(file, ".md"), content);
1483
+ const implFile = path.join(resolverDir, `${doc.resolverName}.ts`);
1484
+ if (!fs.existsSync(implFile)) {
1485
+ fs.writeFileSync(implFile, generateResolverStub(doc.resolverName));
1486
+ console.log(` scaffolded ${path.relative(appPath, implFile)}`);
1487
+ generated++;
1488
+ }
1489
+ const testFile = path.join(resolverDir, `${doc.resolverName}.test.ts`);
1490
+ if (!fs.existsSync(testFile)) {
1491
+ fs.writeFileSync(testFile, generateResolverTestStub(doc.resolverName));
1492
+ console.log(` scaffolded ${path.relative(appPath, testFile)}`);
1493
+ }
1494
+ }
1495
+ console.log(`Scaffolded ${generated} resolver(s) for ${appName}`);
1496
+ return 0;
1497
+ }
1498
+ //#endregion
1191
1499
  //#region src/commands/app/index.ts
1192
1500
  const cwd$1 = process.cwd();
1193
- const rootArgs = z.object({ root: arg(z.string(), {
1194
- alias: "r",
1501
+ const pathArgs = z.object({ path: arg(z.string(), {
1502
+ alias: "p",
1195
1503
  description: "Path to app-compose directory"
1196
1504
  }) });
1197
1505
  const checkCommand = defineCommand({
1198
1506
  name: "check",
1199
1507
  description: "Validate app docs against schemas",
1200
- args: rootArgs,
1201
- run: async (args) => {
1202
- const exitCode = await runCheck({ appRoot: args.root }, cwd$1);
1203
- process.exit(exitCode);
1508
+ args: pathArgs,
1509
+ run: (args) => {
1510
+ return executeCommand(async () => {
1511
+ const exitCode = await runCheck({ appRoot: args.path }, cwd$1);
1512
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1513
+ });
1204
1514
  }
1205
1515
  });
1206
1516
  const syncCheckCommand = defineCommand({
1207
1517
  name: "sync-check",
1208
1518
  description: "Validate source <-> doc correspondence",
1209
- args: rootArgs,
1210
- run: async (args) => {
1211
- const result = await runSyncCheck({ appRoot: args.root }, cwd$1);
1212
- console.log(formatSyncCheckReport(result));
1213
- process.exit(result.exitCode);
1519
+ args: pathArgs,
1520
+ run: (args) => {
1521
+ return executeCommand(async () => {
1522
+ const result = await runSyncCheck({ appRoot: args.path }, cwd$1);
1523
+ console.log(formatSyncCheckReport(result));
1524
+ return result.exitCode === 0 ? success() : silentFailure(result.exitCode);
1525
+ });
1214
1526
  }
1215
1527
  });
1216
- const scaffoldCommand = defineCommand({
1217
- name: "scaffold",
1218
- description: "Generate app doc from schema template",
1219
- args: rootArgs.extend({
1220
- type: arg(z.enum(APP_TYPES), {
1221
- positional: true,
1222
- description: `Scaffold type (${APP_TYPES.join(", ")})`
1223
- }),
1224
- parent: arg(z.string(), {
1528
+ const initCommand$1 = defineCommand({
1529
+ name: "init",
1530
+ description: "Bootstrap a new app with directory structure and README",
1531
+ args: z.object({
1532
+ name: arg(z.string(), {
1225
1533
  positional: true,
1226
1534
  description: "App name"
1227
1535
  }),
1228
- name: arg(z.string().optional(), {
1536
+ dir: arg(z.string(), {
1229
1537
  positional: true,
1230
- description: "Item name (required for most types)"
1538
+ description: "Parent directory where the app will be created"
1231
1539
  })
1232
1540
  }),
1233
- run: async (args) => {
1234
- const exitCode = await runScaffold(args.type, args.parent, args.name, args.root, cwd$1);
1235
- process.exit(exitCode);
1541
+ run: (args) => {
1542
+ return executeCommand(async () => {
1543
+ const exitCode = await runInitAppWithReadme(args.name, args.dir, cwd$1);
1544
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1545
+ });
1546
+ }
1547
+ });
1548
+ const generateCommand = defineCommand({
1549
+ name: "generate",
1550
+ description: "Generate docs and code for an app",
1551
+ subCommands: {
1552
+ doc: defineCommand({
1553
+ name: "doc",
1554
+ description: "Create a documentation file from a schema template",
1555
+ args: pathArgs.extend({
1556
+ type: arg(z.enum(APP_DOC_TYPES), {
1557
+ positional: true,
1558
+ description: `Doc type (${APP_DOC_TYPES.join(", ")})`
1559
+ }),
1560
+ name: arg(z.string().optional(), {
1561
+ positional: true,
1562
+ description: "Item name (required for most types)"
1563
+ })
1564
+ }),
1565
+ run: (args) => {
1566
+ return executeCommand(async () => {
1567
+ const exitCode = await runGenerateDoc(args.type, args.name, args.path, cwd$1);
1568
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1569
+ });
1570
+ }
1571
+ }),
1572
+ code: defineCommand({
1573
+ name: "code",
1574
+ description: "Generate boilerplate source files from docs",
1575
+ args: pathArgs,
1576
+ run: (args) => {
1577
+ return executeCommand(() => {
1578
+ const exitCode = runGenerateAppCode(path.resolve(cwd$1, args.path));
1579
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1580
+ });
1581
+ }
1582
+ })
1236
1583
  }
1237
1584
  });
1238
1585
  const appCommand = defineCommand({
@@ -1241,7 +1588,8 @@ const appCommand = defineCommand({
1241
1588
  subCommands: {
1242
1589
  check: checkCommand,
1243
1590
  "sync-check": syncCheckCommand,
1244
- scaffold: scaffoldCommand
1591
+ init: initCommand$1,
1592
+ generate: generateCommand
1245
1593
  }
1246
1594
  });
1247
1595
  //#endregion
@@ -1527,9 +1875,11 @@ const mockCommand = defineCommand({
1527
1875
  description: "Filter by provider or provider/scenario"
1528
1876
  })
1529
1877
  }),
1530
- run: async (args) => {
1531
- const exitCode = await runMockStart(args.mocksRoot, args.filter, args.port);
1532
- process.exit(exitCode);
1878
+ run: (args) => {
1879
+ return executeCommand(async () => {
1880
+ const exitCode = await runMockStart(args.mocksRoot, args.filter, args.port);
1881
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1882
+ });
1533
1883
  }
1534
1884
  }),
1535
1885
  validate: defineCommand({
@@ -1542,9 +1892,290 @@ const mockCommand = defineCommand({
1542
1892
  description: "Specific scenario paths to validate"
1543
1893
  })
1544
1894
  }),
1545
- run: async (args) => {
1546
- const exitCode = await runMockValidate(args.mocksRoot, args.paths);
1547
- process.exit(exitCode);
1895
+ run: (args) => {
1896
+ return executeCommand(async () => {
1897
+ const exitCode = await runMockValidate(args.mocksRoot, args.paths);
1898
+ return exitCode === 0 ? success() : silentFailure(exitCode);
1899
+ });
1900
+ }
1901
+ })
1902
+ }
1903
+ });
1904
+ //#endregion
1905
+ //#region src/commands/doc/modules.ts
1906
+ const MODULES_DIR$2 = join(PACKAGE_ROOT, "src", "modules");
1907
+ const EXCLUDED_DIRS$2 = new Set(["shared", "testing"]);
1908
+ function countDocs(dir) {
1909
+ if (!existsSync(dir)) return 0;
1910
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).length;
1911
+ }
1912
+ function extractOverview(readmePath) {
1913
+ if (!existsSync(readmePath)) return "";
1914
+ const content = readFileSync(readmePath, "utf-8");
1915
+ const overviewMatch = /## Overview\n\n([\s\S]*?)(?=\n##\s|\n$)/.exec(content);
1916
+ if (!overviewMatch) return "";
1917
+ return overviewMatch[1].trim().split("\n\n")[0];
1918
+ }
1919
+ function extractDependencies(readmePath) {
1920
+ if (!existsSync(readmePath)) return [];
1921
+ const content = readFileSync(readmePath, "utf-8");
1922
+ const depsMatch = /## Module Dependencies\n\n([\s\S]*?)(?=\n##\s|$)/.exec(content);
1923
+ if (!depsMatch) return [];
1924
+ const deps = [];
1925
+ const linePattern = /^- \[([^\]]+)\]/;
1926
+ for (const line of depsMatch[1].trim().split("\n")) {
1927
+ const match = linePattern.exec(line);
1928
+ if (match) deps.push(match[1]);
1929
+ }
1930
+ return deps;
1931
+ }
1932
+ function getModuleOverviews() {
1933
+ if (!existsSync(MODULES_DIR$2)) return [];
1934
+ return readdirSync(MODULES_DIR$2, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DIRS$2.has(d.name)).map((d) => {
1935
+ const modDir = join(MODULES_DIR$2, d.name);
1936
+ const readmePath = join(modDir, "README.md");
1937
+ return {
1938
+ name: d.name,
1939
+ commandCount: countDocs(join(modDir, MODULE_PATHS.docs.commands)),
1940
+ queryCount: countDocs(join(modDir, MODULE_PATHS.docs.queries)),
1941
+ modelCount: countDocs(join(modDir, MODULE_PATHS.docs.models)),
1942
+ overview: extractOverview(readmePath),
1943
+ dependencies: extractDependencies(readmePath)
1944
+ };
1945
+ }).sort((a, b) => a.name.localeCompare(b.name));
1946
+ }
1947
+ function formatModuleOverviews(modules) {
1948
+ if (modules.length === 0) return "No modules found.";
1949
+ const lines = [];
1950
+ for (const mod of modules) {
1951
+ const counts = [
1952
+ `${mod.commandCount} commands`,
1953
+ `${mod.queryCount} queries`,
1954
+ `${mod.modelCount} models`
1955
+ ].join(", ");
1956
+ lines.push(`# ${mod.name} (${counts})`);
1957
+ if (mod.overview) lines.push(mod.overview);
1958
+ if (mod.dependencies.length > 0) lines.push(`Dependencies: ${mod.dependencies.join(", ")}`);
1959
+ else lines.push("Dependencies: none");
1960
+ lines.push("");
1961
+ }
1962
+ lines.push(`${modules.length} modules`);
1963
+ return lines.join("\n");
1964
+ }
1965
+ function runDocModules(format = "text") {
1966
+ const modules = getModuleOverviews();
1967
+ if (format === "json") console.log(JSON.stringify(modules, null, 2));
1968
+ else console.log(formatModuleOverviews(modules));
1969
+ return 0;
1970
+ }
1971
+ //#endregion
1972
+ //#region src/commands/doc/module.ts
1973
+ const MODULES_DIR$1 = join(PACKAGE_ROOT, "src", "modules");
1974
+ const EXCLUDED_DIRS$1 = new Set(["shared", "testing"]);
1975
+ const DOC_TYPE_MAP$1 = {
1976
+ command: MODULE_PATHS.docs.commands,
1977
+ query: MODULE_PATHS.docs.queries,
1978
+ model: MODULE_PATHS.docs.models,
1979
+ feature: MODULE_PATHS.docs.features
1980
+ };
1981
+ function listDocNames(dir) {
1982
+ if (!existsSync(dir)) return [];
1983
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => f.replace(/\.md$/, "")).sort();
1984
+ }
1985
+ function formatDocList(type, names) {
1986
+ if (names.length === 0) return "";
1987
+ return `${type}: ${names.join(", ")}`;
1988
+ }
1989
+ function runDocModule(moduleName, docType, docName, format = "text") {
1990
+ if (!existsSync(MODULES_DIR$1) || EXCLUDED_DIRS$1.has(moduleName)) {
1991
+ console.error(`Module not found: ${moduleName}`);
1992
+ return 1;
1993
+ }
1994
+ const modDir = join(MODULES_DIR$1, moduleName);
1995
+ if (!existsSync(modDir)) {
1996
+ console.error(`Module not found: ${moduleName}`);
1997
+ const available = readdirSync(MODULES_DIR$1, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DIRS$1.has(d.name)).map((d) => d.name).sort();
1998
+ console.error(`Available modules: ${available.join(", ")}`);
1999
+ return 1;
2000
+ }
2001
+ if (docType && docName) {
2002
+ const docSubdir = DOC_TYPE_MAP$1[docType];
2003
+ if (!docSubdir) {
2004
+ console.error(`Unknown doc type: ${docType}`);
2005
+ console.error(`Available types: ${Object.keys(DOC_TYPE_MAP$1).join(", ")}`);
2006
+ return 1;
2007
+ }
2008
+ const docPath = join(modDir, docSubdir, `${docName}.md`);
2009
+ if (!existsSync(docPath)) {
2010
+ console.error(`Doc not found: ${moduleName}/${docType}/${docName}`);
2011
+ const available = listDocNames(join(modDir, docSubdir));
2012
+ if (available.length > 0) console.error(`Available ${docType}s: ${available.join(", ")}`);
2013
+ else console.error(`No ${docType} docs found for ${moduleName}`);
2014
+ return 1;
2015
+ }
2016
+ const content = readFileSync(docPath, "utf-8");
2017
+ if (format === "json") console.log(JSON.stringify({
2018
+ module: moduleName,
2019
+ type: docType,
2020
+ name: docName,
2021
+ content
2022
+ }, null, 2));
2023
+ else console.log(content);
2024
+ return 0;
2025
+ }
2026
+ const readmePath = join(modDir, "README.md");
2027
+ const readme = existsSync(readmePath) ? readFileSync(readmePath, "utf-8") : "";
2028
+ const docs = {};
2029
+ for (const [type, subdir] of Object.entries(DOC_TYPE_MAP$1)) {
2030
+ const names = listDocNames(join(modDir, subdir));
2031
+ if (names.length > 0) docs[type] = names;
2032
+ }
2033
+ if (format === "json") console.log(JSON.stringify({
2034
+ module: moduleName,
2035
+ readme,
2036
+ docs
2037
+ }, null, 2));
2038
+ else {
2039
+ if (readme) console.log(readme);
2040
+ else console.log(`# ${moduleName}\n\nNo README found.\n`);
2041
+ const sections = [];
2042
+ for (const [type, names] of Object.entries(docs)) sections.push(formatDocList(type, names));
2043
+ if (sections.length > 0) {
2044
+ console.log("\n## Available Documentation\n");
2045
+ console.log(sections.join("\n"));
2046
+ }
2047
+ }
2048
+ return 0;
2049
+ }
2050
+ //#endregion
2051
+ //#region src/commands/doc/search.ts
2052
+ const MODULES_DIR = join(PACKAGE_ROOT, "src", "modules");
2053
+ const EXCLUDED_DIRS = new Set(["shared", "testing"]);
2054
+ const DOC_TYPE_MAP = {
2055
+ command: MODULE_PATHS.docs.commands,
2056
+ query: MODULE_PATHS.docs.queries,
2057
+ model: MODULE_PATHS.docs.models,
2058
+ feature: MODULE_PATHS.docs.features
2059
+ };
2060
+ function searchFile(filePath, query, module, type, name) {
2061
+ if (!existsSync(filePath)) return [];
2062
+ const content = readFileSync(filePath, "utf-8");
2063
+ const lowerQuery = query.toLowerCase();
2064
+ const results = [];
2065
+ const lines = content.split("\n");
2066
+ for (let i = 0; i < lines.length; i++) if (lines[i].toLowerCase().includes(lowerQuery)) results.push({
2067
+ module,
2068
+ type,
2069
+ name,
2070
+ line: i + 1,
2071
+ excerpt: lines[i].trim()
2072
+ });
2073
+ return results;
2074
+ }
2075
+ function searchModuleDocs(query, typeFilter) {
2076
+ if (!existsSync(MODULES_DIR)) return [];
2077
+ const results = [];
2078
+ const modules = readdirSync(MODULES_DIR, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DIRS.has(d.name)).sort((a, b) => a.name.localeCompare(b.name));
2079
+ for (const mod of modules) {
2080
+ const modDir = join(MODULES_DIR, mod.name);
2081
+ if (!typeFilter || typeFilter === "readme") results.push(...searchFile(join(modDir, "README.md"), query, mod.name, "readme", "README"));
2082
+ for (const [type, subdir] of Object.entries(DOC_TYPE_MAP)) {
2083
+ if (typeFilter && typeFilter !== type) continue;
2084
+ const docsDir = join(modDir, subdir);
2085
+ if (!existsSync(docsDir)) continue;
2086
+ const files = readdirSync(docsDir).filter((f) => f.endsWith(".md"));
2087
+ for (const file of files) {
2088
+ const name = file.replace(/\.md$/, "");
2089
+ results.push(...searchFile(join(docsDir, file), query, mod.name, type, name));
2090
+ }
2091
+ }
2092
+ }
2093
+ return results;
2094
+ }
2095
+ function formatSearchResults(results) {
2096
+ if (results.length === 0) return "No results found.";
2097
+ const lines = [];
2098
+ for (const r of results) lines.push(`${r.module}/${r.type}/${r.name}:${r.line}: ${r.excerpt}`);
2099
+ lines.push("");
2100
+ lines.push(`${results.length} matches`);
2101
+ return lines.join("\n");
2102
+ }
2103
+ function runDocSearch(query, type, format = "text") {
2104
+ if (type && type !== "readme" && !(type in DOC_TYPE_MAP)) {
2105
+ console.error(`Unknown doc type: ${type}`);
2106
+ console.error(`Available types: readme, ${Object.keys(DOC_TYPE_MAP).join(", ")}`);
2107
+ return 1;
2108
+ }
2109
+ const results = searchModuleDocs(query, type);
2110
+ if (format === "json") console.log(JSON.stringify(results, null, 2));
2111
+ else console.log(formatSearchResults(results));
2112
+ return 0;
2113
+ }
2114
+ //#endregion
2115
+ //#region src/commands/doc/index.ts
2116
+ const formatArg = arg(z.enum(["text", "json"]).default("text"), {
2117
+ alias: "f",
2118
+ description: "Output format (text or json)"
2119
+ });
2120
+ const docCommand = defineCommand({
2121
+ name: "doc",
2122
+ description: "Browse module documentation",
2123
+ subCommands: {
2124
+ modules: defineCommand({
2125
+ name: "modules",
2126
+ description: "List all modules with capabilities overview",
2127
+ args: z.object({ format: formatArg }),
2128
+ run: (args) => {
2129
+ return executeCommand(() => {
2130
+ const exitCode = runDocModules(args.format);
2131
+ return exitCode === 0 ? success() : silentFailure(exitCode);
2132
+ });
2133
+ }
2134
+ }),
2135
+ module: defineCommand({
2136
+ name: "module",
2137
+ description: "Show documentation for a specific module",
2138
+ args: z.object({
2139
+ name: arg(z.string(), {
2140
+ positional: true,
2141
+ description: "Module name"
2142
+ }),
2143
+ type: arg(z.string().optional(), {
2144
+ positional: true,
2145
+ description: "Doc type (command, query, model, feature)"
2146
+ }),
2147
+ docName: arg(z.string().optional(), {
2148
+ positional: true,
2149
+ description: "Doc name"
2150
+ }),
2151
+ format: formatArg
2152
+ }),
2153
+ run: (args) => {
2154
+ return executeCommand(() => {
2155
+ const exitCode = runDocModule(args.name, args.type, args.docName, args.format);
2156
+ return exitCode === 0 ? success() : silentFailure(exitCode);
2157
+ });
2158
+ }
2159
+ }),
2160
+ search: defineCommand({
2161
+ name: "search",
2162
+ description: "Search across all module documentation",
2163
+ args: z.object({
2164
+ query: arg(z.string(), {
2165
+ positional: true,
2166
+ description: "Search query"
2167
+ }),
2168
+ type: arg(z.string().optional(), {
2169
+ alias: "t",
2170
+ description: "Filter by doc type (command, query, model, feature, readme)"
2171
+ }),
2172
+ format: formatArg
2173
+ }),
2174
+ run: (args) => {
2175
+ return executeCommand(() => {
2176
+ const exitCode = runDocSearch(args.query, args.type, args.format);
2177
+ return exitCode === 0 ? success() : silentFailure(exitCode);
2178
+ });
1548
2179
  }
1549
2180
  })
1550
2181
  }
@@ -1558,15 +2189,18 @@ runMain(defineCommand({
1558
2189
  name: "erp-kit",
1559
2190
  description: "ERP module framework CLI",
1560
2191
  subCommands: {
1561
- module: moduleCommand,
2192
+ module: moduleCommand$1,
1562
2193
  app: appCommand,
1563
2194
  mock: mockCommand,
2195
+ doc: docCommand,
1564
2196
  init: defineCommand({
1565
2197
  name: "init",
1566
2198
  description: "First-time setup for a consumer repo",
1567
2199
  run: () => {
1568
- const exitCode = runInit(cwd);
1569
- process.exit(exitCode);
2200
+ return executeCommand(() => {
2201
+ const exitCode = runInit(cwd);
2202
+ return exitCode === 0 ? success() : silentFailure(exitCode);
2203
+ });
1570
2204
  }
1571
2205
  }),
1572
2206
  update: defineCommand({
@@ -1577,8 +2211,10 @@ runMain(defineCommand({
1577
2211
  description: "Resources to update (skills, workflows). Defaults to all."
1578
2212
  }) }),
1579
2213
  run: (args) => {
1580
- const exitCode = runUpdate(cwd, args.resources);
1581
- process.exit(exitCode);
2214
+ return executeCommand(() => {
2215
+ const exitCode = runUpdate(cwd, args.resources);
2216
+ return exitCode === 0 ? success() : silentFailure(exitCode);
2217
+ });
1582
2218
  }
1583
2219
  }),
1584
2220
  license: defineCommand({
@@ -1593,16 +2229,20 @@ runMain(defineCommand({
1593
2229
  description: "Path to license config JSON file"
1594
2230
  }) }),
1595
2231
  run: (args) => {
1596
- const exitCode = runLicenseCheck(args.config);
1597
- process.exit(exitCode);
2232
+ return executeCommand(() => {
2233
+ const exitCode = runLicenseCheck(args.config);
2234
+ return exitCode === 0 ? success() : silentFailure(exitCode);
2235
+ });
1598
2236
  }
1599
2237
  }),
1600
2238
  list: defineCommand({
1601
2239
  name: "list",
1602
2240
  description: "List available license groups",
1603
2241
  run: () => {
1604
- const exitCode = runLicenseList();
1605
- process.exit(exitCode);
2242
+ return executeCommand(() => {
2243
+ const exitCode = runLicenseList();
2244
+ return exitCode === 0 ? success() : silentFailure(exitCode);
2245
+ });
1606
2246
  }
1607
2247
  })
1608
2248
  }