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,41 @@
1
+ package <%= packageName %>.<%= moduleName %>.application.usecases;
2
+
3
+ import <%= packageName %>.<%= moduleName %>.application.dtos.<%= aggregateName %>ResponseDto;
4
+ import <%= packageName %>.<%= moduleName %>.application.queries.<%= useCaseName %>Query;
5
+ import <%= packageName %>.<%= moduleName %>.domain.repositories.<%= aggregateName %>Repository;
6
+ import <%= packageName %>.shared.domain.annotations.ApplicationComponent;
7
+ import <%= packageName %>.shared.domain.interfaces.QueryHandler;
8
+ import lombok.extern.slf4j.Slf4j;
9
+
10
+ /**
11
+ * <%= useCaseName %>QueryHandler
12
+ * TODO: Implement the query logic for "<%= useCaseName %>".
13
+ *
14
+ * Suggested steps:
15
+ * 1. Read parameters from the query record
16
+ * 2. Retrieve data from the repository
17
+ * 3. Map the result to a DTO and return it
18
+ */
19
+ @Slf4j
20
+ @ApplicationComponent
21
+ public class <%= useCaseName %>QueryHandler implements QueryHandler<<%= useCaseName %>Query, <%= aggregateName %>ResponseDto> {
22
+
23
+ private final <%= aggregateName %>Repository repository;
24
+
25
+ public <%= useCaseName %>QueryHandler(<%= aggregateName %>Repository repository) {
26
+ this.repository = repository;
27
+ }
28
+
29
+ @Override
30
+ public <%= aggregateName %>ResponseDto handle(<%= useCaseName %>Query query) {
31
+ log.info("Handling <%= useCaseName %>Query: {}", query);
32
+
33
+ // TODO: Implement query logic
34
+ // Example:
35
+ // return repository.findById(query.id())
36
+ // .map(mapper::toDto)
37
+ // .orElseThrow(() -> new EntityNotFoundException("<%= aggregateName %> not found"));
38
+
39
+ throw new UnsupportedOperationException("<%= useCaseName %> not yet implemented");
40
+ }
41
+ }
@@ -0,0 +1,21 @@
1
+ package <%= packageName %>.<%= moduleName %>.application.commands;
2
+
3
+ <% (imports || []).forEach(imp => { %>
4
+ <%- imp %>
5
+ <% }); %>
6
+ import <%= packageName %>.shared.domain.interfaces.Command;
7
+ import io.swagger.v3.oas.annotations.media.Schema;
8
+
9
+ /**
10
+ * <%= useCaseName %>Command
11
+ * Adds a new <%= entityName %> to the <%= aggregateName %> aggregate.
12
+ */
13
+ public record <%= useCaseName %>Command(
14
+ <%- idType %> id<% if (entityFields && entityFields.length > 0) { %>,<% } %>
15
+ <% (entityFields || []).forEach(function(field, idx) { %>
16
+ <% if (field.schemaExample) { %>
17
+ @Schema(example = "<%= field.schemaExample %>")
18
+ <% } %>
19
+ <%- field.javaType %> <%= field.name %><% if (idx < entityFields.length - 1) { %>,<% } %>
20
+ <% }); %>
21
+ ) implements Command {}
@@ -0,0 +1,43 @@
1
+ package <%= packageName %>.<%= moduleName %>.application.usecases;
2
+
3
+ import <%= packageName %>.<%= moduleName %>.application.commands.<%= useCaseName %>Command;
4
+ import <%= packageName %>.<%= moduleName %>.domain.models.entities.<%= aggregateName %>;
5
+ import <%= packageName %>.<%= moduleName %>.domain.models.entities.<%= entityName %>;
6
+ import <%= packageName %>.<%= moduleName %>.domain.repositories.<%= aggregateName %>Repository;
7
+ import <%= packageName %>.shared.domain.annotations.ApplicationComponent;
8
+ import <%= packageName %>.shared.domain.customExceptions.NotFoundException;
9
+ import <%= packageName %>.shared.domain.interfaces.CommandHandler;
10
+ import lombok.extern.slf4j.Slf4j;
11
+ import org.springframework.transaction.annotation.Transactional;
12
+
13
+ /**
14
+ * <%= useCaseName %>CommandHandler
15
+ * Loads the <%= aggregateName %> aggregate and adds a new <%= entityName %> to it.
16
+ *
17
+ * The aggregate root must expose: <%= addMethodName %>(<%= entityName %> item)
18
+ */
19
+ @Slf4j
20
+ @ApplicationComponent
21
+ public class <%= useCaseName %>CommandHandler implements CommandHandler<<%= useCaseName %>Command> {
22
+
23
+ private final <%= aggregateName %>Repository repository;
24
+
25
+ public <%= useCaseName %>CommandHandler(<%= aggregateName %>Repository repository) {
26
+ this.repository = repository;
27
+ }
28
+
29
+ @Override
30
+ @Transactional
31
+ public void handle(<%= useCaseName %>Command command) {
32
+ log.info("Handling <%= useCaseName %>Command for <%= aggregateName %> id: {}", command.id());
33
+
34
+ <%= aggregateName %> entity = repository.findById(command.id())
35
+ .orElseThrow(() -> new NotFoundException("<%= aggregateName %> not found with id: " + command.id()));
36
+
37
+ <%= entityName %> item = new <%= entityName %>(<% (entityFields || []).forEach(function(field, idx) { %>command.<%= field.name %>()<% if (idx < entityFields.length - 1) { %>, <% } %><% }); %>);
38
+ entity.<%= addMethodName %>(item);
39
+ repository.save(entity);
40
+
41
+ log.info("<%= entityName %> added to <%= aggregateName %> id: {}", command.id());
42
+ }
43
+ }
@@ -0,0 +1,9 @@
1
+ package <%= packageName %>.<%= moduleName %>.application.commands;
2
+
3
+ import <%= packageName %>.shared.domain.interfaces.Command;
4
+
5
+ /**
6
+ * <%= useCaseName %>Command
7
+ * Removes the <%= entityName %> identified by itemId from the <%= aggregateName %> aggregate.
8
+ */
9
+ public record <%= useCaseName %>Command(<%- idType %> id, String itemId) implements Command {}
@@ -0,0 +1,42 @@
1
+ package <%= packageName %>.<%= moduleName %>.application.usecases;
2
+
3
+ import <%= packageName %>.<%= moduleName %>.application.commands.<%= useCaseName %>Command;
4
+ import <%= packageName %>.<%= moduleName %>.domain.models.entities.<%= aggregateName %>;
5
+ import <%= packageName %>.<%= moduleName %>.domain.repositories.<%= aggregateName %>Repository;
6
+ import <%= packageName %>.shared.domain.annotations.ApplicationComponent;
7
+ import <%= packageName %>.shared.domain.customExceptions.NotFoundException;
8
+ import <%= packageName %>.shared.domain.interfaces.CommandHandler;
9
+ import lombok.extern.slf4j.Slf4j;
10
+ import org.springframework.transaction.annotation.Transactional;
11
+
12
+ /**
13
+ * <%= useCaseName %>CommandHandler
14
+ * Loads the <%= aggregateName %> aggregate and removes the <%= entityName %> by itemId.
15
+ *
16
+ * The aggregate root must expose: <%= removeMethodName %>(String itemId)
17
+ */
18
+ @Slf4j
19
+ @ApplicationComponent
20
+ public class <%= useCaseName %>CommandHandler implements CommandHandler<<%= useCaseName %>Command> {
21
+
22
+ private final <%= aggregateName %>Repository repository;
23
+
24
+ public <%= useCaseName %>CommandHandler(<%= aggregateName %>Repository repository) {
25
+ this.repository = repository;
26
+ }
27
+
28
+ @Override
29
+ @Transactional
30
+ public void handle(<%= useCaseName %>Command command) {
31
+ log.info("Handling <%= useCaseName %>Command for <%= aggregateName %> id: {}, itemId: {}",
32
+ command.id(), command.itemId());
33
+
34
+ <%= aggregateName %> entity = repository.findById(command.id())
35
+ .orElseThrow(() -> new NotFoundException("<%= aggregateName %> not found with id: " + command.id()));
36
+
37
+ entity.<%= removeMethodName %>(command.itemId());
38
+ repository.save(entity);
39
+
40
+ log.info("<%= entityName %> id: {} removed from <%= aggregateName %> id: {}", command.itemId(), command.id());
41
+ }
42
+ }
@@ -0,0 +1,9 @@
1
+ package <%= packageName %>.<%= moduleName %>.application.commands;
2
+
3
+ import <%= packageName %>.shared.domain.interfaces.Command;
4
+
5
+ /**
6
+ * <%= useCaseName %>Command
7
+ * Triggers the '<%= domainMethod %>' state transition on the <%= aggregateName %> aggregate.
8
+ */
9
+ public record <%= useCaseName %>Command(<%- idType %> id) implements Command {}
@@ -0,0 +1,39 @@
1
+ package <%= packageName %>.<%= moduleName %>.application.usecases;
2
+
3
+ import <%= packageName %>.<%= moduleName %>.application.commands.<%= useCaseName %>Command;
4
+ import <%= packageName %>.<%= moduleName %>.domain.models.entities.<%= aggregateName %>;
5
+ import <%= packageName %>.<%= moduleName %>.domain.repositories.<%= aggregateName %>Repository;
6
+ import <%= packageName %>.shared.domain.annotations.ApplicationComponent;
7
+ import <%= packageName %>.shared.domain.customExceptions.NotFoundException;
8
+ import <%= packageName %>.shared.domain.interfaces.CommandHandler;
9
+ import lombok.extern.slf4j.Slf4j;
10
+ import org.springframework.transaction.annotation.Transactional;
11
+
12
+ /**
13
+ * <%= useCaseName %>CommandHandler
14
+ * Loads the <%= aggregateName %> aggregate and calls entity.<%= domainMethod %>() to execute the transition.
15
+ */
16
+ @Slf4j
17
+ @ApplicationComponent
18
+ public class <%= useCaseName %>CommandHandler implements CommandHandler<<%= useCaseName %>Command> {
19
+
20
+ private final <%= aggregateName %>Repository repository;
21
+
22
+ public <%= useCaseName %>CommandHandler(<%= aggregateName %>Repository repository) {
23
+ this.repository = repository;
24
+ }
25
+
26
+ @Override
27
+ @Transactional
28
+ public void handle(<%= useCaseName %>Command command) {
29
+ log.info("Handling <%= useCaseName %>Command for id: {}", command.id());
30
+
31
+ <%= aggregateName %> entity = repository.findById(command.id())
32
+ .orElseThrow(() -> new NotFoundException("<%= aggregateName %> not found with id: " + command.id()));
33
+
34
+ entity.<%= domainMethod %>();
35
+ repository.save(entity);
36
+
37
+ log.info("<%= aggregateName %> id: {} transitioned via <%= domainMethod %>()", command.id());
38
+ }
39
+ }
@@ -1,6 +1,7 @@
1
1
  package <%= packageName %>.<%= moduleName %>.application.commands;
2
2
 
3
3
  import <%= packageName %>.shared.domain.interfaces.Command;
4
+ import io.swagger.v3.oas.annotations.media.Schema;
4
5
  <% if (hasValueObjects) { %>
5
6
  import <%= packageName %>.<%= moduleName %>.domain.models.valueObjects.*;
6
7
  <% } %>
@@ -34,6 +35,9 @@ import <%= packageName %>.<%= moduleName %>.application.dtos.Create<%= rel.targe
34
35
  public record Update<%= aggregateName %>Command(
35
36
  <%- idType %> id<% if (commandFields && commandFields.length > 0) { %>,<% } %>
36
37
  <% commandFields.forEach((field, idx) => { %>
38
+ <% if (field.schemaExample) { %>
39
+ @Schema(example = "<%= field.schemaExample %>")
40
+ <% } %>
37
41
  <%- field.javaType %> <%= field.name %><% if (idx < commandFields.length - 1 || (oneToManyRelationships && oneToManyRelationships.length > 0) || (oneToOneRelationships && oneToOneRelationships.length > 0)) { %>,<% } %>
38
42
  <% }); %>
39
43
  <% if (oneToManyRelationships && oneToManyRelationships.length > 0) { %>