eva4j 1.0.13 → 1.0.14
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.
- package/AGENTS.md +51 -9
- package/DOMAIN_YAML_GUIDE.md +150 -0
- package/bin/eva4j.js +31 -1
- package/design-system.md +797 -0
- package/docs/commands/EVALUATE_SYSTEM.md +542 -0
- package/docs/commands/GENERATE_ENTITIES.md +196 -0
- package/docs/commands/INDEX.md +10 -1
- package/examples/domain-endpoints-relations.yaml +353 -0
- package/examples/domain-endpoints-versioned.yaml +144 -0
- package/examples/domain-endpoints.yaml +135 -0
- package/examples/system.yaml +289 -0
- package/package.json +1 -1
- package/src/commands/create.js +6 -3
- package/src/commands/evaluate-system.js +384 -0
- package/src/commands/generate-entities.js +677 -14
- package/src/commands/generate-kafka-event.js +59 -5
- package/src/commands/generate-system.js +243 -0
- package/src/generators/base-generator.js +9 -1
- package/src/utils/naming.js +3 -2
- package/src/utils/system-validator.js +314 -0
- package/src/utils/yaml-to-entity.js +31 -2
- package/templates/aggregate/AggregateRepository.java.ejs +5 -0
- package/templates/aggregate/AggregateRepositoryImpl.java.ejs +9 -0
- package/templates/aggregate/DomainEventHandler.java.ejs +24 -20
- package/templates/aggregate/JpaRepository.java.ejs +5 -0
- package/templates/base/root/skill-build-domain-yaml-references-generate-entities.md.ejs +1103 -0
- package/templates/base/root/skill-build-domain-yaml.ejs +292 -0
- package/templates/base/root/skill-build-system-yaml.ejs +252 -0
- package/templates/base/root/system.yaml.ejs +97 -0
- package/templates/crud/EndpointsController.java.ejs +178 -0
- package/templates/crud/FindByQuery.java.ejs +17 -0
- package/templates/crud/FindByQueryHandler.java.ejs +57 -0
- package/templates/crud/ScaffoldCommand.java.ejs +12 -0
- package/templates/crud/ScaffoldCommandHandler.java.ejs +43 -0
- package/templates/crud/ScaffoldQuery.java.ejs +12 -0
- package/templates/crud/ScaffoldQueryHandler.java.ejs +40 -0
- package/templates/crud/SubEntityAddCommand.java.ejs +17 -0
- package/templates/crud/SubEntityAddCommandHandler.java.ejs +43 -0
- package/templates/crud/SubEntityRemoveCommand.java.ejs +9 -0
- package/templates/crud/SubEntityRemoveCommandHandler.java.ejs +42 -0
- package/templates/crud/TransitionCommand.java.ejs +9 -0
- package/templates/crud/TransitionCommandHandler.java.ejs +39 -0
- package/templates/evaluate/report.html.ejs +971 -0
- package/templates/kafka-event/Event.java.ejs +7 -0
|
@@ -26,7 +26,8 @@ async function parseDomainYaml(yamlPath, packageName = '', moduleName = '') {
|
|
|
26
26
|
|
|
27
27
|
return {
|
|
28
28
|
aggregates,
|
|
29
|
-
allEnums: extractAllEnums(domainData.aggregates)
|
|
29
|
+
allEnums: extractAllEnums(domainData.aggregates),
|
|
30
|
+
endpoints: parseEndpoints(domainData)
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -91,7 +92,8 @@ function parseAggregate(aggregateData) {
|
|
|
91
92
|
valueObjects: parsedValueObjects,
|
|
92
93
|
aggregateMethods,
|
|
93
94
|
allEntities: parsedEntities,
|
|
94
|
-
domainEvents
|
|
95
|
+
domainEvents,
|
|
96
|
+
enums: aggregateEnums
|
|
95
97
|
};
|
|
96
98
|
}
|
|
97
99
|
|
|
@@ -961,6 +963,33 @@ function extractAllEnums(aggregates) {
|
|
|
961
963
|
return Array.from(enumsMap.values());
|
|
962
964
|
}
|
|
963
965
|
|
|
966
|
+
/**
|
|
967
|
+
* Parse the optional endpoints section from domain.yaml.
|
|
968
|
+
* When present, controls which use cases and versioned controllers are generated.
|
|
969
|
+
* @param {Object} domainData - Raw parsed YAML data
|
|
970
|
+
* @returns {Object|null} Parsed endpoints structure or null if not declared
|
|
971
|
+
*/
|
|
972
|
+
function parseEndpoints(domainData) {
|
|
973
|
+
if (!domainData.endpoints) return null;
|
|
974
|
+
const { basePath = '/', versions = [] } = domainData.endpoints;
|
|
975
|
+
return {
|
|
976
|
+
basePath,
|
|
977
|
+
versions: versions.map(v => ({
|
|
978
|
+
version: v.version,
|
|
979
|
+
operations: (v.operations || []).map(op => {
|
|
980
|
+
const method = (op.method || 'GET').toUpperCase();
|
|
981
|
+
return {
|
|
982
|
+
method,
|
|
983
|
+
path: op.path || '/',
|
|
984
|
+
description: op.description || '',
|
|
985
|
+
useCase: toPascalCase(op.useCase),
|
|
986
|
+
type: method === 'GET' ? 'query' : 'command'
|
|
987
|
+
};
|
|
988
|
+
})
|
|
989
|
+
}))
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
|
|
964
993
|
module.exports = {
|
|
965
994
|
parseDomainYaml,
|
|
966
995
|
parseAggregate,
|
|
@@ -20,4 +20,9 @@ public interface <%= rootEntity.name %>Repository {
|
|
|
20
20
|
void deleteById(<%= rootEntity.fields[0].javaType %> id);
|
|
21
21
|
|
|
22
22
|
boolean existsById(<%= rootEntity.fields[0].javaType %> id);
|
|
23
|
+
<% if (findByOps && findByOps.length > 0) { %>
|
|
24
|
+
<% findByOps.forEach(function(op) { %>
|
|
25
|
+
Page<<%= rootEntity.name %>> <%= op.jpaMethodName %>(<%= op.fieldJavaType %> <%= op.fieldName %>, Pageable pageable);
|
|
26
|
+
<% }); %>
|
|
27
|
+
<% } %>
|
|
23
28
|
}
|
|
@@ -58,4 +58,13 @@ public class <%= rootEntity.name %>RepositoryImpl implements <%= rootEntity.name
|
|
|
58
58
|
public boolean existsById(<%= rootEntity.fields[0].javaType %> id) {
|
|
59
59
|
return jpaRepository.existsById(id);
|
|
60
60
|
}
|
|
61
|
+
<% if (findByOps && findByOps.length > 0) { %>
|
|
62
|
+
<% findByOps.forEach(function(op) { %>
|
|
63
|
+
@Override
|
|
64
|
+
public Page<<%= rootEntity.name %>> <%= op.jpaMethodName %>(<%= op.fieldJavaType %> <%= op.fieldName %>, Pageable pageable) {
|
|
65
|
+
return jpaRepository.<%= op.jpaMethodName %>(<%= op.fieldName %>, pageable)
|
|
66
|
+
.map(mapper::toDomain);
|
|
67
|
+
}
|
|
68
|
+
<% }); %>
|
|
69
|
+
<% } %>
|
|
61
70
|
}
|
|
@@ -6,32 +6,37 @@ import org.springframework.transaction.event.TransactionalEventListener;
|
|
|
6
6
|
<% domainEvents.forEach(event => { %>
|
|
7
7
|
import <%= packageName %>.<%= moduleName %>.domain.models.events.<%= event.name %>;
|
|
8
8
|
<% }); %>
|
|
9
|
-
<% if (
|
|
10
|
-
|
|
9
|
+
<% if (broker) { %>
|
|
10
|
+
<% domainEvents.forEach(event => { %>
|
|
11
|
+
import <%= packageName %>.<%= moduleName %>.application.events.<%= event.integrationEventClassName %>;
|
|
12
|
+
<% }); %>
|
|
13
|
+
import <%= packageName %>.<%= moduleName %>.application.ports.MessageBroker;
|
|
11
14
|
<% } %>
|
|
12
15
|
|
|
13
16
|
/**
|
|
14
17
|
* <%= aggregateName %>DomainEventHandler — Domain Event Bridge
|
|
15
18
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
19
|
+
* Connects the internal Spring event bus (ApplicationEventPublisher) with the
|
|
20
|
+
* external messaging port (MessageBroker).
|
|
18
21
|
*
|
|
19
22
|
* Architecture:
|
|
20
23
|
* AggregateRepositoryImpl.save()
|
|
21
|
-
* → eventPublisher.publishEvent(domainEvent)
|
|
22
|
-
* → @TransactionalEventListener(AFTER_COMMIT)
|
|
23
|
-
* → messageBroker.
|
|
24
|
+
* → eventPublisher.publishEvent(domainEvent) [internal Spring bus]
|
|
25
|
+
* → @TransactionalEventListener(AFTER_COMMIT) [this class]
|
|
26
|
+
* → messageBroker.publish*(integrationEvent) [port — broker-agnostic]
|
|
24
27
|
*
|
|
25
|
-
* AFTER_COMMIT
|
|
26
|
-
* database transaction committed successfully, preventing ghost events
|
|
27
|
-
*
|
|
28
|
+
* AFTER_COMMIT guarantees that external events are published only when the
|
|
29
|
+
* database transaction committed successfully, preventing ghost events from
|
|
30
|
+
* rolled-back operations.
|
|
28
31
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
32
|
+
* Domain Events (domain/models/events/) — internal signals scoped to this bounded context.
|
|
33
|
+
* Integration Events (application/events/) — broker-facing projections; changing broker
|
|
34
|
+
* technology (Kafka → RabbitMQ → SNS) only requires changing the MessageBroker adapter.
|
|
35
|
+
* Domain Events — and therefore this class — never need modification.
|
|
31
36
|
*/
|
|
32
37
|
@ApplicationComponent
|
|
33
38
|
public class <%= aggregateName %>DomainEventHandler {
|
|
34
|
-
<% if (
|
|
39
|
+
<% if (broker) { %>
|
|
35
40
|
|
|
36
41
|
private final MessageBroker messageBroker;
|
|
37
42
|
|
|
@@ -42,16 +47,15 @@ public class <%= aggregateName %>DomainEventHandler {
|
|
|
42
47
|
<% domainEvents.forEach(event => { %>
|
|
43
48
|
|
|
44
49
|
/**
|
|
45
|
-
* Handles {@link <%= event.name %>} after the wrapping transaction commits
|
|
46
|
-
*
|
|
50
|
+
* Handles {@link <%= event.name %>} after the wrapping transaction commits.<% if (!broker) { %>
|
|
51
|
+
* <p>
|
|
47
52
|
* TODO: Implement the side effect for this event (e.g., send notification,
|
|
48
|
-
* update a read model, trigger a saga step, etc.)
|
|
49
|
-
* <% } %>
|
|
53
|
+
* update a read model, trigger a saga step, etc.).<% } %>
|
|
50
54
|
*/
|
|
51
55
|
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
|
|
52
|
-
public void on<%= event.name %>(<%=
|
|
53
|
-
<% if (
|
|
54
|
-
messageBroker.
|
|
56
|
+
public void on<%= event.name %>(<%= event.name %> event) {
|
|
57
|
+
<% if (broker) { %>
|
|
58
|
+
messageBroker.publish<%= event.integrationEventClassName %>(new <%= event.integrationEventClassName %>(<% if (event.fields && event.fields.length > 0) { event.fields.forEach(function(field, idx) { %>event.get<%= field.name.charAt(0).toUpperCase() + field.name.slice(1) %>()<%= idx < event.fields.length - 1 ? ', ' : '' %><% }); } %>));
|
|
55
59
|
<% } else { %>
|
|
56
60
|
// TODO: handle <%= event.name %> — add your side-effect logic here
|
|
57
61
|
// e.g.: notificationService.notify(event);
|
|
@@ -8,4 +8,9 @@ import <%= packageName %>.<%= moduleName %>.infrastructure.database.entities.<%=
|
|
|
8
8
|
* Spring Data JPA repository
|
|
9
9
|
*/
|
|
10
10
|
public interface <%= rootEntity.name %>JpaRepository extends JpaRepository<<%= rootEntity.name %>Jpa, <%= rootEntity.fields[0].javaType %>> {
|
|
11
|
+
<% if (findByOps && findByOps.length > 0) { %>
|
|
12
|
+
<% findByOps.forEach(function(op) { %>
|
|
13
|
+
org.springframework.data.domain.Page<<%= rootEntity.name %>Jpa> <%= op.jpaMethodName %>(<%= op.fieldJavaType %> <%= op.fieldName %>, org.springframework.data.domain.Pageable pageable);
|
|
14
|
+
<% }); %>
|
|
15
|
+
<% } %>
|
|
11
16
|
}
|