eva4j 1.0.13 → 1.0.15

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 (106) hide show
  1. package/AGENTS.md +314 -10
  2. package/COMMAND_EVALUATION.md +15 -16
  3. package/DOMAIN_YAML_GUIDE.md +576 -10
  4. package/FUTURE_FEATURES.md +1627 -1168
  5. package/README.md +318 -13
  6. package/bin/eva4j.js +34 -0
  7. package/config/defaults.json +1 -0
  8. package/design-system.md +797 -0
  9. package/docs/commands/EVALUATE_SYSTEM.md +994 -0
  10. package/docs/commands/GENERATE_ENTITIES.md +795 -6
  11. package/docs/commands/INDEX.md +10 -1
  12. package/examples/domain-endpoints-relations.yaml +353 -0
  13. package/examples/domain-endpoints-versioned.yaml +144 -0
  14. package/examples/domain-endpoints.yaml +135 -0
  15. package/examples/domain-events.yaml +166 -20
  16. package/examples/domain-listeners.yaml +212 -0
  17. package/examples/domain-one-to-many.yaml +1 -0
  18. package/examples/domain-one-to-one.yaml +1 -0
  19. package/examples/domain-ports.yaml +414 -0
  20. package/examples/domain-soft-delete.yaml +47 -44
  21. package/examples/system/notification.yaml +147 -0
  22. package/examples/system/product.yaml +185 -0
  23. package/examples/system/system.yaml +112 -0
  24. package/examples/system-report.html +971 -0
  25. package/examples/system.yaml +332 -0
  26. package/package.json +2 -1
  27. package/src/commands/build.js +714 -0
  28. package/src/commands/create.js +7 -3
  29. package/src/commands/detach.js +1 -0
  30. package/src/commands/evaluate-system.js +610 -0
  31. package/src/commands/generate-entities.js +1331 -49
  32. package/src/commands/generate-http-exchange.js +2 -0
  33. package/src/commands/generate-kafka-event.js +98 -11
  34. package/src/generators/base-generator.js +8 -1
  35. package/src/generators/postman-generator.js +188 -0
  36. package/src/generators/shared-generator.js +10 -0
  37. package/src/utils/config-manager.js +54 -0
  38. package/src/utils/context-builder.js +1 -0
  39. package/src/utils/domain-diagram.js +192 -0
  40. package/src/utils/domain-validator.js +970 -0
  41. package/src/utils/fake-data.js +376 -0
  42. package/src/utils/naming.js +3 -2
  43. package/src/utils/system-validator.js +434 -0
  44. package/src/utils/yaml-to-entity.js +302 -8
  45. package/templates/aggregate/AggregateMapper.java.ejs +3 -2
  46. package/templates/aggregate/AggregateRepository.java.ejs +8 -2
  47. package/templates/aggregate/AggregateRepositoryImpl.java.ejs +13 -3
  48. package/templates/aggregate/AggregateRoot.java.ejs +60 -2
  49. package/templates/aggregate/DomainEventHandler.java.ejs +27 -20
  50. package/templates/aggregate/DomainEventRecord.java.ejs +24 -8
  51. package/templates/aggregate/DomainEventSnapshot.java.ejs +46 -0
  52. package/templates/aggregate/JpaAggregateRoot.java.ejs +6 -0
  53. package/templates/aggregate/JpaRepository.java.ejs +5 -0
  54. package/templates/base/gradle/build.gradle.ejs +3 -2
  55. package/templates/base/root/AGENTS.md.ejs +306 -45
  56. package/templates/base/root/skill-build-domain-yaml-references-generate-entities.md.ejs +1663 -0
  57. package/templates/base/root/skill-build-system-yaml.ejs +1446 -0
  58. package/templates/base/root/system.yaml.ejs +97 -0
  59. package/templates/crud/ApplicationMapper.java.ejs +4 -0
  60. package/templates/crud/Controller.java.ejs +4 -4
  61. package/templates/crud/CreateCommand.java.ejs +4 -0
  62. package/templates/crud/CreateItemDto.java.ejs +4 -0
  63. package/templates/crud/CreateValueObjectDto.java.ejs +4 -0
  64. package/templates/crud/DeleteCommandHandler.java.ejs +10 -2
  65. package/templates/crud/EndpointsController.java.ejs +178 -0
  66. package/templates/crud/FindByQuery.java.ejs +17 -0
  67. package/templates/crud/FindByQueryHandler.java.ejs +57 -0
  68. package/templates/crud/ListQuery.java.ejs +1 -1
  69. package/templates/crud/ListQueryHandler.java.ejs +8 -8
  70. package/templates/crud/ScaffoldCommand.java.ejs +12 -0
  71. package/templates/crud/ScaffoldCommandHandler.java.ejs +43 -0
  72. package/templates/crud/ScaffoldQuery.java.ejs +13 -0
  73. package/templates/crud/ScaffoldQueryHandler.java.ejs +41 -0
  74. package/templates/crud/SubEntityAddCommand.java.ejs +21 -0
  75. package/templates/crud/SubEntityAddCommandHandler.java.ejs +43 -0
  76. package/templates/crud/SubEntityRemoveCommand.java.ejs +9 -0
  77. package/templates/crud/SubEntityRemoveCommandHandler.java.ejs +42 -0
  78. package/templates/crud/TransitionCommand.java.ejs +9 -0
  79. package/templates/crud/TransitionCommandHandler.java.ejs +39 -0
  80. package/templates/crud/UpdateCommand.java.ejs +4 -0
  81. package/templates/evaluate/report.html.ejs +1363 -0
  82. package/templates/kafka-event/DomainEventHandlerMethod.ejs +3 -1
  83. package/templates/kafka-event/Event.java.ejs +16 -0
  84. package/templates/kafka-listener/KafkaController.java.ejs +1 -1
  85. package/templates/kafka-listener/KafkaListenerClass.java.ejs +1 -1
  86. package/templates/kafka-listener/ListenerClass.java.ejs +65 -0
  87. package/templates/kafka-listener/ListenerCommand.java.ejs +31 -0
  88. package/templates/kafka-listener/ListenerCommandHandler.java.ejs +23 -0
  89. package/templates/kafka-listener/ListenerIntegrationEvent.java.ejs +37 -0
  90. package/templates/kafka-listener/ListenerMethod.java.ejs +1 -1
  91. package/templates/kafka-listener/ListenerNestedType.java.ejs +28 -0
  92. package/templates/mock/MockEvent.java.ejs +10 -0
  93. package/templates/mock/MockMessageBrokerImpl.java.ejs +35 -0
  94. package/templates/mock/MockMessageBrokerImplMethod.java.ejs +6 -0
  95. package/templates/mock/SpringEventListener.java.ejs +61 -0
  96. package/templates/ports/PortDomainModel.java.ejs +35 -0
  97. package/templates/ports/PortFeignAdapter.java.ejs +67 -0
  98. package/templates/ports/PortFeignClient.java.ejs +45 -0
  99. package/templates/ports/PortFeignConfig.java.ejs +24 -0
  100. package/templates/ports/PortInterface.java.ejs +45 -0
  101. package/templates/ports/PortNestedType.java.ejs +28 -0
  102. package/templates/ports/PortRequestDto.java.ejs +30 -0
  103. package/templates/ports/PortResponseDto.java.ejs +28 -0
  104. package/templates/postman/Collection.json.ejs +1 -1
  105. package/templates/postman/UnifiedCollection.json.ejs +185 -0
  106. package/templates/shared/configurations/eventPublicationConfig/EventPublicationSchemaConfig.java.ejs +109 -0
@@ -0,0 +1,147 @@
1
+ # ─────────────────────────────────────────────────────────────────────────────
2
+ # notification — Domain Model (Supporting Domain)
3
+ # ─────────────────────────────────────────────────────────────────────────────
4
+ # Dispatches notifications to users across multiple channels (EMAIL, SMS, PUSH).
5
+ # Tests: listeners (consuming ProductPublishedEvent + ProductDiscontinuedEvent),
6
+ # enum transitions with triggers, soft delete, scaffold endpoint.
7
+ # ─────────────────────────────────────────────────────────────────────────────
8
+
9
+ aggregates:
10
+
11
+ # ════════════════════════════════════════════════════════════════════════════
12
+ # Aggregate: Notification
13
+ # ════════════════════════════════════════════════════════════════════════════
14
+ - name: Notification
15
+ entities:
16
+ - name: Notification
17
+ isRoot: true
18
+ tableName: notifications
19
+ hasSoftDelete: true
20
+ audit:
21
+ enabled: true
22
+ trackUser: false
23
+ fields:
24
+ - name: id
25
+ type: String
26
+ - name: recipientId
27
+ type: String
28
+ validations:
29
+ - type: NotBlank
30
+ message: "Recipient ID is required"
31
+ - name: channel
32
+ type: NotificationChannel
33
+ validations:
34
+ - type: NotNull
35
+ message: "Channel is required"
36
+ - name: subject
37
+ type: String
38
+ validations:
39
+ - type: NotBlank
40
+ message: "Subject is required"
41
+ - name: message
42
+ type: String
43
+ validations:
44
+ - type: NotBlank
45
+ message: "Message is required"
46
+ - name: status
47
+ type: NotificationStatus
48
+ readOnly: true
49
+ - name: sentAt
50
+ type: LocalDateTime
51
+ readOnly: true
52
+ - name: readAt
53
+ type: LocalDateTime
54
+ readOnly: true
55
+
56
+ enums:
57
+ - name: NotificationChannel
58
+ values:
59
+ - EMAIL
60
+ - SMS
61
+ - PUSH
62
+
63
+ - name: NotificationStatus
64
+ initialValue: PENDING
65
+ transitions:
66
+ - from: PENDING
67
+ to: SENT
68
+ method: send
69
+ - from: SENT
70
+ to: READ
71
+ method: markRead
72
+ - from: [PENDING, SENT]
73
+ to: FAILED
74
+ method: fail
75
+ values:
76
+ - PENDING
77
+ - SENT
78
+ - READ
79
+ - FAILED
80
+
81
+ events:
82
+ # NotificationSentEvent — triggered by send transition
83
+ - name: NotificationSentEvent
84
+ triggers:
85
+ - send
86
+ fields:
87
+ - name: notificationId
88
+ type: String
89
+ - name: recipientId
90
+ type: String
91
+ - name: sentAt
92
+ type: LocalDateTime
93
+
94
+ # ─────────────────────────────────────────────────────────────────────────────
95
+ # Declarative REST endpoints
96
+ # ─────────────────────────────────────────────────────────────────────────────
97
+ endpoints:
98
+ basePath: /notifications
99
+ versions:
100
+ - version: v1
101
+ operations:
102
+ - useCase: CreateNotification
103
+ method: POST
104
+ path: /
105
+ - useCase: GetNotification
106
+ method: GET
107
+ path: /{id}
108
+ - useCase: FindAllNotifications
109
+ method: GET
110
+ path: /
111
+ - useCase: DeleteNotification
112
+ method: DELETE
113
+ path: /{id}
114
+ # Scaffold: MarkNotificationRead doesn't match transition pattern
115
+ # (transition method is markRead → MarkReadNotification, not MarkNotificationRead)
116
+ # → generates ScaffoldCommand stub with TODO
117
+ - useCase: MarkNotificationRead
118
+ method: PUT
119
+ path: /{id}/read
120
+
121
+ # ─────────────────────────────────────────────────────────────────────────────
122
+ # Consumed events (listeners)
123
+ # ─────────────────────────────────────────────────────────────────────────────
124
+ listeners:
125
+ - event: ProductPublishedEvent
126
+ producer: product
127
+ topic: PRODUCT_PUBLISHED
128
+ useCase: SendProductPublishedNotification
129
+ fields:
130
+ - name: productId
131
+ type: String
132
+ - name: name
133
+ type: String
134
+ - name: price
135
+ type: BigDecimal
136
+ - name: publishedAt
137
+ type: LocalDateTime
138
+
139
+ - event: ProductDiscontinuedEvent
140
+ producer: product
141
+ topic: PRODUCT_DISCONTINUED
142
+ useCase: SendProductDiscontinuedNotification
143
+ fields:
144
+ - name: productId
145
+ type: String
146
+ - name: discontinuedAt
147
+ type: LocalDateTime
@@ -0,0 +1,185 @@
1
+ # ─────────────────────────────────────────────────────────────────────────────
2
+ # product — Domain Model (Core Domain)
3
+ # ─────────────────────────────────────────────────────────────────────────────
4
+ # Manages the product catalog and categories. Two aggregates with separate
5
+ # lifecycles. Tests: multi-aggregate endpoints fix, VO-unwrap in raise(),
6
+ # transitions + triggers, cross-aggregate reference.
7
+ # ─────────────────────────────────────────────────────────────────────────────
8
+
9
+ aggregates:
10
+
11
+ # ════════════════════════════════════════════════════════════════════════════
12
+ # Aggregate: Product
13
+ # ════════════════════════════════════════════════════════════════════════════
14
+ - name: Product
15
+ entities:
16
+ - name: Product
17
+ isRoot: true
18
+ tableName: products
19
+ audit:
20
+ enabled: true
21
+ trackUser: true
22
+ fields:
23
+ - name: id
24
+ type: String
25
+ - name: name
26
+ type: String
27
+ validations:
28
+ - type: NotBlank
29
+ message: "Product name is required"
30
+ - name: description
31
+ type: String
32
+ - name: price
33
+ type: Price
34
+ validations:
35
+ - type: NotNull
36
+ message: "Price is required"
37
+ - name: categoryId
38
+ type: String
39
+ reference:
40
+ aggregate: Category
41
+ validations:
42
+ - type: NotBlank
43
+ message: "Category ID is required"
44
+ - name: status
45
+ type: ProductStatus
46
+ readOnly: true
47
+ - name: publishedAt
48
+ type: LocalDateTime
49
+ readOnly: true
50
+
51
+ valueObjects:
52
+ - name: Price
53
+ fields:
54
+ - name: amount
55
+ type: BigDecimal
56
+ - name: currency
57
+ type: String
58
+ methods:
59
+ - name: isPositive
60
+ returnType: boolean
61
+ parameters: []
62
+ body: "return this.amount != null && this.amount.compareTo(java.math.BigDecimal.ZERO) > 0;"
63
+
64
+ enums:
65
+ - name: ProductStatus
66
+ initialValue: DRAFT
67
+ transitions:
68
+ - from: DRAFT
69
+ to: PUBLISHED
70
+ method: publish
71
+ - from: PUBLISHED
72
+ to: DISCONTINUED
73
+ method: discontinue
74
+ - from: DRAFT
75
+ to: DISCONTINUED
76
+ method: discontinue
77
+ values:
78
+ - DRAFT
79
+ - PUBLISHED
80
+ - DISCONTINUED
81
+
82
+ events:
83
+ # ProductPublishedEvent — triggered by publish transition.
84
+ # price: BigDecimal tests VO-unwrap: entity.price is Price, event expects BigDecimal
85
+ # → generator should emit: this.getPrice().getAmount()
86
+ - name: ProductPublishedEvent
87
+ topic: PRODUCT_PUBLISHED
88
+ triggers:
89
+ - publish
90
+ fields:
91
+ - name: productId
92
+ type: String
93
+ - name: name
94
+ type: String
95
+ - name: price
96
+ type: BigDecimal
97
+ - name: publishedAt
98
+ type: LocalDateTime
99
+
100
+ # ProductDiscontinuedEvent — triggered by discontinue transition
101
+ - name: ProductDiscontinuedEvent
102
+ topic: PRODUCT_DISCONTINUED
103
+ triggers:
104
+ - discontinue
105
+ fields:
106
+ - name: productId
107
+ type: String
108
+ - name: discontinuedAt
109
+ type: LocalDateTime
110
+
111
+ # ════════════════════════════════════════════════════════════════════════════
112
+ # Aggregate: Category
113
+ # ════════════════════════════════════════════════════════════════════════════
114
+ - name: Category
115
+ entities:
116
+ - name: Category
117
+ isRoot: true
118
+ tableName: categories
119
+ audit:
120
+ enabled: true
121
+ trackUser: false
122
+ fields:
123
+ - name: id
124
+ type: String
125
+ - name: name
126
+ type: String
127
+ validations:
128
+ - type: NotBlank
129
+ message: "Category name is required"
130
+ - name: description
131
+ type: String
132
+
133
+ events:
134
+ # CategoryCreatedEvent — no triggers, raise() called manually in the handler
135
+ - name: CategoryCreatedEvent
136
+ fields:
137
+ - name: categoryId
138
+ type: String
139
+ - name: name
140
+ type: String
141
+
142
+ # ─────────────────────────────────────────────────────────────────────────────
143
+ # Declarative REST endpoints
144
+ # ─────────────────────────────────────────────────────────────────────────────
145
+ # Multi-aggregate: Product ops are classified to Product, Category ops to
146
+ # Category. Validates the cross-aggregate classification fix.
147
+ # ─────────────────────────────────────────────────────────────────────────────
148
+ endpoints:
149
+ basePath: /
150
+ versions:
151
+ - version: v1
152
+ operations:
153
+ # ── Product ───────────────────────────────────────────────────────────
154
+ - useCase: CreateProduct
155
+ method: POST
156
+ path: /products
157
+ - useCase: GetProduct
158
+ method: GET
159
+ path: /products/{id}
160
+ - useCase: FindAllProducts
161
+ method: GET
162
+ path: /products
163
+ - useCase: UpdateProduct
164
+ method: PUT
165
+ path: /products/{id}
166
+ - useCase: PublishProduct
167
+ method: PUT
168
+ path: /products/{id}/publish
169
+ - useCase: DiscontinueProduct
170
+ method: PUT
171
+ path: /products/{id}/discontinue
172
+
173
+ # ── Category ──────────────────────────────────────────────────────────
174
+ - useCase: CreateCategory
175
+ method: POST
176
+ path: /categories
177
+ - useCase: GetCategory
178
+ method: GET
179
+ path: /categories/{id}
180
+ - useCase: FindAllCategorys
181
+ method: GET
182
+ path: /categories
183
+ - useCase: UpdateCategory
184
+ method: PUT
185
+ path: /categories/{id}
@@ -0,0 +1,112 @@
1
+ system:
2
+ name: product-catalog
3
+ groupId: com.example
4
+ javaVersion: 21
5
+ springBootVersion: 3.5.5
6
+ database: postgresql
7
+
8
+ messaging:
9
+ enabled: true
10
+ broker: kafka
11
+ kafka:
12
+ bootstrapServers: localhost:9092
13
+ defaultGroupId: product-catalog
14
+ topicPrefix: catalog
15
+
16
+ modules:
17
+
18
+ # ─────────────────────────────────────────────
19
+ # CATÁLOGO DE PRODUCTOS
20
+ # ─────────────────────────────────────────────
21
+
22
+ - name: product
23
+ description: "Catálogo de productos y categorías. Gestiona el ciclo de vida de un producto (DRAFT → PUBLISHED → DISCONTINUED). Dos agregados: Product y Category."
24
+ exposes:
25
+ # ── Product ───────────────────────────────
26
+ - method: POST
27
+ path: /products
28
+ useCase: CreateProduct
29
+ description: "Crear nuevo producto en estado DRAFT"
30
+ - method: GET
31
+ path: /products/{id}
32
+ useCase: GetProduct
33
+ description: "Obtener detalle de un producto"
34
+ - method: GET
35
+ path: /products
36
+ useCase: FindAllProducts
37
+ description: "Listar productos con paginación"
38
+ - method: PUT
39
+ path: /products/{id}
40
+ useCase: UpdateProduct
41
+ description: "Actualizar datos de un producto en estado DRAFT"
42
+ - method: PUT
43
+ path: /products/{id}/publish
44
+ useCase: PublishProduct
45
+ description: "Publicar un producto: DRAFT → PUBLISHED. Emite ProductPublishedEvent."
46
+ - method: PUT
47
+ path: /products/{id}/discontinue
48
+ useCase: DiscontinueProduct
49
+ description: "Discontinuar un producto: PUBLISHED/DRAFT → DISCONTINUED"
50
+ # ── Category ──────────────────────────────
51
+ - method: POST
52
+ path: /categories
53
+ useCase: CreateCategory
54
+ description: "Crear nueva categoría de productos"
55
+ - method: GET
56
+ path: /categories/{id}
57
+ useCase: GetCategory
58
+ description: "Obtener detalle de una categoría"
59
+ - method: GET
60
+ path: /categories
61
+ useCase: FindAllCategorys
62
+ description: "Listar categorías con paginación"
63
+ - method: PUT
64
+ path: /categories/{id}
65
+ useCase: UpdateCategory
66
+ description: "Actualizar nombre/descripción de una categoría"
67
+
68
+ # ─────────────────────────────────────────────
69
+ # NOTIFICACIONES
70
+ # ─────────────────────────────────────────────
71
+
72
+ - name: notification
73
+ description: "Despacha notificaciones a usuarios por EMAIL, SMS o PUSH. Reacciona a eventos del dominio product para informar a usuarios interesados."
74
+ exposes:
75
+ - method: POST
76
+ path: /notifications
77
+ useCase: CreateNotification
78
+ description: "Crear y encolar una notificación manualmente"
79
+ - method: GET
80
+ path: /notifications/{id}
81
+ useCase: GetNotification
82
+ description: "Obtener estado de una notificación"
83
+ - method: GET
84
+ path: /notifications
85
+ useCase: FindAllNotifications
86
+ description: "Listar notificaciones con paginación"
87
+ - method: DELETE
88
+ path: /notifications/{id}
89
+ useCase: DeleteNotification
90
+ description: "Eliminar lógicamente una notificación (soft delete)"
91
+ - method: PUT
92
+ path: /notifications/{id}/read
93
+ useCase: MarkNotificationRead
94
+ description: "Marcar notificación como leída"
95
+
96
+ integrations:
97
+ async:
98
+ # Producto publicado → notification envía alerta a usuarios suscritos
99
+ - event: ProductPublishedEvent
100
+ producer: product
101
+ topic: PRODUCT_PUBLISHED
102
+ consumers:
103
+ - module: notification
104
+ useCase: SendProductPublishedNotification
105
+
106
+ # Producto discontinuado → notification informa aos usuarios
107
+ - event: ProductDiscontinuedEvent
108
+ producer: product
109
+ topic: PRODUCT_DISCONTINUED
110
+ consumers:
111
+ - module: notification
112
+ useCase: SendProductDiscontinuedNotification