eva4j 1.0.0
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/LICENSE +21 -0
- package/QUICK_REFERENCE.md +204 -0
- package/README.md +912 -0
- package/USAGE.md +349 -0
- package/bin/eva4j.js +234 -0
- package/config/defaults.json +46 -0
- package/package.json +57 -0
- package/src/commands/add-kafka-client.js +193 -0
- package/src/commands/add-module.js +221 -0
- package/src/commands/create.js +92 -0
- package/src/commands/detach.js +495 -0
- package/src/commands/generate-http-exchange.js +309 -0
- package/src/commands/generate-kafka-event.js +453 -0
- package/src/commands/generate-kafka-listener.js +267 -0
- package/src/commands/generate-resource.js +265 -0
- package/src/commands/generate-usecase.js +198 -0
- package/src/commands/info.js +63 -0
- package/src/generators/base-generator.js +150 -0
- package/src/generators/module-generator.js +48 -0
- package/src/generators/shared-generator.js +153 -0
- package/src/utils/config-manager.js +156 -0
- package/src/utils/context-builder.js +149 -0
- package/src/utils/naming.js +137 -0
- package/src/utils/template-engine.js +55 -0
- package/src/utils/validator.js +159 -0
- package/templates/base/application/Application.java.ejs +27 -0
- package/templates/base/docker/docker-compose.yml.ejs +41 -0
- package/templates/base/gradle/build.gradle.ejs +70 -0
- package/templates/base/gradle/settings.gradle.ejs +1 -0
- package/templates/base/resources/application-develop.yml.ejs +5 -0
- package/templates/base/resources/application-local.yml.ejs +5 -0
- package/templates/base/resources/application-production.yml.ejs +9 -0
- package/templates/base/resources/application-test.yml.ejs +5 -0
- package/templates/base/resources/application.yml.ejs +31 -0
- package/templates/base/resources/parameters/develop/cors.yml.ejs +4 -0
- package/templates/base/resources/parameters/develop/db.yaml.ejs +21 -0
- package/templates/base/resources/parameters/develop/kafka.yml.ejs +26 -0
- package/templates/base/resources/parameters/local/cors.yml.ejs +4 -0
- package/templates/base/resources/parameters/local/db.yaml.ejs +21 -0
- package/templates/base/resources/parameters/local/kafka.yml.ejs +26 -0
- package/templates/base/resources/parameters/production/cors.yml.ejs +4 -0
- package/templates/base/resources/parameters/production/db.yaml.ejs +21 -0
- package/templates/base/resources/parameters/production/kafka.yml.ejs +26 -0
- package/templates/base/root/README.md.ejs +126 -0
- package/templates/base/root/gitignore.ejs +42 -0
- package/templates/http-exchange/Adapter.java.ejs +39 -0
- package/templates/http-exchange/Config.java.ejs +24 -0
- package/templates/http-exchange/FeignClient.java.ejs +23 -0
- package/templates/http-exchange/Port.java.ejs +14 -0
- package/templates/kafka-event/Event.java.ejs +10 -0
- package/templates/kafka-event/KafkaConfigBean.java.ejs +7 -0
- package/templates/kafka-event/KafkaMessageBroker.java.ejs +32 -0
- package/templates/kafka-event/MessageBroker.java.ejs +8 -0
- package/templates/kafka-event/MessageBrokerImplMethod.java.ejs +9 -0
- package/templates/kafka-event/MessageBrokerMethod.java.ejs +1 -0
- package/templates/kafka-listener/KafkaController.java.ejs +34 -0
- package/templates/kafka-listener/ListenerMethod.java.ejs +9 -0
- package/templates/kafka-listener/ValueField.java.ejs +4 -0
- package/templates/module/controller.java.ejs +96 -0
- package/templates/module/exception.java.ejs +18 -0
- package/templates/module/mapper.java.ejs +67 -0
- package/templates/module/model.java.ejs +29 -0
- package/templates/module/package-info.java.ejs +7 -0
- package/templates/module/repository.java.ejs +26 -0
- package/templates/module/request-dto.java.ejs +24 -0
- package/templates/module/response-dto.java.ejs +26 -0
- package/templates/module/service-impl.java.ejs +112 -0
- package/templates/module/service.java.ejs +45 -0
- package/templates/module/update-dto.java.ejs +25 -0
- package/templates/resource/Command.java.ejs +9 -0
- package/templates/resource/CommandHandler.java.ejs +22 -0
- package/templates/resource/Controller.java.ejs +73 -0
- package/templates/resource/Query.java.ejs +12 -0
- package/templates/resource/QueryHandler.java.ejs +31 -0
- package/templates/resource/ResponseDto.java.ejs +6 -0
- package/templates/shared/annotations/ApplicationComponent.java.ejs +9 -0
- package/templates/shared/annotations/DomainComponent.java.ejs +9 -0
- package/templates/shared/annotations/LogAfter.java.ejs +11 -0
- package/templates/shared/annotations/LogBefore.java.ejs +11 -0
- package/templates/shared/annotations/LogExceptions.java.ejs +11 -0
- package/templates/shared/annotations/LogTimer.java.ejs +11 -0
- package/templates/shared/configurations/kafkaConfig/KafkaConfig.java.ejs +49 -0
- package/templates/shared/configurations/loggerConfig/HandlerLogs.java.ejs +56 -0
- package/templates/shared/configurations/securityConfig/SecurityConfig.java.ejs +57 -0
- package/templates/shared/configurations/swaggerConfig/SwaggerConfig.java.ejs +31 -0
- package/templates/shared/configurations/useCaseConfig/UseCaseAutoRegister.java.ejs +51 -0
- package/templates/shared/configurations/useCaseConfig/UseCaseConfig.java.ejs +25 -0
- package/templates/shared/configurations/useCaseConfig/UseCaseContainer.java.ejs +29 -0
- package/templates/shared/configurations/useCaseConfig/UseCaseMediator.java.ejs +38 -0
- package/templates/shared/customExceptions/BadRequestException.java.ejs +11 -0
- package/templates/shared/customExceptions/ConflictException.java.ejs +8 -0
- package/templates/shared/customExceptions/ForbiddenException.java.ejs +8 -0
- package/templates/shared/customExceptions/ImportFileException.java.ejs +6 -0
- package/templates/shared/customExceptions/NotFoundException.java.ejs +8 -0
- package/templates/shared/customExceptions/UnauthorizedException.java.ejs +9 -0
- package/templates/shared/customExceptions/ValidationException.java.ejs +17 -0
- package/templates/shared/errorMessage/ErrorMessage.java.ejs +5 -0
- package/templates/shared/errorMessage/FullErrorMessage.java.ejs +9 -0
- package/templates/shared/errorMessage/ShortErrorMessage.java.ejs +6 -0
- package/templates/shared/eventEnvelope/EventEnvelope.java.ejs +13 -0
- package/templates/shared/eventEnvelope/EventMetadata.java.ejs +24 -0
- package/templates/shared/filters/CorrelationIdFilter.java.ejs +45 -0
- package/templates/shared/handlerException/HandlerExceptions.java.ejs +148 -0
- package/templates/shared/interfaces/Command.java.ejs +4 -0
- package/templates/shared/interfaces/CommandHandler.java.ejs +5 -0
- package/templates/shared/interfaces/Dispatchable.java.ejs +4 -0
- package/templates/shared/interfaces/Handler.java.ejs +4 -0
- package/templates/shared/interfaces/Query.java.ejs +4 -0
- package/templates/shared/interfaces/QueryHandler.java.ejs +5 -0
- package/templates/shared/package-info.java.ejs +8 -0
- package/templates/usecase/command/Command.java.ejs +7 -0
- package/templates/usecase/command/CommandHandler.java.ejs +21 -0
- package/templates/usecase/query/Query.java.ejs +10 -0
- package/templates/usecase/query/QueryHandler.java.ejs +22 -0
- package/templates/usecase/query/ResponseDto.java.ejs +5 -0
package/USAGE.md
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# eva4j - Installation & Usage Guide
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
### Local Development
|
|
6
|
+
|
|
7
|
+
1. Clone or navigate to the eva4j directory:
|
|
8
|
+
```bash
|
|
9
|
+
cd c:\Documentos\eva4j
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
2. Install dependencies:
|
|
13
|
+
```bash
|
|
14
|
+
npm install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
3. Link the CLI globally (for local testing):
|
|
18
|
+
```bash
|
|
19
|
+
npm link
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Now you can use `eva4j` command from anywhere!
|
|
23
|
+
|
|
24
|
+
### Publish to npm (optional)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm publish
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then install globally:
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g eva4j
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### 1. Create a New Spring Boot Project
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
eva4j create my-shop
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This will prompt you for:
|
|
44
|
+
- Group ID (e.g., `com.company`)
|
|
45
|
+
- Java version (21, 22, or 23)
|
|
46
|
+
- Spring Boot version
|
|
47
|
+
- Dependencies (Web, JPA, Security, Validation, Actuator)
|
|
48
|
+
- Database type (PostgreSQL, MySQL, H2)
|
|
49
|
+
- Author name
|
|
50
|
+
|
|
51
|
+
**Generated structure:**
|
|
52
|
+
```
|
|
53
|
+
my-shop/
|
|
54
|
+
├── src/main/java/com/company/myshop/
|
|
55
|
+
│ └── MyShopApplication.java
|
|
56
|
+
├── src/main/resources/
|
|
57
|
+
│ ├── application.yml (base config)
|
|
58
|
+
│ ├── application-local.yml
|
|
59
|
+
│ ├── application-develop.yml
|
|
60
|
+
│ ├── application-test.yml
|
|
61
|
+
│ └── application-production.yml
|
|
62
|
+
├── build.gradle (includes Spring Modulith)
|
|
63
|
+
├── settings.gradle
|
|
64
|
+
├── .eva4j.json (project configuration)
|
|
65
|
+
├── docker-compose.yml (if database selected)
|
|
66
|
+
├── .gitignore
|
|
67
|
+
└── README.md
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 2. Add Your First Module
|
|
71
|
+
|
|
72
|
+
Navigate to your project:
|
|
73
|
+
```bash
|
|
74
|
+
cd my-shop
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Add a domain module (e.g., "user"):
|
|
78
|
+
```bash
|
|
79
|
+
eva4j add module user
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**First module automatically creates `shared` module!**
|
|
83
|
+
|
|
84
|
+
The CLI will:
|
|
85
|
+
1. Detect this is the first module
|
|
86
|
+
2. Create the `shared` module with:
|
|
87
|
+
- Base entities (BaseEntity, AuditableEntity, SoftDeletableEntity)
|
|
88
|
+
- Value objects (Money, Email, Address)
|
|
89
|
+
- Domain exceptions
|
|
90
|
+
- Common DTOs (ApiResponse, PageResponse)
|
|
91
|
+
- Enums (Status, Currency, ErrorCode)
|
|
92
|
+
3. Create the `user` module with Spring Modulith structure:
|
|
93
|
+
- `package-info.java` with @ApplicationModule annotation
|
|
94
|
+
- `application/` - Empty directory for controllers, services, DTOs
|
|
95
|
+
- `domain/` - Empty directory for entities and value objects
|
|
96
|
+
- `infrastructure/` - Empty directory for repositories
|
|
97
|
+
|
|
98
|
+
### 3. Add More Modules
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
eva4j add module product
|
|
102
|
+
eva4j add module order
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Each module includes:
|
|
106
|
+
- **package-info.java**: Spring Modulith configuration with `@ApplicationModule`
|
|
107
|
+
- **application/**: Empty directory for controllers, services, DTOs, mappers
|
|
108
|
+
- **domain/**: Empty directory for entities, value objects, domain logic
|
|
109
|
+
- **infrastructure/**: Empty directory for repositories, external integrations
|
|
110
|
+
|
|
111
|
+
You can then add your own classes following hexagonal/modular architecture principles.
|
|
112
|
+
|
|
113
|
+
## Project Structure
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
my-shop/
|
|
117
|
+
├── src/
|
|
118
|
+
│ ├── main/java/com/company/myshop/
|
|
119
|
+
│ │ ├── MyShopApplication.java
|
|
120
|
+
│ │ ├── shared/ # Domain (business)
|
|
121
|
+
│ │ │ ├── domain/
|
|
122
|
+
│ │ │ │ ├── base/
|
|
123
|
+
│ │ │ │ │ ├── BaseEntity.java
|
|
124
|
+
│ │ │ │ │ ├── AuditableEntity.java
|
|
125
|
+
│ │ │ │ │ └── SoftDeletableEntity.java
|
|
126
|
+
│ │ │ │ ├── valueobject/
|
|
127
|
+
│ │ │ │ │ ├── Money.java
|
|
128
|
+
│ │ │ │ │ ├── Email.java
|
|
129
|
+
│ │ │ │ │ └── Address.java
|
|
130
|
+
│ │ │ │ └── exception/
|
|
131
|
+
│ │ │ │ ├── DomainException.java
|
|
132
|
+
│ │ │ │ ├── EntityNotFoundException.java
|
|
133
|
+
│ │ │ │ └── ValidationException.java
|
|
134
|
+
│ │ │ ├── dto/base/
|
|
135
|
+
│ │ │ │ ├── ApiResponse.java
|
|
136
|
+
│ │ │ │ ├── PageResponse.java
|
|
137
|
+
│ │ │ │ └── ErrorDetail.java
|
|
138
|
+
│ │ │ ├── enums/
|
|
139
|
+
│ │ │ │ ├── Status.java
|
|
140
|
+
│ │ │ │ ├── Currency.java
|
|
141
|
+
│ │ │ │ └── ErrorCode.java
|
|
142
|
+
│ │ │ └── constants/
|
|
143
|
+
│ │ │ └── DomainConstants.java
|
|
144
|
+
│ │ ├── user/ # Domain module
|
|
145
|
+
│ │ │ ├── package-info.java # @ApplicationModule
|
|
146
|
+
│ │ │ ├── application/ # Controllers, Services, DTOs
|
|
147
|
+
│ │ │ ├── domain/ # Entities, Value Objects
|
|
148
|
+
│ │ │ └── infrastructure/ # Repositories
|
|
149
|
+
│ │ └── product/ # Another domain module
|
|
150
|
+
│ │ └── ... (same structure)
|
|
151
|
+
│ └── resources/
|
|
152
|
+
│ ├── application.yml
|
|
153
|
+
│ ├── application-local.yml
|
|
154
|
+
│ ├── application-develop.yml
|
|
155
|
+
│ ├── application-test.yml
|
|
156
|
+
│ └── application-production.yml
|
|
157
|
+
└── build.gradle
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Running the Application
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Using Gradle wrapper
|
|
164
|
+
./gradlew bootRun
|
|
165
|
+
|
|
166
|
+
# Or build and run
|
|
167
|
+
./gradlew build
|
|
168
|
+
java -jar build/libs/my-shop-1.0.0.jar
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Environment Profiles
|
|
172
|
+
|
|
173
|
+
The application includes multiple Spring profiles:
|
|
174
|
+
|
|
175
|
+
- **local**: Development on local machine (DEBUG logs, create-drop, SQL visible)
|
|
176
|
+
- **develop**: Development environment (INFO logs, update schema)
|
|
177
|
+
- **test**: Testing environment (INFO logs, update schema)
|
|
178
|
+
- **production**: Production environment (WARN logs, validate schema, swagger disabled)
|
|
179
|
+
|
|
180
|
+
Set the profile using the `PROFILE` environment variable:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Local development (default if not set)
|
|
184
|
+
PROFILE=local ./gradlew bootRun
|
|
185
|
+
|
|
186
|
+
# Development environment
|
|
187
|
+
PROFILE=develop ./gradlew bootRun
|
|
188
|
+
|
|
189
|
+
# Production
|
|
190
|
+
PROFILE=production java -jar build/libs/my-shop-1.0.0.jar
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Default profile: `develop`
|
|
194
|
+
|
|
195
|
+
## API Documentation
|
|
196
|
+
|
|
197
|
+
Once running, visit:
|
|
198
|
+
- Swagger UI: http://localhost:8001/api/v1/swagger-ui.html
|
|
199
|
+
- OpenAPI: http://localhost:8001/api/v1/api-docs
|
|
200
|
+
- Health: http://localhost:8001/api/v1/actuator/health
|
|
201
|
+
|
|
202
|
+
**Note**: Context path is `/api/v1` and default port is `8001` (configurable in application.yml)
|
|
203
|
+
|
|
204
|
+
## Architecture
|
|
205
|
+
|
|
206
|
+
### Spring Modulith
|
|
207
|
+
The project uses Spring Modulith for modular monolith architecture. Each module is annotated with `@ApplicationModule` and can only depend on the `shared` module.
|
|
208
|
+
|
|
209
|
+
### Shared Module (Domain)
|
|
210
|
+
Business domain: base entities, value objects, domain exceptions, shared enums. This module is automatically created when you add your first domain module.
|
|
211
|
+
|
|
212
|
+
### Domain Modules (Features)
|
|
213
|
+
Each module follows a layered structure:
|
|
214
|
+
- **application/**: Application layer (controllers, services, DTOs, mappers)
|
|
215
|
+
- **domain/**: Domain layer (entities, value objects, domain logic)
|
|
216
|
+
- **infrastructure/**: Infrastructure layer (repositories, external integrations)
|
|
217
|
+
|
|
218
|
+
Modules are self-contained and can only reference the `shared` module, promoting loose coupling.
|
|
219
|
+
|
|
220
|
+
## Commands Reference
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Create project
|
|
224
|
+
eva4j create <project-name>
|
|
225
|
+
|
|
226
|
+
# Add module
|
|
227
|
+
eva4j add module <module-name>
|
|
228
|
+
|
|
229
|
+
# Display project info
|
|
230
|
+
eva4j info
|
|
231
|
+
|
|
232
|
+
# Version
|
|
233
|
+
eva4j -v
|
|
234
|
+
|
|
235
|
+
# Help
|
|
236
|
+
eva4j --help
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Project Configuration Persistence
|
|
240
|
+
|
|
241
|
+
Eva4j automatically saves project configuration in `.eva4j.json` file at the project root. This file tracks:
|
|
242
|
+
- Project metadata (name, group ID, package name, versions)
|
|
243
|
+
- Selected dependencies
|
|
244
|
+
- Added modules with their options (soft-delete, audit)
|
|
245
|
+
- Creation and update timestamps
|
|
246
|
+
|
|
247
|
+
**Benefits:**
|
|
248
|
+
- Persist configuration across sessions
|
|
249
|
+
- Track module history
|
|
250
|
+
- Share configuration with team members (committed to git)
|
|
251
|
+
- Validate module additions against existing modules
|
|
252
|
+
|
|
253
|
+
**Example `.eva4j.json`:**
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"projectName": "my-shop",
|
|
257
|
+
"groupId": "com.company",
|
|
258
|
+
"artifactId": "my-shop",
|
|
259
|
+
"packageName": "com.company.myshop",
|
|
260
|
+
"javaVersion": "21",
|
|
261
|
+
"springBootVersion": "3.5.5",
|
|
262
|
+
"springModulithVersion": "1.4.6",
|
|
263
|
+
"dependencies": ["web", "data-jpa", "validation"],
|
|
264
|
+
"modules": [
|
|
265
|
+
{
|
|
266
|
+
"name": "user",
|
|
267
|
+
"hasSoftDelete": true,
|
|
268
|
+
"hasAudit": true,
|
|
269
|
+
"createdAt": "2026-01-27T10:30:00.000Z"
|
|
270
|
+
}
|
|
271
|
+
],
|
|
272
|
+
"createdAt": "2026-01-27T10:25:00.000Z",
|
|
273
|
+
"updatedAt": "2026-01-27T10:30:00.000Z"
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**View project info:**
|
|
278
|
+
```bash
|
|
279
|
+
cd my-shop
|
|
280
|
+
eva4j info
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
This displays:
|
|
284
|
+
- Project details (name, group ID, package)
|
|
285
|
+
- Versions (Java, Spring Boot, Spring Modulith)
|
|
286
|
+
- Dependencies
|
|
287
|
+
- Modules with features
|
|
288
|
+
- Timestamps
|
|
289
|
+
|
|
290
|
+
## Tips
|
|
291
|
+
|
|
292
|
+
1. **First Module**: Always generates the shared module automatically
|
|
293
|
+
2. **Soft Delete**: Enable for entities that should not be permanently deleted
|
|
294
|
+
3. **Audit Fields**: Enable to track who created/modified entities
|
|
295
|
+
4. **Spring Modulith**: Each module is isolated and can only depend on `shared`
|
|
296
|
+
5. **Profiles**: Use `local` for development, `production` for deployment
|
|
297
|
+
6. **Virtual Threads**: Enabled by default for better performance (Java 21+)
|
|
298
|
+
7. **Configuration Tracking**: Use `eva4j info` to view project details and module history
|
|
299
|
+
8. **Team Collaboration**: `.eva4j.json` is tracked in git for team coordination
|
|
300
|
+
|
|
301
|
+
## Example Workflow
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# 1. Create project
|
|
305
|
+
eva4j create ecommerce
|
|
306
|
+
|
|
307
|
+
# 2. Navigate to project
|
|
308
|
+
cd ecommerce
|
|
309
|
+
|
|
310
|
+
# 3. View project info
|
|
311
|
+
eva4j info
|
|
312
|
+
|
|
313
|
+
# 4. Add domain modules
|
|
314
|
+
eva4j add module user # Creates shared + user
|
|
315
|
+
eva4j add module product # Just creates product
|
|
316
|
+
eva4j add module order # Just creates order
|
|
317
|
+
eva4j add module payment # Just creates payment
|
|
318
|
+
|
|
319
|
+
# 5. Check configuration and modules
|
|
320
|
+
eva4j info
|
|
321
|
+
|
|
322
|
+
# 6. Start database (if using Docker)
|
|
323
|
+
docker-compose up -d
|
|
324
|
+
|
|
325
|
+
# 7. Run application
|
|
326
|
+
./gradlew bootRun
|
|
327
|
+
|
|
328
|
+
# 8. Visit Swagger
|
|
329
|
+
# http://localhost:8001/api/v1/swagger-ui.html
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Troubleshooting
|
|
333
|
+
|
|
334
|
+
**Issue**: "Not in a Spring Boot project directory"
|
|
335
|
+
- Solution: Make sure you're in the project root (where build.gradle exists)
|
|
336
|
+
|
|
337
|
+
**Issue**: Module already exists
|
|
338
|
+
- Solution: Choose a different module name or delete the existing module folder
|
|
339
|
+
|
|
340
|
+
**Issue**: Permission denied (Linux/Mac)
|
|
341
|
+
- Solution: `chmod +x ./gradlew`
|
|
342
|
+
|
|
343
|
+
## Contributing
|
|
344
|
+
|
|
345
|
+
Issues and pull requests welcome at: https://github.com/your-repo/eva4j
|
|
346
|
+
|
|
347
|
+
## License
|
|
348
|
+
|
|
349
|
+
MIT
|
package/bin/eva4j.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Command } = require('commander');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const packageJson = require('../package.json');
|
|
6
|
+
const createCommand = require('../src/commands/create');
|
|
7
|
+
const addModuleCommand = require('../src/commands/add-module');
|
|
8
|
+
const addKafkaClientCommand = require('../src/commands/add-kafka-client');
|
|
9
|
+
const generateUsecaseCommand = require('../src/commands/generate-usecase');
|
|
10
|
+
const generateHttpExchangeCommand = require('../src/commands/generate-http-exchange');
|
|
11
|
+
const generateKafkaEventCommand = require('../src/commands/generate-kafka-event');
|
|
12
|
+
const generateKafkaListenerCommand = require('../src/commands/generate-kafka-listener');
|
|
13
|
+
const generateResourceCommand = require('../src/commands/generate-resource');
|
|
14
|
+
const infoCommand = require('../src/commands/info');
|
|
15
|
+
const detachCommand = require('../src/commands/detach');
|
|
16
|
+
|
|
17
|
+
const program = new Command();
|
|
18
|
+
|
|
19
|
+
program
|
|
20
|
+
.name('eva4j')
|
|
21
|
+
.description(chalk.blue('CLI for generating Spring Boot projects with modular architecture'))
|
|
22
|
+
.version(packageJson.version, '-v, --version', 'Output the current version');
|
|
23
|
+
|
|
24
|
+
// Create command
|
|
25
|
+
program
|
|
26
|
+
.command('create <project-name>')
|
|
27
|
+
.description('Create a new Spring Boot project')
|
|
28
|
+
.action(async (projectName, options) => {
|
|
29
|
+
try {
|
|
30
|
+
await createCommand(projectName, options);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error(chalk.red('Error:'), error.message);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Add module command
|
|
38
|
+
program
|
|
39
|
+
.command('add <type> [name]')
|
|
40
|
+
.description('Add components to the project. Use: module [name], kafka-client')
|
|
41
|
+
.action(async (type, name, options) => {
|
|
42
|
+
if (type === 'kafka-client') {
|
|
43
|
+
try {
|
|
44
|
+
await addKafkaClientCommand(options);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error(chalk.red('Error:'), error.message);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (type !== 'module') {
|
|
53
|
+
console.error(chalk.red(`❌ Unknown type: ${type}`));
|
|
54
|
+
console.log(chalk.yellow('\nUsage:'));
|
|
55
|
+
console.log(chalk.gray(' eva4j add module [module-name] # Interactive or with name'));
|
|
56
|
+
console.log(chalk.gray(' eva4j add kafka-client'));
|
|
57
|
+
console.log(chalk.gray('\nExamples:'));
|
|
58
|
+
console.log(chalk.gray(' eva4j add module user'));
|
|
59
|
+
console.log(chalk.gray(' eva4j add module # Will prompt for name\n'));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
await addModuleCommand(name, options);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error(chalk.red('Error:'), error.message);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Generate command
|
|
72
|
+
program
|
|
73
|
+
.command('generate <type> <module> [name]')
|
|
74
|
+
.alias('g')
|
|
75
|
+
.description('Generate components (usecase, http-exchange, kafka-event, kafka-listener, resource)')
|
|
76
|
+
.action(async (type, module, name, options) => {
|
|
77
|
+
if (type === 'usecase') {
|
|
78
|
+
if (!module) {
|
|
79
|
+
console.error(chalk.red('❌ Module name is required'));
|
|
80
|
+
console.log(chalk.gray('Usage: eva4j generate usecase <module> [name]'));
|
|
81
|
+
console.log(chalk.gray('Examples:'));
|
|
82
|
+
console.log(chalk.gray(' eva4j generate usecase user create-user'));
|
|
83
|
+
console.log(chalk.gray(' eva4j generate usecase user # Will prompt for name\n'));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
await generateUsecaseCommand(module, name, options);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error(chalk.red('Error:'), error.message);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (type === 'http-exchange') {
|
|
96
|
+
if (!module) {
|
|
97
|
+
console.error(chalk.red('❌ Module name is required'));
|
|
98
|
+
console.log(chalk.gray('Usage: eva4j generate http-exchange <module> [port-name]'));
|
|
99
|
+
console.log(chalk.gray('Examples:'));
|
|
100
|
+
console.log(chalk.gray(' eva4j generate http-exchange user product-service'));
|
|
101
|
+
console.log(chalk.gray(' eva4j generate http-exchange user # Will prompt for port name\n'));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
await generateHttpExchangeCommand(module, name, options);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error(chalk.red('Error:'), error.message);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (type === 'kafka-event') {
|
|
114
|
+
if (!module) {
|
|
115
|
+
console.error(chalk.red('❌ Module name is required'));
|
|
116
|
+
console.log(chalk.gray('Usage: eva4j generate kafka-event <module> [event-name]'));
|
|
117
|
+
console.log(chalk.gray('Examples:'));
|
|
118
|
+
console.log(chalk.gray(' eva4j generate kafka-event user product-created'));
|
|
119
|
+
console.log(chalk.gray(' eva4j generate kafka-event user # Will prompt for event name\n'));
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
await generateKafkaEventCommand(module, name, options);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error(chalk.red('Error:'), error.message);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (type === 'kafka-listener') {
|
|
132
|
+
if (!module) {
|
|
133
|
+
console.error(chalk.red('❌ Module name is required'));
|
|
134
|
+
console.log(chalk.gray('Usage: eva4j generate kafka-listener <module>'));
|
|
135
|
+
console.log(chalk.gray('Examples:'));
|
|
136
|
+
console.log(chalk.gray(' eva4j generate kafka-listener user'));
|
|
137
|
+
console.log(chalk.gray(' eva4j g kafka-listener order\n'));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
await generateKafkaListenerCommand(module, options);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error(chalk.red('Error:'), error.message);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (type === 'resource') {
|
|
150
|
+
if (!module) {
|
|
151
|
+
console.error(chalk.red('❌ Module name is required'));
|
|
152
|
+
console.log(chalk.gray('Usage: eva4j generate resource <module>'));
|
|
153
|
+
console.log(chalk.gray('Examples:'));
|
|
154
|
+
console.log(chalk.gray(' eva4j generate resource user'));
|
|
155
|
+
console.log(chalk.gray(' eva4j g resource product\n'));
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
await generateResourceCommand(module, options);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error(chalk.red('Error:'), error.message);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
console.error(chalk.red(`❌ Unknown type: ${type}`));
|
|
168
|
+
console.log(chalk.yellow('\nUsage:'));
|
|
169
|
+
console.log(chalk.gray(' eva4j generate usecase <name> <module>'));
|
|
170
|
+
console.log(chalk.gray(' eva4j generate http-exchange <port-name> <module>'));
|
|
171
|
+
console.log(chalk.gray(' eva4j generate kafka-event <event-name> <module>'));
|
|
172
|
+
console.log(chalk.gray(' eva4j generate kafka-listener <module>'));
|
|
173
|
+
console.log(chalk.gray(' eva4j generate resource <module>'));
|
|
174
|
+
console.log(chalk.gray('\nExamples:'));
|
|
175
|
+
console.log(chalk.gray(' eva4j generate usecase create-provider provider'));
|
|
176
|
+
console.log(chalk.gray(' eva4j g http-exchange user-service-port user'));
|
|
177
|
+
console.log(chalk.gray(' eva4j g kafka-event user-created user'));
|
|
178
|
+
console.log(chalk.gray(' eva4j g kafka-listener user'));
|
|
179
|
+
console.log(chalk.gray(' eva4j g resource product\n'));
|
|
180
|
+
process.exit(1);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Info command
|
|
184
|
+
program
|
|
185
|
+
.command('info')
|
|
186
|
+
.description('Display project information and configuration')
|
|
187
|
+
.action(async (options) => {
|
|
188
|
+
try {
|
|
189
|
+
await infoCommand(options);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error(chalk.red('Error:'), error.message);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Detach command
|
|
197
|
+
program
|
|
198
|
+
.command('detach [module-name]')
|
|
199
|
+
.description('Extract a module into a standalone microservice')
|
|
200
|
+
.action(async (moduleName, options) => {
|
|
201
|
+
try {
|
|
202
|
+
await detachCommand(moduleName, options);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error(chalk.red('Error:'), error.message);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Help command
|
|
210
|
+
program.on('--help', () => {
|
|
211
|
+
console.log('');
|
|
212
|
+
console.log(chalk.blue('Examples:'));
|
|
213
|
+
console.log(chalk.gray(' $ eva4j create my-project'));
|
|
214
|
+
console.log(chalk.gray(' $ eva4j add module user'));
|
|
215
|
+
console.log(chalk.gray(' $ eva4j add module product'));
|
|
216
|
+
console.log(chalk.gray(' $ eva4j add kafka-client'));
|
|
217
|
+
console.log(chalk.gray(' $ eva4j generate usecase create-provider provider'));
|
|
218
|
+
console.log(chalk.gray(' $ eva4j g usecase get-all-products product'));
|
|
219
|
+
console.log(chalk.gray(' $ eva4j g http-exchange user-service-port user'));
|
|
220
|
+
console.log(chalk.gray(' $ eva4j g kafka-event user-created user'));
|
|
221
|
+
console.log(chalk.gray(' $ eva4j detach user'));
|
|
222
|
+
console.log(chalk.gray(' $ eva4j info'));
|
|
223
|
+
console.log('');
|
|
224
|
+
console.log(chalk.blue('For more information, visit:'));
|
|
225
|
+
console.log(chalk.gray(' https://github.com/your-repo/eva4j'));
|
|
226
|
+
console.log('');
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Show help if no command provided
|
|
230
|
+
if (!process.argv.slice(2).length) {
|
|
231
|
+
program.outputHelp();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"javaVersion": 21,
|
|
4
|
+
"springBootVersion": "3.5.5",
|
|
5
|
+
"dependencyManagementVersion": "1.1.7",
|
|
6
|
+
"springModulithVersion": "1.4.6",
|
|
7
|
+
"springCloudVersion": "2025.0.0",
|
|
8
|
+
"gradleVersion": "8.7",
|
|
9
|
+
"encoding": "UTF-8",
|
|
10
|
+
"server": {
|
|
11
|
+
"port": 8040,
|
|
12
|
+
"contextPath": "/"
|
|
13
|
+
},
|
|
14
|
+
"database": {
|
|
15
|
+
"type": "h2",
|
|
16
|
+
"ddlAuto": "update",
|
|
17
|
+
"showSql": true
|
|
18
|
+
},
|
|
19
|
+
"logging": {
|
|
20
|
+
"level": "INFO"
|
|
21
|
+
},
|
|
22
|
+
"features": {
|
|
23
|
+
"enableScheduling": false,
|
|
24
|
+
"enableAsync": false,
|
|
25
|
+
"includeSwagger": true,
|
|
26
|
+
"includeActuator": true,
|
|
27
|
+
"includeDevtools": true,
|
|
28
|
+
"includeLombok": true,
|
|
29
|
+
"includeDocker": true
|
|
30
|
+
},
|
|
31
|
+
"testing": {
|
|
32
|
+
"includeTestcontainers": false,
|
|
33
|
+
"includeIntegrationTests": true
|
|
34
|
+
},
|
|
35
|
+
"shared": {
|
|
36
|
+
"hasSoftDelete": true,
|
|
37
|
+
"hasAudit": true,
|
|
38
|
+
"includeValueObjects": true,
|
|
39
|
+
"includeDomainEvents": false
|
|
40
|
+
},
|
|
41
|
+
"module": {
|
|
42
|
+
"hasSoftDelete": true,
|
|
43
|
+
"hasAudit": true,
|
|
44
|
+
"generateTests": true
|
|
45
|
+
}
|
|
46
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eva4j",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A powerful Node.js CLI for generating Spring Boot projects with modular architecture that enables efficient monolith-first development with seamless transition to microservices",
|
|
5
|
+
"main": "bin/eva4j.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"eva4j": "./bin/eva4j.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/eva4j.js",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"cli",
|
|
15
|
+
"spring-boot",
|
|
16
|
+
"java",
|
|
17
|
+
"gradle",
|
|
18
|
+
"scaffolding",
|
|
19
|
+
"generator",
|
|
20
|
+
"microservices",
|
|
21
|
+
"hexagonal-architecture",
|
|
22
|
+
"clean-architecture",
|
|
23
|
+
"cqrs",
|
|
24
|
+
"spring-modulith",
|
|
25
|
+
"modular-monolith",
|
|
26
|
+
"kafka",
|
|
27
|
+
"rest-api",
|
|
28
|
+
"boilerplate",
|
|
29
|
+
"code-generator",
|
|
30
|
+
"openfeign",
|
|
31
|
+
"event-driven"
|
|
32
|
+
],
|
|
33
|
+
"author": "asuridev",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/asuridev/eva4j.git"
|
|
38
|
+
},
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/asuridev/eva4j/issues"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/asuridev/eva4j#readme",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"chalk": "^4.1.2",
|
|
45
|
+
"commander": "^11.1.0",
|
|
46
|
+
"ejs": "^3.1.9",
|
|
47
|
+
"fs-extra": "^11.2.0",
|
|
48
|
+
"inquirer": "^8.2.6",
|
|
49
|
+
"js-yaml": "^4.1.0",
|
|
50
|
+
"ora": "^5.4.1",
|
|
51
|
+
"pluralize": "^8.0.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=14.0.0"
|
|
56
|
+
}
|
|
57
|
+
}
|