@dawudesign/node-hexa-cli 0.2.4 → 0.2.6

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 (3) hide show
  1. package/README.md +43 -115
  2. package/dist/index.js +6 -119
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,17 +2,16 @@
2
2
 
3
3
  > Scaffold and enforce **NestJS Hexagonal DDD** architecture from the command line.
4
4
 
5
- **node-hexa** automates the repetitive parts of clean architecture in NestJS:
6
-
7
- - **Scaffold** — generates a full bounded context with dependency injection pre-wired, in one command
8
- - **Enforce** — statically analyzes your TypeScript source and reports architecture violations
9
- - **Document** — exports a Mermaid diagram and architecture report as Markdown or SVG
5
+ - **Scaffold** generate a full NestJS project or bounded context in one command
6
+ - **Enforce** — statically analyze your TypeScript source and report architecture violations
7
+ - **Document** — export a Mermaid diagram and architecture report
10
8
 
11
9
  ---
12
10
 
13
11
  ## Requirements
14
12
 
15
- - **Node.js ≥ 20**
13
+ - Node.js ≥ 20
14
+ - npm or pnpm
16
15
 
17
16
  ---
18
17
 
@@ -22,37 +21,13 @@
22
21
  npm install -g @dawudesign/node-hexa-cli
23
22
  ```
24
23
 
25
- Verify:
26
-
27
- ```bash
28
- node-hexa --version
29
- node-hexa --help
30
- ```
31
-
32
- ---
33
-
34
- ## Quickstart
35
-
36
- ```bash
37
- # 1. Create a new NestJS Hexagonal DDD project
38
- node-hexa init my-app
39
- cd my-app
40
-
41
- # 2. Start the server
42
- pnpm start:dev
43
-
44
- # 3. Verify architecture is clean
45
- node-hexa check .
46
- # ✓ Architecture check passed
47
- ```
48
-
49
24
  ---
50
25
 
51
26
  ## Commands
52
27
 
53
28
  ### `init`
54
29
 
55
- Creates a new NestJS project with the complete Hexagonal DDD structure.
30
+ Create a new NestJS project with the full Hexagonal DDD structure.
56
31
 
57
32
  ```bash
58
33
  node-hexa init <name>
@@ -60,112 +35,80 @@ node-hexa init <name>
60
35
 
61
36
  ```bash
62
37
  node-hexa init my-app
38
+ cd my-app
39
+ pnpm start:dev
63
40
  ```
64
41
 
65
- Generates:
42
+ Generated structure:
66
43
 
67
- ```text
44
+ ```
68
45
  my-app/
69
46
  ├── src/
70
47
  │ ├── main.ts
71
48
  │ ├── app.module.ts
72
- └── contexts/
73
- └── iam/
74
- │ ├── iam.module.ts
75
- │ ├── domain/
76
- │ │ ├── entities/user.entity.ts
77
- │ │ └── ports/user.repository.port.ts
78
- │ ├── application/
79
- │ │ └── use-cases/create-user.usecase.ts
80
- │ └── infrastructure/
81
- │ ├── http/user.controller.ts
82
- │ └── persistence/in-memory-user.repository.ts
49
+ ├── contexts/ ← add your bounded contexts here
50
+ └── shared/
83
51
  └── node-hexa.config.json
84
52
  ```
85
53
 
86
- ---
87
-
88
- ### `generate context`
89
-
90
- Generates a complete bounded context inside an existing NestJS project.
91
-
92
- ```bash
93
- node-hexa generate context <name>
94
- ```
54
+ Then add your first bounded context:
95
55
 
96
56
  ```bash
97
57
  cd my-app
98
58
  node-hexa generate context orders
99
- # ✓ Context 'orders' generated at src/contexts/orders/
100
- # → Import OrdersModule in your AppModule to activate it.
101
59
  ```
102
60
 
103
61
  ---
104
62
 
105
- ### `generate usecase`
63
+ ### `generate`
106
64
 
107
- Generates a use case with its DTO and Vitest spec inside an existing bounded context.
65
+ Generate scaffolding inside an existing project.
108
66
 
109
67
  ```bash
68
+ node-hexa generate context <name>
110
69
  node-hexa generate usecase <name> <context>
70
+ node-hexa generate aggregate <name> <context>
111
71
  ```
112
72
 
113
73
  ```bash
114
- node-hexa generate usecase delete-user iam
115
- # ✓ Use case 'delete-user' generated in context 'iam'
116
- ```
117
-
118
- Generated files:
119
-
120
- ```text
121
- src/contexts/iam/application/use-cases/
122
- ├── delete-user.usecase.ts
123
- ├── delete-user.dto.ts
124
- └── delete-user.usecase.spec.ts
125
- ```
126
-
127
- ---
128
-
129
- ### `generate aggregate`
130
-
131
- Generates a full DDD aggregate (entity, value object, port, use case, in-memory repository, HTTP controller, NestJS module).
74
+ # New bounded context
75
+ node-hexa generate context orders
132
76
 
133
- ```bash
134
- node-hexa generate aggregate <name> <context>
135
- ```
77
+ # Use case inside a context
78
+ node-hexa generate usecase delete-user iam
136
79
 
137
- ```bash
80
+ # Full DDD aggregate (entity, port, use case, controller, repository)
138
81
  node-hexa generate aggregate product catalog
139
- # ✓ Aggregate 'product' generated in context 'catalog'
140
82
  ```
141
83
 
142
84
  ---
143
85
 
144
86
  ### `check`
145
87
 
146
- Checks architecture rules exits `0` if clean, `1` if violations found. Designed for CI/CD.
88
+ Check architecture violations. Exits `0` if clean, `1` if violations found. Designed for CI.
147
89
 
148
90
  ```bash
149
- node-hexa check <path> [--watch]
91
+ node-hexa check <path>
92
+ node-hexa check <path> --watch
150
93
  ```
151
94
 
152
95
  ```bash
153
96
  # One-shot (CI)
154
97
  node-hexa check .
155
98
 
156
- # Watch mode (development)
99
+ # Watch mode
157
100
  node-hexa check . --watch
158
101
  ```
159
102
 
160
103
  Output:
161
104
 
162
- ```text
105
+ ```
163
106
  ✓ Architecture check passed
164
107
  ```
165
108
 
166
109
  or:
167
110
 
168
- ```text
111
+ ```
169
112
  ✗ Architecture violations detected
170
113
 
171
114
  [CRITICAL] Domain must not depend on infrastructure → UserEntity
@@ -182,27 +125,19 @@ Full analysis: layers, violations, bounded contexts, Mermaid diagram, and score.
182
125
  node-hexa analyze <path>
183
126
  ```
184
127
 
185
- ```bash
186
- node-hexa analyze .
187
- ```
188
-
189
128
  ---
190
129
 
191
130
  ### `list`
192
131
 
193
- Lists all bounded contexts and their components.
132
+ List all bounded contexts and their components.
194
133
 
195
134
  ```bash
196
135
  node-hexa list <path>
197
136
  ```
198
137
 
199
- ```bash
200
- node-hexa list .
201
- ```
202
-
203
138
  Output:
204
139
 
205
- ```text
140
+ ```
206
141
  Bounded Contexts (2)
207
142
 
208
143
  IAM
@@ -220,27 +155,21 @@ Bounded Contexts (2)
220
155
 
221
156
  ### `docs`
222
157
 
223
- Generates an `architecture.md` at the project root with the Mermaid diagram, violations, and score.
158
+ Generate an `architecture.md` at the project root with the Mermaid diagram and violations.
224
159
 
225
160
  ```bash
226
161
  node-hexa docs <path>
227
162
  ```
228
163
 
229
- ```bash
230
- node-hexa docs .
231
- # Architecture documentation generated: ./architecture.md
232
- ```
233
-
234
164
  ---
235
165
 
236
166
  ### `graph`
237
167
 
238
- Generates an `architecture.svg` dependency graph (requires `@mermaid-js/mermaid-cli`).
168
+ Generate an `architecture.svg` dependency graph (requires `@mermaid-js/mermaid-cli`).
239
169
 
240
170
  ```bash
241
171
  npm install -g @mermaid-js/mermaid-cli
242
- node-hexa graph .
243
- # Architecture graph generated: ./architecture.svg
172
+ node-hexa graph <path>
244
173
  ```
245
174
 
246
175
  ---
@@ -258,8 +187,8 @@ node-hexa graph .
258
187
  ```
259
188
 
260
189
  | Key | Type | Default | Description |
261
- | --- | --- | --- | --- |
262
- | `architecture` | `string` | required | Architecture type — `hexagonal-ddd` |
190
+ |-----|------|---------|-------------|
191
+ | `architecture` | `string` | `"hexagonal-ddd"` | Architecture type |
263
192
  | `strict` | `boolean` | `true` | `false` silences `MEDIUM` violations |
264
193
  | `contextsDir` | `string` | `"src/contexts"` | Path to bounded contexts directory |
265
194
 
@@ -267,17 +196,16 @@ node-hexa graph .
267
196
 
268
197
  ## Violation rules
269
198
 
270
- | Violation | Severity | Score penalty |
271
- | --- | --- | --- |
272
- | Domain imports from infrastructure / adapter | `CRITICAL` | −25 pts |
273
- | Domain imports from application | `CRITICAL` | −25 pts |
274
- | Application imports from infrastructure / adapter | `HIGH` | −15 pts |
275
- | Domain imports a framework (`@nestjs/*`, `prisma`, etc.) | `CRITICAL` | −25 pts |
276
-
277
- Score = `100 − sum of penalties`, minimum 0.
199
+ | Violation | Severity |
200
+ |-----------|----------|
201
+ | Domain imports from infrastructure or adapter | `CRITICAL` |
202
+ | Domain imports from application | `CRITICAL` |
203
+ | Domain imports a framework (`@nestjs/*`, `prisma`…) | `CRITICAL` |
204
+ | Application imports from infrastructure or adapter | `HIGH` |
278
205
 
279
206
  ---
280
207
 
281
208
  ## License
282
209
 
283
- MIT — free to use, modify and distribute.
210
+ MIT
211
+
package/dist/index.js CHANGED
@@ -403,10 +403,7 @@ function generateProject(name) {
403
403
  const src = import_node_path5.default.join(base, "src");
404
404
  import_node_fs4.default.rmSync(src, { recursive: true, force: true });
405
405
  const dirs = [
406
- "src/contexts/iam/domain/ports",
407
- "src/contexts/iam/application/use-cases",
408
- "src/contexts/iam/infrastructure/http",
409
- "src/contexts/iam/infrastructure/persistence",
406
+ "src/contexts",
410
407
  "src/shared"
411
408
  ];
412
409
  dirs.forEach((dir) => {
@@ -427,127 +424,17 @@ bootstrap();
427
424
  import_node_fs4.default.writeFileSync(
428
425
  import_node_path5.default.join(base, "src/app.module.ts"),
429
426
  `import { Module } from '@nestjs/common';
430
- import { IamModule } from './contexts/iam/iam.module';
431
427
 
432
428
  @Module({
433
- imports: [IamModule],
434
- })
435
- export class AppModule {}
436
- `
437
- );
438
- import_node_fs4.default.writeFileSync(
439
- import_node_path5.default.join(base, "src/contexts/iam/domain/entities/user.entity.ts"),
440
- `export class User {
441
- constructor(
442
- public readonly id: string,
443
- public readonly email: string,
444
- public readonly name: string,
445
- ) {}
446
- }
447
- `
448
- );
449
- import_node_fs4.default.writeFileSync(
450
- import_node_path5.default.join(base, "src/contexts/iam/domain/ports/user.repository.port.ts"),
451
- `import { User } from '../entities/user.entity';
452
-
453
- export const USER_REPOSITORY_PORT = Symbol('UserRepositoryPort');
454
-
455
- export interface UserRepositoryPort {
456
- save(user: User): Promise<void>;
457
- findById(id: string): Promise<User | null>;
458
- }
459
- `
460
- );
461
- import_node_fs4.default.writeFileSync(
462
- import_node_path5.default.join(base, "src/contexts/iam/application/use-cases/create-user.usecase.ts"),
463
- `import { Inject, Injectable } from '@nestjs/common';
464
- import { User } from '../../domain/entities/user.entity';
465
- import {
466
- USER_REPOSITORY_PORT,
467
- UserRepositoryPort,
468
- } from '../../domain/ports/user.repository.port';
469
- import { randomUUID } from 'node:crypto';
470
-
471
- export interface CreateUserDto {
472
- email: string;
473
- name: string;
474
- }
475
-
476
- @Injectable()
477
- export class CreateUserUseCase {
478
- constructor(
479
- @Inject(USER_REPOSITORY_PORT)
480
- private readonly userRepository: UserRepositoryPort,
481
- ) {}
482
-
483
- async execute(dto: CreateUserDto): Promise<User> {
484
- const user = new User(randomUUID(), dto.email, dto.name);
485
- await this.userRepository.save(user);
486
- return user;
487
- }
488
- }
489
- `
490
- );
491
- import_node_fs4.default.writeFileSync(
492
- import_node_path5.default.join(
493
- base,
494
- "src/contexts/iam/infrastructure/persistence/in-memory-user.repository.ts"
495
- ),
496
- `import { Injectable } from '@nestjs/common';
497
- import { User } from '../../domain/entities/user.entity';
498
- import { UserRepositoryPort } from '../../domain/ports/user.repository.port';
499
-
500
- @Injectable()
501
- export class InMemoryUserRepository implements UserRepositoryPort {
502
- private readonly store = new Map<string, User>();
503
-
504
- async save(user: User): Promise<void> {
505
- this.store.set(user.id, user);
506
- }
507
-
508
- async findById(id: string): Promise<User | null> {
509
- return this.store.get(id) ?? null;
510
- }
511
- }
512
- `
513
- );
514
- import_node_fs4.default.writeFileSync(
515
- import_node_path5.default.join(base, "src/contexts/iam/infrastructure/http/user.controller.ts"),
516
- `import { Body, Controller, Post } from '@nestjs/common';
517
- import { CreateUserUseCase, CreateUserDto } from '../../application/use-cases/create-user.usecase';
518
-
519
- @Controller('users')
520
- export class UserController {
521
- constructor(private readonly createUser: CreateUserUseCase) {}
522
-
523
- @Post()
524
- async create(@Body() dto: CreateUserDto) {
525
- return this.createUser.execute(dto);
526
- }
527
- }
528
- `
529
- );
530
- import_node_fs4.default.writeFileSync(
531
- import_node_path5.default.join(base, "src/contexts/iam/iam.module.ts"),
532
- `import { Module } from '@nestjs/common';
533
- import { USER_REPOSITORY_PORT } from './domain/ports/user.repository.port';
534
- import { InMemoryUserRepository } from './infrastructure/persistence/in-memory-user.repository';
535
- import { CreateUserUseCase } from './application/use-cases/create-user.usecase';
536
- import { UserController } from './infrastructure/http/user.controller';
537
-
538
- @Module({
539
- controllers: [UserController],
540
- providers: [
541
- {
542
- provide: USER_REPOSITORY_PORT,
543
- useClass: InMemoryUserRepository,
544
- },
545
- CreateUserUseCase,
429
+ imports: [
430
+ // Import your bounded context modules here
431
+ // e.g. import { OrdersModule } from './contexts/orders/orders.module';
546
432
  ],
547
433
  })
548
- export class IamModule {}
434
+ export class AppModule {}
549
435
  `
550
436
  );
437
+ import_node_fs4.default.writeFileSync(import_node_path5.default.join(base, "src/contexts/.gitkeep"), "");
551
438
  import_node_fs4.default.writeFileSync(import_node_path5.default.join(base, "src/shared/.gitkeep"), "");
552
439
  import_node_fs4.default.writeFileSync(
553
440
  import_node_path5.default.join(base, "node-hexa.config.json"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dawudesign/node-hexa-cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "CLI to scaffold and analyze NestJS Hexagonal DDD projects",
5
5
  "keywords": [
6
6
  "nestjs",