eva4j 1.0.14 → 1.0.16

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 (139) hide show
  1. package/.agents/skills/skill-creator/LICENSE.txt +202 -0
  2. package/.agents/skills/skill-creator/SKILL.md +485 -0
  3. package/.agents/skills/skill-creator/agents/analyzer.md +274 -0
  4. package/.agents/skills/skill-creator/agents/comparator.md +202 -0
  5. package/.agents/skills/skill-creator/agents/grader.md +223 -0
  6. package/.agents/skills/skill-creator/assets/eval_review.html +146 -0
  7. package/.agents/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  8. package/.agents/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  9. package/.agents/skills/skill-creator/references/schemas.md +430 -0
  10. package/.agents/skills/skill-creator/scripts/__init__.py +0 -0
  11. package/.agents/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  12. package/.agents/skills/skill-creator/scripts/generate_report.py +326 -0
  13. package/.agents/skills/skill-creator/scripts/improve_description.py +247 -0
  14. package/.agents/skills/skill-creator/scripts/package_skill.py +136 -0
  15. package/.agents/skills/skill-creator/scripts/quick_validate.py +103 -0
  16. package/.agents/skills/skill-creator/scripts/run_eval.py +310 -0
  17. package/.agents/skills/skill-creator/scripts/run_loop.py +328 -0
  18. package/.agents/skills/skill-creator/scripts/utils.py +47 -0
  19. package/AGENTS.md +268 -6
  20. package/COMMAND_EVALUATION.md +15 -16
  21. package/DOMAIN_YAML_GUIDE.md +430 -14
  22. package/FUTURE_FEATURES.md +1627 -1168
  23. package/README.md +461 -13
  24. package/bin/eva4j.js +32 -14
  25. package/config/defaults.json +1 -0
  26. package/docs/commands/EVALUATE_SYSTEM.md +746 -261
  27. package/docs/commands/EXPORT_DIAGRAM.md +153 -0
  28. package/docs/commands/GENERATE_ENTITIES.md +599 -6
  29. package/docs/commands/INDEX.md +7 -0
  30. package/examples/domain-events.yaml +166 -20
  31. package/examples/domain-listeners.yaml +212 -0
  32. package/examples/domain-one-to-many.yaml +1 -0
  33. package/examples/domain-one-to-one.yaml +1 -0
  34. package/examples/domain-ports.yaml +414 -0
  35. package/examples/domain-soft-delete.yaml +47 -44
  36. package/examples/system/notification.yaml +147 -0
  37. package/examples/system/product.yaml +185 -0
  38. package/examples/system/system.yaml +112 -0
  39. package/examples/system-report.html +971 -0
  40. package/examples/system.yaml +46 -3
  41. package/package.json +2 -1
  42. package/src/agents/design-reviewer.agent.md +163 -0
  43. package/src/commands/build.js +714 -0
  44. package/src/commands/create.js +1 -0
  45. package/src/commands/detach.js +149 -108
  46. package/src/commands/evaluate-system.js +234 -8
  47. package/src/commands/export-diagram.js +522 -0
  48. package/src/commands/generate-entities.js +685 -66
  49. package/src/commands/generate-http-exchange.js +2 -0
  50. package/src/commands/generate-kafka-event.js +43 -10
  51. package/src/generators/base-generator.js +18 -6
  52. package/src/generators/postman-generator.js +188 -0
  53. package/src/generators/shared-generator.js +12 -2
  54. package/src/skills/build-system-yaml/SKILL.md +323 -0
  55. package/src/skills/build-system-yaml/references/domain-yaml-spec.md +410 -0
  56. package/src/skills/build-system-yaml/references/module-spec.md +367 -0
  57. package/src/skills/build-system-yaml/references/system-yaml-spec.md +178 -0
  58. package/src/utils/config-manager.js +54 -0
  59. package/src/utils/context-builder.js +1 -0
  60. package/src/utils/domain-diagram.js +192 -0
  61. package/src/utils/domain-validator.js +1020 -0
  62. package/src/utils/fake-data.js +376 -0
  63. package/src/utils/system-validator.js +319 -199
  64. package/src/utils/yaml-to-entity.js +272 -7
  65. package/templates/aggregate/AggregateMapper.java.ejs +3 -2
  66. package/templates/aggregate/AggregateRepository.java.ejs +3 -2
  67. package/templates/aggregate/AggregateRepositoryImpl.java.ejs +6 -5
  68. package/templates/aggregate/AggregateRoot.java.ejs +60 -2
  69. package/templates/aggregate/DomainEventHandler.java.ejs +4 -1
  70. package/templates/aggregate/DomainEventRecord.java.ejs +24 -8
  71. package/templates/aggregate/DomainEventSnapshot.java.ejs +46 -0
  72. package/templates/aggregate/JpaAggregateRoot.java.ejs +6 -0
  73. package/templates/base/docker/Dockerfile.ejs +21 -0
  74. package/templates/base/gradle/build.gradle.ejs +3 -2
  75. package/templates/base/root/AGENTS.md.ejs +306 -45
  76. package/templates/crud/ApplicationMapper.java.ejs +4 -0
  77. package/templates/crud/Controller.java.ejs +4 -4
  78. package/templates/crud/CreateCommand.java.ejs +4 -0
  79. package/templates/crud/CreateCommandHandler.java.ejs +3 -6
  80. package/templates/crud/CreateItemDto.java.ejs +4 -0
  81. package/templates/crud/CreateValueObjectDto.java.ejs +4 -0
  82. package/templates/crud/DeleteCommandHandler.java.ejs +12 -6
  83. package/templates/crud/EndpointsController.java.ejs +6 -6
  84. package/templates/crud/FindByQuery.java.ejs +1 -1
  85. package/templates/crud/FindByQueryHandler.java.ejs +3 -9
  86. package/templates/crud/GetQueryHandler.java.ejs +2 -5
  87. package/templates/crud/ListQuery.java.ejs +1 -1
  88. package/templates/crud/ListQueryHandler.java.ejs +8 -14
  89. package/templates/crud/ScaffoldCommandHandler.java.ejs +2 -4
  90. package/templates/crud/ScaffoldQuery.java.ejs +3 -2
  91. package/templates/crud/ScaffoldQueryHandler.java.ejs +5 -6
  92. package/templates/crud/SubEntityAddCommand.java.ejs +4 -0
  93. package/templates/crud/SubEntityAddCommandHandler.java.ejs +2 -6
  94. package/templates/crud/SubEntityRemoveCommandHandler.java.ejs +2 -7
  95. package/templates/crud/TransitionCommandHandler.java.ejs +2 -6
  96. package/templates/crud/UpdateCommand.java.ejs +4 -0
  97. package/templates/crud/UpdateCommandHandler.java.ejs +2 -5
  98. package/templates/evaluate/report.html.ejs +394 -2
  99. package/templates/kafka-event/DomainEventHandlerMethod.ejs +3 -1
  100. package/templates/kafka-event/Event.java.ejs +9 -0
  101. package/templates/kafka-listener/KafkaController.java.ejs +1 -1
  102. package/templates/kafka-listener/KafkaListenerClass.java.ejs +1 -1
  103. package/templates/kafka-listener/ListenerClass.java.ejs +65 -0
  104. package/templates/kafka-listener/ListenerCommand.java.ejs +31 -0
  105. package/templates/kafka-listener/ListenerCommandHandler.java.ejs +25 -0
  106. package/templates/kafka-listener/ListenerIntegrationEvent.java.ejs +37 -0
  107. package/templates/kafka-listener/ListenerMethod.java.ejs +1 -1
  108. package/templates/kafka-listener/ListenerNestedType.java.ejs +28 -0
  109. package/templates/mock/MockEvent.java.ejs +10 -0
  110. package/templates/mock/MockMessageBrokerImpl.java.ejs +35 -0
  111. package/templates/mock/MockMessageBrokerImplMethod.java.ejs +6 -0
  112. package/templates/mock/SpringEventListener.java.ejs +61 -0
  113. package/templates/ports/PortDomainModel.java.ejs +35 -0
  114. package/templates/ports/PortFeignAdapter.java.ejs +67 -0
  115. package/templates/ports/PortFeignClient.java.ejs +45 -0
  116. package/templates/ports/PortFeignConfig.java.ejs +24 -0
  117. package/templates/ports/PortInterface.java.ejs +45 -0
  118. package/templates/ports/PortNestedType.java.ejs +28 -0
  119. package/templates/ports/PortRequestDto.java.ejs +30 -0
  120. package/templates/ports/PortResponseDto.java.ejs +28 -0
  121. package/templates/postman/Collection.json.ejs +1 -1
  122. package/templates/postman/UnifiedCollection.json.ejs +185 -0
  123. package/templates/shared/annotations/LogAfter.java.ejs +2 -0
  124. package/templates/shared/annotations/LogBefore.java.ejs +2 -0
  125. package/templates/shared/annotations/LogExceptions.java.ejs +2 -0
  126. package/templates/shared/annotations/LogLevel.java.ejs +8 -0
  127. package/templates/shared/annotations/LogTimer.java.ejs +1 -0
  128. package/templates/shared/annotations/Loggable.java.ejs +17 -0
  129. package/templates/shared/configurations/eventPublicationConfig/EventPublicationSchemaConfig.java.ejs +109 -0
  130. package/templates/shared/configurations/loggerConfig/HandlerLogs.java.ejs +120 -32
  131. package/templates/shared/errorMessage/ErrorResponse.java.ejs +23 -0
  132. package/templates/shared/handlerException/HandlerExceptions.java.ejs +99 -79
  133. package/src/commands/generate-system.js +0 -243
  134. package/templates/base/root/skill-build-domain-yaml-references-generate-entities.md.ejs +0 -1103
  135. package/templates/base/root/skill-build-domain-yaml.ejs +0 -292
  136. package/templates/base/root/skill-build-system-yaml.ejs +0 -252
  137. package/templates/shared/errorMessage/ErrorMessage.java.ejs +0 -5
  138. package/templates/shared/errorMessage/FullErrorMessage.java.ejs +0 -9
  139. package/templates/shared/errorMessage/ShortErrorMessage.java.ejs +0 -6
@@ -0,0 +1,192 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Generates Mermaid classDiagram text per module from parsed domain.yaml objects.
5
+ *
6
+ * @param {Object} domainConfigs Plain object { [moduleName]: parsedDomainYaml }
7
+ * @returns {{ [moduleName]: string }} Map of module → Mermaid diagram text (empty string if no aggregates)
8
+ */
9
+ function generateDomainDiagrams(domainConfigs) {
10
+ const result = {};
11
+ for (const [moduleName, config] of Object.entries(domainConfigs)) {
12
+ result[moduleName] = generateModuleDiagram(moduleName, config);
13
+ }
14
+ return result;
15
+ }
16
+
17
+ // ── Helpers ───────────────────────────────────────────────────────────────────
18
+
19
+ const AUDIT_FIELDS = new Set(['createdAt', 'updatedAt', 'createdBy', 'updatedBy']);
20
+
21
+ /** Normalize to PascalCase (capitalize first letter only). */
22
+ function toPascal(name) {
23
+ if (!name) return name;
24
+ return name.charAt(0).toUpperCase() + name.slice(1);
25
+ }
26
+
27
+ function fieldPrefix(field) {
28
+ if (field.hidden) return '-';
29
+ if (field.readOnly) return '~';
30
+ return '+';
31
+ }
32
+
33
+ // ── Per-module diagram builder ────────────────────────────────────────────────
34
+
35
+ function generateModuleDiagram(moduleName, config) {
36
+ const aggregates = config.aggregates || [];
37
+ if (aggregates.length === 0) return '';
38
+
39
+ // Flat diagram — namespace blocks are avoided because Mermaid's layout engine
40
+ // can place inner classes outside the visual boundary, causing overflow.
41
+ // Aggregates are separated by %% comment dividers instead.
42
+ const lines = ['classDiagram'];
43
+ const relationships = []; // Collected per-aggregate, emitted at the end
44
+ const notes = []; // `note for ClassName "..."` — for cross-aggregate refs
45
+
46
+ // Build a set of all entity/VO/enum PascalCase class names defined in this module
47
+ // so we can distinguish intra-module from cross-aggregate relationships.
48
+ const localClasses = new Set();
49
+ for (const aggregate of aggregates) {
50
+ for (const e of aggregate.entities || []) localClasses.add(toPascal(e.name));
51
+ for (const v of aggregate.valueObjects || []) localClasses.add(toPascal(v.name));
52
+ for (const en of aggregate.enums || []) localClasses.add(toPascal(en.name));
53
+ }
54
+
55
+ for (const aggregate of aggregates) {
56
+ const entities = aggregate.entities || [];
57
+ const valueObjects = aggregate.valueObjects || [];
58
+ const enums = aggregate.enums || [];
59
+
60
+ lines.push('');
61
+ lines.push(` %% ── Aggregate: ${aggregate.name} ─────────────────────`);
62
+
63
+ // ── Entities ─────────────────────────────────────────────────────────────
64
+ for (const entity of entities) {
65
+ const className = toPascal(entity.name);
66
+ lines.push(` class ${className} {`);
67
+ lines.push(` ${entity.isRoot ? '<<aggregate root>>' : '<<entity>>'}`);
68
+
69
+ for (const field of entity.fields || []) {
70
+ if (AUDIT_FIELDS.has(field.name)) continue;
71
+ lines.push(` ${fieldPrefix(field)}${field.type} ${field.name}`);
72
+ }
73
+
74
+ if (entity.audit?.enabled) {
75
+ lines.push(` +LocalDateTime createdAt`);
76
+ lines.push(` +LocalDateTime updatedAt`);
77
+ }
78
+ if (entity.audit?.trackUser) {
79
+ lines.push(` +String createdBy`);
80
+ lines.push(` +String updatedBy`);
81
+ }
82
+
83
+ lines.push(` }`);
84
+ }
85
+
86
+ // ── Value objects ─────────────────────────────────────────────────────────
87
+ for (const vo of valueObjects) {
88
+ const className = toPascal(vo.name);
89
+ lines.push(` class ${className} {`);
90
+ lines.push(` <<value object>>`);
91
+ for (const field of vo.fields || []) {
92
+ lines.push(` +${field.type} ${field.name}`);
93
+ }
94
+ lines.push(` }`);
95
+ }
96
+
97
+ // ── Enums ─────────────────────────────────────────────────────────────────
98
+ for (const en of enums) {
99
+ const className = toPascal(en.name);
100
+ lines.push(` class ${className} {`);
101
+ lines.push(` <<enumeration>>`);
102
+ for (const val of en.values || []) {
103
+ lines.push(` ${val}`);
104
+ }
105
+ lines.push(` }`);
106
+ }
107
+
108
+ // ── Collect relationships ─────────────────────────────────────────────────
109
+ const voNames = new Set(valueObjects.map((v) => toPascal(v.name)));
110
+ const enumNames = new Set(enums.map((e) => toPascal(e.name)));
111
+
112
+ for (const entity of entities) {
113
+ const srcClass = toPascal(entity.name);
114
+
115
+ // Structural JPA relationships — only emit if target is a local class
116
+ for (const rel of entity.relationships || []) {
117
+ const target = toPascal(rel.target || rel.targetEntity || '');
118
+ if (!target) continue;
119
+ if (!localClasses.has(target)) continue; // skip cross-aggregate targets
120
+ const label = rel.mappedBy ? ` : ${rel.mappedBy}` : '';
121
+ switch (rel.type) {
122
+ case 'OneToMany':
123
+ relationships.push(` ${srcClass} "1" --o "*" ${target}${label}`);
124
+ break;
125
+ case 'OneToOne':
126
+ relationships.push(` ${srcClass} "1" --o "1" ${target}${label}`);
127
+ break;
128
+ case 'ManyToOne':
129
+ relationships.push(` ${srcClass} "*" --> "1" ${target}`);
130
+ break;
131
+ case 'ManyToMany':
132
+ relationships.push(` ${srcClass} "*" --> "*" ${target}`);
133
+ break;
134
+ default:
135
+ relationships.push(` ${srcClass} --> ${target}${label}`);
136
+ }
137
+ }
138
+
139
+ // Field-level type references within the same module (deduplicated)
140
+ const seenEdges = new Set();
141
+ const crossRefs = []; // cross-aggregate reference fields for this entity
142
+
143
+ for (const field of entity.fields || []) {
144
+ if (AUDIT_FIELDS.has(field.name)) continue;
145
+
146
+ const fieldType = toPascal(field.type);
147
+
148
+ if (enumNames.has(fieldType)) {
149
+ const key = `${srcClass}-->${fieldType}`;
150
+ if (!seenEdges.has(key)) {
151
+ relationships.push(` ${srcClass} --> ${fieldType} : ${field.name}`);
152
+ seenEdges.add(key);
153
+ }
154
+ } else if (voNames.has(fieldType)) {
155
+ const key = `${srcClass}*--${fieldType}`;
156
+ if (!seenEdges.has(key)) {
157
+ relationships.push(` ${srcClass} *-- ${fieldType} : ${field.name}`);
158
+ seenEdges.add(key);
159
+ }
160
+ } else if (field.reference) {
161
+ // Cross-aggregate reference: render as a note instead of an arrow
162
+ // to avoid undefined ghost nodes appearing outside the diagram.
163
+ const refModule = field.reference.module;
164
+ const refAggregate = field.reference.aggregate;
165
+ const label =
166
+ refModule && refModule !== moduleName
167
+ ? `${field.name} → ${refAggregate} (${refModule})`
168
+ : `${field.name} → ${refAggregate}`;
169
+ crossRefs.push(label);
170
+ }
171
+ }
172
+
173
+ if (crossRefs.length > 0) {
174
+ notes.push(` note for ${srcClass} "refs: ${crossRefs.join(', ')}"`);
175
+ }
176
+ }
177
+ }
178
+
179
+ if (relationships.length > 0) {
180
+ lines.push('');
181
+ lines.push(...relationships);
182
+ }
183
+
184
+ if (notes.length > 0) {
185
+ lines.push('');
186
+ lines.push(...notes);
187
+ }
188
+
189
+ return lines.join('\n');
190
+ }
191
+
192
+ module.exports = { generateDomainDiagrams };