@tailor-platform/erp-kit 0.2.0 → 0.2.2

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 (637) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -26
  3. package/dist/cli.mjs +1613 -0
  4. package/package.json +14 -13
  5. package/schemas/app-compose/business-flow.yml +3 -0
  6. package/schemas/app-compose/story.yml +13 -1
  7. package/schemas/module/command.yml +9 -0
  8. package/schemas/module/module.yml +4 -0
  9. package/schemas/module/query.yml +9 -0
  10. package/skills/erp-kit-app-1-requirements/SKILL.md +8 -14
  11. package/skills/erp-kit-app-2-requirements-review/SKILL.md +102 -0
  12. package/skills/erp-kit-app-2-requirements-review/references/best-practices-check.md +66 -0
  13. package/skills/erp-kit-app-2-requirements-review/references/boundary-consistency-check.md +69 -0
  14. package/skills/erp-kit-app-2-requirements-review/references/requirements-report-format.md +25 -0
  15. package/skills/erp-kit-app-3-plan/SKILL.md +157 -0
  16. package/skills/erp-kit-app-3-plan/references/resolver-extraction.md +107 -0
  17. package/skills/erp-kit-app-3-plan/references/screen-extraction.md +74 -0
  18. package/skills/erp-kit-app-3-plan/references/story-extraction.md +86 -0
  19. package/skills/erp-kit-app-4-plan-review/SKILL.md +177 -0
  20. package/skills/erp-kit-app-4-plan-review/references/actor-flow-parity.md +73 -0
  21. package/skills/erp-kit-app-4-plan-review/references/business-flow-story-parity.md +86 -0
  22. package/skills/erp-kit-app-4-plan-review/references/orphan-detection.md +69 -0
  23. package/skills/erp-kit-app-4-plan-review/references/parity-report-format.md +52 -0
  24. package/skills/erp-kit-app-4-plan-review/references/story-resolver-parity.md +83 -0
  25. package/skills/erp-kit-app-4-plan-review/references/story-screen-parity.md +73 -0
  26. package/skills/erp-kit-app-5-impl-backend/SKILL.md +105 -0
  27. package/skills/erp-kit-app-5-impl-backend/references/app-config.md +38 -0
  28. package/skills/erp-kit-app-5-impl-backend/references/module-wiring.md +48 -0
  29. package/skills/erp-kit-app-5-impl-backend/references/resolver-patterns.md +68 -0
  30. package/skills/erp-kit-app-6-impl-frontend/SKILL.md +74 -0
  31. package/skills/erp-kit-app-6-impl-frontend/references/pages.md +160 -0
  32. package/skills/erp-kit-app-7-impl-review/SKILL.md +176 -0
  33. package/skills/erp-kit-app-7-impl-review/references/impl-parity-report-format.md +52 -0
  34. package/skills/erp-kit-app-7-impl-review/references/module-wiring-parity.md +84 -0
  35. package/skills/erp-kit-app-7-impl-review/references/resolver-doc-code-parity.md +86 -0
  36. package/skills/erp-kit-app-7-impl-review/references/screen-doc-code-parity.md +86 -0
  37. package/skills/erp-kit-module-1-requirements/SKILL.md +126 -0
  38. package/skills/erp-kit-module-1-requirements/references/boundary-analysis.md +51 -0
  39. package/skills/erp-kit-module-1-requirements/references/erp-research.md +57 -0
  40. package/skills/erp-kit-module-1-requirements/references/feature-doc.md +61 -0
  41. package/skills/erp-kit-module-2-requirements-review/SKILL.md +112 -0
  42. package/skills/erp-kit-module-2-requirements-review/references/best-practices-check.md +79 -0
  43. package/skills/erp-kit-module-2-requirements-review/references/boundary-consistency-check.md +70 -0
  44. package/skills/erp-kit-module-2-requirements-review/references/requirements-report-format.md +25 -0
  45. package/skills/erp-kit-module-3-plan/SKILL.md +107 -0
  46. package/skills/erp-kit-module-3-plan/references/command-extraction.md +87 -0
  47. package/skills/erp-kit-module-3-plan/references/model-extraction.md +72 -0
  48. package/skills/erp-kit-module-3-plan/references/query-extraction.md +59 -0
  49. package/skills/erp-kit-module-4-plan-review/SKILL.md +158 -0
  50. package/skills/erp-kit-module-4-plan-review/references/command-model-consistency.md +46 -0
  51. package/skills/erp-kit-module-4-plan-review/references/feature-command-parity.md +97 -0
  52. package/skills/erp-kit-module-4-plan-review/references/feature-model-parity.md +47 -0
  53. package/skills/erp-kit-module-4-plan-review/references/feature-query-parity.md +70 -0
  54. package/skills/erp-kit-module-4-plan-review/references/parity-report-format.md +52 -0
  55. package/skills/erp-kit-module-5-impl/SKILL.md +118 -0
  56. package/skills/erp-kit-module-5-impl/references/command-impl.md +68 -0
  57. package/skills/erp-kit-module-5-impl/references/exports.md +10 -0
  58. package/skills/erp-kit-module-5-impl/references/model-impl.md +45 -0
  59. package/skills/erp-kit-module-5-impl/references/query-impl.md +53 -0
  60. package/skills/erp-kit-module-6-impl-review/SKILL.md +187 -0
  61. package/skills/erp-kit-module-6-impl-review/references/command-doc-code-parity.md +92 -0
  62. package/skills/erp-kit-module-6-impl-review/references/command-doc-test-parity.md +93 -0
  63. package/skills/erp-kit-module-6-impl-review/references/error-implementation-parity.md +95 -0
  64. package/skills/{erp-kit-module-5-impl-review → erp-kit-module-6-impl-review}/references/errors.md +1 -1
  65. package/skills/erp-kit-module-6-impl-review/references/impl-parity-report-format.md +52 -0
  66. package/skills/erp-kit-module-6-impl-review/references/model-doc-code-parity.md +80 -0
  67. package/skills/erp-kit-module-shared/SKILL.md +1 -1
  68. package/skills/erp-kit-module-shared/references/commands.md +1 -1
  69. package/skills/erp-kit-module-shared/references/errors.md +12 -9
  70. package/skills/erp-kit-module-shared/references/queries.md +109 -36
  71. package/skills/erp-kit-module-shared/references/testing.md +10 -0
  72. package/skills/erp-kit-update/SKILL.md +2 -2
  73. package/src/app.ts +1 -1
  74. package/src/commands/check.ts +1 -1
  75. package/src/commands/index.ts +16 -5
  76. package/src/commands/init.test.ts +22 -69
  77. package/src/commands/init.ts +28 -115
  78. package/src/commands/lib/distribute.test.ts +126 -0
  79. package/src/commands/lib/distribute.ts +129 -0
  80. package/src/commands/parse-doc-test-cases.ts +55 -0
  81. package/src/commands/scaffold.test.ts +74 -33
  82. package/src/commands/scaffold.ts +54 -18
  83. package/src/commands/sync-check.test.ts +173 -0
  84. package/src/commands/sync-check.ts +103 -2
  85. package/src/commands/update.test.ts +87 -0
  86. package/src/commands/update.ts +41 -0
  87. package/src/generator/generate-code.test.ts +23 -12
  88. package/src/generator/generate-code.ts +22 -16
  89. package/src/integration.test.ts +1 -1
  90. package/src/module.ts +20 -65
  91. package/src/modules/item-management/README.md +8 -0
  92. package/src/modules/item-management/command/activateItem.generated.ts +1 -1
  93. package/src/modules/item-management/command/activateItem.test.ts +12 -18
  94. package/src/modules/item-management/command/activateItem.ts +9 -5
  95. package/src/modules/item-management/command/assignItemToTaxonomy.generated.ts +1 -1
  96. package/src/modules/item-management/command/assignItemToTaxonomy.test.ts +10 -24
  97. package/src/modules/item-management/command/assignItemToTaxonomy.ts +19 -16
  98. package/src/modules/item-management/command/createItem.generated.ts +1 -1
  99. package/src/modules/item-management/command/createItem.test.ts +11 -11
  100. package/src/modules/item-management/command/createItem.ts +16 -7
  101. package/src/modules/item-management/command/createTaxonomyNode.generated.ts +1 -1
  102. package/src/modules/item-management/command/createTaxonomyNode.test.ts +9 -9
  103. package/src/modules/item-management/command/createTaxonomyNode.ts +33 -14
  104. package/src/modules/item-management/command/deactivateItem.generated.ts +1 -1
  105. package/src/modules/item-management/command/deactivateItem.test.ts +12 -18
  106. package/src/modules/item-management/command/deactivateItem.ts +9 -5
  107. package/src/modules/item-management/command/deleteItem.generated.ts +1 -1
  108. package/src/modules/item-management/command/deleteItem.test.ts +10 -16
  109. package/src/modules/item-management/command/deleteItem.ts +9 -5
  110. package/src/modules/item-management/command/deleteTaxonomyNode.generated.ts +1 -1
  111. package/src/modules/item-management/command/deleteTaxonomyNode.test.ts +10 -16
  112. package/src/modules/item-management/command/deleteTaxonomyNode.ts +22 -12
  113. package/src/modules/item-management/command/moveTaxonomyNode.generated.ts +1 -1
  114. package/src/modules/item-management/command/moveTaxonomyNode.test.ts +10 -10
  115. package/src/modules/item-management/command/moveTaxonomyNode.ts +63 -19
  116. package/src/modules/item-management/command/reactivateItem.generated.ts +1 -1
  117. package/src/modules/item-management/command/reactivateItem.test.ts +12 -18
  118. package/src/modules/item-management/command/reactivateItem.ts +9 -5
  119. package/src/modules/item-management/command/removeItemFromTaxonomy.generated.ts +1 -1
  120. package/src/modules/item-management/command/removeItemFromTaxonomy.test.ts +9 -16
  121. package/src/modules/item-management/command/removeItemFromTaxonomy.ts +11 -6
  122. package/src/modules/item-management/command/updateItem.generated.ts +1 -1
  123. package/src/modules/item-management/command/updateItem.test.ts +16 -16
  124. package/src/modules/item-management/command/updateItem.ts +11 -6
  125. package/src/modules/item-management/command/updateTaxonomyNode.generated.ts +1 -1
  126. package/src/modules/item-management/command/updateTaxonomyNode.test.ts +14 -20
  127. package/src/modules/item-management/command/updateTaxonomyNode.ts +9 -6
  128. package/src/modules/item-management/docs/commands/ActivateItem.md +8 -0
  129. package/src/modules/item-management/docs/commands/AssignItemToTaxonomy.md +7 -0
  130. package/src/modules/item-management/docs/commands/CreateItem.md +10 -0
  131. package/src/modules/item-management/docs/commands/CreateTaxonomyNode.md +9 -0
  132. package/src/modules/item-management/docs/commands/DeactivateItem.md +8 -0
  133. package/src/modules/item-management/docs/commands/DeleteItem.md +7 -0
  134. package/src/modules/item-management/docs/commands/DeleteTaxonomyNode.md +7 -0
  135. package/src/modules/item-management/docs/commands/MoveTaxonomyNode.md +10 -0
  136. package/src/modules/item-management/docs/commands/ReactivateItem.md +8 -0
  137. package/src/modules/item-management/docs/commands/RemoveItemFromTaxonomy.md +5 -0
  138. package/src/modules/item-management/docs/commands/UpdateItem.md +15 -0
  139. package/src/modules/item-management/docs/commands/UpdateTaxonomyNode.md +9 -0
  140. package/src/modules/item-management/docs/queries/CalculateNodeDepth.md +8 -0
  141. package/src/modules/item-management/docs/queries/CalculateSubtreeDepth.md +7 -0
  142. package/src/modules/item-management/docs/queries/DetectCircularReference.md +9 -0
  143. package/src/modules/item-management/docs/queries/GetItem.md +9 -0
  144. package/src/modules/item-management/docs/queries/GetItemTaxonomyAssignment.md +5 -0
  145. package/src/modules/item-management/docs/queries/GetTaxonomyNode.md +7 -0
  146. package/src/modules/item-management/docs/queries/GetTaxonomyNodeAssignments.md +5 -0
  147. package/src/modules/item-management/docs/queries/GetTaxonomyNodeChildren.md +6 -0
  148. package/src/modules/item-management/index.ts +0 -51
  149. package/src/modules/item-management/lib/errors.generated.ts +24 -24
  150. package/src/modules/item-management/lib/permissions.generated.ts +1 -1
  151. package/src/modules/item-management/lib/types.ts +1 -1
  152. package/src/modules/item-management/module.ts +1 -1
  153. package/src/modules/item-management/query/calculateNodeDepth.generated.ts +1 -1
  154. package/src/modules/item-management/query/calculateNodeDepth.test.ts +21 -6
  155. package/src/modules/item-management/query/calculateNodeDepth.ts +2 -2
  156. package/src/modules/item-management/query/calculateSubtreeDepth.generated.ts +1 -1
  157. package/src/modules/item-management/query/calculateSubtreeDepth.test.ts +17 -5
  158. package/src/modules/item-management/query/calculateSubtreeDepth.ts +2 -2
  159. package/src/modules/item-management/query/detectCircularReference.generated.ts +1 -1
  160. package/src/modules/item-management/query/detectCircularReference.test.ts +25 -7
  161. package/src/modules/item-management/query/detectCircularReference.ts +4 -4
  162. package/src/modules/item-management/query/getItem.generated.ts +1 -1
  163. package/src/modules/item-management/query/getItem.test.ts +25 -7
  164. package/src/modules/item-management/query/getItem.ts +2 -2
  165. package/src/modules/item-management/query/getItemTaxonomyAssignment.generated.ts +1 -1
  166. package/src/modules/item-management/query/getItemTaxonomyAssignment.test.ts +9 -3
  167. package/src/modules/item-management/query/getItemTaxonomyAssignment.ts +2 -2
  168. package/src/modules/item-management/query/getTaxonomyNode.generated.ts +1 -1
  169. package/src/modules/item-management/query/getTaxonomyNode.test.ts +17 -5
  170. package/src/modules/item-management/query/getTaxonomyNode.ts +2 -2
  171. package/src/modules/item-management/query/getTaxonomyNodeAssignments.generated.ts +1 -1
  172. package/src/modules/item-management/query/getTaxonomyNodeAssignments.test.ts +9 -3
  173. package/src/modules/item-management/query/getTaxonomyNodeAssignments.ts +2 -2
  174. package/src/modules/item-management/query/getTaxonomyNodeChildren.generated.ts +1 -1
  175. package/src/modules/item-management/query/getTaxonomyNodeChildren.test.ts +13 -4
  176. package/src/modules/item-management/query/getTaxonomyNodeChildren.ts +2 -2
  177. package/src/modules/item-management/tailor.config.ts +6 -4
  178. package/src/modules/item-management/tailor.d.ts +13 -0
  179. package/src/modules/primitives/README.md +8 -0
  180. package/src/modules/primitives/command/activateCategory.generated.ts +1 -1
  181. package/src/modules/primitives/command/activateCategory.test.ts +8 -18
  182. package/src/modules/primitives/command/activateCategory.ts +9 -5
  183. package/src/modules/primitives/command/activateCurrency.generated.ts +1 -1
  184. package/src/modules/primitives/command/activateCurrency.test.ts +8 -18
  185. package/src/modules/primitives/command/activateCurrency.ts +9 -5
  186. package/src/modules/primitives/command/activateUnit.generated.ts +1 -1
  187. package/src/modules/primitives/command/activateUnit.test.ts +8 -15
  188. package/src/modules/primitives/command/activateUnit.ts +9 -5
  189. package/src/modules/primitives/command/createCategory.generated.ts +1 -1
  190. package/src/modules/primitives/command/createCategory.test.ts +29 -44
  191. package/src/modules/primitives/command/createCategory.ts +9 -5
  192. package/src/modules/primitives/command/createCurrency.generated.ts +1 -1
  193. package/src/modules/primitives/command/createCurrency.test.ts +53 -78
  194. package/src/modules/primitives/command/createCurrency.ts +9 -6
  195. package/src/modules/primitives/command/createExchangeRate.generated.ts +1 -1
  196. package/src/modules/primitives/command/createExchangeRate.test.ts +59 -97
  197. package/src/modules/primitives/command/createExchangeRate.ts +13 -7
  198. package/src/modules/primitives/command/createUnit.generated.ts +1 -1
  199. package/src/modules/primitives/command/createUnit.test.ts +59 -90
  200. package/src/modules/primitives/command/createUnit.ts +9 -6
  201. package/src/modules/primitives/command/deactivateCategory.generated.ts +1 -1
  202. package/src/modules/primitives/command/deactivateCategory.test.ts +15 -33
  203. package/src/modules/primitives/command/deactivateCategory.ts +9 -5
  204. package/src/modules/primitives/command/deactivateCurrency.generated.ts +1 -1
  205. package/src/modules/primitives/command/deactivateCurrency.test.ts +12 -26
  206. package/src/modules/primitives/command/deactivateCurrency.ts +9 -5
  207. package/src/modules/primitives/command/deactivateUnit.generated.ts +1 -1
  208. package/src/modules/primitives/command/deactivateUnit.test.ts +15 -30
  209. package/src/modules/primitives/command/deactivateUnit.ts +14 -7
  210. package/src/modules/primitives/command/setBaseCurrency.generated.ts +1 -1
  211. package/src/modules/primitives/command/setBaseCurrency.test.ts +18 -40
  212. package/src/modules/primitives/command/setBaseCurrency.ts +15 -7
  213. package/src/modules/primitives/command/setReferenceUnit.generated.ts +1 -1
  214. package/src/modules/primitives/command/setReferenceUnit.test.ts +22 -44
  215. package/src/modules/primitives/command/setReferenceUnit.ts +21 -9
  216. package/src/modules/primitives/docs/commands/ActivateCategory.md +6 -0
  217. package/src/modules/primitives/docs/commands/ActivateCurrency.md +6 -0
  218. package/src/modules/primitives/docs/commands/ActivateUnit.md +6 -0
  219. package/src/modules/primitives/docs/commands/CreateCategory.md +6 -0
  220. package/src/modules/primitives/docs/commands/CreateCurrency.md +10 -0
  221. package/src/modules/primitives/docs/commands/CreateExchangeRate.md +11 -0
  222. package/src/modules/primitives/docs/commands/CreateUnit.md +10 -0
  223. package/src/modules/primitives/docs/commands/DeactivateCategory.md +7 -0
  224. package/src/modules/primitives/docs/commands/DeactivateCurrency.md +7 -0
  225. package/src/modules/primitives/docs/commands/DeactivateUnit.md +7 -0
  226. package/src/modules/primitives/docs/commands/SetBaseCurrency.md +7 -0
  227. package/src/modules/primitives/docs/commands/SetReferenceUnit.md +7 -0
  228. package/src/modules/primitives/docs/queries/ConvertAmount.md +14 -0
  229. package/src/modules/primitives/docs/queries/ConvertQuantity.md +13 -0
  230. package/src/modules/primitives/docs/queries/GetBaseCurrency.md +5 -0
  231. package/src/modules/primitives/docs/queries/GetCurrency.md +7 -0
  232. package/src/modules/primitives/docs/queries/GetUnit.md +7 -0
  233. package/src/modules/primitives/docs/queries/GetUoMCategory.md +7 -0
  234. package/src/modules/primitives/docs/queries/ListUnitsByCategory.md +15 -5
  235. package/src/modules/primitives/index.ts +0 -49
  236. package/src/modules/primitives/lib/errors.generated.ts +23 -23
  237. package/src/modules/primitives/lib/permissions.generated.ts +1 -1
  238. package/src/modules/primitives/lib/types.ts +1 -1
  239. package/src/modules/primitives/module.ts +1 -1
  240. package/src/modules/primitives/query/convertAmount.generated.ts +1 -1
  241. package/src/modules/primitives/query/convertAmount.test.ts +110 -77
  242. package/src/modules/primitives/query/convertAmount.ts +61 -47
  243. package/src/modules/primitives/query/convertQuantity.generated.ts +1 -1
  244. package/src/modules/primitives/query/convertQuantity.test.ts +99 -69
  245. package/src/modules/primitives/query/convertQuantity.ts +12 -10
  246. package/src/modules/primitives/query/getBaseCurrency.generated.ts +1 -1
  247. package/src/modules/primitives/query/getBaseCurrency.test.ts +10 -4
  248. package/src/modules/primitives/query/getBaseCurrency.ts +2 -2
  249. package/src/modules/primitives/query/getCurrency.generated.ts +1 -1
  250. package/src/modules/primitives/query/getCurrency.test.ts +17 -5
  251. package/src/modules/primitives/query/getCurrency.ts +2 -2
  252. package/src/modules/primitives/query/getUnit.generated.ts +1 -1
  253. package/src/modules/primitives/query/getUnit.test.ts +17 -5
  254. package/src/modules/primitives/query/getUnit.ts +2 -2
  255. package/src/modules/primitives/query/getUoMCategory.generated.ts +1 -1
  256. package/src/modules/primitives/query/getUoMCategory.test.ts +17 -5
  257. package/src/modules/primitives/query/getUoMCategory.ts +2 -2
  258. package/src/modules/primitives/query/listUnitsByCategory.generated.ts +1 -1
  259. package/src/modules/primitives/query/listUnitsByCategory.test.ts +80 -0
  260. package/src/modules/primitives/query/listUnitsByCategory.ts +19 -3
  261. package/src/modules/primitives/tailor.config.ts +6 -4
  262. package/src/modules/primitives/tailor.d.ts +13 -0
  263. package/src/modules/product-management/README.md +52 -0
  264. package/src/modules/product-management/command/activateProduct.generated.ts +6 -0
  265. package/src/modules/product-management/command/activateProduct.test.ts +40 -0
  266. package/src/modules/product-management/command/activateProduct.ts +42 -0
  267. package/src/modules/product-management/command/assignProductToCategory.generated.ts +6 -0
  268. package/src/modules/product-management/command/assignProductToCategory.test.ts +90 -0
  269. package/src/modules/product-management/command/assignProductToCategory.ts +62 -0
  270. package/src/modules/product-management/command/createProduct.generated.ts +6 -0
  271. package/src/modules/product-management/command/createProduct.test.ts +149 -0
  272. package/src/modules/product-management/command/createProduct.ts +73 -0
  273. package/src/modules/product-management/command/createProductAttribute.generated.ts +6 -0
  274. package/src/modules/product-management/command/createProductAttribute.test.ts +70 -0
  275. package/src/modules/product-management/command/createProductAttribute.ts +53 -0
  276. package/src/modules/product-management/command/createProductAttributeValue.generated.ts +6 -0
  277. package/src/modules/product-management/command/createProductAttributeValue.test.ts +68 -0
  278. package/src/modules/product-management/command/createProductAttributeValue.ts +63 -0
  279. package/src/modules/product-management/command/createProductCategory.generated.ts +6 -0
  280. package/src/modules/product-management/command/createProductCategory.test.ts +135 -0
  281. package/src/modules/product-management/command/createProductCategory.ts +82 -0
  282. package/src/modules/product-management/command/deactivateProduct.generated.ts +6 -0
  283. package/src/modules/product-management/command/deactivateProduct.test.ts +40 -0
  284. package/src/modules/product-management/command/deactivateProduct.ts +42 -0
  285. package/src/modules/product-management/command/deleteProduct.generated.ts +6 -0
  286. package/src/modules/product-management/command/deleteProduct.test.ts +42 -0
  287. package/src/modules/product-management/command/deleteProduct.ts +42 -0
  288. package/src/modules/product-management/command/deleteProductAttribute.generated.ts +6 -0
  289. package/src/modules/product-management/command/deleteProductAttribute.test.ts +49 -0
  290. package/src/modules/product-management/command/deleteProductAttribute.ts +45 -0
  291. package/src/modules/product-management/command/deleteProductAttributeValue.generated.ts +6 -0
  292. package/src/modules/product-management/command/deleteProductAttributeValue.test.ts +71 -0
  293. package/src/modules/product-management/command/deleteProductAttributeValue.ts +68 -0
  294. package/src/modules/product-management/command/deleteProductCategory.generated.ts +6 -0
  295. package/src/modules/product-management/command/deleteProductCategory.test.ts +74 -0
  296. package/src/modules/product-management/command/deleteProductCategory.ts +53 -0
  297. package/src/modules/product-management/command/generateVariants.generated.ts +6 -0
  298. package/src/modules/product-management/command/generateVariants.test.ts +365 -0
  299. package/src/modules/product-management/command/generateVariants.ts +168 -0
  300. package/src/modules/product-management/command/moveProductCategory.generated.ts +6 -0
  301. package/src/modules/product-management/command/moveProductCategory.test.ts +170 -0
  302. package/src/modules/product-management/command/moveProductCategory.ts +124 -0
  303. package/src/modules/product-management/command/reactivateProduct.generated.ts +6 -0
  304. package/src/modules/product-management/command/reactivateProduct.test.ts +40 -0
  305. package/src/modules/product-management/command/reactivateProduct.ts +42 -0
  306. package/src/modules/product-management/command/removeProductFromCategory.generated.ts +6 -0
  307. package/src/modules/product-management/command/removeProductFromCategory.test.ts +42 -0
  308. package/src/modules/product-management/command/removeProductFromCategory.ts +32 -0
  309. package/src/modules/product-management/command/setProductAttributeAssignment.generated.ts +6 -0
  310. package/src/modules/product-management/command/setProductAttributeAssignment.test.ts +206 -0
  311. package/src/modules/product-management/command/setProductAttributeAssignment.ts +102 -0
  312. package/src/modules/product-management/command/updateProduct.generated.ts +6 -0
  313. package/src/modules/product-management/command/updateProduct.test.ts +168 -0
  314. package/src/modules/product-management/command/updateProduct.ts +95 -0
  315. package/src/modules/product-management/command/updateProductAttribute.generated.ts +6 -0
  316. package/src/modules/product-management/command/updateProductAttribute.test.ts +101 -0
  317. package/src/modules/product-management/command/updateProductAttribute.ts +68 -0
  318. package/src/modules/product-management/command/updateProductAttributeValue.generated.ts +6 -0
  319. package/src/modules/product-management/command/updateProductAttributeValue.test.ts +80 -0
  320. package/src/modules/product-management/command/updateProductAttributeValue.ts +58 -0
  321. package/src/modules/product-management/command/updateProductCategory.generated.ts +6 -0
  322. package/src/modules/product-management/command/updateProductCategory.test.ts +80 -0
  323. package/src/modules/product-management/command/updateProductCategory.ts +66 -0
  324. package/src/modules/product-management/db/product.ts +47 -0
  325. package/src/modules/product-management/db/productAttribute.ts +26 -0
  326. package/src/modules/product-management/db/productAttributeAssignment.ts +58 -0
  327. package/src/modules/product-management/db/productAttributeValue.ts +39 -0
  328. package/src/modules/product-management/db/productCategory.ts +34 -0
  329. package/src/modules/product-management/db/productCategoryAssignment.ts +49 -0
  330. package/src/modules/product-management/db/productVariant.ts +52 -0
  331. package/src/modules/product-management/docs/commands/ActivateProduct.md +39 -0
  332. package/src/modules/product-management/docs/commands/AssignProductToCategory.md +43 -0
  333. package/src/modules/product-management/docs/commands/CreateProduct.md +48 -0
  334. package/src/modules/product-management/docs/commands/CreateProductAttribute.md +39 -0
  335. package/src/modules/product-management/docs/commands/CreateProductAttributeValue.md +42 -0
  336. package/src/modules/product-management/docs/commands/CreateProductCategory.md +54 -0
  337. package/src/modules/product-management/docs/commands/DeactivateProduct.md +39 -0
  338. package/src/modules/product-management/docs/commands/DeleteProduct.md +42 -0
  339. package/src/modules/product-management/docs/commands/DeleteProductAttribute.md +39 -0
  340. package/src/modules/product-management/docs/commands/DeleteProductAttributeValue.md +42 -0
  341. package/src/modules/product-management/docs/commands/DeleteProductCategory.md +43 -0
  342. package/src/modules/product-management/docs/commands/GenerateVariants.md +68 -0
  343. package/src/modules/product-management/docs/commands/MoveProductCategory.md +54 -0
  344. package/src/modules/product-management/docs/commands/ReactivateProduct.md +38 -0
  345. package/src/modules/product-management/docs/commands/RemoveProductFromCategory.md +34 -0
  346. package/src/modules/product-management/docs/commands/SetProductAttributeAssignment.md +62 -0
  347. package/src/modules/product-management/docs/commands/UpdateProduct.md +61 -0
  348. package/src/modules/product-management/docs/commands/UpdateProductAttribute.md +46 -0
  349. package/src/modules/product-management/docs/commands/UpdateProductAttributeValue.md +47 -0
  350. package/src/modules/product-management/docs/commands/UpdateProductCategory.md +46 -0
  351. package/src/modules/product-management/docs/features/attribute-management.md +48 -0
  352. package/src/modules/product-management/docs/features/product-category.md +71 -0
  353. package/src/modules/product-management/docs/features/product-lifecycle.md +66 -0
  354. package/src/modules/product-management/docs/features/variant-generation.md +77 -0
  355. package/src/modules/product-management/docs/models/Product.md +58 -0
  356. package/src/modules/product-management/docs/models/ProductAttribute.md +37 -0
  357. package/src/modules/product-management/docs/models/ProductAttributeAssignment.md +41 -0
  358. package/src/modules/product-management/docs/models/ProductAttributeValue.md +40 -0
  359. package/src/modules/product-management/docs/models/ProductCategory.md +46 -0
  360. package/src/modules/product-management/docs/models/ProductCategoryAssignment.md +37 -0
  361. package/src/modules/product-management/docs/models/ProductVariant.md +41 -0
  362. package/src/modules/product-management/docs/queries/CalculateCategoryDepth.md +47 -0
  363. package/src/modules/product-management/docs/queries/DetectCategoryCircularReference.md +51 -0
  364. package/src/modules/product-management/docs/queries/GetProduct.md +42 -0
  365. package/src/modules/product-management/docs/queries/GetProductAttribute.md +42 -0
  366. package/src/modules/product-management/docs/queries/GetProductAttributeAssignment.md +34 -0
  367. package/src/modules/product-management/docs/queries/GetProductAttributeValue.md +40 -0
  368. package/src/modules/product-management/docs/queries/GetProductCategory.md +42 -0
  369. package/src/modules/product-management/docs/queries/GetProductCategoryAssignment.md +34 -0
  370. package/src/modules/product-management/docs/queries/GetProductVariant.md +41 -0
  371. package/src/modules/product-management/docs/queries/ListAttributeAssignmentsByAttribute.md +34 -0
  372. package/src/modules/product-management/docs/queries/ListCategoryAssignmentsByProduct.md +35 -0
  373. package/src/modules/product-management/docs/queries/ListProductAttributeAssignments.md +34 -0
  374. package/src/modules/product-management/docs/queries/ListProductAttributeValues.md +36 -0
  375. package/src/modules/product-management/docs/queries/ListProductCategoryAssignments.md +34 -0
  376. package/src/modules/product-management/docs/queries/ListProductCategoryChildren.md +34 -0
  377. package/src/modules/product-management/docs/queries/ListProductVariants.md +34 -0
  378. package/src/modules/product-management/generated/enums.ts +9 -0
  379. package/src/modules/product-management/generated/kysely-tailordb.ts +100 -0
  380. package/src/modules/product-management/index.ts +2 -0
  381. package/src/modules/product-management/lib/_db_deps.ts +17 -0
  382. package/src/modules/product-management/lib/errors.generated.ts +152 -0
  383. package/src/modules/product-management/lib/permissions.generated.ts +25 -0
  384. package/src/modules/product-management/lib/types.ts +51 -0
  385. package/src/modules/product-management/module.ts +201 -0
  386. package/src/modules/product-management/query/calculateCategoryDepth.generated.ts +5 -0
  387. package/src/modules/product-management/query/calculateCategoryDepth.test.ts +72 -0
  388. package/src/modules/product-management/query/calculateCategoryDepth.ts +37 -0
  389. package/src/modules/product-management/query/detectCategoryCircularReference.generated.ts +5 -0
  390. package/src/modules/product-management/query/detectCategoryCircularReference.test.ts +72 -0
  391. package/src/modules/product-management/query/detectCategoryCircularReference.ts +44 -0
  392. package/src/modules/product-management/query/getProduct.generated.ts +5 -0
  393. package/src/modules/product-management/query/getProduct.test.ts +59 -0
  394. package/src/modules/product-management/query/getProduct.ts +18 -0
  395. package/src/modules/product-management/query/getProductAttribute.generated.ts +5 -0
  396. package/src/modules/product-management/query/getProductAttribute.test.ts +59 -0
  397. package/src/modules/product-management/query/getProductAttribute.ts +18 -0
  398. package/src/modules/product-management/query/getProductAttributeAssignment.generated.ts +5 -0
  399. package/src/modules/product-management/query/getProductAttributeAssignment.test.ts +37 -0
  400. package/src/modules/product-management/query/getProductAttributeAssignment.ts +18 -0
  401. package/src/modules/product-management/query/getProductAttributeValue.generated.ts +5 -0
  402. package/src/modules/product-management/query/getProductAttributeValue.test.ts +31 -0
  403. package/src/modules/product-management/query/getProductAttributeValue.ts +16 -0
  404. package/src/modules/product-management/query/getProductCategory.generated.ts +5 -0
  405. package/src/modules/product-management/query/getProductCategory.test.ts +59 -0
  406. package/src/modules/product-management/query/getProductCategory.ts +18 -0
  407. package/src/modules/product-management/query/getProductCategoryAssignment.generated.ts +5 -0
  408. package/src/modules/product-management/query/getProductCategoryAssignment.test.ts +37 -0
  409. package/src/modules/product-management/query/getProductCategoryAssignment.ts +18 -0
  410. package/src/modules/product-management/query/getProductVariant.generated.ts +5 -0
  411. package/src/modules/product-management/query/getProductVariant.test.ts +43 -0
  412. package/src/modules/product-management/query/getProductVariant.ts +20 -0
  413. package/src/modules/product-management/query/listAttributeAssignmentsByAttribute.generated.ts +5 -0
  414. package/src/modules/product-management/query/listAttributeAssignmentsByAttribute.test.ts +31 -0
  415. package/src/modules/product-management/query/listAttributeAssignmentsByAttribute.ts +16 -0
  416. package/src/modules/product-management/query/listCategoryAssignmentsByProduct.generated.ts +5 -0
  417. package/src/modules/product-management/query/listCategoryAssignmentsByProduct.test.ts +31 -0
  418. package/src/modules/product-management/query/listCategoryAssignmentsByProduct.ts +16 -0
  419. package/src/modules/product-management/query/listProductAttributeAssignments.generated.ts +5 -0
  420. package/src/modules/product-management/query/listProductAttributeAssignments.test.ts +31 -0
  421. package/src/modules/product-management/query/listProductAttributeAssignments.ts +16 -0
  422. package/src/modules/product-management/query/listProductAttributeValues.generated.ts +5 -0
  423. package/src/modules/product-management/query/listProductAttributeValues.test.ts +31 -0
  424. package/src/modules/product-management/query/listProductAttributeValues.ts +17 -0
  425. package/src/modules/product-management/query/listProductCategoryAssignments.generated.ts +5 -0
  426. package/src/modules/product-management/query/listProductCategoryAssignments.test.ts +31 -0
  427. package/src/modules/product-management/query/listProductCategoryAssignments.ts +16 -0
  428. package/src/modules/product-management/query/listProductCategoryChildren.generated.ts +5 -0
  429. package/src/modules/product-management/query/listProductCategoryChildren.test.ts +31 -0
  430. package/src/modules/product-management/query/listProductCategoryChildren.ts +16 -0
  431. package/src/modules/product-management/query/listProductVariants.generated.ts +5 -0
  432. package/src/modules/product-management/query/listProductVariants.test.ts +31 -0
  433. package/src/modules/product-management/query/listProductVariants.ts +16 -0
  434. package/src/modules/product-management/tailor.config.ts +13 -0
  435. package/src/modules/product-management/tailor.d.ts +13 -0
  436. package/src/modules/product-management/testing/fixtures.ts +151 -0
  437. package/src/modules/user-management/README.md +9 -3
  438. package/src/modules/user-management/command/activateUser.generated.ts +1 -1
  439. package/src/modules/user-management/command/activateUser.test.ts +12 -65
  440. package/src/modules/user-management/command/activateUser.ts +5 -20
  441. package/src/modules/user-management/command/assignPermissionToRole.generated.ts +1 -1
  442. package/src/modules/user-management/command/assignPermissionToRole.test.ts +25 -60
  443. package/src/modules/user-management/command/assignPermissionToRole.ts +5 -24
  444. package/src/modules/user-management/command/assignRoleToUser.generated.ts +1 -1
  445. package/src/modules/user-management/command/assignRoleToUser.test.ts +35 -87
  446. package/src/modules/user-management/command/assignRoleToUser.ts +5 -24
  447. package/src/modules/user-management/command/createPermission.generated.ts +1 -1
  448. package/src/modules/user-management/command/createPermission.test.ts +23 -33
  449. package/src/modules/user-management/command/createPermission.ts +4 -5
  450. package/src/modules/user-management/command/createRole.generated.ts +1 -1
  451. package/src/modules/user-management/command/createRole.test.ts +17 -27
  452. package/src/modules/user-management/command/createRole.ts +4 -5
  453. package/src/modules/user-management/command/createUser.generated.ts +1 -1
  454. package/src/modules/user-management/command/createUser.test.ts +31 -118
  455. package/src/modules/user-management/command/createUser.ts +7 -25
  456. package/src/modules/user-management/command/deactivateUser.generated.ts +1 -1
  457. package/src/modules/user-management/command/deactivateUser.test.ts +12 -65
  458. package/src/modules/user-management/command/deactivateUser.ts +6 -21
  459. package/src/modules/user-management/command/reactivateUser.generated.ts +1 -1
  460. package/src/modules/user-management/command/reactivateUser.test.ts +13 -66
  461. package/src/modules/user-management/command/reactivateUser.ts +5 -20
  462. package/src/modules/user-management/command/revokePermissionFromRole.generated.ts +1 -1
  463. package/src/modules/user-management/command/revokePermissionFromRole.test.ts +24 -62
  464. package/src/modules/user-management/command/revokePermissionFromRole.ts +5 -24
  465. package/src/modules/user-management/command/revokeRoleFromUser.generated.ts +1 -1
  466. package/src/modules/user-management/command/revokeRoleFromUser.test.ts +24 -60
  467. package/src/modules/user-management/command/revokeRoleFromUser.ts +5 -24
  468. package/src/modules/user-management/docs/commands/ActivateUser.md +7 -0
  469. package/src/modules/user-management/docs/commands/AssignPermissionToRole.md +7 -0
  470. package/src/modules/user-management/docs/commands/AssignRoleToUser.md +9 -0
  471. package/src/modules/user-management/docs/commands/CreatePermission.md +12 -0
  472. package/src/modules/user-management/docs/commands/CreateRole.md +9 -0
  473. package/src/modules/user-management/docs/commands/CreateUser.md +11 -0
  474. package/src/modules/user-management/docs/commands/DeactivateUser.md +7 -0
  475. package/src/modules/user-management/docs/commands/ReactivateUser.md +7 -0
  476. package/src/modules/user-management/docs/commands/RevokePermissionFromRole.md +7 -0
  477. package/src/modules/user-management/docs/commands/RevokeRoleFromUser.md +7 -0
  478. package/src/modules/user-management/index.ts +0 -30
  479. package/src/modules/user-management/lib/errors.generated.ts +14 -14
  480. package/src/modules/user-management/lib/permissions.generated.ts +1 -2
  481. package/src/modules/user-management/lib/recomputeUserPermissions.ts +4 -3
  482. package/src/modules/user-management/lib/types.ts +1 -1
  483. package/src/modules/user-management/module.ts +2 -7
  484. package/src/modules/user-management/tailor.config.ts +6 -4
  485. package/src/modules/user-management/tailor.d.ts +13 -0
  486. package/src/modules/user-management/testing/fixtures.ts +1 -20
  487. package/src/schemas.ts +1 -1
  488. package/src/{modules/shared → shared}/defineCommand.test.ts +23 -7
  489. package/src/{modules/shared → shared}/defineCommand.ts +19 -10
  490. package/src/{modules/shared/internal.ts → shared/index.ts} +9 -1
  491. package/src/shared/pagination.test.ts +43 -0
  492. package/src/shared/pagination.ts +22 -0
  493. package/src/{modules/shared → shared}/types.ts +13 -0
  494. package/src/{modules/testing → testing}/index.ts +14 -7
  495. package/src/testing.ts +1 -1
  496. package/src/util.ts +8 -0
  497. package/templates/config/license.config.json +4 -0
  498. package/templates/scaffold/app/backend/.env.example +1 -0
  499. package/templates/scaffold/app/backend/__dot__gitignore +4 -0
  500. package/templates/scaffold/app/backend/eslint.config.js +32 -0
  501. package/templates/scaffold/app/backend/package.json +31 -0
  502. package/templates/scaffold/app/backend/seed/data/AuditEvent.jsonl +0 -0
  503. package/templates/scaffold/app/backend/seed/data/Permission.jsonl +0 -0
  504. package/templates/scaffold/app/backend/seed/data/Permission.schema.ts +20 -0
  505. package/templates/scaffold/app/backend/seed/data/Role.jsonl +0 -0
  506. package/templates/scaffold/app/backend/seed/data/Role.schema.ts +20 -0
  507. package/templates/scaffold/app/backend/seed/data/RolePermission.jsonl +0 -0
  508. package/templates/scaffold/app/backend/seed/data/RolePermission.schema.ts +24 -0
  509. package/templates/scaffold/app/backend/seed/data/User.jsonl +1 -0
  510. package/templates/scaffold/app/backend/seed/data/User.schema.ts +20 -0
  511. package/templates/scaffold/app/backend/seed/data/UserRole.jsonl +0 -0
  512. package/templates/scaffold/app/backend/seed/data/UserRole.schema.ts +24 -0
  513. package/templates/scaffold/app/backend/seed/data/_User.jsonl +1 -0
  514. package/templates/scaffold/app/backend/seed/data/_User.schema.ts +30 -0
  515. package/templates/scaffold/app/backend/seed/exec.mjs +659 -0
  516. package/templates/scaffold/app/backend/src/executors/permissionCreated.ts +3 -0
  517. package/templates/scaffold/app/backend/src/executors/permissionDeleted.ts +3 -0
  518. package/templates/scaffold/app/backend/src/generated/kysely-tailordb.ts +83 -0
  519. package/templates/scaffold/app/backend/src/modules.ts +9 -0
  520. package/templates/scaffold/app/backend/src/resolvers/createUser.ts +46 -0
  521. package/templates/scaffold/app/backend/tailor.config.ts +68 -0
  522. package/templates/scaffold/app/backend/tailor.d.ts +15 -0
  523. package/templates/scaffold/app/backend/tsconfig.json +19 -0
  524. package/templates/scaffold/app/docs/actors/.gitkeep +0 -0
  525. package/templates/scaffold/app/docs/business-flow/.gitkeep +0 -0
  526. package/templates/scaffold/app/docs/resolver/.gitkeep +0 -0
  527. package/templates/scaffold/app/docs/screen/.gitkeep +0 -0
  528. package/templates/scaffold/app/frontend/.env.example +2 -0
  529. package/templates/scaffold/app/frontend/__dot__gitignore +3 -0
  530. package/templates/scaffold/app/frontend/components.json +23 -0
  531. package/templates/scaffold/app/frontend/eslint.config.js +48 -0
  532. package/templates/scaffold/app/frontend/index.html +13 -0
  533. package/templates/scaffold/app/frontend/package.json +53 -0
  534. package/templates/scaffold/app/frontend/scripts/generate-graphql.mjs +6 -0
  535. package/templates/scaffold/app/frontend/src/App.tsx +58 -0
  536. package/templates/scaffold/app/frontend/src/components/composed/empty-state.tsx +26 -0
  537. package/templates/scaffold/app/frontend/src/components/composed/error-fallback.tsx +28 -0
  538. package/templates/scaffold/app/frontend/src/components/composed/loading.tsx +13 -0
  539. package/templates/scaffold/app/frontend/src/components/ui/badge.tsx +39 -0
  540. package/templates/scaffold/app/frontend/src/components/ui/button.tsx +60 -0
  541. package/templates/scaffold/app/frontend/src/components/ui/card.tsx +75 -0
  542. package/templates/scaffold/app/frontend/src/components/ui/form.tsx +152 -0
  543. package/templates/scaffold/app/frontend/src/components/ui/input.tsx +21 -0
  544. package/templates/scaffold/app/frontend/src/components/ui/label.tsx +21 -0
  545. package/templates/scaffold/app/frontend/src/components/ui/spinner.tsx +16 -0
  546. package/templates/scaffold/app/frontend/src/components/ui/table.tsx +90 -0
  547. package/templates/scaffold/app/frontend/src/graphql/generated/graphql-env.d.ts +103 -0
  548. package/templates/scaffold/app/frontend/src/graphql/generated/schema.graphql +1235 -0
  549. package/templates/scaffold/app/frontend/src/graphql/index.ts +15 -0
  550. package/templates/scaffold/app/frontend/src/index.css +5 -0
  551. package/templates/scaffold/app/frontend/src/lib/auth-client.ts +17 -0
  552. package/templates/scaffold/app/frontend/src/lib/utils.ts +6 -0
  553. package/templates/scaffold/app/frontend/src/main.tsx +10 -0
  554. package/templates/scaffold/app/frontend/src/pages/page.tsx +20 -0
  555. package/templates/scaffold/app/frontend/src/pages/user-management/page.tsx +19 -0
  556. package/templates/scaffold/app/frontend/src/pages/user-management/profile/page.tsx +97 -0
  557. package/templates/scaffold/app/frontend/src/pages/user-management/user/[id]/components/user-detail.tsx +58 -0
  558. package/templates/scaffold/app/frontend/src/pages/user-management/user/[id]/page.tsx +51 -0
  559. package/templates/scaffold/app/frontend/src/pages/user-management/user/components/users-table.tsx +101 -0
  560. package/templates/scaffold/app/frontend/src/pages/user-management/user/create/components/create-user-form.tsx +99 -0
  561. package/templates/scaffold/app/frontend/src/pages/user-management/user/create/page.tsx +19 -0
  562. package/templates/scaffold/app/frontend/src/pages/user-management/user/page.tsx +61 -0
  563. package/templates/scaffold/app/frontend/src/providers/graphql-provider.tsx +21 -0
  564. package/templates/scaffold/app/frontend/tsconfig.app.json +35 -0
  565. package/templates/scaffold/app/frontend/tsconfig.json +16 -0
  566. package/templates/scaffold/app/frontend/tsconfig.node.json +23 -0
  567. package/templates/scaffold/app/frontend/vite.config.ts +23 -0
  568. package/templates/scaffold/module/command/.gitkeep +0 -0
  569. package/templates/scaffold/module/db/.gitkeep +0 -0
  570. package/templates/scaffold/module/executor/.gitkeep +0 -0
  571. package/templates/scaffold/module/generated/.gitkeep +0 -0
  572. package/templates/scaffold/module/index.ts +2 -0
  573. package/templates/scaffold/module/lib/errors.ts +1 -0
  574. package/templates/scaffold/module/lib/types.ts +4 -0
  575. package/templates/scaffold/module/module.ts +7 -0
  576. package/templates/scaffold/module/permissions.ts +3 -0
  577. package/templates/scaffold/module/query/.gitkeep +0 -0
  578. package/templates/scaffold/module/tailor.config.ts +13 -0
  579. package/templates/scaffold/module/testing/fixtures.ts +1 -0
  580. package/templates/workflows/erp-kit-check.yml +37 -0
  581. package/dist/cli.js +0 -1654
  582. package/skills/erp-kit-app-1-requirements/references/structure.md +0 -27
  583. package/skills/erp-kit-app-2-breakdown/SKILL.md +0 -95
  584. package/skills/erp-kit-app-2-breakdown/references/screen-detailview.md +0 -106
  585. package/skills/erp-kit-app-2-breakdown/references/screen-form.md +0 -139
  586. package/skills/erp-kit-app-2-breakdown/references/screen-listview.md +0 -153
  587. package/skills/erp-kit-app-2-breakdown/references/structure.md +0 -27
  588. package/skills/erp-kit-app-3-doc-review/SKILL.md +0 -116
  589. package/skills/erp-kit-app-3-doc-review/references/structure.md +0 -27
  590. package/skills/erp-kit-app-4-design/SKILL.md +0 -256
  591. package/skills/erp-kit-app-4-design/references/component.md +0 -50
  592. package/skills/erp-kit-app-4-design/references/screen-detailview.md +0 -106
  593. package/skills/erp-kit-app-4-design/references/screen-form.md +0 -139
  594. package/skills/erp-kit-app-4-design/references/screen-listview.md +0 -153
  595. package/skills/erp-kit-app-4-design/references/structure.md +0 -27
  596. package/skills/erp-kit-app-5-design-review/SKILL.md +0 -290
  597. package/skills/erp-kit-app-5-design-review/references/component.md +0 -50
  598. package/skills/erp-kit-app-5-design-review/references/screen-detailview.md +0 -106
  599. package/skills/erp-kit-app-5-design-review/references/screen-form.md +0 -139
  600. package/skills/erp-kit-app-5-design-review/references/screen-listview.md +0 -153
  601. package/skills/erp-kit-app-6-impl-spec/SKILL.md +0 -127
  602. package/skills/erp-kit-app-6-impl-spec/references/auth.md +0 -72
  603. package/skills/erp-kit-app-6-impl-spec/references/structure.md +0 -27
  604. package/skills/erp-kit-module-1-docs/SKILL.md +0 -111
  605. package/skills/erp-kit-module-2-feature-breakdown/SKILL.md +0 -76
  606. package/skills/erp-kit-module-3-doc-review/SKILL.md +0 -294
  607. package/skills/erp-kit-module-4-tdd/SKILL.md +0 -94
  608. package/skills/erp-kit-module-4-tdd/references/exports.md +0 -8
  609. package/skills/erp-kit-module-5-impl-review/SKILL.md +0 -410
  610. package/src/commands/scaffold-templates.ts +0 -65
  611. package/src/modules/shared/index.ts +0 -1
  612. package/src/modules/user-management/command/logAuditEvent.generated.ts +0 -6
  613. package/src/modules/user-management/command/logAuditEvent.test.ts +0 -187
  614. package/src/modules/user-management/command/logAuditEvent.ts +0 -56
  615. package/src/modules/user-management/db/auditEvent.ts +0 -47
  616. package/src/modules/user-management/docs/commands/LogAuditEvent.md +0 -37
  617. package/src/modules/user-management/docs/features/audit-trail.md +0 -80
  618. package/src/modules/user-management/docs/models/AuditEvent.md +0 -36
  619. /package/skills/{erp-kit-module-2-feature-breakdown → erp-kit-module-3-plan}/references/naming.md +0 -0
  620. /package/skills/{erp-kit-module-4-tdd → erp-kit-module-5-impl}/references/cross-module-dependency.md +0 -0
  621. /package/skills/{erp-kit-module-4-tdd → erp-kit-module-5-impl}/references/db-relations.md +0 -0
  622. /package/skills/{erp-kit-module-4-tdd → erp-kit-module-5-impl}/references/generated-code.md +0 -0
  623. /package/skills/{erp-kit-module-4-tdd → erp-kit-module-5-impl}/references/models.md +0 -0
  624. /package/skills/{erp-kit-module-5-impl-review → erp-kit-module-6-impl-review}/references/commands.md +0 -0
  625. /package/skills/{erp-kit-module-5-impl-review → erp-kit-module-6-impl-review}/references/testing.md +0 -0
  626. /package/src/modules/{product-management → audit}/.gitkeep +0 -0
  627. /package/src/{modules/shared → shared}/createContext.test.ts +0 -0
  628. /package/src/{modules/shared → shared}/createContext.ts +0 -0
  629. /package/src/{modules/shared → shared}/definePermissions.test.ts +0 -0
  630. /package/src/{modules/shared → shared}/definePermissions.ts +0 -0
  631. /package/src/{modules/shared → shared}/defineQuery.test.ts +0 -0
  632. /package/src/{modules/shared → shared}/defineQuery.ts +0 -0
  633. /package/src/{modules/shared → shared}/entityTypes.ts +0 -0
  634. /package/src/{modules/shared → shared}/errors.ts +0 -0
  635. /package/src/{modules/shared → shared}/requirePermission.test.ts +0 -0
  636. /package/src/{modules/shared → shared}/requirePermission.ts +0 -0
  637. /package/src/{modules/shared → shared}/result.ts +0 -0
package/dist/cli.js DELETED
@@ -1,1654 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/cli.ts
4
- import { runMain } from "politty";
5
-
6
- // src/commands/index.ts
7
- import { z as z5 } from "zod";
8
- import { defineCommand as defineCommand5, arg as arg5 } from "politty";
9
-
10
- // src/commands/init.ts
11
- import fs from "fs";
12
- import path2 from "path";
13
- import chalk from "chalk";
14
-
15
- // src/util.ts
16
- import path from "path";
17
- var PACKAGE_ROOT = path.resolve(import.meta.dirname, "..");
18
-
19
- // src/commands/init.ts
20
- var SKILLS_SRC = path2.join(PACKAGE_ROOT, "skills");
21
- function discoverFrameworkSkills() {
22
- if (!fs.existsSync(SKILLS_SRC)) return [];
23
- return fs.readdirSync(SKILLS_SRC, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("erp-kit-")).map((entry) => entry.name);
24
- }
25
- function copyDirectoryRecursive(srcDir, destDir, force) {
26
- let copied = 0;
27
- let skipped = 0;
28
- for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
29
- const srcPath = path2.join(srcDir, entry.name);
30
- const destPath = path2.join(destDir, entry.name);
31
- if (entry.isDirectory()) {
32
- const sub = copyDirectoryRecursive(srcPath, destPath, force);
33
- copied += sub.copied;
34
- skipped += sub.skipped;
35
- } else {
36
- if (!force && fs.existsSync(destPath)) {
37
- skipped++;
38
- continue;
39
- }
40
- fs.mkdirSync(destDir, { recursive: true });
41
- fs.copyFileSync(srcPath, destPath);
42
- copied++;
43
- }
44
- }
45
- return { copied, skipped };
46
- }
47
- function runInit(cwd5, force) {
48
- console.log(chalk.bold("erp-kit init\n"));
49
- const skillsDest = path2.join(cwd5, ".agents", "skills");
50
- if (force && fs.existsSync(skillsDest)) {
51
- let removedCount = 0;
52
- for (const entry of fs.readdirSync(skillsDest)) {
53
- if (entry.startsWith("erp-kit-")) {
54
- fs.rmSync(path2.join(skillsDest, entry), { recursive: true, force: true });
55
- removedCount++;
56
- }
57
- }
58
- if (removedCount > 0) {
59
- console.log(chalk.green(` Removed ${removedCount} existing erp-kit-* skills`));
60
- }
61
- }
62
- let copiedCount = 0;
63
- let skippedCount = 0;
64
- const frameworkSkills = discoverFrameworkSkills();
65
- for (const skill of frameworkSkills) {
66
- const srcSkillDir = path2.join(SKILLS_SRC, skill);
67
- if (!fs.existsSync(srcSkillDir)) continue;
68
- const destDir = path2.join(skillsDest, skill);
69
- const result = copyDirectoryRecursive(srcSkillDir, destDir, force);
70
- copiedCount += result.copied;
71
- if (result.skipped > 0) {
72
- console.log(chalk.yellow(` Skipped ${skill}/ (${result.skipped} existing files)`));
73
- skippedCount += result.skipped;
74
- }
75
- }
76
- console.log(chalk.green(` Copied ${copiedCount} skill files to .agents/skills/`));
77
- if (skippedCount > 0) {
78
- console.log(
79
- chalk.yellow(` Skipped ${skippedCount} existing files (use --force to overwrite)`)
80
- );
81
- }
82
- const claudeSkills = path2.join(cwd5, ".claude", "skills");
83
- const relTarget = path2.relative(path2.dirname(claudeSkills), skillsDest);
84
- const claudeSkillsExists = (() => {
85
- try {
86
- fs.lstatSync(claudeSkills);
87
- return true;
88
- } catch {
89
- return false;
90
- }
91
- })();
92
- if (claudeSkillsExists) {
93
- const stat2 = fs.lstatSync(claudeSkills);
94
- if (stat2.isSymbolicLink()) {
95
- const current = fs.readlinkSync(claudeSkills);
96
- if (current === relTarget) {
97
- console.log(chalk.green(" .claude/skills -> .agents/skills/ (already linked)"));
98
- } else if (force) {
99
- fs.unlinkSync(claudeSkills);
100
- fs.symlinkSync(relTarget, claudeSkills);
101
- console.log(chalk.green(" .claude/skills -> .agents/skills/ (relinked)"));
102
- } else {
103
- console.log(
104
- chalk.yellow(` Skipped .claude/skills (symlink exists -> ${current}, use --force)`)
105
- );
106
- }
107
- } else {
108
- console.log(chalk.yellow(" Skipped .claude/skills (directory exists, not a symlink)"));
109
- }
110
- } else {
111
- fs.mkdirSync(path2.dirname(claudeSkills), { recursive: true });
112
- fs.symlinkSync(relTarget, claudeSkills);
113
- console.log(chalk.green(" .claude/skills -> .agents/skills/ (linked)"));
114
- }
115
- console.log(chalk.bold.green("\nDone! Run `erp-kit check` to validate your docs."));
116
- return 0;
117
- }
118
-
119
- // src/commands/license.ts
120
- import fs2 from "fs";
121
- import { execSync } from "child_process";
122
- var licenseGroups = {
123
- // https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L225
124
- reciprocal: [
125
- "APSL-1.0",
126
- "APSL-1.1",
127
- "APSL-1.2",
128
- "APSL-2.0",
129
- "CDDL-1.0",
130
- "CDDL-1.1",
131
- "CPL-1.0",
132
- "EPL-1.0",
133
- "EPL-2.0",
134
- "FreeImage",
135
- "IPL-1.0",
136
- "MPL-1.0",
137
- "MPL-1.1",
138
- "MPL-2.0",
139
- "Ruby"
140
- ],
141
- // https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L249
142
- notice: [
143
- "AFL-1.1",
144
- "AFL-1.2",
145
- "AFL-2.0",
146
- "AFL-2.1",
147
- "AFL-3.0",
148
- "Apache-1.0",
149
- "Apache-1.1",
150
- "Apache-2.0",
151
- "Artistic-1.0-cl8",
152
- "Artistic-1.0-Perl",
153
- "Artistic-1.0",
154
- "Artistic-2.0",
155
- "BSL-1.0",
156
- "BSD-2-Clause-FreeBSD",
157
- "BSD-2-Clause-NetBSD",
158
- "BSD-2-Clause",
159
- "BSD-3-Clause-Attribution",
160
- "BSD-3-Clause-Clear",
161
- "BSD-3-Clause-LBNL",
162
- "BSD-3-Clause",
163
- "BSD-4-Clause",
164
- "BSD-4-Clause-UC",
165
- "BSD-Protection",
166
- "CC-BY-1.0",
167
- "CC-BY-2.0",
168
- "CC-BY-2.5",
169
- "CC-BY-3.0",
170
- "CC-BY-4.0",
171
- "FTL",
172
- "ISC",
173
- "ImageMagick",
174
- "Libpng",
175
- "Lil-1.0",
176
- "Linux-OpenIB",
177
- "LPL-1.02",
178
- "LPL-1.0",
179
- "MS-PL",
180
- "MIT",
181
- "NCSA",
182
- "OpenSSL",
183
- "PHP-3.01",
184
- "PHP-3.0",
185
- "PIL",
186
- "Python-2.0",
187
- "Python-2.0-complete",
188
- "PostgreSQL",
189
- "SGI-B-1.0",
190
- "SGI-B-1.1",
191
- "SGI-B-2.0",
192
- "Unicode-DFS-2015",
193
- "Unicode-DFS-2016",
194
- "Unicode-TOU",
195
- "UPL-1.0",
196
- "W3C-19980720",
197
- "W3C-20150513",
198
- "W3C",
199
- "X11",
200
- "Xnet",
201
- "Zend-2.0",
202
- "zlib-acknowledgement",
203
- "Zlib",
204
- "ZPL-1.1",
205
- "ZPL-2.0",
206
- "ZPL-2.1"
207
- ],
208
- // https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L324
209
- unencumbered: ["CC0-1.0", "Unlicense", "0BSD"]
210
- };
211
- function buildAllowSet(config) {
212
- const set = /* @__PURE__ */ new Set();
213
- for (const group of config.groups) {
214
- for (const license of licenseGroups[group]) {
215
- set.add(license);
216
- }
217
- }
218
- if (config.allow) {
219
- for (const license of config.allow) {
220
- set.add(license);
221
- }
222
- }
223
- if (config.deny) {
224
- for (const license of config.deny) {
225
- set.delete(license);
226
- }
227
- }
228
- return set;
229
- }
230
- function isLicenseAllowed(licenseString, allowSet) {
231
- if (/\s+(?:OR|AND)\s+/i.test(licenseString)) {
232
- const licenses = licenseString.replace(/[()]/g, "").trim().split(/\s+(?:OR|AND)\s+/i).map((l) => l.trim()).filter((l) => l.length > 0);
233
- return licenses.every((l) => allowSet.has(l));
234
- }
235
- return allowSet.has(licenseString);
236
- }
237
- function runLicenseList() {
238
- for (const [group, licenses] of Object.entries(licenseGroups)) {
239
- console.log(`${group} (${licenses.length} licenses):`);
240
- for (const license of licenses) {
241
- console.log(` ${license}`);
242
- }
243
- console.log();
244
- }
245
- return 0;
246
- }
247
- function runLicenseCheck(configPath) {
248
- const raw = fs2.readFileSync(configPath, "utf-8");
249
- const config = JSON.parse(raw);
250
- const validGroups = Object.keys(licenseGroups);
251
- for (const group of config.groups) {
252
- if (!validGroups.includes(group)) {
253
- console.error(`Unknown license group: "${group}". Valid groups: ${validGroups.join(", ")}`);
254
- return 2;
255
- }
256
- }
257
- const allowSet = buildAllowSet(config);
258
- console.log("Checking licenses...\n");
259
- execSync("pnpm licenses list", { stdio: "inherit" });
260
- const output = execSync("pnpm licenses list --json");
261
- const licensesJson = JSON.parse(output.toString());
262
- const violations = [];
263
- for (const [license, packages] of Object.entries(licensesJson)) {
264
- if (!isLicenseAllowed(license, allowSet)) {
265
- for (const pkg of packages) {
266
- violations.push({ package: pkg.name, license });
267
- }
268
- }
269
- }
270
- if (violations.length === 0) {
271
- console.log("All licenses are allowed.");
272
- return 0;
273
- }
274
- console.error("Found dependencies with disallowed licenses:\n");
275
- for (const violation of violations) {
276
- console.error(` - ${violation.package}`);
277
- console.error(` License: ${violation.license}
278
- `);
279
- }
280
- return 1;
281
- }
282
-
283
- // src/commands/module/index.ts
284
- import { z as z2 } from "zod";
285
- import { defineCommand as defineCommand2, arg as arg2 } from "politty";
286
-
287
- // src/mdschema.ts
288
- import path3 from "path";
289
- import fs3 from "fs";
290
- import { execFile } from "child_process";
291
- import { createRequire } from "module";
292
- var require2 = createRequire(import.meta.url);
293
- function getMdschemaBin() {
294
- const pkgPath = require2.resolve("@jackchuka/mdschema/package.json");
295
- const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
296
- const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.mdschema;
297
- if (!bin) {
298
- throw new Error("Could not resolve mdschema binary from package.json bin field");
299
- }
300
- return path3.join(path3.dirname(pkgPath), bin);
301
- }
302
- function runMdschema(args, cwd5) {
303
- return new Promise((resolve4) => {
304
- execFile(
305
- getMdschemaBin(),
306
- args,
307
- { encoding: "utf-8", cwd: cwd5, timeout: 3e4 },
308
- (error, stdout, stderr) => {
309
- if (error) {
310
- const execError = error;
311
- resolve4({
312
- exitCode: execError.code === "ENOENT" ? 127 : execError.status ?? 1,
313
- stdout: stdout ?? "",
314
- stderr: stderr ?? ""
315
- });
316
- } else {
317
- resolve4({ exitCode: 0, stdout: stdout ?? "", stderr: stderr ?? "" });
318
- }
319
- }
320
- );
321
- });
322
- }
323
-
324
- // src/schemas.ts
325
- import path4 from "path";
326
- var SCHEMAS_ROOT = path4.join(PACKAGE_ROOT, "schemas");
327
- var MODULE_SCHEMAS = {
328
- module: path4.join(SCHEMAS_ROOT, "module", "module.yml"),
329
- command: path4.join(SCHEMAS_ROOT, "module", "command.yml"),
330
- model: path4.join(SCHEMAS_ROOT, "module", "model.yml"),
331
- feature: path4.join(SCHEMAS_ROOT, "module", "feature.yml"),
332
- query: path4.join(SCHEMAS_ROOT, "module", "query.yml")
333
- };
334
- var APP_COMPOSE_SCHEMAS = {
335
- requirements: path4.join(SCHEMAS_ROOT, "app-compose", "requirements.yml"),
336
- actors: path4.join(SCHEMAS_ROOT, "app-compose", "actors.yml"),
337
- "business-flow": path4.join(SCHEMAS_ROOT, "app-compose", "business-flow.yml"),
338
- story: path4.join(SCHEMAS_ROOT, "app-compose", "story.yml"),
339
- screen: path4.join(SCHEMAS_ROOT, "app-compose", "screen.yml"),
340
- resolver: path4.join(SCHEMAS_ROOT, "app-compose", "resolver.yml")
341
- };
342
- var ALL_SCHEMAS = {
343
- ...MODULE_SCHEMAS,
344
- ...APP_COMPOSE_SCHEMAS
345
- };
346
-
347
- // src/commands/check.ts
348
- function buildCheckTargets(config) {
349
- const targets = [];
350
- if (config.modulesRoot) {
351
- const m = config.modulesRoot;
352
- targets.push(
353
- { glob: `${m}/[a-zA-Z]*/docs/features/*.md`, schemaKey: "feature" },
354
- { glob: `${m}/[a-zA-Z]*/docs/commands/*.md`, schemaKey: "command" },
355
- { glob: `${m}/[a-zA-Z]*/docs/models/*.md`, schemaKey: "model" },
356
- { glob: `${m}/[a-zA-Z]*/docs/queries/*.md`, schemaKey: "query" },
357
- { glob: `${m}/[a-zA-Z]*/README.md`, schemaKey: "module" }
358
- );
359
- }
360
- if (config.appRoot) {
361
- const a = config.appRoot;
362
- targets.push(
363
- { glob: `${a}/[a-zA-Z]*/README.md`, schemaKey: "requirements" },
364
- { glob: `${a}/[a-zA-Z]*/docs/actors/*.md`, schemaKey: "actors" },
365
- { glob: `${a}/[a-zA-Z]*/docs/business-flow/*/README.md`, schemaKey: "business-flow" },
366
- { glob: `${a}/[a-zA-Z]*/docs/business-flow/*/story/*.md`, schemaKey: "story" },
367
- { glob: `${a}/[a-zA-Z]*/docs/screen/*.md`, schemaKey: "screen" },
368
- { glob: `${a}/[a-zA-Z]*/docs/resolver/*.md`, schemaKey: "resolver" }
369
- );
370
- }
371
- return targets;
372
- }
373
- async function runCheck(config, cwd5) {
374
- const targets = buildCheckTargets(config);
375
- const results = await Promise.all(
376
- targets.map(async (target) => {
377
- const schemaPath = ALL_SCHEMAS[target.schemaKey];
378
- if (!schemaPath) {
379
- console.error(`Unknown schema key: ${target.schemaKey}`);
380
- return 2;
381
- }
382
- const { exitCode, stdout, stderr } = await runMdschema(
383
- ["check", target.glob, "--schema", schemaPath],
384
- cwd5
385
- );
386
- if (stdout.trim()) console.log(stdout);
387
- if (stderr.trim()) console.error(stderr);
388
- return exitCode;
389
- })
390
- );
391
- if (results.includes(2)) return 2;
392
- return results.some((code) => code !== 0) ? 1 : 0;
393
- }
394
-
395
- // src/commands/sync-check.ts
396
- import path5 from "path";
397
- import fg from "fast-glob";
398
- import chalk2 from "chalk";
399
- function moduleCategories(root) {
400
- return [
401
- {
402
- name: "command",
403
- sourcePattern: `${root}/*/command/*.ts`,
404
- docPattern: `${root}/*/docs/commands/*.md`,
405
- exclusions: [/\.test\.ts$/, /\.generated\.ts$/]
406
- },
407
- {
408
- name: "model",
409
- sourcePattern: `${root}/*/db/*.ts`,
410
- docPattern: `${root}/*/docs/models/*.md`,
411
- exclusions: [/\.test\.ts$/, /^index\.ts$/]
412
- },
413
- {
414
- name: "query",
415
- sourcePattern: `${root}/*/query/*.ts`,
416
- docPattern: `${root}/*/docs/queries/*.md`,
417
- exclusions: [/\.test\.ts$/]
418
- }
419
- ];
420
- }
421
- function appComposeCategories(root) {
422
- return [
423
- {
424
- name: "resolver",
425
- sourcePattern: `${root}/*/backend/src/modules/**/resolvers/*.ts`,
426
- docPattern: `${root}/*/docs/resolver/*.md`,
427
- exclusions: [/\.test\.ts$/, /^index\.ts$/]
428
- }
429
- ];
430
- }
431
- function shouldExclude(fileName, exclusions) {
432
- return exclusions.some((pattern) => pattern.test(fileName));
433
- }
434
- async function runSyncCheck(config, cwd5) {
435
- const errors = [];
436
- let totalSources = 0;
437
- let totalDocs = 0;
438
- const allCategories = [];
439
- if (config.modulesRoot) {
440
- allCategories.push(...moduleCategories(config.modulesRoot));
441
- }
442
- if (config.appRoot) {
443
- allCategories.push(...appComposeCategories(config.appRoot));
444
- }
445
- for (const category of allCategories) {
446
- const sources = await fg(category.sourcePattern, { cwd: cwd5 });
447
- const docs = await fg(category.docPattern, { cwd: cwd5 });
448
- const sourceBasenames = /* @__PURE__ */ new Map();
449
- const docBasenames = /* @__PURE__ */ new Map();
450
- for (const sourcePath of sources) {
451
- const fileName = path5.basename(sourcePath);
452
- if (shouldExclude(fileName, category.exclusions)) continue;
453
- let basename2 = path5.basename(sourcePath, path5.extname(sourcePath));
454
- if (basename2.endsWith(".generated")) {
455
- basename2 = basename2.slice(0, -".generated".length);
456
- }
457
- sourceBasenames.set(basename2.toLowerCase(), sourcePath);
458
- }
459
- for (const docPath of docs) {
460
- const basename2 = path5.basename(docPath, path5.extname(docPath));
461
- docBasenames.set(basename2.toLowerCase(), docPath);
462
- }
463
- for (const [basename2, sourcePath] of sourceBasenames) {
464
- if (!docBasenames.has(basename2)) {
465
- errors.push({
466
- type: "missing-doc",
467
- category: category.name,
468
- sourcePath,
469
- expectedBasename: basename2
470
- });
471
- }
472
- }
473
- for (const [basename2, docPath] of docBasenames) {
474
- if (!sourceBasenames.has(basename2)) {
475
- errors.push({
476
- type: "orphaned-doc",
477
- category: category.name,
478
- docPath,
479
- expectedBasename: basename2
480
- });
481
- }
482
- }
483
- totalSources += sourceBasenames.size;
484
- totalDocs += docBasenames.size;
485
- }
486
- return {
487
- exitCode: errors.length > 0 ? 1 : 0,
488
- errors,
489
- summary: {
490
- categoriesChecked: allCategories.length,
491
- totalSources,
492
- totalDocs
493
- }
494
- };
495
- }
496
- function formatSyncCheckReport(result) {
497
- const lines = [];
498
- lines.push(chalk2.bold("docs-sync-check: Checking source-documentation correspondence...\n"));
499
- if (result.errors.length > 0) {
500
- lines.push(chalk2.red.bold("Errors:\n"));
501
- const byCategory = /* @__PURE__ */ new Map();
502
- for (const error of result.errors) {
503
- const existing = byCategory.get(error.category) ?? [];
504
- existing.push(error);
505
- byCategory.set(error.category, existing);
506
- }
507
- for (const [category, categoryErrors] of byCategory) {
508
- lines.push(chalk2.cyan(` Category: ${category}
509
- `));
510
- for (const error of categoryErrors) {
511
- if (error.type === "missing-doc") {
512
- lines.push(` ${chalk2.red(error.sourcePath)}`);
513
- lines.push(` ${chalk2.yellow("Missing documentation for:")} ${error.expectedBasename}`);
514
- } else {
515
- lines.push(` ${chalk2.red(error.docPath)}`);
516
- lines.push(
517
- ` ${chalk2.yellow("Orphaned documentation:")} no source file for ${error.expectedBasename}`
518
- );
519
- }
520
- lines.push("");
521
- }
522
- }
523
- } else {
524
- lines.push(chalk2.green("All source files have corresponding documentation.\n"));
525
- }
526
- lines.push(chalk2.bold("Summary:"));
527
- lines.push(` Categories checked: ${result.summary.categoriesChecked}`);
528
- lines.push(
529
- ` Source files: ${result.summary.totalSources}, Doc files: ${result.summary.totalDocs}`
530
- );
531
- if (result.errors.length > 0) {
532
- lines.push(chalk2.red(` Errors: ${result.errors.length}`));
533
- lines.push("");
534
- lines.push(chalk2.red.bold(`docs-sync-check failed with ${result.errors.length} error(s).`));
535
- } else {
536
- lines.push(chalk2.green(" Errors: 0"));
537
- lines.push("");
538
- lines.push(chalk2.green.bold("docs-sync-check passed."));
539
- }
540
- return lines.join("\n");
541
- }
542
-
543
- // src/commands/scaffold.ts
544
- import path6 from "path";
545
- import fs4 from "fs";
546
-
547
- // src/commands/scaffold-templates.ts
548
- function getModuleSrcTemplates() {
549
- return [
550
- { type: "dir", path: "db" },
551
- { type: "dir", path: "command" },
552
- { type: "dir", path: "executor" },
553
- { type: "dir", path: "generated" },
554
- { type: "dir", path: "query" },
555
- { type: "file", path: "module.ts", content: () => MODULE_TEMPLATE },
556
- { type: "file", path: "index.ts", content: () => INDEX_TEMPLATE },
557
- { type: "file", path: "permissions.ts", content: (n) => permissionsTemplate(n) },
558
- { type: "file", path: "tailor.config.ts", content: (n) => tailorConfigTemplate(n) },
559
- { type: "file", path: "lib/errors.ts", content: () => ERRORS_TEMPLATE },
560
- { type: "file", path: "lib/types.ts", content: () => TYPES_TEMPLATE },
561
- { type: "file", path: "testing/fixtures.ts", content: () => FIXTURES_TEMPLATE }
562
- ];
563
- }
564
- var MODULE_TEMPLATE = `export const defineModule = () => {
565
- return {
566
- db: {},
567
- commands: {},
568
- queries: {},
569
- };
570
- };
571
- `;
572
- var INDEX_TEMPLATE = `export { defineModule } from "./module";
573
- export { permissions, own, all } from "./permissions";
574
- `;
575
- var ERRORS_TEMPLATE = `import { createDomainError } from "../../shared/internal";
576
- `;
577
- var TYPES_TEMPLATE = `import type { InferSchema, Selectable, Insertable, Updateable } from "../../shared/internal";
578
- import type { DB } from "../generated/kysely-tailordb";
579
-
580
- export type Schema = InferSchema<DB>;
581
- `;
582
- var FIXTURES_TEMPLATE = `// Add test fixtures here
583
- `;
584
- function permissionsTemplate(moduleName) {
585
- return `import { definePermissions } from "../shared/internal";
586
-
587
- export const { permissions, own, all } = definePermissions("${moduleName}", [] as const);
588
- `;
589
- }
590
- function tailorConfigTemplate(moduleName) {
591
- return `import { defineConfig, defineGenerators } from "@tailor-platform/sdk";
592
-
593
- export default defineConfig({
594
- name: "${moduleName}",
595
- db: { "main-db": { files: [\`./db/*.ts\`] } },
596
- });
597
-
598
- export const generators = defineGenerators(
599
- ["@tailor-platform/kysely-type", { distPath: \`./generated/kysely-tailordb.ts\` }],
600
- ["@tailor-platform/enum-constants", { distPath: "./generated/enums.ts" }],
601
- );
602
- `;
603
- }
604
-
605
- // src/commands/scaffold.ts
606
- var MODULE_TYPES = ["module", "feature", "command", "model", "query"];
607
- var APP_TYPES = [
608
- "requirements",
609
- "actors",
610
- "business-flow",
611
- "story",
612
- "screen",
613
- "resolver"
614
- ];
615
- var ALL_TYPES = [...MODULE_TYPES, ...APP_TYPES];
616
- var MODULE_DIR_MAP = {
617
- feature: "docs/features",
618
- command: "docs/commands",
619
- model: "docs/models",
620
- query: "docs/queries"
621
- };
622
- var APP_DIR_MAP = {
623
- actors: "docs/actors",
624
- "business-flow": "docs/business-flow",
625
- screen: "docs/screen",
626
- resolver: "docs/resolver"
627
- };
628
- function resolveScaffoldPath(type, parentName, name, root) {
629
- if (type === "module" || type === "requirements") {
630
- return path6.join(root, parentName, "README.md");
631
- }
632
- if (!name) {
633
- throw new Error(`Name is required for scaffold type "${type}"`);
634
- }
635
- if (type === "business-flow") {
636
- return path6.join(root, parentName, "docs/business-flow", name, "README.md");
637
- }
638
- if (type === "story") {
639
- const parts = name.split("/");
640
- if (parts.length !== 2) {
641
- throw new Error(
642
- `Story name must be "<flow>/<story>" (e.g., "onboarding/admin--create-user")`
643
- );
644
- }
645
- return path6.join(root, parentName, "docs/business-flow", parts[0], "story", `${parts[1]}.md`);
646
- }
647
- if (MODULE_DIR_MAP[type]) {
648
- return path6.join(root, parentName, MODULE_DIR_MAP[type], `${name}.md`);
649
- }
650
- if (APP_DIR_MAP[type]) {
651
- return path6.join(root, parentName, APP_DIR_MAP[type], `${name}.md`);
652
- }
653
- throw new Error(`Unknown scaffold type: ${type}`);
654
- }
655
- async function runScaffold(type, parentName, name, root, cwd5) {
656
- const outputPath = resolveScaffoldPath(type, parentName, name, root);
657
- const absoluteOutput = path6.resolve(cwd5, outputPath);
658
- if (fs4.existsSync(absoluteOutput)) {
659
- console.error(`File already exists: ${outputPath}`);
660
- return 1;
661
- }
662
- const schemaPath = ALL_SCHEMAS[type];
663
- if (!schemaPath) {
664
- console.error(`No schema found for type: ${type}`);
665
- return 2;
666
- }
667
- try {
668
- fs4.mkdirSync(path6.dirname(absoluteOutput), { recursive: true });
669
- } catch (err) {
670
- console.error(
671
- `Failed to create directory: ${err instanceof Error ? err.message : String(err)}`
672
- );
673
- return 1;
674
- }
675
- const { exitCode, stdout, stderr } = await runMdschema(
676
- ["generate", "--schema", schemaPath, "--output", absoluteOutput],
677
- cwd5
678
- );
679
- if (stdout.trim()) console.log(stdout);
680
- if (stderr.trim()) console.error(stderr);
681
- if (exitCode !== 0) return exitCode;
682
- if (type === "module") {
683
- scaffoldModuleSrc(path6.dirname(absoluteOutput), parentName);
684
- }
685
- return exitCode;
686
- }
687
- function scaffoldModuleSrc(moduleDir, moduleName) {
688
- for (const entry of getModuleSrcTemplates()) {
689
- const fullPath = path6.join(moduleDir, entry.path);
690
- if (entry.type === "dir") {
691
- fs4.mkdirSync(fullPath, { recursive: true });
692
- fs4.writeFileSync(path6.join(fullPath, ".gitkeep"), "");
693
- } else {
694
- fs4.mkdirSync(path6.dirname(fullPath), { recursive: true });
695
- fs4.writeFileSync(fullPath, entry.content(moduleName));
696
- }
697
- }
698
- }
699
-
700
- // src/commands/module/list.ts
701
- import { readdirSync, existsSync } from "fs";
702
- import { join } from "path";
703
- import chalk3 from "chalk";
704
- var MODULES_DIR = join(PACKAGE_ROOT, "src", "modules");
705
- var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["shared", "testing"]);
706
- function countFiles(dir, pattern, exclusions) {
707
- if (!existsSync(dir)) return 0;
708
- return readdirSync(dir).filter((f) => pattern.test(f) && !exclusions.some((p) => p.test(f))).length;
709
- }
710
- function listModules() {
711
- if (!existsSync(MODULES_DIR)) return [];
712
- return readdirSync(MODULES_DIR, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DIRS.has(d.name)).map((d) => {
713
- const modDir = join(MODULES_DIR, d.name);
714
- return {
715
- name: d.name,
716
- commands: countFiles(join(modDir, "command"), /\.ts$/, [/\.test\.ts$/]),
717
- models: countFiles(join(modDir, "db"), /\.ts$/, [/\.test\.ts$/, /^index\.ts$/]),
718
- features: countFiles(join(modDir, "docs", "features"), /\.md$/, [])
719
- };
720
- }).sort((a, b) => a.name.localeCompare(b.name));
721
- }
722
- function formatModuleList(modules) {
723
- if (modules.length === 0) return "No modules found.";
724
- const lines = [];
725
- lines.push(chalk3.bold("Modules:\n"));
726
- const nameWidth = Math.max(...modules.map((m) => m.name.length), 4);
727
- for (const mod of modules) {
728
- const counts = [
729
- `${mod.commands} commands`,
730
- `${mod.models} models`,
731
- `${mod.features} features`
732
- ].join(", ");
733
- lines.push(` ${mod.name.padEnd(nameWidth)} ${counts}`);
734
- }
735
- lines.push("");
736
- lines.push(`${modules.length} modules`);
737
- return lines.join("\n");
738
- }
739
- function runModuleList() {
740
- const modules = listModules();
741
- console.log(formatModuleList(modules));
742
- return 0;
743
- }
744
-
745
- // src/commands/module/generate.ts
746
- import path8 from "path";
747
- import { defineCommand, arg } from "politty";
748
- import { z } from "zod";
749
-
750
- // src/generator/generate-code.ts
751
- import fs5 from "fs";
752
- import path7 from "path";
753
-
754
- // src/generator/parse-command-doc.ts
755
- import { fromMarkdown } from "mdast-util-from-markdown";
756
- import { toString } from "mdast-util-to-string";
757
- function parseCommandDoc(fileName, markdown) {
758
- const commandName = fileName.charAt(0).toLowerCase() + fileName.slice(1);
759
- const tree = fromMarkdown(markdown);
760
- return {
761
- commandName,
762
- errors: parseErrorScenarios(tree),
763
- externalDependencies: parseExternalDependencies(tree)
764
- };
765
- }
766
- function errorCodeToClassName(code) {
767
- const pascal = code.toLowerCase().split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
768
- return pascal + "Error";
769
- }
770
- function isHeading(node) {
771
- return node.type === "heading";
772
- }
773
- function isList(node) {
774
- return node.type === "list";
775
- }
776
- function getNodesUnderHeading(tree, headingText) {
777
- const nodes = [];
778
- let collecting = false;
779
- for (const node of tree.children) {
780
- if (isHeading(node)) {
781
- if (collecting) break;
782
- if (node.depth === 2 && toString(node) === headingText) {
783
- collecting = true;
784
- continue;
785
- }
786
- }
787
- if (collecting) {
788
- nodes.push(node);
789
- }
790
- }
791
- return nodes;
792
- }
793
- var ERROR_PATTERN = /^([A-Z_]+):\s*(.+)$/;
794
- function parseErrorScenarios(tree) {
795
- const nodes = getNodesUnderHeading(tree, "Error Scenarios");
796
- const errors = [];
797
- for (const node of nodes) {
798
- if (!isList(node)) continue;
799
- for (const item of node.children) {
800
- const text = toString(item);
801
- const match = ERROR_PATTERN.exec(text);
802
- if (match) {
803
- errors.push({ code: match[1], description: match[2].trim() });
804
- }
805
- }
806
- }
807
- return errors;
808
- }
809
- var DEPENDENCY_PATTERN = /^([^:]+)::(.+)$/;
810
- function parseExternalDependencies(tree) {
811
- const nodes = getNodesUnderHeading(tree, "External Dependencies");
812
- const deps = [];
813
- for (const node of nodes) {
814
- if (!isList(node)) continue;
815
- for (const item of node.children) {
816
- const firstChild = item.children[0];
817
- if (firstChild?.type !== "paragraph") continue;
818
- for (const inline of firstChild.children) {
819
- if (inline.type === "link" || inline.type === "linkReference") {
820
- const linkText = toString(inline);
821
- const match = DEPENDENCY_PATTERN.exec(linkText);
822
- if (match) {
823
- deps.push({ module: match[1], entity: match[2] });
824
- }
825
- }
826
- }
827
- }
828
- }
829
- return deps;
830
- }
831
-
832
- // src/generator/generate-code.ts
833
- function generateErrors(docs) {
834
- const seen = /* @__PURE__ */ new Set();
835
- const lines = [];
836
- for (const doc of docs) {
837
- for (const error of doc.errors) {
838
- if (seen.has(error.code)) continue;
839
- seen.add(error.code);
840
- const className = errorCodeToClassName(error.code);
841
- lines.push(`export const ${className} = createDomainError(`);
842
- lines.push(` "${className}", "${error.code}",`);
843
- const escapedDesc = error.description.replace(/`/g, "'");
844
- lines.push(` (identifier: string) => \`${escapedDesc}: \${identifier}\`,`);
845
- lines.push(`);`);
846
- lines.push(``);
847
- }
848
- }
849
- if (lines.length === 0) return "";
850
- return `// @generated \u2014 do not edit
851
- import { createDomainError } from "../../shared/internal";
852
-
853
- ${lines.join("\n")}`;
854
- }
855
- function generateCommandStub(doc) {
856
- const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
857
- const inputType = `${pascal}Input`;
858
- return `import { ok, type CommandContext } from "../../shared/internal";
859
- import type { DB } from "../generated/kysely-tailordb";
860
-
861
- export interface ${inputType} {
862
- // TODO: define input fields
863
- }
864
-
865
- export async function run(db: DB, input: ${inputType}, ctx: CommandContext) {
866
- // TODO: implement
867
- return ok({});
868
- }
869
- `;
870
- }
871
- function generateTestStub(doc) {
872
- const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
873
- return `import { describe, expect, it } from "vitest";
874
- import { createMockDb } from "../../testing/index";
875
- import type { CommandContext } from "../../shared/internal";
876
- import type { DB } from "../generated/kysely-tailordb";
877
- import { run, ${pascal}Input } from "./${doc.commandName}";
878
-
879
- describe("${doc.commandName} - test scenario", () => {
880
- const ctx: CommandContext = {
881
- actorId: "test-actor",
882
- permissions: ["TODO:${doc.commandName}"],
883
- };
884
-
885
- it("should be implemented", async () => {
886
- const { db } = createMockDb<DB>();
887
- const result = await run(db, {} as ${pascal}Input, ctx);
888
- expect(result.ok).toBe(true);
889
- });
890
- });
891
- `;
892
- }
893
- function generateCommandShell(doc) {
894
- const lines = [
895
- `// @generated \u2014 do not edit`,
896
- `import { defineCommand } from "../../shared/internal";`,
897
- `import { permissions } from "../lib/permissions.generated";`,
898
- `import { run } from "./${doc.commandName}";`,
899
- ``,
900
- `export const ${doc.commandName} = defineCommand(permissions.${doc.commandName}, run);`,
901
- ``
902
- ];
903
- return lines.join("\n");
904
- }
905
- function generateQueryShell(doc) {
906
- const lines = [
907
- `// @generated \u2014 do not edit`,
908
- `import { defineQuery } from "../../shared/internal";`,
909
- `import { run } from "./${doc.commandName}";`,
910
- ``,
911
- `export const ${doc.commandName} = defineQuery(run);`,
912
- ``
913
- ];
914
- return lines.join("\n");
915
- }
916
- function generateQueryStub(doc) {
917
- const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
918
- const inputType = `${pascal}Input`;
919
- return `import type { ReadonlyDB } from "../../shared/internal";
920
- import type { DB } from "../generated/kysely-tailordb";
921
-
922
- export interface ${inputType} {
923
- // TODO: define input fields
924
- }
925
-
926
- export async function run(db: ReadonlyDB<DB>, input: ${inputType}) {
927
- // TODO: implement
928
- return {};
929
- }
930
- `;
931
- }
932
- function generateQueryTestStub(doc) {
933
- const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
934
- const inputType = `${pascal}Input`;
935
- return `import { describe, expect, it } from "vitest";
936
- import { createMockDb } from "../../testing/index";
937
- import type { DB } from "../generated/kysely-tailordb";
938
- import { run, type ${inputType} } from "./${doc.commandName}";
939
-
940
- describe("${doc.commandName}", () => {
941
- it("should be implemented", async () => {
942
- const { db } = createMockDb<DB>();
943
- const result = await run(db, {} as ${inputType});
944
- expect(result).toBeDefined();
945
- });
946
- });
947
- `;
948
- }
949
- function generatePermissions(moduleName, commandNames) {
950
- const sorted = [...commandNames].sort();
951
- const entries = sorted.map((name) => ` "${name}",`).join("\n");
952
- return `// @generated \u2014 do not edit
953
- import { definePermissions } from "../../shared/internal";
954
-
955
- export const { permissions, own, all } = definePermissions("${moduleName}", [
956
- ${entries}
957
- ] as const);
958
- `;
959
- }
960
- function runGenerateCode(modulePath, moduleName) {
961
- const docsDir = path7.join(modulePath, "docs", "commands");
962
- const libDir = path7.join(modulePath, "lib");
963
- const commandDir = path7.join(modulePath, "command");
964
- if (!fs5.existsSync(docsDir)) {
965
- console.error(`No docs/commands/ directory found at ${docsDir}`);
966
- return 1;
967
- }
968
- const mdFiles = fs5.readdirSync(docsDir).filter((f) => f.endsWith(".md"));
969
- if (mdFiles.length === 0) {
970
- console.error(`No command docs found in ${docsDir}`);
971
- return 1;
972
- }
973
- const parsedDocs = [];
974
- for (const file of mdFiles) {
975
- const content = fs5.readFileSync(path7.join(docsDir, file), "utf-8");
976
- const name = path7.basename(file, ".md");
977
- parsedDocs.push(parseCommandDoc(name, content));
978
- }
979
- const queryDocsDir = path7.join(modulePath, "docs", "queries");
980
- const allDocsForErrors = [...parsedDocs];
981
- if (fs5.existsSync(queryDocsDir)) {
982
- const queryFiles = fs5.readdirSync(queryDocsDir).filter((f) => f.endsWith(".md"));
983
- for (const file of queryFiles) {
984
- const content = fs5.readFileSync(path7.join(queryDocsDir, file), "utf-8");
985
- const name = path7.basename(file, ".md");
986
- allDocsForErrors.push(parseCommandDoc(name, content));
987
- }
988
- }
989
- let generated = 0;
990
- const errorsContent = generateErrors(allDocsForErrors);
991
- if (errorsContent) {
992
- fs5.mkdirSync(libDir, { recursive: true });
993
- const errorsFile = path7.join(libDir, "errors.generated.ts");
994
- fs5.writeFileSync(errorsFile, errorsContent);
995
- console.log(` wrote ${path7.relative(modulePath, errorsFile)}`);
996
- generated++;
997
- }
998
- const commandNames = parsedDocs.map((d) => d.commandName);
999
- const permissionsContent = generatePermissions(moduleName, commandNames);
1000
- const permissionsFile = path7.join(libDir, "permissions.generated.ts");
1001
- fs5.writeFileSync(permissionsFile, permissionsContent);
1002
- console.log(` wrote ${path7.relative(modulePath, permissionsFile)}`);
1003
- generated++;
1004
- fs5.mkdirSync(commandDir, { recursive: true });
1005
- for (const doc of parsedDocs) {
1006
- const implFile = path7.join(commandDir, `${doc.commandName}.ts`);
1007
- const shellContent = generateCommandShell(doc);
1008
- const shellFile = path7.join(commandDir, `${doc.commandName}.generated.ts`);
1009
- fs5.writeFileSync(shellFile, shellContent);
1010
- console.log(` wrote ${path7.relative(modulePath, shellFile)}`);
1011
- generated++;
1012
- if (!fs5.existsSync(implFile)) {
1013
- fs5.writeFileSync(implFile, generateCommandStub(doc));
1014
- console.log(` scaffolded ${path7.relative(modulePath, implFile)}`);
1015
- }
1016
- const testFile = path7.join(commandDir, `${doc.commandName}.test.ts`);
1017
- if (!fs5.existsSync(testFile)) {
1018
- fs5.writeFileSync(testFile, generateTestStub(doc));
1019
- console.log(` scaffolded ${path7.relative(modulePath, testFile)}`);
1020
- }
1021
- }
1022
- if (fs5.existsSync(queryDocsDir)) {
1023
- const queryFiles = fs5.readdirSync(queryDocsDir).filter((f) => f.endsWith(".md"));
1024
- if (queryFiles.length > 0) {
1025
- const queryDir = path7.join(modulePath, "query");
1026
- fs5.mkdirSync(queryDir, { recursive: true });
1027
- for (const file of queryFiles) {
1028
- const content = fs5.readFileSync(path7.join(queryDocsDir, file), "utf-8");
1029
- const name = path7.basename(file, ".md");
1030
- const doc = parseCommandDoc(name, content);
1031
- const shellFile = path7.join(queryDir, `${doc.commandName}.generated.ts`);
1032
- fs5.writeFileSync(shellFile, generateQueryShell(doc));
1033
- console.log(` wrote ${path7.relative(modulePath, shellFile)}`);
1034
- generated++;
1035
- const implFile = path7.join(queryDir, `${doc.commandName}.ts`);
1036
- if (!fs5.existsSync(implFile)) {
1037
- fs5.writeFileSync(implFile, generateQueryStub(doc));
1038
- console.log(` scaffolded ${path7.relative(modulePath, implFile)}`);
1039
- }
1040
- const testFile = path7.join(queryDir, `${doc.commandName}.test.ts`);
1041
- if (!fs5.existsSync(testFile)) {
1042
- fs5.writeFileSync(testFile, generateQueryTestStub(doc));
1043
- console.log(` scaffolded ${path7.relative(modulePath, testFile)}`);
1044
- }
1045
- }
1046
- }
1047
- }
1048
- console.log(`Generated ${generated} file(s) for ${moduleName}`);
1049
- return 0;
1050
- }
1051
-
1052
- // src/commands/module/generate.ts
1053
- var cwd = process.cwd();
1054
- var codeCommand = defineCommand({
1055
- name: "code",
1056
- description: "Generate errors, permissions, command shells, and query shells from docs",
1057
- args: z.object({
1058
- root: arg(z.string(), {
1059
- alias: "r",
1060
- description: "Path to modules directory"
1061
- }),
1062
- module: arg(z.string(), {
1063
- positional: true,
1064
- description: "Module name (e.g., primitives, item-management)"
1065
- })
1066
- }),
1067
- run: (args) => {
1068
- const modulePath = path8.resolve(cwd, args.root, args.module);
1069
- console.log(`Generating code for ${args.module}...`);
1070
- const exitCode = runGenerateCode(modulePath, args.module);
1071
- process.exit(exitCode);
1072
- }
1073
- });
1074
- var generateCommand = defineCommand({
1075
- name: "generate",
1076
- description: "Generate code from model definitions and docs",
1077
- subCommands: {
1078
- code: codeCommand
1079
- }
1080
- });
1081
-
1082
- // src/commands/module/index.ts
1083
- var cwd2 = process.cwd();
1084
- var rootArgs = z2.object({
1085
- root: arg2(z2.string(), {
1086
- alias: "r",
1087
- description: "Path to modules directory"
1088
- })
1089
- });
1090
- var listCommand = defineCommand2({
1091
- name: "list",
1092
- description: "List available modules",
1093
- run: () => {
1094
- const exitCode = runModuleList();
1095
- process.exit(exitCode);
1096
- }
1097
- });
1098
- var checkCommand = defineCommand2({
1099
- name: "check",
1100
- description: "Validate module docs against schemas",
1101
- args: rootArgs,
1102
- run: async (args) => {
1103
- const exitCode = await runCheck({ modulesRoot: args.root }, cwd2);
1104
- process.exit(exitCode);
1105
- }
1106
- });
1107
- var syncCheckCommand = defineCommand2({
1108
- name: "sync-check",
1109
- description: "Validate source <-> doc correspondence",
1110
- args: rootArgs,
1111
- run: async (args) => {
1112
- const result = await runSyncCheck({ modulesRoot: args.root }, cwd2);
1113
- console.log(formatSyncCheckReport(result));
1114
- process.exit(result.exitCode);
1115
- }
1116
- });
1117
- var scaffoldCommand = defineCommand2({
1118
- name: "scaffold",
1119
- description: "Generate module doc from schema template",
1120
- args: rootArgs.extend({
1121
- type: arg2(z2.enum(MODULE_TYPES), {
1122
- positional: true,
1123
- description: `Scaffold type (${MODULE_TYPES.join(", ")})`
1124
- }),
1125
- parent: arg2(z2.string(), {
1126
- positional: true,
1127
- description: "Module name"
1128
- }),
1129
- name: arg2(z2.string().optional(), {
1130
- positional: true,
1131
- description: "Item name (required for feature, command, model)"
1132
- })
1133
- }),
1134
- run: async (args) => {
1135
- const exitCode = await runScaffold(
1136
- args.type,
1137
- args.parent,
1138
- args.name,
1139
- args.root,
1140
- cwd2
1141
- );
1142
- process.exit(exitCode);
1143
- }
1144
- });
1145
- var moduleCommand = defineCommand2({
1146
- name: "module",
1147
- description: "Module management",
1148
- subCommands: {
1149
- list: listCommand,
1150
- check: checkCommand,
1151
- "sync-check": syncCheckCommand,
1152
- scaffold: scaffoldCommand,
1153
- generate: generateCommand
1154
- }
1155
- });
1156
-
1157
- // src/commands/app/index.ts
1158
- import { z as z3 } from "zod";
1159
- import { defineCommand as defineCommand3, arg as arg3 } from "politty";
1160
- var cwd3 = process.cwd();
1161
- var rootArgs2 = z3.object({
1162
- root: arg3(z3.string(), {
1163
- alias: "r",
1164
- description: "Path to app-compose directory"
1165
- })
1166
- });
1167
- var checkCommand2 = defineCommand3({
1168
- name: "check",
1169
- description: "Validate app docs against schemas",
1170
- args: rootArgs2,
1171
- run: async (args) => {
1172
- const exitCode = await runCheck({ appRoot: args.root }, cwd3);
1173
- process.exit(exitCode);
1174
- }
1175
- });
1176
- var syncCheckCommand2 = defineCommand3({
1177
- name: "sync-check",
1178
- description: "Validate source <-> doc correspondence",
1179
- args: rootArgs2,
1180
- run: async (args) => {
1181
- const result = await runSyncCheck({ appRoot: args.root }, cwd3);
1182
- console.log(formatSyncCheckReport(result));
1183
- process.exit(result.exitCode);
1184
- }
1185
- });
1186
- var scaffoldCommand2 = defineCommand3({
1187
- name: "scaffold",
1188
- description: "Generate app doc from schema template",
1189
- args: rootArgs2.extend({
1190
- type: arg3(z3.enum(APP_TYPES), {
1191
- positional: true,
1192
- description: `Scaffold type (${APP_TYPES.join(", ")})`
1193
- }),
1194
- parent: arg3(z3.string(), {
1195
- positional: true,
1196
- description: "App name"
1197
- }),
1198
- name: arg3(z3.string().optional(), {
1199
- positional: true,
1200
- description: "Item name (required for most types)"
1201
- })
1202
- }),
1203
- run: async (args) => {
1204
- const exitCode = await runScaffold(
1205
- args.type,
1206
- args.parent,
1207
- args.name,
1208
- args.root,
1209
- cwd3
1210
- );
1211
- process.exit(exitCode);
1212
- }
1213
- });
1214
- var appCommand = defineCommand3({
1215
- name: "app",
1216
- description: "App-compose management",
1217
- subCommands: {
1218
- check: checkCommand2,
1219
- "sync-check": syncCheckCommand2,
1220
- scaffold: scaffoldCommand2
1221
- }
1222
- });
1223
-
1224
- // src/commands/mock/index.ts
1225
- import { z as z4 } from "zod";
1226
- import { defineCommand as defineCommand4, arg as arg4 } from "politty";
1227
-
1228
- // src/commands/mock/start.ts
1229
- import { createServer, request as httpRequest } from "http";
1230
- import { createServer as createNetServer } from "net";
1231
- import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
1232
- import { resolve as resolve2, relative, join as join2 } from "path";
1233
-
1234
- // src/mockServer.ts
1235
- import { readFileSync } from "fs";
1236
- import { dirname, resolve } from "path";
1237
- async function createMockServer(mockJsonPath, port) {
1238
- const { MockoonServer, createLoggerInstance, listenServerEvents } = await import("@mockoon/commons-server");
1239
- const resolvedPath = resolve(mockJsonPath);
1240
- const environment = JSON.parse(readFileSync(resolvedPath, "utf-8"));
1241
- if (port !== void 0) {
1242
- environment.port = port;
1243
- }
1244
- const actualPort = environment.port;
1245
- const logger = createLoggerInstance(null);
1246
- const server = new MockoonServer(environment, {
1247
- environmentDirectory: dirname(resolvedPath),
1248
- enableAdminApi: false,
1249
- disableTls: true,
1250
- enableRandomLatency: false,
1251
- maxTransactionLogs: 100,
1252
- envVarsPrefix: "MOCKOON_"
1253
- });
1254
- listenServerEvents(server, environment, logger, false);
1255
- await new Promise((resolve4, reject) => {
1256
- server.on("started", resolve4);
1257
- server.on("error", (errorCode, originalError) => {
1258
- reject(originalError ?? new Error(`Mockoon error: ${errorCode}`));
1259
- });
1260
- server.start();
1261
- });
1262
- return {
1263
- url: `http://127.0.0.1:${actualPort}`,
1264
- port: actualPort,
1265
- stop: () => new Promise((resolve4) => {
1266
- server.on("stopped", resolve4);
1267
- server.stop();
1268
- })
1269
- };
1270
- }
1271
-
1272
- // src/commands/mock/start.ts
1273
- function readdirSafe(dir) {
1274
- try {
1275
- return readdirSync2(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1276
- } catch {
1277
- return [];
1278
- }
1279
- }
1280
- function discoverMocks(mocksDir, filters) {
1281
- const mocks = [];
1282
- for (const provider of readdirSafe(mocksDir)) {
1283
- const providerDir = join2(mocksDir, provider);
1284
- for (const scenario of readdirSafe(providerDir)) {
1285
- const mockPath = join2(providerDir, scenario, "mock.json");
1286
- if (!existsSync2(mockPath)) continue;
1287
- mocks.push({ provider, scenario, mockPath });
1288
- }
1289
- }
1290
- if (filters.length === 0) return mocks;
1291
- return mocks.filter(
1292
- ({ provider, scenario }) => filters.some((f) => f === provider || f === `${provider}/${scenario}`)
1293
- );
1294
- }
1295
- function findFreePort() {
1296
- return new Promise((resolve4, reject) => {
1297
- const srv = createNetServer();
1298
- srv.listen(0, "127.0.0.1", () => {
1299
- const addr = srv.address();
1300
- const port = typeof addr === "object" && addr ? addr.port : 0;
1301
- srv.close(() => resolve4(port));
1302
- });
1303
- srv.on("error", reject);
1304
- });
1305
- }
1306
- async function startMock(mock) {
1307
- const port = await findFreePort();
1308
- const server = await createMockServer(mock.mockPath, port);
1309
- const route = `/${mock.provider}/${mock.scenario}`;
1310
- return { server, route, provider: mock.provider, scenario: mock.scenario };
1311
- }
1312
- function createProxy(routeTable) {
1313
- return createServer((req, res) => {
1314
- const match = req.url?.match(/^\/([^/?]+)\/([^/?]+)(\/[^?]*)?(\?.*)?$/);
1315
- if (!match) {
1316
- res.writeHead(404, { "Content-Type": "application/json" });
1317
- res.end(JSON.stringify({ error: "Not found. Use /{provider}/{scenario}/..." }));
1318
- return;
1319
- }
1320
- const [, provider, scenario] = match;
1321
- const key = `/${provider}/${scenario}`;
1322
- const target = routeTable.get(key);
1323
- if (!target) {
1324
- res.writeHead(404, { "Content-Type": "application/json" });
1325
- res.end(
1326
- JSON.stringify({
1327
- error: `Unknown route: ${key}`,
1328
- available: [...routeTable.keys()]
1329
- })
1330
- );
1331
- return;
1332
- }
1333
- const downstream = (req.url ?? "/").slice(key.length) || "/";
1334
- const proxyReq = httpRequest(
1335
- {
1336
- hostname: "127.0.0.1",
1337
- port: target.server.port,
1338
- path: downstream,
1339
- method: req.method,
1340
- headers: { ...req.headers, host: `127.0.0.1:${target.server.port}` }
1341
- },
1342
- (proxyRes) => {
1343
- res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
1344
- proxyRes.pipe(res);
1345
- }
1346
- );
1347
- proxyReq.on("error", (err) => {
1348
- if (!res.headersSent) {
1349
- res.writeHead(502, { "Content-Type": "application/json" });
1350
- }
1351
- res.end(JSON.stringify({ error: "Bad gateway", detail: err.message }));
1352
- });
1353
- req.pipe(proxyReq);
1354
- });
1355
- }
1356
- async function runMockStart(mocksRoot, filters, port) {
1357
- const mocksDir = resolve2(mocksRoot);
1358
- const mocks = discoverMocks(mocksDir, filters);
1359
- if (mocks.length === 0) {
1360
- console.error("No matching mocks found.");
1361
- if (filters.length > 0) {
1362
- console.error(`Filters: ${filters.join(", ")}`);
1363
- console.error(`Available mocks are under: ${relative(process.cwd(), mocksDir)}/`);
1364
- }
1365
- return 1;
1366
- }
1367
- console.log(`Starting ${mocks.length} mock(s)...
1368
- `);
1369
- const running = [];
1370
- for (const mock of mocks) {
1371
- const info = await startMock(mock);
1372
- running.push(info);
1373
- }
1374
- const routeTable = /* @__PURE__ */ new Map();
1375
- for (const r of running) {
1376
- routeTable.set(r.route, r);
1377
- }
1378
- console.log("Route table:");
1379
- console.log("\u2500".repeat(50));
1380
- for (const [route, { server }] of routeTable) {
1381
- console.log(` ${route} \u2192 127.0.0.1:${server.port}`);
1382
- }
1383
- console.log("\u2500".repeat(50));
1384
- const proxy = createProxy(routeTable);
1385
- proxy.listen(port, () => {
1386
- console.log(`
1387
- Reverse proxy listening on http://localhost:${port}`);
1388
- console.log("Press Ctrl+C to stop all mocks.\n");
1389
- });
1390
- function shutdown() {
1391
- console.log("\nShutting down...");
1392
- proxy.close();
1393
- for (const { server } of running) {
1394
- void server.stop();
1395
- }
1396
- process.exit(0);
1397
- }
1398
- process.on("SIGINT", shutdown);
1399
- process.on("SIGTERM", shutdown);
1400
- return new Promise(() => void 0);
1401
- }
1402
-
1403
- // src/commands/mock/validate.ts
1404
- import { readdir, readFile, stat } from "fs/promises";
1405
- import { join as join3, resolve as resolve3, relative as relative2, dirname as dirname2, basename } from "path";
1406
- import chalk4 from "chalk";
1407
- function pass(msg) {
1408
- console.log(chalk4.green(`\u2713 ${msg}`));
1409
- }
1410
- function fail(ctx, msg) {
1411
- console.log(chalk4.red(`\u2717 ${msg}`));
1412
- ctx.failures++;
1413
- }
1414
- async function subdirs(dir) {
1415
- const entries = await readdir(dir);
1416
- const dirs = [];
1417
- for (const entry of entries) {
1418
- const full = join3(dir, entry);
1419
- const s = await stat(full);
1420
- if (s.isDirectory()) dirs.push(entry);
1421
- }
1422
- return dirs.sort();
1423
- }
1424
- function checkStructure(ctx, entries, label) {
1425
- if (entries.includes("README.md")) {
1426
- pass(`${label}: has README.md`);
1427
- } else {
1428
- fail(ctx, `${label}: missing README.md`);
1429
- }
1430
- if (entries.includes("mock.json")) {
1431
- pass(`${label}: has mock.json`);
1432
- return true;
1433
- }
1434
- fail(ctx, `${label}: missing mock.json`);
1435
- return false;
1436
- }
1437
- async function checkSchema(ctx, data, label) {
1438
- const commons = await import("@mockoon/commons");
1439
- const schema = commons.EnvironmentSchemaNoFix;
1440
- const result = schema.validate(data, { abortEarly: false });
1441
- if (!result.error) {
1442
- pass(`${label}: valid Mockoon schema`);
1443
- } else {
1444
- for (const detail of result.error.details) {
1445
- fail(ctx, `${label}: schema \u2014 ${detail.message}`);
1446
- }
1447
- }
1448
- }
1449
- function checkResponseQuality(ctx, data, label) {
1450
- const routes = data.routes ?? [];
1451
- for (const route of routes) {
1452
- for (const resp of route.responses ?? []) {
1453
- const respLabel = `${label} \u2192 ${route.uuid}/${resp.uuid}`;
1454
- const headers = resp.headers ?? [];
1455
- const hasContentType = headers.some((h) => h.key.toLowerCase() === "content-type");
1456
- if (hasContentType) {
1457
- pass(`${respLabel}: has Content-Type`);
1458
- } else {
1459
- fail(ctx, `${respLabel}: missing Content-Type header`);
1460
- }
1461
- if (resp.label && resp.label.trim().length > 0) {
1462
- pass(`${respLabel}: has label "${resp.label}"`);
1463
- } else {
1464
- fail(ctx, `${respLabel}: missing or empty label`);
1465
- }
1466
- }
1467
- }
1468
- }
1469
- function checkDatabucketRefs(ctx, data, label) {
1470
- const bucketIds = new Set((data.data ?? []).map((d) => d.id));
1471
- for (const route of data.routes ?? []) {
1472
- for (const resp of route.responses ?? []) {
1473
- if (resp.bodyType === "DATABUCKET") {
1474
- const respLabel = `${label} \u2192 ${route.uuid}/${resp.uuid}`;
1475
- if (resp.databucketID && bucketIds.has(resp.databucketID)) {
1476
- pass(`${respLabel}: databucket "${resp.databucketID}" exists`);
1477
- } else {
1478
- fail(ctx, `${respLabel}: databucketID "${resp.databucketID}" not found in data array`);
1479
- }
1480
- }
1481
- }
1482
- }
1483
- }
1484
- async function discoverAllScenarios(mocksDir) {
1485
- const scenarios = [];
1486
- const providers = await subdirs(mocksDir);
1487
- for (const provider of providers) {
1488
- const providerDir = join3(mocksDir, provider);
1489
- for (const scenario of await subdirs(providerDir)) {
1490
- scenarios.push(`${provider}/${scenario}`);
1491
- }
1492
- }
1493
- return scenarios;
1494
- }
1495
- function resolveScenarioDir(arg6) {
1496
- const abs = resolve3(arg6);
1497
- if (basename(abs) === "mock.json") return dirname2(abs);
1498
- return abs;
1499
- }
1500
- async function validateScenario(ctx, scenarioDir, mocksDir) {
1501
- const label = relative2(mocksDir, scenarioDir);
1502
- console.log(chalk4.bold(`
1503
- \u2500\u2500 ${label} \u2500\u2500`));
1504
- let entries;
1505
- try {
1506
- entries = await readdir(scenarioDir);
1507
- } catch {
1508
- fail(ctx, `${label}: directory not found`);
1509
- return;
1510
- }
1511
- const hasMock = checkStructure(ctx, entries, label);
1512
- if (!hasMock) return;
1513
- const mockPath = join3(scenarioDir, "mock.json");
1514
- let data;
1515
- try {
1516
- data = JSON.parse(await readFile(mockPath, "utf-8"));
1517
- } catch (err) {
1518
- const errMsg = err instanceof Error ? err.message : String(err);
1519
- fail(ctx, `${label}: invalid JSON \u2014 ${errMsg}`);
1520
- return;
1521
- }
1522
- await checkSchema(ctx, data, label);
1523
- checkResponseQuality(ctx, data, label);
1524
- checkDatabucketRefs(ctx, data, label);
1525
- }
1526
- async function runMockValidate(mocksRoot, paths) {
1527
- const ctx = { failures: 0 };
1528
- const mocksDir = resolve3(mocksRoot);
1529
- const targets = paths.length > 0 ? paths.map(resolveScenarioDir) : (await discoverAllScenarios(mocksDir)).map((s) => join3(mocksDir, s));
1530
- if (targets.length === 0) {
1531
- fail(ctx, "No scenarios found under mocks/");
1532
- return 1;
1533
- }
1534
- console.log(chalk4.bold("\nValidating mock configs...\n"));
1535
- for (const target of targets) {
1536
- await validateScenario(ctx, target, mocksDir);
1537
- }
1538
- console.log(chalk4.bold("\n\u2500\u2500 summary \u2500\u2500"));
1539
- if (ctx.failures === 0) {
1540
- console.log(chalk4.green("\u2713 All checks passed"));
1541
- } else {
1542
- console.log(chalk4.red(`\u2717 ${ctx.failures} check(s) failed`));
1543
- }
1544
- return ctx.failures === 0 ? 0 : 1;
1545
- }
1546
-
1547
- // src/commands/mock/index.ts
1548
- var startCommand = defineCommand4({
1549
- name: "start",
1550
- description: "Start mock API servers with reverse proxy",
1551
- args: z4.object({
1552
- mocksRoot: arg4(z4.string().default("./mocks"), {
1553
- description: "Path to mocks directory"
1554
- }),
1555
- port: arg4(z4.coerce.number().default(3e3), {
1556
- alias: "p",
1557
- description: "Reverse proxy port"
1558
- }),
1559
- filter: arg4(z4.array(z4.string()).default([]), {
1560
- positional: true,
1561
- description: "Filter by provider or provider/scenario"
1562
- })
1563
- }),
1564
- run: async (args) => {
1565
- const exitCode = await runMockStart(args.mocksRoot, args.filter, args.port);
1566
- process.exit(exitCode);
1567
- }
1568
- });
1569
- var validateCommand = defineCommand4({
1570
- name: "validate",
1571
- description: "Validate mock scenario configs",
1572
- args: z4.object({
1573
- mocksRoot: arg4(z4.string().default("./mocks"), {
1574
- description: "Path to mocks directory"
1575
- }),
1576
- paths: arg4(z4.array(z4.string()).default([]), {
1577
- positional: true,
1578
- description: "Specific scenario paths to validate"
1579
- })
1580
- }),
1581
- run: async (args) => {
1582
- const exitCode = await runMockValidate(args.mocksRoot, args.paths);
1583
- process.exit(exitCode);
1584
- }
1585
- });
1586
- var mockCommand = defineCommand4({
1587
- name: "mock",
1588
- description: "Mock API server management",
1589
- subCommands: {
1590
- start: startCommand,
1591
- validate: validateCommand
1592
- }
1593
- });
1594
-
1595
- // src/commands/index.ts
1596
- var cwd4 = process.cwd();
1597
- var initCommand = defineCommand5({
1598
- name: "init",
1599
- description: "Set up consumer repo with framework skills",
1600
- args: z5.object({
1601
- force: arg5(z5.boolean().default(false), {
1602
- alias: "f",
1603
- description: "Overwrite existing skills"
1604
- })
1605
- }),
1606
- run: (args) => {
1607
- const exitCode = runInit(cwd4, args.force);
1608
- process.exit(exitCode);
1609
- }
1610
- });
1611
- var licenseCheckCommand = defineCommand5({
1612
- name: "check",
1613
- description: "Check dependency licenses against allowlist",
1614
- args: z5.object({
1615
- config: arg5(z5.string(), {
1616
- alias: "c",
1617
- description: "Path to license config JSON file"
1618
- })
1619
- }),
1620
- run: (args) => {
1621
- const exitCode = runLicenseCheck(args.config);
1622
- process.exit(exitCode);
1623
- }
1624
- });
1625
- var licenseListCommand = defineCommand5({
1626
- name: "list",
1627
- description: "List available license groups",
1628
- run: () => {
1629
- const exitCode = runLicenseList();
1630
- process.exit(exitCode);
1631
- }
1632
- });
1633
- var licenseCommand = defineCommand5({
1634
- name: "license",
1635
- description: "License management",
1636
- subCommands: {
1637
- check: licenseCheckCommand,
1638
- list: licenseListCommand
1639
- }
1640
- });
1641
- var mainCommand = defineCommand5({
1642
- name: "erp-kit",
1643
- description: "ERP module framework CLI",
1644
- subCommands: {
1645
- module: moduleCommand,
1646
- app: appCommand,
1647
- mock: mockCommand,
1648
- init: initCommand,
1649
- license: licenseCommand
1650
- }
1651
- });
1652
-
1653
- // src/cli.ts
1654
- void runMain(mainCommand);