nestjs-ddd-cli 2.0.1 → 2.1.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/README.md +351 -61
- package/dist/commands/generate-entity.js +3 -3
- package/dist/commands/generate-entity.js.map +1 -1
- package/dist/commands/generate-event.js +1 -1
- package/dist/commands/generate-event.js.map +1 -1
- package/dist/commands/generate-service.js +1 -1
- package/dist/commands/generate-service.js.map +1 -1
- package/dist/commands/generate-usecase.js +2 -2
- package/dist/commands/generate-usecase.js.map +1 -1
- package/dist/templates/command/create-command.hbs +1 -1
- package/dist/templates/entity/entity.hbs +13 -9
- package/dist/templates/mapper/mapper.hbs +14 -8
- package/dist/templates/orm-entity/orm-entity.hbs +17 -3
- package/dist/templates/repository/repository.hbs +1 -1
- package/dist/templates/usecase/create-usecase.hbs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# NestJS DDD CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
🏗️ **An opinionated CLI for pragmatic Domain-Driven Design with NestJS**
|
|
4
|
+
|
|
5
|
+
Stop writing boilerplate. Start building business logic.
|
|
6
|
+
|
|
7
|
+
Generate production-ready NestJS code following proven DDD/CQRS patterns with consistent structure and immutable architecture principles.
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
@@ -76,94 +80,380 @@ ddd generate all User -m user-management
|
|
|
76
80
|
| **Complete CRUD** | `ddd scaffold <name> -m <module>` | All files for an entity |
|
|
77
81
|
| **All Entity Files** | `ddd generate all <name> -m <module>` | Entity + related files |
|
|
78
82
|
|
|
79
|
-
##
|
|
83
|
+
## Quick Start
|
|
84
|
+
|
|
85
|
+
### 🚀 **Generate Your First Feature**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# 1. Create complete scaffolding for a User management feature
|
|
89
|
+
ddd scaffold User -m user-management
|
|
80
90
|
|
|
91
|
+
# 2. Add business logic to the generated files
|
|
92
|
+
# 3. Update index.ts exports
|
|
93
|
+
# 4. Run migrations
|
|
94
|
+
# 5. Import module in app.module.ts
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**What you get in seconds:**
|
|
98
|
+
```
|
|
99
|
+
📁 modules/user-management/
|
|
100
|
+
├── 📄 user-management.module.ts ✅ NestJS module configured
|
|
101
|
+
├── 📁 application/
|
|
102
|
+
│ ├── 📁 controllers/
|
|
103
|
+
│ │ └── 📄 user.controller.ts ✅ REST endpoints (GET, POST, PUT, DELETE)
|
|
104
|
+
│ ├── 📁 domain/
|
|
105
|
+
│ │ ├── 📁 entities/
|
|
106
|
+
│ │ │ └── 📄 user.entity.ts ✅ Domain entity with interfaces
|
|
107
|
+
│ │ └── 📁 usecases/
|
|
108
|
+
│ │ ├── 📄 create-user.usecase.ts ✅ Business logic for creation
|
|
109
|
+
│ │ ├── 📄 update-user.usecase.ts ✅ Business logic for updates
|
|
110
|
+
│ │ └── 📄 delete-user.usecase.ts ✅ Business logic for deletion
|
|
111
|
+
│ └── 📁 dto/
|
|
112
|
+
│ ├── 📁 requests/
|
|
113
|
+
│ │ ├── 📄 create-user.dto.ts ✅ Request validation schemas
|
|
114
|
+
│ │ └── 📄 update-user.dto.ts ✅ Update validation schemas
|
|
115
|
+
│ └── 📁 responses/
|
|
116
|
+
│ └── 📄 user.response.ts ✅ Response data contracts
|
|
117
|
+
└── 📁 infrastructure/
|
|
118
|
+
├── 📁 repositories/
|
|
119
|
+
│ └── 📄 user.repository.ts ✅ CRUD operations + custom queries
|
|
120
|
+
├── 📁 orm-entities/
|
|
121
|
+
│ └── 📄 user.orm-entity.ts ✅ Database schema (TypeORM)
|
|
122
|
+
└── 📁 mappers/
|
|
123
|
+
└── 📄 user.mapper.ts ✅ Domain ↔ Database mapping
|
|
81
124
|
```
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
│ │ ├── entities/ # Domain entities
|
|
89
|
-
│ │ ├── events/ # Domain events
|
|
90
|
-
│ │ ├── services/ # Domain services
|
|
91
|
-
│ │ └── usecases/ # Use cases/command handlers
|
|
92
|
-
│ ├── dto/
|
|
93
|
-
│ │ ├── requests/ # Request DTOs
|
|
94
|
-
│ │ └── responses/ # Response DTOs
|
|
95
|
-
│ └── queries/ # CQRS query handlers
|
|
96
|
-
├── infrastructure/
|
|
97
|
-
│ ├── mappers/ # Domain ↔ ORM mappers
|
|
98
|
-
│ ├── orm-entities/ # Database entities
|
|
99
|
-
│ └── repositories/ # Repository implementations
|
|
100
|
-
└── [module-name].module.ts # NestJS module
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## Examples
|
|
104
|
-
|
|
105
|
-
### Create a new feature from scratch
|
|
125
|
+
|
|
126
|
+
> **🚀 From zero to production-ready in under 30 seconds**
|
|
127
|
+
|
|
128
|
+
## Real-World Examples
|
|
129
|
+
|
|
130
|
+
### 🏢 **E-commerce Platform**
|
|
106
131
|
|
|
107
132
|
```bash
|
|
108
|
-
#
|
|
109
|
-
ddd scaffold
|
|
133
|
+
# Generate order management
|
|
134
|
+
ddd scaffold Order -m orders
|
|
110
135
|
|
|
111
|
-
#
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
136
|
+
# Add payment processing
|
|
137
|
+
ddd generate service PaymentProcessor -m orders
|
|
138
|
+
ddd generate event OrderPaid -m orders
|
|
139
|
+
|
|
140
|
+
# Add inventory checking
|
|
141
|
+
ddd generate query CheckStock -m inventory
|
|
142
|
+
ddd generate service StockValidator -m inventory
|
|
115
143
|
```
|
|
116
144
|
|
|
117
|
-
|
|
145
|
+
**Result:** Complete order system with payment processing and inventory management
|
|
146
|
+
```
|
|
147
|
+
📁 modules/orders/
|
|
148
|
+
├── 📄 orders.module.ts
|
|
149
|
+
├── 📁 application/domain/services/
|
|
150
|
+
│ └── 📄 payment-processor.service.ts 🆕 Payment business logic
|
|
151
|
+
├── 📁 application/domain/events/
|
|
152
|
+
│ └── 📄 order-paid.event.ts 🆕 Order payment event
|
|
153
|
+
└── ... (all CRUD operations)
|
|
154
|
+
|
|
155
|
+
📁 modules/inventory/
|
|
156
|
+
├── 📁 application/queries/
|
|
157
|
+
│ └── 📄 check-stock.handler.ts 🆕 Stock checking query
|
|
158
|
+
├── 📁 application/domain/services/
|
|
159
|
+
│ └── 📄 stock-validator.service.ts 🆕 Stock validation logic
|
|
160
|
+
└── ... (all CRUD operations)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 🏥 **Healthcare System**
|
|
118
164
|
|
|
119
165
|
```bash
|
|
120
|
-
#
|
|
121
|
-
ddd
|
|
166
|
+
# Patient management
|
|
167
|
+
ddd scaffold Patient -m patients
|
|
168
|
+
|
|
169
|
+
# Medical records with events
|
|
170
|
+
ddd scaffold MedicalRecord -m medical-records
|
|
171
|
+
ddd generate event RecordCreated -m medical-records
|
|
172
|
+
ddd generate event RecordUpdated -m medical-records
|
|
173
|
+
|
|
174
|
+
# Appointment scheduling
|
|
175
|
+
ddd generate query FindAvailableSlots -m appointments
|
|
176
|
+
ddd generate service AppointmentScheduler -m appointments
|
|
122
177
|
```
|
|
123
178
|
|
|
124
|
-
###
|
|
179
|
+
### 🎓 **Learning Management System**
|
|
125
180
|
|
|
126
181
|
```bash
|
|
127
|
-
#
|
|
128
|
-
ddd
|
|
182
|
+
# Course management
|
|
183
|
+
ddd scaffold Course -m courses
|
|
184
|
+
ddd generate service CourseEnrollment -m courses
|
|
185
|
+
ddd generate event StudentEnrolled -m courses
|
|
186
|
+
|
|
187
|
+
# Progress tracking
|
|
188
|
+
ddd generate query GetStudentProgress -m progress
|
|
189
|
+
ddd generate service ProgressCalculator -m progress
|
|
190
|
+
```
|
|
129
191
|
|
|
130
|
-
|
|
131
|
-
ddd generate service PolicyValidation -m policies
|
|
192
|
+
> **🎯 Each example follows identical patterns** - Learn once, apply everywhere.
|
|
132
193
|
|
|
133
|
-
|
|
134
|
-
|
|
194
|
+
## Philosophy & Principles
|
|
195
|
+
|
|
196
|
+
This CLI embodies **pragmatic Domain-Driven Design** with unwavering consistency:
|
|
197
|
+
|
|
198
|
+
### 🔒 **Immutable Architecture**
|
|
199
|
+
- **"Code once, never touch"** - Each generated component remains unchanged after creation
|
|
200
|
+
- **Evolution over modification** - New requirements create new use cases, never modify existing ones
|
|
201
|
+
- **Predictable structure** - Every project follows identical patterns, enabling instant developer onboarding
|
|
202
|
+
|
|
203
|
+
### 🎯 **Opinionated by Design**
|
|
204
|
+
- **Zero configuration fatigue** - One way to do things, the right way
|
|
205
|
+
- **Consistent naming** - PascalCase entities, kebab-case modules, predictable file names
|
|
206
|
+
- **Proven patterns** - Battle-tested DDD/CQRS structure from real-world enterprise applications
|
|
207
|
+
|
|
208
|
+
### 🚀 **Developer Experience First**
|
|
209
|
+
- **No bikeshedding** - Spend time on business logic, not folder structure debates
|
|
210
|
+
- **IDE-friendly** - Barrel exports, clear interfaces, TypeScript-first approach
|
|
211
|
+
- **Team consistency** - Every developer generates identical code structure
|
|
212
|
+
|
|
213
|
+
### 🏗️ **Enterprise Ready**
|
|
214
|
+
- **Separation of concerns** - Domain logic isolated from infrastructure
|
|
215
|
+
- **CQRS compliance** - Commands for writes, queries for reads
|
|
216
|
+
- **Testable by default** - Clean interfaces enable easy unit testing
|
|
217
|
+
|
|
218
|
+
## What Makes This Different?
|
|
219
|
+
|
|
220
|
+
### 🎨 **Structure That Scales**
|
|
221
|
+
|
|
222
|
+
Every module follows this **identical, battle-tested structure**:
|
|
135
223
|
|
|
136
|
-
# Generate a query handler
|
|
137
|
-
ddd generate query GetPolicyDetails -m policies
|
|
138
224
|
```
|
|
225
|
+
modules/
|
|
226
|
+
└── [feature-name]/ # 🏠 Feature boundary
|
|
227
|
+
├── [feature-name].module.ts # 🔧 NestJS module wiring
|
|
228
|
+
├── application/ # 📋 Application layer
|
|
229
|
+
│ ├── commands/ # ✍️ CQRS commands (writes)
|
|
230
|
+
│ │ ├── create-[entity].command.ts # └─ Create operations
|
|
231
|
+
│ │ ├── update-[entity].command.ts # └─ Update operations
|
|
232
|
+
│ │ ├── delete-[entity].command.ts # └─ Delete operations
|
|
233
|
+
│ │ └── index.ts # └─ Barrel exports
|
|
234
|
+
│ ├── controllers/ # 🌐 HTTP/GraphQL endpoints
|
|
235
|
+
│ │ ├── [entity].controller.ts # └─ REST API endpoints
|
|
236
|
+
│ │ └── index.ts # └─ Barrel exports
|
|
237
|
+
│ ├── domain/ # 🧠 Pure business logic
|
|
238
|
+
│ │ ├── entities/ # 📦 Business objects
|
|
239
|
+
│ │ │ ├── [entity].entity.ts # └─ Domain entity
|
|
240
|
+
│ │ │ └── index.ts # └─ Barrel exports
|
|
241
|
+
│ │ ├── events/ # 🎯 Domain events
|
|
242
|
+
│ │ │ ├── [entity]-created.event.ts # └─ Event definitions
|
|
243
|
+
│ │ │ └── index.ts # └─ Barrel exports
|
|
244
|
+
│ │ ├── services/ # ⚙️ Domain services
|
|
245
|
+
│ │ │ ├── [entity].service.ts # └─ Business rules
|
|
246
|
+
│ │ │ └── index.ts # └─ Barrel exports
|
|
247
|
+
│ │ └── usecases/ # 🎬 Use case operations
|
|
248
|
+
│ │ ├── create-[entity].usecase.ts# └─ Create business logic
|
|
249
|
+
│ │ ├── update-[entity].usecase.ts# └─ Update business logic
|
|
250
|
+
│ │ ├── delete-[entity].usecase.ts# └─ Delete business logic
|
|
251
|
+
│ │ └── index.ts # └─ Barrel exports
|
|
252
|
+
│ ├── dto/ # 📄 Data contracts
|
|
253
|
+
│ │ ├── requests/ # 📤 Inbound data
|
|
254
|
+
│ │ │ ├── create-[entity].dto.ts # └─ Create request
|
|
255
|
+
│ │ │ ├── update-[entity].dto.ts # └─ Update request
|
|
256
|
+
│ │ │ └── index.ts # └─ Barrel exports
|
|
257
|
+
│ │ ├── responses/ # 📥 Outbound data
|
|
258
|
+
│ │ │ ├── [entity].response.ts # └─ Entity response
|
|
259
|
+
│ │ │ └── index.ts # └─ Barrel exports
|
|
260
|
+
│ │ └── index.ts # └─ Barrel exports
|
|
261
|
+
│ └── queries/ # 🔍 CQRS queries (reads)
|
|
262
|
+
│ ├── get-[entity].handler.ts # └─ Single entity query
|
|
263
|
+
│ ├── list-[entities].handler.ts # └─ Multiple entities query
|
|
264
|
+
│ └── index.ts # └─ Barrel exports
|
|
265
|
+
└── infrastructure/ # 🏗️ Infrastructure layer
|
|
266
|
+
├── mappers/ # 🔄 Data transformation
|
|
267
|
+
│ ├── [entity].mapper.ts # └─ Domain ↔ ORM mapping
|
|
268
|
+
│ └── index.ts # └─ Barrel exports
|
|
269
|
+
├── orm-entities/ # 🗄️ Database schema
|
|
270
|
+
│ ├── [entity].orm-entity.ts # └─ TypeORM entity
|
|
271
|
+
│ └── index.ts # └─ Barrel exports
|
|
272
|
+
└── repositories/ # 💾 Data access
|
|
273
|
+
├── [entity].repository.ts # └─ Repository implementation
|
|
274
|
+
└── index.ts # └─ Barrel exports
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
> **🎯 Every feature looks identical** - No surprises, no confusion, just consistency.
|
|
139
278
|
|
|
140
|
-
|
|
279
|
+
### 🧠 **Smart Defaults & Conventions**
|
|
141
280
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
281
|
+
```bash
|
|
282
|
+
# Naming follows strict patterns
|
|
283
|
+
ddd generate entity UserProfile # → user-profile.entity.ts
|
|
284
|
+
ddd generate service OrderValidator # → order-validator.service.ts
|
|
285
|
+
ddd generate event PaymentProcessed # → payment-processed.event.ts
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Built-in Intelligence:**
|
|
289
|
+
- **🔄 Barrel exports** - Automatic `index.ts` files for clean imports
|
|
290
|
+
- **🔒 TypeScript strict** - Zero `any` types, full type safety
|
|
291
|
+
- **💉 DI ready** - Injectable decorators configured
|
|
292
|
+
- **📋 Interface first** - Clear contracts between layers
|
|
293
|
+
- **📁 Predictable paths** - Same location every time
|
|
294
|
+
|
|
295
|
+
### 💡 **Enterprise Patterns**
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// ✅ Commands (writes) - Tell, don't ask
|
|
299
|
+
@CommandHandler(CreateUserCommand)
|
|
300
|
+
export class CreateUserHandler {
|
|
301
|
+
async execute(command: CreateUserCommand): Promise<void> {
|
|
302
|
+
// Returns nothing - just does the work
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ✅ Queries (reads) - Ask, don't tell
|
|
307
|
+
@QueryHandler(GetUserQuery)
|
|
308
|
+
export class GetUserHandler {
|
|
309
|
+
async execute(query: GetUserQuery): Promise<UserResponse> {
|
|
310
|
+
// Returns data - no side effects
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ✅ Domain Events - Loose coupling
|
|
315
|
+
export class UserCreatedEvent implements IEvent {
|
|
316
|
+
constructor(public readonly userId: string) {}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**Battle-tested principles:**
|
|
321
|
+
- **Command/Query Separation** - Writes vs reads clearly separated
|
|
322
|
+
- **Domain Events** - Decoupled communication between bounded contexts
|
|
323
|
+
- **Repository Pattern** - Abstract data access from business logic
|
|
324
|
+
- **Clean Architecture** - Dependencies point inward to domain
|
|
147
325
|
|
|
148
326
|
## After Generation
|
|
149
327
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
328
|
+
### 🔧 **Your 5-Minute Setup Checklist:**
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# ✅ 1. Generated files are ready - Review structure
|
|
332
|
+
ls -la modules/your-feature/
|
|
333
|
+
|
|
334
|
+
# ✅ 2. Add business properties to entities
|
|
335
|
+
# Edit: application/domain/entities/[entity].entity.ts
|
|
336
|
+
# Add: name: string; email: string; etc.
|
|
337
|
+
|
|
338
|
+
# ✅ 3. Update DTOs with validation rules
|
|
339
|
+
# Edit: application/dto/requests/create-[entity].dto.ts
|
|
340
|
+
# Add: @IsEmail() email: string; @IsNotEmpty() name: string;
|
|
341
|
+
|
|
342
|
+
# ✅ 4. Configure database mappings
|
|
343
|
+
# Edit: infrastructure/orm-entities/[entity].orm-entity.ts
|
|
344
|
+
# Add: @Column() name: string; @Column() email: string;
|
|
345
|
+
|
|
346
|
+
# ✅ 5. Wire up the module
|
|
347
|
+
# Edit: app.module.ts
|
|
348
|
+
# Add: YourFeatureModule to imports array
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### 🎯 **Focus on Business Value:**
|
|
352
|
+
```typescript
|
|
353
|
+
// ✅ Write business rules in domain services
|
|
354
|
+
export class OrderValidator {
|
|
355
|
+
validateBusinessRules(order: Order): ValidationResult {
|
|
356
|
+
// Your domain logic here - not infrastructure concerns
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// ✅ Add complex queries for reporting
|
|
361
|
+
@QueryHandler(GetMonthlyRevenueQuery)
|
|
362
|
+
export class GetMonthlyRevenueHandler {
|
|
363
|
+
async execute(query: GetMonthlyRevenueQuery) {
|
|
364
|
+
// Complex business queries - not CRUD
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// ✅ Handle domain events for integration
|
|
369
|
+
@EventsHandler(OrderCreatedEvent)
|
|
370
|
+
export class OrderCreatedHandler {
|
|
371
|
+
async handle(event: OrderCreatedEvent) {
|
|
372
|
+
// Send emails, update analytics, etc.
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
> **🚀 From scaffolding to production in minutes, not days**
|
|
378
|
+
|
|
379
|
+
## Why This CLI Exists
|
|
380
|
+
|
|
381
|
+
### 😤 **The Problem**
|
|
382
|
+
- Endless debates about folder structure
|
|
383
|
+
- Inconsistent naming across team members
|
|
384
|
+
- Copy-pasting boilerplate between features
|
|
385
|
+
- Mixed patterns in the same codebase
|
|
386
|
+
- New developers spending weeks learning "our way"
|
|
387
|
+
|
|
388
|
+
### 🎯 **The Solution**
|
|
389
|
+
- **One structure** that works for all features
|
|
390
|
+
- **Zero configuration** - works out of the box
|
|
391
|
+
- **Battle-tested patterns** from real enterprise apps
|
|
392
|
+
- **Instant onboarding** - same structure everywhere
|
|
393
|
+
- **Focus on business logic** instead of architecture decisions
|
|
155
394
|
|
|
156
|
-
|
|
395
|
+
### 🏆 **The Result**
|
|
396
|
+
- 10x faster feature development
|
|
397
|
+
- Consistent codebase architecture
|
|
398
|
+
- Easy code reviews and maintenance
|
|
399
|
+
- New developers productive from day one
|
|
400
|
+
- No more "where does this file go?" questions
|
|
157
401
|
|
|
158
|
-
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Contributing & Development
|
|
405
|
+
|
|
406
|
+
### 🔧 **Local Development**
|
|
159
407
|
|
|
160
408
|
```bash
|
|
161
|
-
#
|
|
409
|
+
# Clone and setup
|
|
410
|
+
git clone https://github.com/eshe-huli/nestjs-ddd-cli
|
|
411
|
+
cd nestjs-ddd-cli
|
|
412
|
+
npm install
|
|
413
|
+
|
|
414
|
+
# Test changes locally
|
|
162
415
|
npm run dev -- generate entity Test -m test
|
|
163
416
|
|
|
164
|
-
#
|
|
417
|
+
# Build for production
|
|
165
418
|
npm run build
|
|
166
419
|
|
|
167
|
-
# Test globally
|
|
420
|
+
# Test globally installed version
|
|
168
421
|
ddd generate entity Test -m test
|
|
169
|
-
```
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### 🧪 **Testing Your Changes**
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
# Create a test project
|
|
428
|
+
mkdir test-project && cd test-project
|
|
429
|
+
|
|
430
|
+
# Test scaffolding
|
|
431
|
+
ddd scaffold Product -m inventory
|
|
432
|
+
|
|
433
|
+
# Verify structure matches expectations
|
|
434
|
+
tree modules/inventory/
|
|
435
|
+
|
|
436
|
+
# Test individual generators
|
|
437
|
+
ddd generate service ProductValidator -m inventory
|
|
438
|
+
ddd generate event ProductCreated -m inventory
|
|
439
|
+
ddd generate query GetProductsByCategory -m inventory
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### 📋 **Template Structure**
|
|
443
|
+
```
|
|
444
|
+
src/templates/
|
|
445
|
+
├── 📁 entity/ # Domain entity templates
|
|
446
|
+
├── 📁 service/ # Domain service templates
|
|
447
|
+
├── 📁 event/ # Domain event templates
|
|
448
|
+
├── 📁 query/ # Query handler templates
|
|
449
|
+
├── 📁 usecase/ # Use case templates
|
|
450
|
+
├── 📁 controller/ # Controller templates
|
|
451
|
+
├── 📁 repository/ # Repository templates
|
|
452
|
+
└── 📁 ... (more templates)
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
> **🤝 Pull requests welcome!** Help make DDD development even better.
|
|
456
|
+
|
|
457
|
+
## License
|
|
458
|
+
|
|
459
|
+
MIT - Build amazing things 🚀
|
|
@@ -51,7 +51,7 @@ async function generateEntity(entityName, options) {
|
|
|
51
51
|
const templateData = (0, file_utils_1.prepareTemplateData)(entityName, options.module);
|
|
52
52
|
// Generate domain entity
|
|
53
53
|
const entityTemplatePath = path.join(__dirname, '../templates/entity/entity.hbs');
|
|
54
|
-
const entityOutputPath = path.join(modulePath, '
|
|
54
|
+
const entityOutputPath = path.join(modulePath, 'domain/entities', `${(0, naming_utils_1.toKebabCase)(entityName)}.entity.ts`);
|
|
55
55
|
if (await (0, file_utils_1.fileExists)(entityOutputPath)) {
|
|
56
56
|
console.log(chalk_1.default.yellow(`Entity ${entityName} already exists. Skipping...`));
|
|
57
57
|
return;
|
|
@@ -79,11 +79,11 @@ async function generateEntity(entityName, options) {
|
|
|
79
79
|
await updateIndexFiles(modulePath, entityName, options);
|
|
80
80
|
console.log(chalk_1.default.green(`✅ Entity ${entityName} generated successfully!`));
|
|
81
81
|
}
|
|
82
|
-
async function updateIndexFiles(
|
|
82
|
+
async function updateIndexFiles(_modulePath, _entityName, options) {
|
|
83
83
|
// This would update the index.ts files to include the new exports
|
|
84
84
|
// For now, we'll just log a reminder
|
|
85
85
|
console.log(chalk_1.default.yellow(`\n⚠️ Remember to update the following index files:`));
|
|
86
|
-
console.log(` -
|
|
86
|
+
console.log(` - domain/entities/index.ts`);
|
|
87
87
|
if (!options.skipOrm) {
|
|
88
88
|
console.log(` - infrastructure/orm-entities/index.ts`);
|
|
89
89
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-entity.js","sourceRoot":"","sources":["../../src/commands/generate-entity.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,wCAkEC;AAvED,2CAA6B;AAC7B,kDAA0B;AAC1B,oDAA2G;AAC3G,wDAAoD;AAE7C,KAAK,UAAU,cAAc,CAAC,UAAkB,EAAE,OAAY;IACnE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,sBAAsB,UAAU,EAAE,CAAC,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,IAAA,gCAAmB,EAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAErE,yBAAyB;IACzB,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAC;IAClF,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAChC,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"generate-entity.js","sourceRoot":"","sources":["../../src/commands/generate-entity.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,7 +51,7 @@ async function generateEvent(eventName, options) {
|
|
|
51
51
|
// Generate domain event
|
|
52
52
|
const templateData = (0, file_utils_1.prepareTemplateData)(eventName, options.module);
|
|
53
53
|
const templatePath = path.join(__dirname, '../templates/event/domain-event.hbs');
|
|
54
|
-
const outputPath = path.join(modulePath, '
|
|
54
|
+
const outputPath = path.join(modulePath, 'domain/events', `${(0, naming_utils_1.toKebabCase)(eventName)}.event.ts`);
|
|
55
55
|
await (0, file_utils_1.generateFromTemplate)(templatePath, outputPath, templateData);
|
|
56
56
|
console.log(chalk_1.default.green(`✅ Domain event ${eventName} generated successfully!`));
|
|
57
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-event.js","sourceRoot":"","sources":["../../src/commands/generate-event.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,sCAsBC;AA3BD,2CAA6B;AAC7B,kDAA0B;AAC1B,oDAA+F;AAC/F,wDAAoD;AAE7C,KAAK,UAAU,aAAa,CAAC,SAAiB,EAAE,OAAY;IACjE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,4BAA4B,SAAS,EAAE,CAAC,CAAC,CAAC;IAEjE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3D,wBAAwB;IACxB,MAAM,YAAY,GAAG,IAAA,gCAAmB,EAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qCAAqC,CAAC,CAAC;IACjF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"generate-event.js","sourceRoot":"","sources":["../../src/commands/generate-event.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,sCAsBC;AA3BD,2CAA6B;AAC7B,kDAA0B;AAC1B,oDAA+F;AAC/F,wDAAoD;AAE7C,KAAK,UAAU,aAAa,CAAC,SAAiB,EAAE,OAAY;IACjE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,4BAA4B,SAAS,EAAE,CAAC,CAAC,CAAC;IAEjE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3D,wBAAwB;IACxB,MAAM,YAAY,GAAG,IAAA,gCAAmB,EAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qCAAqC,CAAC,CAAC;IACjF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,UAAU,EACV,eAAe,EACf,GAAG,IAAA,0BAAW,EAAC,SAAS,CAAC,WAAW,CACrC,CAAC;IAEF,MAAM,IAAA,iCAAoB,EAAC,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;IAEnE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,kBAAkB,SAAS,0BAA0B,CAAC,CAAC,CAAC;AAClF,CAAC"}
|
|
@@ -51,7 +51,7 @@ async function generateService(serviceName, options) {
|
|
|
51
51
|
// Generate domain service
|
|
52
52
|
const templateData = (0, file_utils_1.prepareTemplateData)(serviceName, options.module);
|
|
53
53
|
const templatePath = path.join(__dirname, '../templates/service/domain-service.hbs');
|
|
54
|
-
const outputPath = path.join(modulePath, '
|
|
54
|
+
const outputPath = path.join(modulePath, 'domain/services', `${(0, naming_utils_1.toKebabCase)(serviceName)}.service.ts`);
|
|
55
55
|
await (0, file_utils_1.generateFromTemplate)(templatePath, outputPath, templateData);
|
|
56
56
|
console.log(chalk_1.default.green(`✅ Domain service ${serviceName} generated successfully!`));
|
|
57
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-service.js","sourceRoot":"","sources":["../../src/commands/generate-service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,0CAsBC;AA3BD,2CAA6B;AAC7B,kDAA0B;AAC1B,oDAA+F;AAC/F,wDAAoD;AAE7C,KAAK,UAAU,eAAe,CAAC,WAAmB,EAAE,OAAY;IACrE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC,CAAC;IAErE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3D,0BAA0B;IAC1B,MAAM,YAAY,GAAG,IAAA,gCAAmB,EAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,yCAAyC,CAAC,CAAC;IACrF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"generate-service.js","sourceRoot":"","sources":["../../src/commands/generate-service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,0CAsBC;AA3BD,2CAA6B;AAC7B,kDAA0B;AAC1B,oDAA+F;AAC/F,wDAAoD;AAE7C,KAAK,UAAU,eAAe,CAAC,WAAmB,EAAE,OAAY;IACrE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC,CAAC;IAErE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3D,0BAA0B;IAC1B,MAAM,YAAY,GAAG,IAAA,gCAAmB,EAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,yCAAyC,CAAC,CAAC;IACrF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,UAAU,EACV,iBAAiB,EACjB,GAAG,IAAA,0BAAW,EAAC,WAAW,CAAC,aAAa,CACzC,CAAC;IAEF,MAAM,IAAA,iCAAoB,EAAC,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;IAEnE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,oBAAoB,WAAW,0BAA0B,CAAC,CAAC,CAAC;AACtF,CAAC"}
|
|
@@ -53,7 +53,7 @@ async function generateUseCase(useCaseName, options) {
|
|
|
53
53
|
const templateData = (0, file_utils_1.prepareTemplateData)(entityName, options.module);
|
|
54
54
|
// Generate use case
|
|
55
55
|
const useCaseTemplatePath = path.join(__dirname, '../templates/usecase/create-usecase.hbs');
|
|
56
|
-
const useCaseOutputPath = path.join(modulePath, 'application/
|
|
56
|
+
const useCaseOutputPath = path.join(modulePath, 'application/usecases', `${(0, naming_utils_1.toKebabCase)(useCaseName)}.use-case.ts`);
|
|
57
57
|
await (0, file_utils_1.generateFromTemplate)(useCaseTemplatePath, useCaseOutputPath, templateData);
|
|
58
58
|
// Generate command
|
|
59
59
|
const commandTemplatePath = path.join(__dirname, '../templates/command/create-command.hbs');
|
|
@@ -65,7 +65,7 @@ async function generateUseCase(useCaseName, options) {
|
|
|
65
65
|
await (0, file_utils_1.generateFromTemplate)(dtoTemplatePath, dtoOutputPath, templateData);
|
|
66
66
|
console.log(chalk_1.default.green(`✅ Use case ${useCaseName} generated successfully!`));
|
|
67
67
|
console.log(chalk_1.default.yellow(`\n⚠️ Remember to update the following index files:`));
|
|
68
|
-
console.log(` - application/
|
|
68
|
+
console.log(` - application/usecases/index.ts`);
|
|
69
69
|
console.log(` - application/commands/index.ts`);
|
|
70
70
|
console.log(` - application/dto/requests/index.ts`);
|
|
71
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-usecase.js","sourceRoot":"","sources":["../../src/commands/generate-usecase.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,0CAiDC;AAtDD,2CAA6B;AAC7B,kDAA0B;AAC1B,oDAA+F;AAC/F,
|
|
1
|
+
{"version":3,"file":"generate-usecase.js","sourceRoot":"","sources":["../../src/commands/generate-usecase.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CommandHandler, ICommandHandler } from "@nestjs/cqrs";
|
|
2
|
-
import { Create{{entityNamePascal}}UseCase } from "@modules/{{moduleNameKebab}}/application/
|
|
2
|
+
import { Create{{entityNamePascal}}UseCase } from "@modules/{{moduleNameKebab}}/application/usecases/create-{{entityNameKebab}}.use-case";
|
|
3
3
|
import { Create{{entityNamePascal}}Dto } from "@modules/{{moduleNameKebab}}/application/dto/requests/create-{{entityNameKebab}}.dto";
|
|
4
4
|
|
|
5
5
|
export class Create{{entityNamePascal}}Command {
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export interface {{entityNamePascal}}EntityProps {
|
|
2
|
+
id?: string;
|
|
3
|
+
isActive?: boolean;
|
|
4
|
+
createdAt?: Date;
|
|
5
|
+
updatedAt?: Date;
|
|
6
|
+
deletedAt?: Date;
|
|
7
7
|
// Add your domain properties here
|
|
8
8
|
// Example: name: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export class {{entityNamePascal}}Entity
|
|
11
|
+
export class {{entityNamePascal}}Entity {
|
|
12
|
+
public readonly id?: string;
|
|
13
|
+
public readonly isActive?: boolean;
|
|
14
|
+
public readonly createdAt?: Date;
|
|
15
|
+
public readonly updatedAt?: Date;
|
|
16
|
+
public readonly deletedAt?: Date;
|
|
12
17
|
// Add your domain properties here
|
|
13
|
-
// Example: name: string;
|
|
18
|
+
// Example: public readonly name: string;
|
|
14
19
|
|
|
15
20
|
constructor(props: {{entityNamePascal}}EntityProps) {
|
|
16
|
-
super();
|
|
17
21
|
Object.assign(this, props);
|
|
18
22
|
}
|
|
19
23
|
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import { BaseMapper } from "@core/mappers/base.mapper";
|
|
2
1
|
import { {{entityNamePascal}}OrmEntity } from "@modules/{{moduleNameKebab}}/infrastructure/orm-entities/{{entityNameKebab}}.orm-entity";
|
|
3
|
-
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/
|
|
2
|
+
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/domain/entities/{{entityNameKebab}}.entity";
|
|
4
3
|
import { Injectable } from "@nestjs/common";
|
|
5
4
|
|
|
6
5
|
@Injectable()
|
|
7
|
-
export class {{entityNamePascal}}Mapper
|
|
8
|
-
{{entityNamePascal}}Entity,
|
|
9
|
-
{{entityNamePascal}}OrmEntity
|
|
10
|
-
> {
|
|
6
|
+
export class {{entityNamePascal}}Mapper {
|
|
11
7
|
toOrmEntity(domainEntity: {{entityNamePascal}}Entity): {{entityNamePascal}}OrmEntity {
|
|
12
|
-
|
|
8
|
+
if (!domainEntity) {
|
|
9
|
+
throw new Error('Domain entity is required');
|
|
10
|
+
}
|
|
13
11
|
|
|
14
|
-
const ormEntity = new {{entityNamePascal}}OrmEntity(
|
|
12
|
+
const ormEntity = new {{entityNamePascal}}OrmEntity();
|
|
15
13
|
ormEntity.id = domainEntity.id;
|
|
14
|
+
ormEntity.isActive = domainEntity.isActive;
|
|
15
|
+
ormEntity.createdAt = domainEntity.createdAt;
|
|
16
|
+
ormEntity.updatedAt = domainEntity.updatedAt;
|
|
17
|
+
ormEntity.deletedAt = domainEntity.deletedAt;
|
|
16
18
|
// Map your properties from camelCase to snake_case
|
|
17
19
|
// Example: ormEntity.property_name = domainEntity.propertyName;
|
|
18
20
|
|
|
@@ -22,6 +24,10 @@ export class {{entityNamePascal}}Mapper extends BaseMapper<
|
|
|
22
24
|
toDomainEntity(ormEntity: {{entityNamePascal}}OrmEntity): {{entityNamePascal}}Entity {
|
|
23
25
|
const entity = new {{entityNamePascal}}Entity({
|
|
24
26
|
id: ormEntity.id,
|
|
27
|
+
isActive: ormEntity.isActive,
|
|
28
|
+
createdAt: ormEntity.createdAt,
|
|
29
|
+
updatedAt: ormEntity.updatedAt,
|
|
30
|
+
deletedAt: ormEntity.deletedAt,
|
|
25
31
|
// Map your properties from snake_case to camelCase
|
|
26
32
|
// Example: propertyName: ormEntity.property_name,
|
|
27
33
|
});
|
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Column, Entity } from "typeorm";
|
|
1
|
+
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
|
3
2
|
|
|
4
3
|
@Entity("{{tableName}}")
|
|
5
|
-
export class {{entityNamePascal}}OrmEntity
|
|
4
|
+
export class {{entityNamePascal}}OrmEntity {
|
|
5
|
+
@PrimaryGeneratedColumn("uuid")
|
|
6
|
+
id?: string;
|
|
7
|
+
|
|
8
|
+
@Column({ name: "is_active", default: true })
|
|
9
|
+
isActive?: boolean;
|
|
10
|
+
|
|
11
|
+
@Column({ name: "created_at", type: "timestamp", default: () => "CURRENT_TIMESTAMP" })
|
|
12
|
+
createdAt?: Date;
|
|
13
|
+
|
|
14
|
+
@Column({ name: "updated_at", type: "timestamp", default: () => "CURRENT_TIMESTAMP" })
|
|
15
|
+
updatedAt?: Date;
|
|
16
|
+
|
|
17
|
+
@Column({ name: "deleted_at", type: "timestamp", nullable: true })
|
|
18
|
+
deletedAt?: Date;
|
|
19
|
+
|
|
6
20
|
// Add your columns here
|
|
7
21
|
// Example:
|
|
8
22
|
// @Column()
|
|
@@ -2,7 +2,7 @@ import { InjectRepository } from "@nestjs/typeorm";
|
|
|
2
2
|
import { Repository } from "typeorm";
|
|
3
3
|
import { {{entityNamePascal}}Mapper } from "@modules/{{moduleNameKebab}}/infrastructure/mappers/{{entityNameKebab}}.mapper";
|
|
4
4
|
import { {{entityNamePascal}}OrmEntity } from "@modules/{{moduleNameKebab}}/infrastructure/orm-entities/{{entityNameKebab}}.orm-entity";
|
|
5
|
-
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/
|
|
5
|
+
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/domain/entities/{{entityNameKebab}}.entity";
|
|
6
6
|
import { Injectable } from "@nestjs/common";
|
|
7
7
|
|
|
8
8
|
@Injectable()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/
|
|
1
|
+
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/domain/entities/{{entityNameKebab}}.entity";
|
|
2
2
|
import { {{entityNamePascal}}Repository } from "@modules/{{moduleNameKebab}}/infrastructure/repositories/{{entityNameKebab}}.repository";
|
|
3
3
|
import { Create{{entityNamePascal}}Command } from "@modules/{{moduleNameKebab}}/application/commands/create-{{entityNameKebab}}.command";
|
|
4
4
|
import { Injectable } from "@nestjs/common";
|