@archi-code/ddd 0.0.0-stage → 3.0.0-alpha.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 (336) hide show
  1. package/LICENSE +46 -0
  2. package/README.md +2795 -2
  3. package/SKILL.md +106 -0
  4. package/ddd-skills/archi-code-ddd/imports.md +94 -0
  5. package/ddd-skills/archi-code-ddd/layers.md +314 -0
  6. package/ddd-skills/archi-code-ddd/patterns.md +683 -0
  7. package/ddd-skills/archi-code-ddd/what-not-to-do.md +196 -0
  8. package/ddd-skills/archi-code-ddd/where-each-class-goes.md +64 -0
  9. package/ddd-skills/ddd-agregados/GUIA.md +114 -0
  10. package/ddd-skills/ddd-agregados/references/consistencia-eventual.md +158 -0
  11. package/ddd-skills/ddd-agregados/references/ejemplo-ecommerce.md +52 -0
  12. package/ddd-skills/ddd-agregados/references/fabricas.md +193 -0
  13. package/ddd-skills/ddd-agregados/references/implementacion-ts.md +706 -0
  14. package/ddd-skills/ddd-arquitectura/GUIA.md +80 -0
  15. package/ddd-skills/ddd-arquitectura/assets/dependency-cruiser.cjs +99 -0
  16. package/ddd-skills/ddd-arquitectura/references/estilos-adicionales.md +51 -0
  17. package/ddd-skills/ddd-arquitectura/references/estructura-hexagonal-ts.md +406 -0
  18. package/ddd-skills/ddd-arquitectura/references/modulos.md +48 -0
  19. package/ddd-skills/ddd-auditoria-refactorizacion/GUIA.md +85 -0
  20. package/ddd-skills/ddd-auditoria-refactorizacion/references/ejemplo-auditoria.md +314 -0
  21. package/ddd-skills/ddd-auditoria-refactorizacion/references/lista-comprobacion.md +54 -0
  22. package/ddd-skills/ddd-auditoria-refactorizacion/references/plan-migracion.md +73 -0
  23. package/ddd-skills/ddd-auditoria-refactorizacion/scripts/scan_ddd_smells.py +264 -0
  24. package/ddd-skills/ddd-context-mapping/GUIA.md +83 -0
  25. package/ddd-skills/ddd-context-mapping/references/anticorrupcion-ts.md +419 -0
  26. package/ddd-skills/ddd-context-mapping/references/estilos-integracion.md +152 -0
  27. package/ddd-skills/ddd-event-sourcing-cqrs/GUIA.md +92 -0
  28. package/ddd-skills/ddd-event-sourcing-cqrs/references/event-sourcing-ts.md +476 -0
  29. package/ddd-skills/ddd-event-sourcing-cqrs/references/proyecciones-cqrs-ts.md +285 -0
  30. package/ddd-skills/ddd-eventos-dominio/GUIA.md +106 -0
  31. package/ddd-skills/ddd-eventos-dominio/references/diseno-eventos.md +130 -0
  32. package/ddd-skills/ddd-eventos-dominio/references/ejemplo-ecommerce.md +240 -0
  33. package/ddd-skills/ddd-eventos-dominio/references/publicacion-ts.md +529 -0
  34. package/ddd-skills/ddd-orquestador/GUIA.md +40 -0
  35. package/ddd-skills/ddd-orquestador/references/chuleta-reglas.md +35 -0
  36. package/ddd-skills/ddd-repositorios-persistencia/GUIA.md +121 -0
  37. package/ddd-skills/ddd-repositorios-persistencia/references/implementacion-ts.md +314 -0
  38. package/ddd-skills/ddd-repositorios-persistencia/references/tests-repositorios.md +191 -0
  39. package/ddd-skills/ddd-repositorios-persistencia/references/transacciones-ts.md +301 -0
  40. package/ddd-skills/ddd-servicios-capa-aplicacion/GUIA.md +99 -0
  41. package/ddd-skills/ddd-servicios-capa-aplicacion/references/capa-aplicacion-ts.md +264 -0
  42. package/ddd-skills/ddd-servicios-capa-aplicacion/references/ejemplo-ecommerce.md +321 -0
  43. package/ddd-skills/ddd-servicios-capa-aplicacion/references/servicios-dominio-ts.md +190 -0
  44. package/ddd-skills/ddd-value-objects-entidades/GUIA.md +118 -0
  45. package/ddd-skills/ddd-value-objects-entidades/references/ejemplo-ecommerce.md +87 -0
  46. package/ddd-skills/ddd-value-objects-entidades/references/entidades-ts.md +218 -0
  47. package/ddd-skills/ddd-value-objects-entidades/references/persistencia-valores.md +88 -0
  48. package/ddd-skills/ddd-value-objects-entidades/references/specification-y-diseno-flexible.md +119 -0
  49. package/ddd-skills/ddd-value-objects-entidades/references/validacion.md +96 -0
  50. package/ddd-skills/ddd-value-objects-entidades/references/value-objects-ts.md +376 -0
  51. package/dist/cjs/application/event/event-bus.d.ts +4 -0
  52. package/dist/cjs/application/event/event-bus.js +2 -0
  53. package/dist/cjs/application/event/event-listener.d.ts +4 -0
  54. package/dist/cjs/application/event/event-listener.js +6 -0
  55. package/dist/cjs/application/event/listens-to.d.ts +15 -0
  56. package/dist/cjs/application/event/listens-to.js +28 -0
  57. package/dist/cjs/application/exceptions/aggregate-not-found.exception.d.ts +5 -0
  58. package/dist/cjs/application/exceptions/aggregate-not-found.exception.js +17 -0
  59. package/dist/cjs/application/exceptions/application-exception-code.d.ts +7 -0
  60. package/dist/cjs/application/exceptions/application-exception-code.js +11 -0
  61. package/dist/cjs/application/exceptions/application.exception.d.ts +6 -0
  62. package/dist/cjs/application/exceptions/application.exception.js +16 -0
  63. package/dist/cjs/application/exceptions/concurrency.exception.d.ts +5 -0
  64. package/dist/cjs/application/exceptions/concurrency.exception.js +17 -0
  65. package/dist/cjs/application/exceptions/not-allowed.exception.d.ts +5 -0
  66. package/dist/cjs/application/exceptions/not-allowed.exception.js +17 -0
  67. package/dist/cjs/application/exceptions/unexpected-error.exception.d.ts +5 -0
  68. package/dist/cjs/application/exceptions/unexpected-error.exception.js +17 -0
  69. package/dist/cjs/application/index.d.ts +14 -0
  70. package/dist/cjs/application/index.js +23 -0
  71. package/dist/cjs/application/ports/clock.d.ts +3 -0
  72. package/dist/cjs/application/ports/clock.js +2 -0
  73. package/dist/cjs/application/ports/logger.d.ts +8 -0
  74. package/dist/cjs/application/ports/logger.js +2 -0
  75. package/dist/cjs/application/use-case/use-case.d.ts +6 -0
  76. package/dist/cjs/application/use-case/use-case.js +25 -0
  77. package/dist/cjs/application/value-object-builder/value-object-builder.d.ts +16 -0
  78. package/dist/cjs/application/value-object-builder/value-object-builder.js +51 -0
  79. package/dist/cjs/domain/aggregate/aggregate-root.d.ts +9 -0
  80. package/dist/cjs/domain/aggregate/aggregate-root.js +17 -0
  81. package/dist/cjs/domain/entity/entity.d.ts +9 -0
  82. package/dist/cjs/domain/entity/entity.js +19 -0
  83. package/dist/cjs/domain/event/event-base.d.ts +23 -0
  84. package/dist/cjs/domain/event/event-base.js +21 -0
  85. package/dist/cjs/domain/exceptions/domain-exception-code.d.ts +7 -0
  86. package/dist/cjs/domain/exceptions/domain-exception-code.js +11 -0
  87. package/dist/cjs/domain/exceptions/domain.exception.d.ts +6 -0
  88. package/dist/cjs/domain/exceptions/domain.exception.js +16 -0
  89. package/dist/cjs/domain/exceptions/invalid-event-definition.exception.d.ts +4 -0
  90. package/dist/cjs/domain/exceptions/invalid-event-definition.exception.js +19 -0
  91. package/dist/cjs/domain/exceptions/required-value.exception.d.ts +4 -0
  92. package/dist/cjs/domain/exceptions/required-value.exception.js +20 -0
  93. package/dist/cjs/domain/exceptions/type-primitive.exception.d.ts +4 -0
  94. package/dist/cjs/domain/exceptions/type-primitive.exception.js +20 -0
  95. package/dist/cjs/domain/exceptions/validation.exception.d.ts +14 -0
  96. package/dist/cjs/domain/exceptions/validation.exception.js +23 -0
  97. package/dist/cjs/domain/index.d.ts +17 -0
  98. package/dist/cjs/domain/index.js +36 -0
  99. package/dist/cjs/domain/primitive/primitive-types.d.ts +20 -0
  100. package/dist/cjs/domain/primitive/primitive-types.js +2 -0
  101. package/dist/cjs/domain/repository/aggregate-finder.d.ts +4 -0
  102. package/dist/cjs/domain/repository/aggregate-finder.js +2 -0
  103. package/dist/cjs/domain/repository/aggregate-remover.d.ts +4 -0
  104. package/dist/cjs/domain/repository/aggregate-remover.js +2 -0
  105. package/dist/cjs/domain/repository/aggregate-saver.d.ts +4 -0
  106. package/dist/cjs/domain/repository/aggregate-saver.js +2 -0
  107. package/dist/cjs/domain/specification/specification.d.ts +9 -0
  108. package/dist/cjs/domain/specification/specification.js +44 -0
  109. package/dist/cjs/domain/type/abstract-type.d.ts +18 -0
  110. package/dist/cjs/domain/type/abstract-type.js +61 -0
  111. package/dist/cjs/domain/type/array-type.d.ts +17 -0
  112. package/dist/cjs/domain/type/array-type.js +64 -0
  113. package/dist/cjs/domain/type/boolean-type.d.ts +4 -0
  114. package/dist/cjs/domain/type/boolean-type.js +16 -0
  115. package/dist/cjs/domain/type/composite/composite-brand.d.ts +4 -0
  116. package/dist/cjs/domain/type/composite/composite-brand.js +15 -0
  117. package/dist/cjs/domain/type/composite/composite-field.d.ts +18 -0
  118. package/dist/cjs/domain/type/composite/composite-field.js +86 -0
  119. package/dist/cjs/domain/type/composite/composite-issues.d.ts +6 -0
  120. package/dist/cjs/domain/type/composite/composite-issues.js +35 -0
  121. package/dist/cjs/domain/type/composite/composite.d.ts +26 -0
  122. package/dist/cjs/domain/type/composite/composite.js +51 -0
  123. package/dist/cjs/domain/type/date-type.d.ts +19 -0
  124. package/dist/cjs/domain/type/date-type.js +70 -0
  125. package/dist/cjs/domain/type/enum-type.d.ts +7 -0
  126. package/dist/cjs/domain/type/enum-type.js +30 -0
  127. package/dist/cjs/domain/type/id-type.d.ts +7 -0
  128. package/dist/cjs/domain/type/id-type.js +17 -0
  129. package/dist/cjs/domain/type/index.d.ts +15 -0
  130. package/dist/cjs/domain/type/index.js +29 -0
  131. package/dist/cjs/domain/type/json-type.d.ts +9 -0
  132. package/dist/cjs/domain/type/json-type.js +46 -0
  133. package/dist/cjs/domain/type/number-type.d.ts +4 -0
  134. package/dist/cjs/domain/type/number-type.js +16 -0
  135. package/dist/cjs/domain/type/required/required-mark.d.ts +8 -0
  136. package/dist/cjs/domain/type/required/required-mark.js +13 -0
  137. package/dist/cjs/domain/type/required/required-type.d.ts +7 -0
  138. package/dist/cjs/domain/type/required/required-type.js +21 -0
  139. package/dist/cjs/domain/type/string-type.d.ts +4 -0
  140. package/dist/cjs/domain/type/string-type.js +16 -0
  141. package/dist/cjs/domain/type/uuid-type.d.ts +7 -0
  142. package/dist/cjs/domain/type/uuid-type.js +27 -0
  143. package/dist/cjs/infrastructure/clock/fixed-clock.d.ts +8 -0
  144. package/dist/cjs/infrastructure/clock/fixed-clock.js +19 -0
  145. package/dist/cjs/infrastructure/clock/system-clock.d.ts +4 -0
  146. package/dist/cjs/infrastructure/clock/system-clock.js +9 -0
  147. package/dist/cjs/infrastructure/event/domain-event-bus.d.ts +16 -0
  148. package/dist/cjs/infrastructure/event/domain-event-bus.js +60 -0
  149. package/dist/cjs/infrastructure/event/event-channel.d.ts +9 -0
  150. package/dist/cjs/infrastructure/event/event-channel.js +2 -0
  151. package/dist/cjs/infrastructure/event/event-registry.d.ts +9 -0
  152. package/dist/cjs/infrastructure/event/event-registry.js +43 -0
  153. package/dist/cjs/infrastructure/event/in-memory/emitter.d.ts +11 -0
  154. package/dist/cjs/infrastructure/event/in-memory/emitter.js +54 -0
  155. package/dist/cjs/infrastructure/event/in-memory/in-memory-event-channel.d.ts +16 -0
  156. package/dist/cjs/infrastructure/event/in-memory/in-memory-event-channel.js +50 -0
  157. package/dist/cjs/infrastructure/exceptions/event-delivery.exception.d.ts +5 -0
  158. package/dist/cjs/infrastructure/exceptions/event-delivery.exception.js +20 -0
  159. package/dist/cjs/infrastructure/exceptions/infrastructure-exception-code.d.ts +6 -0
  160. package/dist/cjs/infrastructure/exceptions/infrastructure-exception-code.js +10 -0
  161. package/dist/cjs/infrastructure/exceptions/infrastructure.exception.d.ts +6 -0
  162. package/dist/cjs/infrastructure/exceptions/infrastructure.exception.js +16 -0
  163. package/dist/cjs/infrastructure/exceptions/internal-error.exception.d.ts +5 -0
  164. package/dist/cjs/infrastructure/exceptions/internal-error.exception.js +17 -0
  165. package/dist/cjs/infrastructure/exceptions/kind/exception-classifier.d.ts +4 -0
  166. package/dist/cjs/infrastructure/exceptions/kind/exception-classifier.js +34 -0
  167. package/dist/cjs/infrastructure/exceptions/kind/exception-kind.d.ts +9 -0
  168. package/dist/cjs/infrastructure/exceptions/kind/exception-kind.js +13 -0
  169. package/dist/cjs/infrastructure/exceptions/unknown-event.exception.d.ts +4 -0
  170. package/dist/cjs/infrastructure/exceptions/unknown-event.exception.js +19 -0
  171. package/dist/cjs/infrastructure/index.d.ts +21 -0
  172. package/dist/cjs/infrastructure/index.js +33 -0
  173. package/dist/cjs/infrastructure/logging/console-logger.d.ts +17 -0
  174. package/dist/cjs/infrastructure/logging/console-logger.js +37 -0
  175. package/dist/cjs/infrastructure/logging/in-memory-logger.d.ts +15 -0
  176. package/dist/cjs/infrastructure/logging/in-memory-logger.js +27 -0
  177. package/dist/cjs/infrastructure/logging/log-serializer.d.ts +7 -0
  178. package/dist/cjs/infrastructure/logging/log-serializer.js +59 -0
  179. package/dist/cjs/infrastructure/logging/silent-logger.d.ts +7 -0
  180. package/dist/cjs/infrastructure/logging/silent-logger.js +18 -0
  181. package/dist/cjs/shared/exceptions/abstract.exception.d.ts +25 -0
  182. package/dist/cjs/shared/exceptions/abstract.exception.js +59 -0
  183. package/dist/cjs/shared/exceptions/brand/exception-brand.d.ts +6 -0
  184. package/dist/cjs/shared/exceptions/brand/exception-brand.js +29 -0
  185. package/dist/cjs/shared/exceptions/received/received-value.d.ts +4 -0
  186. package/dist/cjs/shared/exceptions/received/received-value.js +13 -0
  187. package/dist/cjs/shared/index.d.ts +8 -0
  188. package/dist/cjs/shared/index.js +13 -0
  189. package/dist/cjs/shared/issue-collection-error.d.ts +9 -0
  190. package/dist/cjs/shared/issue-collection-error.js +11 -0
  191. package/dist/cjs/shared/issue-collector.d.ts +8 -0
  192. package/dist/cjs/shared/issue-collector.js +41 -0
  193. package/dist/esm/application/event/event-bus.d.ts +4 -0
  194. package/dist/esm/application/event/event-bus.js +1 -0
  195. package/dist/esm/application/event/event-listener.d.ts +4 -0
  196. package/dist/esm/application/event/event-listener.js +2 -0
  197. package/dist/esm/application/event/listens-to.d.ts +15 -0
  198. package/dist/esm/application/event/listens-to.js +25 -0
  199. package/dist/esm/application/exceptions/aggregate-not-found.exception.d.ts +5 -0
  200. package/dist/esm/application/exceptions/aggregate-not-found.exception.js +13 -0
  201. package/dist/esm/application/exceptions/application-exception-code.d.ts +7 -0
  202. package/dist/esm/application/exceptions/application-exception-code.js +8 -0
  203. package/dist/esm/application/exceptions/application.exception.d.ts +6 -0
  204. package/dist/esm/application/exceptions/application.exception.js +12 -0
  205. package/dist/esm/application/exceptions/concurrency.exception.d.ts +5 -0
  206. package/dist/esm/application/exceptions/concurrency.exception.js +13 -0
  207. package/dist/esm/application/exceptions/not-allowed.exception.d.ts +5 -0
  208. package/dist/esm/application/exceptions/not-allowed.exception.js +13 -0
  209. package/dist/esm/application/exceptions/unexpected-error.exception.d.ts +5 -0
  210. package/dist/esm/application/exceptions/unexpected-error.exception.js +13 -0
  211. package/dist/esm/application/index.d.ts +14 -0
  212. package/dist/esm/application/index.js +10 -0
  213. package/dist/esm/application/ports/clock.d.ts +3 -0
  214. package/dist/esm/application/ports/clock.js +1 -0
  215. package/dist/esm/application/ports/logger.d.ts +8 -0
  216. package/dist/esm/application/ports/logger.js +1 -0
  217. package/dist/esm/application/use-case/use-case.d.ts +6 -0
  218. package/dist/esm/application/use-case/use-case.js +21 -0
  219. package/dist/esm/application/value-object-builder/value-object-builder.d.ts +16 -0
  220. package/dist/esm/application/value-object-builder/value-object-builder.js +47 -0
  221. package/dist/esm/domain/aggregate/aggregate-root.d.ts +9 -0
  222. package/dist/esm/domain/aggregate/aggregate-root.js +13 -0
  223. package/dist/esm/domain/entity/entity.d.ts +9 -0
  224. package/dist/esm/domain/entity/entity.js +15 -0
  225. package/dist/esm/domain/event/event-base.d.ts +23 -0
  226. package/dist/esm/domain/event/event-base.js +17 -0
  227. package/dist/esm/domain/exceptions/domain-exception-code.d.ts +7 -0
  228. package/dist/esm/domain/exceptions/domain-exception-code.js +8 -0
  229. package/dist/esm/domain/exceptions/domain.exception.d.ts +6 -0
  230. package/dist/esm/domain/exceptions/domain.exception.js +12 -0
  231. package/dist/esm/domain/exceptions/invalid-event-definition.exception.d.ts +4 -0
  232. package/dist/esm/domain/exceptions/invalid-event-definition.exception.js +15 -0
  233. package/dist/esm/domain/exceptions/required-value.exception.d.ts +4 -0
  234. package/dist/esm/domain/exceptions/required-value.exception.js +16 -0
  235. package/dist/esm/domain/exceptions/type-primitive.exception.d.ts +4 -0
  236. package/dist/esm/domain/exceptions/type-primitive.exception.js +16 -0
  237. package/dist/esm/domain/exceptions/validation.exception.d.ts +14 -0
  238. package/dist/esm/domain/exceptions/validation.exception.js +19 -0
  239. package/dist/esm/domain/index.d.ts +17 -0
  240. package/dist/esm/domain/index.js +12 -0
  241. package/dist/esm/domain/primitive/primitive-types.d.ts +20 -0
  242. package/dist/esm/domain/primitive/primitive-types.js +1 -0
  243. package/dist/esm/domain/repository/aggregate-finder.d.ts +4 -0
  244. package/dist/esm/domain/repository/aggregate-finder.js +1 -0
  245. package/dist/esm/domain/repository/aggregate-remover.d.ts +4 -0
  246. package/dist/esm/domain/repository/aggregate-remover.js +1 -0
  247. package/dist/esm/domain/repository/aggregate-saver.d.ts +4 -0
  248. package/dist/esm/domain/repository/aggregate-saver.js +1 -0
  249. package/dist/esm/domain/specification/specification.d.ts +9 -0
  250. package/dist/esm/domain/specification/specification.js +40 -0
  251. package/dist/esm/domain/type/abstract-type.d.ts +18 -0
  252. package/dist/esm/domain/type/abstract-type.js +57 -0
  253. package/dist/esm/domain/type/array-type.d.ts +17 -0
  254. package/dist/esm/domain/type/array-type.js +60 -0
  255. package/dist/esm/domain/type/boolean-type.d.ts +4 -0
  256. package/dist/esm/domain/type/boolean-type.js +12 -0
  257. package/dist/esm/domain/type/composite/composite-brand.d.ts +4 -0
  258. package/dist/esm/domain/type/composite/composite-brand.js +11 -0
  259. package/dist/esm/domain/type/composite/composite-field.d.ts +18 -0
  260. package/dist/esm/domain/type/composite/composite-field.js +82 -0
  261. package/dist/esm/domain/type/composite/composite-issues.d.ts +6 -0
  262. package/dist/esm/domain/type/composite/composite-issues.js +31 -0
  263. package/dist/esm/domain/type/composite/composite.d.ts +26 -0
  264. package/dist/esm/domain/type/composite/composite.js +48 -0
  265. package/dist/esm/domain/type/date-type.d.ts +19 -0
  266. package/dist/esm/domain/type/date-type.js +64 -0
  267. package/dist/esm/domain/type/enum-type.d.ts +7 -0
  268. package/dist/esm/domain/type/enum-type.js +26 -0
  269. package/dist/esm/domain/type/id-type.d.ts +7 -0
  270. package/dist/esm/domain/type/id-type.js +13 -0
  271. package/dist/esm/domain/type/index.d.ts +15 -0
  272. package/dist/esm/domain/type/index.js +12 -0
  273. package/dist/esm/domain/type/json-type.d.ts +9 -0
  274. package/dist/esm/domain/type/json-type.js +42 -0
  275. package/dist/esm/domain/type/number-type.d.ts +4 -0
  276. package/dist/esm/domain/type/number-type.js +12 -0
  277. package/dist/esm/domain/type/required/required-mark.d.ts +8 -0
  278. package/dist/esm/domain/type/required/required-mark.js +9 -0
  279. package/dist/esm/domain/type/required/required-type.d.ts +7 -0
  280. package/dist/esm/domain/type/required/required-type.js +18 -0
  281. package/dist/esm/domain/type/string-type.d.ts +4 -0
  282. package/dist/esm/domain/type/string-type.js +12 -0
  283. package/dist/esm/domain/type/uuid-type.d.ts +7 -0
  284. package/dist/esm/domain/type/uuid-type.js +23 -0
  285. package/dist/esm/infrastructure/clock/fixed-clock.d.ts +8 -0
  286. package/dist/esm/infrastructure/clock/fixed-clock.js +15 -0
  287. package/dist/esm/infrastructure/clock/system-clock.d.ts +4 -0
  288. package/dist/esm/infrastructure/clock/system-clock.js +5 -0
  289. package/dist/esm/infrastructure/event/domain-event-bus.d.ts +16 -0
  290. package/dist/esm/infrastructure/event/domain-event-bus.js +56 -0
  291. package/dist/esm/infrastructure/event/event-channel.d.ts +9 -0
  292. package/dist/esm/infrastructure/event/event-channel.js +1 -0
  293. package/dist/esm/infrastructure/event/event-registry.d.ts +9 -0
  294. package/dist/esm/infrastructure/event/event-registry.js +39 -0
  295. package/dist/esm/infrastructure/event/in-memory/emitter.d.ts +11 -0
  296. package/dist/esm/infrastructure/event/in-memory/emitter.js +50 -0
  297. package/dist/esm/infrastructure/event/in-memory/in-memory-event-channel.d.ts +16 -0
  298. package/dist/esm/infrastructure/event/in-memory/in-memory-event-channel.js +46 -0
  299. package/dist/esm/infrastructure/exceptions/event-delivery.exception.d.ts +5 -0
  300. package/dist/esm/infrastructure/exceptions/event-delivery.exception.js +16 -0
  301. package/dist/esm/infrastructure/exceptions/infrastructure-exception-code.d.ts +6 -0
  302. package/dist/esm/infrastructure/exceptions/infrastructure-exception-code.js +7 -0
  303. package/dist/esm/infrastructure/exceptions/infrastructure.exception.d.ts +6 -0
  304. package/dist/esm/infrastructure/exceptions/infrastructure.exception.js +12 -0
  305. package/dist/esm/infrastructure/exceptions/internal-error.exception.d.ts +5 -0
  306. package/dist/esm/infrastructure/exceptions/internal-error.exception.js +13 -0
  307. package/dist/esm/infrastructure/exceptions/kind/exception-classifier.d.ts +4 -0
  308. package/dist/esm/infrastructure/exceptions/kind/exception-classifier.js +30 -0
  309. package/dist/esm/infrastructure/exceptions/kind/exception-kind.d.ts +9 -0
  310. package/dist/esm/infrastructure/exceptions/kind/exception-kind.js +10 -0
  311. package/dist/esm/infrastructure/exceptions/unknown-event.exception.d.ts +4 -0
  312. package/dist/esm/infrastructure/exceptions/unknown-event.exception.js +15 -0
  313. package/dist/esm/infrastructure/index.d.ts +21 -0
  314. package/dist/esm/infrastructure/index.js +15 -0
  315. package/dist/esm/infrastructure/logging/console-logger.d.ts +17 -0
  316. package/dist/esm/infrastructure/logging/console-logger.js +33 -0
  317. package/dist/esm/infrastructure/logging/in-memory-logger.d.ts +15 -0
  318. package/dist/esm/infrastructure/logging/in-memory-logger.js +23 -0
  319. package/dist/esm/infrastructure/logging/log-serializer.d.ts +7 -0
  320. package/dist/esm/infrastructure/logging/log-serializer.js +55 -0
  321. package/dist/esm/infrastructure/logging/silent-logger.d.ts +7 -0
  322. package/dist/esm/infrastructure/logging/silent-logger.js +14 -0
  323. package/dist/esm/package.json +3 -0
  324. package/dist/esm/shared/exceptions/abstract.exception.d.ts +25 -0
  325. package/dist/esm/shared/exceptions/abstract.exception.js +55 -0
  326. package/dist/esm/shared/exceptions/brand/exception-brand.d.ts +6 -0
  327. package/dist/esm/shared/exceptions/brand/exception-brand.js +25 -0
  328. package/dist/esm/shared/exceptions/received/received-value.d.ts +4 -0
  329. package/dist/esm/shared/exceptions/received/received-value.js +9 -0
  330. package/dist/esm/shared/index.d.ts +8 -0
  331. package/dist/esm/shared/index.js +5 -0
  332. package/dist/esm/shared/issue-collection-error.d.ts +9 -0
  333. package/dist/esm/shared/issue-collection-error.js +7 -0
  334. package/dist/esm/shared/issue-collector.d.ts +8 -0
  335. package/dist/esm/shared/issue-collector.js +37 -0
  336. package/package.json +95 -4
@@ -0,0 +1,88 @@
1
+ # Persistir value objects sin deformar el modelo
2
+
3
+ ## Principio
4
+
5
+ El modelo de datos se subordina al de dominio. Claves, integridad referencial e índices no deben dictar cómo se modelan los objetos [IDDD cap. 6]. El informe y la analítica, mejor sobre un modelo de datos propio y no sobre las tablas de producción [IDDD cap. 6].
6
+
7
+ Antes de convertir un valor en entidad "porque tiene tabla", responde [IDDD cap. 6]:
8
+ 1. ¿Es una cosa del dominio o mide, cuantifica o describe una cosa?
9
+ 2. ¿Tiene la mayoría de las características de valor?
10
+ 3. ¿Lo hago entidad solo porque el modelo de datos lo guarda como entidad?
11
+ 4. ¿El dominio exige identidad única, me importan los ejemplares y su continuidad de cambio?
12
+
13
+ "Describe, sí, sí, no" → value object.
14
+
15
+ ## Opciones
16
+
17
+ | Opción | Cuándo | Notas |
18
+ |---|---|---|
19
+ | Columnas en la fila del padre | Un único value object (`total_amount`, `total_currency`) | La opción por defecto y la más limpia [IDDD cap. 6] |
20
+ | Varios valores serializados en una columna (JSON) | Colecciones pequeñas que no se consultan por dentro | Cuidado con el tamaño de columna y la consulta [IDDD cap. 6]. En PostgreSQL, `jsonb` |
21
+ | Tabla propia para una colección | Colecciones grandes o que se consultan | La fila tiene clave técnica, pero en el modelo sigue siendo valor [IDDD cap. 6] |
22
+ | Tabla de unión | Colecciones referenciadas | Variante de la anterior [IDDD cap. 6] |
23
+ | Estado como enum | Tipos estándar | Guarda el código, no un objeto [IDDD cap. 6] |
24
+
25
+ *DDD in PHP* resume las mismas alternativas (valor embebido, serialización como LOB y mapeo ad hoc con el ORM) [PHP: Value Objects].
26
+
27
+ ## En TypeScript
28
+
29
+ `[Fuera de los libros: convención de @archi-code/ddd]`
30
+ * Nada de mappers escritos a mano ni decoradores de ORM en las clases de dominio. El agregado da sus datos planos con `toPrimitives()` y se rehace con `static fromPrimitives()`; el repositorio solo llama a `order.toPrimitives()` y `Order.fromPrimitives(...)`, y la versión de concurrencia la recuerda él mismo en un `WeakMap<Order, number>`, nunca el agregado. Nada comprueba en ejecución que no se pierda ningún campo privado: lo prueba el spec del agregado con el viaje de ida y vuelta (`Order.fromPrimitives(order.toPrimitives()).toPrimitives()` igual a `order.toPrimitives()`).
31
+ * Los primitivos ya dan la forma de cada opción de la tabla: un value object simple es su valor, un `Composite` es un objeto (`shippingAddress: { street, city, country }`), una lista de composites es una lista de objetos (`lines: { items: [...] }`) y un `EnumType` es la opción del enum (`status: 'pending'`).
32
+ * Con un almacén de documentos (MongoDB), los primitivos se guardan tal cual. Con tablas, el repositorio decide cómo se reparten en columnas: el formato de la fila sigue en infraestructura y no deforma el modelo.
33
+
34
+ ```ts
35
+ import type { PrimitiveTypes } from '@archi-code/ddd/domain';
36
+
37
+ type OrderPrimitives = PrimitiveTypes<Order>;
38
+
39
+ interface OrderRow {
40
+ id: string;
41
+ customer_id: string;
42
+ ship_street: string;
43
+ ship_city: string;
44
+ ship_country: string;
45
+ lines: OrderPrimitives['lines']['items'];
46
+ status: string;
47
+ stock_reservation: string | null;
48
+ payment_authorization: OrderPrimitives['paymentAuthorization'];
49
+ version: number;
50
+ }
51
+
52
+ function rowOf(order: Order, version: number): OrderRow {
53
+ const primitives = order.toPrimitives();
54
+ return {
55
+ id: primitives.id,
56
+ customer_id: primitives.customerId,
57
+ ship_street: primitives.shippingAddress.street,
58
+ ship_city: primitives.shippingAddress.city,
59
+ ship_country: primitives.shippingAddress.country,
60
+ lines: primitives.lines.items,
61
+ status: primitives.status,
62
+ stock_reservation: primitives.stockReservation,
63
+ payment_authorization: primitives.paymentAuthorization,
64
+ version: version + 1,
65
+ };
66
+ }
67
+
68
+ function orderOf(row: OrderRow): Order {
69
+ return Order.fromPrimitives({
70
+ id: row.id,
71
+ customerId: row.customer_id,
72
+ lines: { items: row.lines },
73
+ shippingAddress: {
74
+ street: row.ship_street,
75
+ city: row.ship_city,
76
+ country: row.ship_country,
77
+ },
78
+ status: row.status as Status,
79
+ stockReservation: row.stock_reservation,
80
+ paymentAuthorization: row.payment_authorization,
81
+ });
82
+ }
83
+ ```
84
+
85
+ `Order`, `ShippingAddress` y `Status` son los de `ddd-skills/ddd-agregados/references/implementacion-ts.md`. La dirección va en columnas de la fila del padre, las líneas y la autorización de pago en columnas JSON (`jsonb` en PostgreSQL) y el estado como su código. Con el driver `pg`, una columna `jsonb` se lee ya como objeto (la fecha de caducidad de la autorización llega como texto ISO, que `ExpiresAt` convierte), y al escribir el parámetro se pasa como `JSON.stringify(row.lines)` (un array sin convertir lo enviaría como array de PostgreSQL). La `version` se guarda junto a los primitivos, nunca dentro: `rowOf` recibe la que el repositorio recuerda para ese agregado en su `WeakMap` (`0` si es nuevo) y, tras cargar con `orderOf`, el repositorio anota `row.version` en ese `WeakMap`; la consulta con la condición de versión y cuándo se actualiza el `WeakMap` están en `ddd-skills/ddd-repositorios-persistencia/GUIA.md`.
86
+
87
+ * Al cargar, `fromPrimitives` rehace cada value object con su constructor, que valida: un dato corrupto falla al cargar (`ValidationException`) en vez de propagarse. No se repiten reglas de creación ni se registran eventos.
88
+ * Con Prisma o Drizzle, el esquema es de infraestructura y el repositorio sigue pasando por `order.toPrimitives()` y `Order.fromPrimitives()`.
@@ -0,0 +1,119 @@
1
+ # Specification y diseño flexible (Supple Design)
2
+
3
+ Contenido: 1. Diseño flexible · 2. Specification · 3. Specification para consultar · 4. Errores frecuentes
4
+
5
+ ## 1. Diseño flexible
6
+
7
+ Conjunto de patrones de Evans para que el modelo sea fácil de usar y de cambiar. IDDD aplica varios de ellos de forma explícita; los que no aparecen en las fuentes del proyecto se marcan `[Fuera de los libros: Evans, Domain-Driven Design, 2003]`.
8
+
9
+ ### Intention Revealing Interfaces
10
+
11
+ Los nombres de clases y métodos dicen **qué** consiguen, en el lenguaje ubicuo, no **cómo**. IDDD lo ilustra con `Tenant.activate()` y `deactivate()` en lugar de `setActive(boolean)`: varios setters para una sola petición vuelven ambigua la intención y complican publicar un único evento con significado [IDDD cap. 5, citando a Evans]. IDDD defiende también nombres fluidos (`valuePercentage()` frente a `getValuePercentage()`) [IDDD cap. 6].
12
+
13
+ ```ts
14
+ order.setStatus('cancelled');
15
+ price.amount.value * 21 / 100;
16
+ ```
17
+
18
+ ```ts
19
+ order.cancel(new CancellationReason('customer request'), clock);
20
+ price.percentage('21');
21
+ ```
22
+
23
+ El primero revela cómo; el segundo, la intención (`CancellationReason` es un `Required(StringType)` con nombre y `percentage` el de `Money` en `ddd-skills/ddd-value-objects-entidades/references/value-objects-ts.md`).
24
+
25
+ ### Side-Effect-Free Functions
26
+
27
+ Las operaciones que devuelven un resultado no cambian estado observable. En los value objects todos los métodos lo son, porque son inmutables [IDDD cap. 6]. Pasa solo valores como argumentos, no entidades: así se puede demostrar que no hay efectos secundarios [IDDD cap. 6]. Aplica también a entidades: separa consultas (devuelven algo, no cambian nada) de comandos (cambian estado, no devuelven datos de negocio).
28
+
29
+ ### Assertions
30
+
31
+ `[Fuera de los libros: Evans 2003]`. Cuando una operación sí tiene efectos, haz explícitos sus resultados y las invariantes que mantiene: en los tests (tests de aceptación con lenguaje del negocio) y en guardas del código. IDDD trata las guardas de autoencapsulación como aserciones que protegen el estado [IDDD cap. 5].
32
+
33
+ ### Conceptual Contours
34
+
35
+ `[Fuera de los libros: Evans 2003]`. Divide los objetos y operaciones siguiendo las líneas naturales del dominio, de modo que los cambios habituales del negocio afecten a una sola pieza. Señal práctica: si cada cambio de regla toca muchas clases a la vez, los contornos están mal trazados. Es la misma intuición que lleva a los "todos conceptuales" de los value objects [IDDD cap. 6].
36
+
37
+ ### Standalone Classes
38
+
39
+ `[Fuera de los libros: Evans 2003]`. Reduce las dependencias de cada clase al mínimo imprescindible. Los value objects que solo dependen de su propio tipo y de sus atributos son el caso ideal, y IDDD recomienda exactamente eso [IDDD cap. 6].
40
+
41
+ ### Closure of Operations
42
+
43
+ `[Fuera de los libros: Evans 2003]`. Cuando sea natural, una operación devuelve el mismo tipo que recibe: `Money.add(Money): Money`, `DateRange.extendTo(EndDate): DateRange`, `Specification.and(Specification): Specification`. Permite combinar operaciones sin introducir conceptos nuevos.
44
+
45
+ ## 2. Specification
46
+
47
+ Un objeto que responde si otro objeto cumple un criterio del negocio. Evans y Fowler lo describen; IDDD lo propone como forma de implementar validadores de objetos completos [IDDD cap. 5, citando a Evans y Fowler] y *DDD in PHP* lo usa para consultar repositorios [PHP: Repositories; PHP: Factories].
48
+
49
+ Tres usos clásicos `[Fuera de los libros: Evans 2003]`:
50
+ 1. **Validar:** ¿este objeto cumple la regla?
51
+ 2. **Seleccionar:** ¿qué objetos de una colección la cumplen?
52
+ 3. **Construir a la carta:** crear algo que cumpla la regla.
53
+
54
+ Cuándo merece la pena: la regla tiene nombre en el lenguaje ("cliente moroso", "pedido apto para envío urgente"), se usa en varios sitios o se combina con otras. Si es una condición de una línea usada una vez, un método del agregado basta.
55
+
56
+ No se escribe la base ni las combinaciones: `Specification<T>` viene de `@archi-code/ddd/domain`. Declara `isSatisfiedBy` como abstracto y da `and`, `or` y `not`, que devuelven otra `Specification<T>` (clausura de operaciones: se pueden seguir encadenando) y cortan en cuanto la respuesta está decidida. `and` y `or` aceptan cualquier `SatisfiedBy<T>` (un objeto con `isSatisfiedBy`), que es la interfaz `Specification` de los libros [IDDD cap. 5].
57
+
58
+ Reglas de negocio con nombre:
59
+
60
+ ```ts
61
+ import { Specification } from '@archi-code/ddd/domain';
62
+
63
+ export interface StockSnapshot {
64
+ covers(sku: Sku, quantity: Quantity): boolean;
65
+ }
66
+
67
+ export class EligibleForExpressShipping extends Specification<Order> {
68
+ constructor(private readonly centralStock: StockSnapshot) {
69
+ super();
70
+ }
71
+
72
+ isSatisfiedBy(order: Order): boolean {
73
+ return (
74
+ order.shippingAddress.country.value === 'ES' &&
75
+ order.lines.items.every((line) => this.centralStock.covers(line.sku, line.quantity))
76
+ );
77
+ }
78
+ }
79
+
80
+ export class OrderAbove extends Specification<Order> {
81
+ constructor(private readonly threshold: Money) {
82
+ super();
83
+ }
84
+
85
+ isSatisfiedBy(order: Order): boolean {
86
+ return order.total().covers(this.threshold);
87
+ }
88
+ }
89
+
90
+ const freeExpress = new EligibleForExpressShipping(stock).and(
91
+ new OrderAbove(Money.fromPrimitives({ amount: 5000, currency: 'EUR' })),
92
+ );
93
+ freeExpress.isSatisfiedBy(order);
94
+ ```
95
+
96
+ `Order`, `Money`, `Sku` y `Quantity` son los de `ddd-skills/ddd-agregados/references/implementacion-ts.md`. La especificación recibe datos de otros agregados ya cargados (`StockSnapshot`), no repositorios: misma regla que para los agregados [IDDD cap. 10].
97
+
98
+ ## 3. Specification para consultar
99
+
100
+ *DDD in PHP* propone sustituir los métodos `find...` que crecen sin fin en los repositorios por un método `query(specification)` [PHP: Repositories; PHP: Factories]. Aquí no se hace: el repositorio solo obtiene y persiste, sin lógica ni consultas de negocio `[Fuera de los libros: convención de @archi-code/ddd]`. Una selección con nombre del negocio ("pedidos pendientes desde hace más de un día") es una consulta de lectura: una interfaz en `application/`, implementada en infraestructura directamente sobre la base de datos, que devuelve ids o DTOs.
101
+
102
+ ```ts
103
+ export interface StaleOrders {
104
+ ids(pendingSince: Date, limit: number): Promise<OrderId[]>;
105
+ }
106
+ ```
107
+
108
+ La interfaz vive en `application/` y su implementación (`PgStaleOrders`, una consulta SQL; los filtros pueden escribirse con `@archi-code/criteria`) en infraestructura. Quien la usa (un programador de tareas, por ejemplo) ejecuta un caso de uso por cada id, y ese caso de uso carga el pedido con `AggregateFinder<Order>`.
109
+
110
+ La Specification se queda para validar, seleccionar sobre datos ya cargados o construir.
111
+
112
+ Úsalo con mesura `[Fuera de los libros]`: si acabas construyendo un lenguaje de consultas genérico, has reinventado el ORM. Para pantallas, mejor consultas de lectura (`ddd-skills/ddd-repositorios-persistencia/GUIA.md`).
113
+
114
+ ## 4. Errores frecuentes
115
+
116
+ * Especificaciones genéricas sin nombre de negocio (`FieldEqualsSpecification`).
117
+ * Especificaciones que cargan datos por su cuenta (inyectan repositorios).
118
+ * Usar Specification para invariantes del agregado: la invariante se protege dentro del agregado, siempre; la especificación sirve para validar, seleccionar o construir.
119
+ * Interfaces que revelan intención en el nombre pero no en el comportamiento: `confirm()` que en realidad también envía correos.
@@ -0,0 +1,96 @@
1
+ # Validación
2
+
3
+ ## Tres niveles
4
+
5
+ Que todos los atributos sean válidos no implica que el objeto lo sea, y que cada objeto sea válido no implica que su composición lo sea [IDDD cap. 5]. Por eso hay tres niveles [IDDD cap. 5; PHP: Entities]:
6
+
7
+ | Nivel | Qué comprueba | Dónde |
8
+ |---|---|---|
9
+ | Atributo | Un valor aislado: formato, rango, obligatoriedad | Constructor del value object (`Required(...)` y `@Validations`); un `Composite` con reglas `custom` para lo que combina sus campos |
10
+ | Objeto completo | Combinaciones de atributos de una entidad | La propia entidad en sus métodos, o un validador separado en el mismo módulo (un servicio de dominio o `Specification`s) |
11
+ | Composición | Varios objetos o agregados juntos | Servicio de dominio que recibe lo cargado o lee por `AggregateFinder` |
12
+
13
+ IDDD llama a lo del primer nivel más bien **aserciones** que protegen el estado, no "validación" en el sentido de un framework [IDDD cap. 5]. Con el paquete, un value object que existe es válido: su constructor convierte, comprueba `Required` y ejecuta todas sus reglas, y si falla alguna lanza una `ValidationException` con todas `[Fuera de los libros: convención de @archi-code/ddd]`. A eso se suma la autorización, que no es validación del modelo: la comprueba el caso de uso (`NotAllowedException`).
14
+
15
+ ## Objeto completo: ¿dentro o fuera de la entidad?
16
+
17
+ IDDD advierte que meter toda la validación en la entidad le da demasiadas responsabilidades y que la validación suele cambiar más que la entidad; propone un validador separado (Specification o Strategy) en el mismo módulo, con validación diferida [IDDD cap. 5].
18
+
19
+ Criterio práctico `[Fuera de los libros]`:
20
+ * **Invariantes** (lo que nunca puede ser falso: un pedido sin líneas) → en la entidad o el agregado, siempre. Se tratan en `ddd-skills/ddd-agregados/GUIA.md`.
21
+ * **Reglas de completitud o calidad** que dependen del momento ("para publicar, la ficha necesita al menos tres fotos") → validador separado, invocado cuando toca.
22
+
23
+ ## Patrón de notificación
24
+
25
+ Para devolver todos los errores en vez de parar en el primero, IDDD y *DDD in PHP* usan un manejador de notificación que recibe los fallos [IDDD cap. 5; PHP: Entities]. Con el paquete no se escribe ese manejador `[Fuera de los libros: convención de @archi-code/ddd]`:
26
+
27
+ * **Entrada de un caso de uso:** `ValueObjectBuilder.build({...})` ejecuta todas las factorías y lanza una sola `ValidationException` cuyos `errors` (`ValidationIssue`: `{ field, code, message }`) llevan el campo y el código de cada problema; `ValueObjectBuilder.buildList` nombra los elementos de una lista por su posición (`lines.1.quantity`).
28
+
29
+ ```ts
30
+ import { ValueObjectBuilder } from '@archi-code/ddd/application';
31
+
32
+ const command = ValueObjectBuilder.build({
33
+ customerId: () => new CustomerId(input.customerId),
34
+ email: () => new Email(input.email),
35
+ lines: () => ValueObjectBuilder.buildList(input.lines, (line) => OrderLine.fromPrimitives(line)),
36
+ });
37
+ // input { customerId: 'x', email: 'ana', lines: [...] } → una ValidationException:
38
+ // errors: [
39
+ // { field: 'customerId', code: 'DOM003', message: 'Validation Error: Expected a valid UUID, but received "x".' },
40
+ // { field: 'email', code: 'isEmail', message: 'Email: Value does not satisfy isEmail' },
41
+ // ]
42
+ ```
43
+
44
+ * **Un objeto ya construido** (la ficha de un producto que se quiere publicar, en el contexto de Catálogo): un servicio de dominio recoge los `ValidationIssue` y lanza una sola `new ValidationException(issues)`.
45
+
46
+ ```ts
47
+ import { ValidationException } from '@archi-code/ddd/domain';
48
+ import type { ValidationIssue } from '@archi-code/ddd/domain';
49
+
50
+ export class ListingReadyToPublish {
51
+ check(listing: ProductListing): void {
52
+ const issues: ValidationIssue[] = [];
53
+ if (listing.photos.value < 3) {
54
+ issues.push({ field: 'photos', code: 'tooFewPhotos', message: 'At least 3 photos' });
55
+ }
56
+ if (!listing.description.isLongEnough()) {
57
+ issues.push({ field: 'description', code: 'tooShort', message: 'Describe the product' });
58
+ }
59
+ if (listing.price.isZero()) {
60
+ issues.push({ field: 'price', code: 'zeroPrice', message: 'A listing needs a price' });
61
+ }
62
+ if (issues.length > 0) {
63
+ throw new ValidationException(issues);
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ `ProductListing` es un agregado con `photos` (`PhotoCount`), `description` (`ListingDescription`, con su método `isLongEnough()`) y `price` (`Money`). Nunca captures la `ValidationException` de un value object para quedarte con un valor inválido.
70
+
71
+ ## Validación diferida y estados intermedios
72
+
73
+ Un agregado puede estar en un estado intermedio legítimo en el que no procede validar. Se puede modelar con un estado y publicar un evento cuando la validación ya tiene sentido [IDDD cap. 5].
74
+
75
+ ## Interfaz frente a dominio
76
+
77
+ * La interfaz valida formato para dar buena experiencia (campo vacío, longitud). Eso no sustituye a la validación del modelo, donde vive el conocimiento profundo [IDDD cap. 4].
78
+ * No dupliques reglas de negocio en el esquema del DTO. Si el DTO comprueba "email válido" y `new Email(...)` también, que el DTO solo compruebe que es un `string` y deje la regla al value object `[Fuera de los libros]`. La entrada de un caso de uso llega sin validar a propósito: `toCommand` construye los value objects, así que todos los adaptadores pasan por las mismas reglas.
79
+
80
+ ## Errores con nombre
81
+
82
+ `[Fuera de los libros]`
83
+ * Una clase de error por regla de negocio (`OrderMustHaveLines`, `CurrencyMismatch`), con un código estable para traducir a mensajes de usuario y a códigos HTTP en el adaptador. Con el paquete, una subclase de `DomainException` (de `@archi-code/ddd/domain`) con su código en el segundo argumento.
84
+ * No uses `Error('invalid')` en el dominio.
85
+
86
+ ```ts
87
+ import { DomainException } from '@archi-code/ddd/domain';
88
+
89
+ export class OrderMustHaveLines extends DomainException {
90
+ constructor() {
91
+ super('An order needs at least one line', ['ORD002']);
92
+ }
93
+ }
94
+ ```
95
+
96
+ `error.code` es `'ORD002'`. En la entrada, `ExceptionClassifier.classify(error)` (de `@archi-code/ddd/infrastructure`) da el tipo de fallo sin tablas por excepción: `ExceptionKind.Invalid` para una `ValidationException` o cualquier `DomainException` (422 en HTTP) y `ExceptionKind.Malformed` para un error de conversión u obligatoriedad lanzado solo (400); el punto de entrada cambia el estado de un código cuando el negocio lo pide (`ORD001` → 409).