nestjs-ddd-cli 2.2.1 → 3.2.1

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 (254) hide show
  1. package/README.md +247 -408
  2. package/ddd.schema.json +111 -0
  3. package/dist/commands/aggregate-validator.d.ts +9 -0
  4. package/dist/commands/aggregate-validator.js +953 -0
  5. package/dist/commands/aggregate-validator.js.map +1 -0
  6. package/dist/commands/ai-assist.d.ts +8 -0
  7. package/dist/commands/ai-assist.js +337 -0
  8. package/dist/commands/ai-assist.js.map +1 -0
  9. package/dist/commands/api-contracts.d.ts +9 -0
  10. package/dist/commands/api-contracts.js +1368 -0
  11. package/dist/commands/api-contracts.js.map +1 -0
  12. package/dist/commands/api-docs.d.ts +8 -0
  13. package/dist/commands/api-docs.js +408 -0
  14. package/dist/commands/api-docs.js.map +1 -0
  15. package/dist/commands/api-versioning.d.ts +11 -0
  16. package/dist/commands/api-versioning.js +643 -0
  17. package/dist/commands/api-versioning.js.map +1 -0
  18. package/dist/commands/audit-logging.d.ts +9 -0
  19. package/dist/commands/audit-logging.js +1129 -0
  20. package/dist/commands/audit-logging.js.map +1 -0
  21. package/dist/commands/batch-generate.d.ts +10 -0
  22. package/dist/commands/batch-generate.js +405 -0
  23. package/dist/commands/batch-generate.js.map +1 -0
  24. package/dist/commands/caching-strategies.d.ts +9 -0
  25. package/dist/commands/caching-strategies.js +874 -0
  26. package/dist/commands/caching-strategies.js.map +1 -0
  27. package/dist/commands/code-analyzer.d.ts +42 -0
  28. package/dist/commands/code-analyzer.js +474 -0
  29. package/dist/commands/code-analyzer.js.map +1 -0
  30. package/dist/commands/database-seeding.d.ts +6 -0
  31. package/dist/commands/database-seeding.js +621 -0
  32. package/dist/commands/database-seeding.js.map +1 -0
  33. package/dist/commands/db-optimization.d.ts +7 -0
  34. package/dist/commands/db-optimization.js +687 -0
  35. package/dist/commands/db-optimization.js.map +1 -0
  36. package/dist/commands/dependency-graph.d.ts +6 -0
  37. package/dist/commands/dependency-graph.js +329 -0
  38. package/dist/commands/dependency-graph.js.map +1 -0
  39. package/dist/commands/doctor-enhanced.d.ts +22 -0
  40. package/dist/commands/doctor-enhanced.js +543 -0
  41. package/dist/commands/doctor-enhanced.js.map +1 -0
  42. package/dist/commands/doctor.d.ts +4 -0
  43. package/dist/commands/doctor.js +151 -0
  44. package/dist/commands/doctor.js.map +1 -0
  45. package/dist/commands/env-manager.d.ts +6 -0
  46. package/dist/commands/env-manager.js +419 -0
  47. package/dist/commands/env-manager.js.map +1 -0
  48. package/dist/commands/event-sourcing-full.d.ts +10 -0
  49. package/dist/commands/event-sourcing-full.js +1107 -0
  50. package/dist/commands/event-sourcing-full.js.map +1 -0
  51. package/dist/commands/feature-flags.d.ts +9 -0
  52. package/dist/commands/feature-flags.js +824 -0
  53. package/dist/commands/feature-flags.js.map +1 -0
  54. package/dist/commands/filter-dsl.d.ts +10 -0
  55. package/dist/commands/filter-dsl.js +1407 -0
  56. package/dist/commands/filter-dsl.js.map +1 -0
  57. package/dist/commands/generate-all.js +485 -32
  58. package/dist/commands/generate-all.js.map +1 -1
  59. package/dist/commands/generate-deployment.d.ts +8 -0
  60. package/dist/commands/generate-deployment.js +746 -0
  61. package/dist/commands/generate-deployment.js.map +1 -0
  62. package/dist/commands/generate-domain-service.d.ts +14 -0
  63. package/dist/commands/generate-domain-service.js +796 -0
  64. package/dist/commands/generate-domain-service.js.map +1 -0
  65. package/dist/commands/generate-entity.js +82 -24
  66. package/dist/commands/generate-entity.js.map +1 -1
  67. package/dist/commands/generate-from-schema.d.ts +56 -0
  68. package/dist/commands/generate-from-schema.js +222 -0
  69. package/dist/commands/generate-from-schema.js.map +1 -0
  70. package/dist/commands/generate-orchestrator.d.ts +14 -0
  71. package/dist/commands/generate-orchestrator.js +887 -0
  72. package/dist/commands/generate-orchestrator.js.map +1 -0
  73. package/dist/commands/generate-repository.d.ts +14 -0
  74. package/dist/commands/generate-repository.js +1019 -0
  75. package/dist/commands/generate-repository.js.map +1 -0
  76. package/dist/commands/generate-shared.d.ts +4 -0
  77. package/dist/commands/generate-shared.js +388 -0
  78. package/dist/commands/generate-shared.js.map +1 -0
  79. package/dist/commands/generate-value-object.d.ts +32 -0
  80. package/dist/commands/generate-value-object.js +700 -0
  81. package/dist/commands/generate-value-object.js.map +1 -0
  82. package/dist/commands/graphql-subscriptions.d.ts +6 -0
  83. package/dist/commands/graphql-subscriptions.js +607 -0
  84. package/dist/commands/graphql-subscriptions.js.map +1 -0
  85. package/dist/commands/graphql-types.d.ts +5 -0
  86. package/dist/commands/graphql-types.js +423 -0
  87. package/dist/commands/graphql-types.js.map +1 -0
  88. package/dist/commands/health-probes-advanced.d.ts +6 -0
  89. package/dist/commands/health-probes-advanced.js +655 -0
  90. package/dist/commands/health-probes-advanced.js.map +1 -0
  91. package/dist/commands/i18n-setup.d.ts +10 -0
  92. package/dist/commands/i18n-setup.js +677 -0
  93. package/dist/commands/i18n-setup.js.map +1 -0
  94. package/dist/commands/init-config.d.ts +6 -0
  95. package/dist/commands/init-config.js +370 -0
  96. package/dist/commands/init-config.js.map +1 -0
  97. package/dist/commands/init-project.js +56 -6
  98. package/dist/commands/init-project.js.map +1 -1
  99. package/dist/commands/interactive-scaffold.d.ts +5 -0
  100. package/dist/commands/interactive-scaffold.js +271 -0
  101. package/dist/commands/interactive-scaffold.js.map +1 -0
  102. package/dist/commands/metrics-prometheus.d.ts +6 -0
  103. package/dist/commands/metrics-prometheus.js +681 -0
  104. package/dist/commands/metrics-prometheus.js.map +1 -0
  105. package/dist/commands/migration-engine.d.ts +6 -0
  106. package/dist/commands/migration-engine.js +446 -0
  107. package/dist/commands/migration-engine.js.map +1 -0
  108. package/dist/commands/migration.d.ts +12 -0
  109. package/dist/commands/migration.js +484 -0
  110. package/dist/commands/migration.js.map +1 -0
  111. package/dist/commands/monorepo.d.ts +8 -0
  112. package/dist/commands/monorepo.js +483 -0
  113. package/dist/commands/monorepo.js.map +1 -0
  114. package/dist/commands/multi-database.d.ts +5 -0
  115. package/dist/commands/multi-database.js +439 -0
  116. package/dist/commands/multi-database.js.map +1 -0
  117. package/dist/commands/observability-tracing.d.ts +10 -0
  118. package/dist/commands/observability-tracing.js +740 -0
  119. package/dist/commands/observability-tracing.js.map +1 -0
  120. package/dist/commands/openapi-export.d.ts +8 -0
  121. package/dist/commands/openapi-export.js +359 -0
  122. package/dist/commands/openapi-export.js.map +1 -0
  123. package/dist/commands/perf-analyzer.d.ts +8 -0
  124. package/dist/commands/perf-analyzer.js +423 -0
  125. package/dist/commands/perf-analyzer.js.map +1 -0
  126. package/dist/commands/rate-limiting.d.ts +10 -0
  127. package/dist/commands/rate-limiting.js +953 -0
  128. package/dist/commands/rate-limiting.js.map +1 -0
  129. package/dist/commands/recipe-plugin.d.ts +56 -0
  130. package/dist/commands/recipe-plugin.js +315 -0
  131. package/dist/commands/recipe-plugin.js.map +1 -0
  132. package/dist/commands/recipe.d.ts +6 -0
  133. package/dist/commands/recipe.js +3941 -0
  134. package/dist/commands/recipe.js.map +1 -0
  135. package/dist/commands/recipes/elasticsearch.recipe.d.ts +1 -0
  136. package/dist/commands/recipes/elasticsearch.recipe.js +761 -0
  137. package/dist/commands/recipes/elasticsearch.recipe.js.map +1 -0
  138. package/dist/commands/recipes/event-sourcing.recipe.d.ts +1 -0
  139. package/dist/commands/recipes/event-sourcing.recipe.js +889 -0
  140. package/dist/commands/recipes/event-sourcing.recipe.js.map +1 -0
  141. package/dist/commands/recipes/index.d.ts +7 -0
  142. package/dist/commands/recipes/index.js +24 -0
  143. package/dist/commands/recipes/index.js.map +1 -0
  144. package/dist/commands/recipes/message-queue.recipe.d.ts +1 -0
  145. package/dist/commands/recipes/message-queue.recipe.js +706 -0
  146. package/dist/commands/recipes/message-queue.recipe.js.map +1 -0
  147. package/dist/commands/recipes/middleware.recipe.d.ts +1 -0
  148. package/dist/commands/recipes/middleware.recipe.js +383 -0
  149. package/dist/commands/recipes/middleware.recipe.js.map +1 -0
  150. package/dist/commands/recipes/multi-tenancy.recipe.d.ts +1 -0
  151. package/dist/commands/recipes/multi-tenancy.recipe.js +520 -0
  152. package/dist/commands/recipes/multi-tenancy.recipe.js.map +1 -0
  153. package/dist/commands/recipes/oauth2.recipe.d.ts +1 -0
  154. package/dist/commands/recipes/oauth2.recipe.js +472 -0
  155. package/dist/commands/recipes/oauth2.recipe.js.map +1 -0
  156. package/dist/commands/recipes/websocket.recipe.d.ts +1 -0
  157. package/dist/commands/recipes/websocket.recipe.js +453 -0
  158. package/dist/commands/recipes/websocket.recipe.js.map +1 -0
  159. package/dist/commands/resilience-patterns.d.ts +13 -0
  160. package/dist/commands/resilience-patterns.js +1029 -0
  161. package/dist/commands/resilience-patterns.js.map +1 -0
  162. package/dist/commands/security-patterns.d.ts +11 -0
  163. package/dist/commands/security-patterns.js +2233 -0
  164. package/dist/commands/security-patterns.js.map +1 -0
  165. package/dist/commands/template-debug.d.ts +27 -0
  166. package/dist/commands/template-debug.js +388 -0
  167. package/dist/commands/template-debug.js.map +1 -0
  168. package/dist/commands/test-factory-full.d.ts +9 -0
  169. package/dist/commands/test-factory-full.js +1570 -0
  170. package/dist/commands/test-factory-full.js.map +1 -0
  171. package/dist/commands/test-scaffold.d.ts +7 -0
  172. package/dist/commands/test-scaffold.js +621 -0
  173. package/dist/commands/test-scaffold.js.map +1 -0
  174. package/dist/index.js +1088 -0
  175. package/dist/index.js.map +1 -1
  176. package/dist/templates/ai-context/CLAUDE.md.hbs +158 -0
  177. package/dist/templates/ai-context/conventions.md.hbs +154 -0
  178. package/dist/templates/command/create-command.hbs +6 -14
  179. package/dist/templates/command/delete-command.hbs +19 -0
  180. package/dist/templates/command/update-command.hbs +24 -0
  181. package/dist/templates/controller/controller.hbs +64 -17
  182. package/dist/templates/dto/create-dto.hbs +29 -5
  183. package/dist/templates/dto/filter-dto.hbs +52 -0
  184. package/dist/templates/dto/filter-query.dto.hbs +148 -0
  185. package/dist/templates/dto/paginated-response.dto.hbs +29 -0
  186. package/dist/templates/dto/pagination-query.dto.hbs +30 -0
  187. package/dist/templates/dto/response-dto.hbs +38 -0
  188. package/dist/templates/dto/update-dto.hbs +11 -0
  189. package/dist/templates/entity/entity.hbs +32 -1
  190. package/dist/templates/event/domain-event.hbs +33 -7
  191. package/dist/templates/event/event-handler.hbs +40 -0
  192. package/dist/templates/exception/base-exceptions.hbs +69 -0
  193. package/dist/templates/exception/entity-not-found.exception.hbs +7 -0
  194. package/dist/templates/mapper/mapper.hbs +49 -24
  195. package/dist/templates/module/module.hbs +34 -10
  196. package/dist/templates/orm-entity/orm-entity.hbs +63 -12
  197. package/dist/templates/prisma/prisma-mapper.hbs +71 -0
  198. package/dist/templates/prisma/prisma-repository.hbs +114 -0
  199. package/dist/templates/prisma/prisma-schema.hbs +20 -0
  200. package/dist/templates/prisma/prisma-service.hbs +51 -0
  201. package/dist/templates/query/get-all.query.hbs +50 -0
  202. package/dist/templates/query/get-by-id.query.hbs +31 -0
  203. package/dist/templates/repository/repository.hbs +55 -13
  204. package/dist/templates/resolver/graphql-input.hbs +54 -0
  205. package/dist/templates/resolver/graphql-type.hbs +58 -0
  206. package/dist/templates/resolver/pagination-args.hbs +33 -0
  207. package/dist/templates/resolver/resolver.hbs +62 -0
  208. package/dist/templates/shared/prisma-query-builder.util.hbs +189 -0
  209. package/dist/templates/shared/query-builder.util.hbs +218 -0
  210. package/dist/templates/test/controller.spec.hbs +124 -0
  211. package/dist/templates/test/repository.spec.hbs +158 -0
  212. package/dist/templates/test/usecase.spec.hbs +116 -0
  213. package/dist/templates/usecase/create-usecase.hbs +19 -7
  214. package/dist/templates/usecase/delete-usecase.hbs +17 -0
  215. package/dist/templates/usecase/update-usecase.hbs +31 -0
  216. package/dist/utils/config.utils.d.ts +45 -0
  217. package/dist/utils/config.utils.js +211 -0
  218. package/dist/utils/config.utils.js.map +1 -0
  219. package/dist/utils/error.utils.d.ts +145 -0
  220. package/dist/utils/error.utils.js +422 -0
  221. package/dist/utils/error.utils.js.map +1 -0
  222. package/dist/utils/field.utils.d.ts +54 -0
  223. package/dist/utils/field.utils.js +389 -0
  224. package/dist/utils/field.utils.js.map +1 -0
  225. package/dist/utils/file.utils.d.ts +19 -8
  226. package/dist/utils/file.utils.js +135 -4
  227. package/dist/utils/file.utils.js.map +1 -1
  228. package/dist/utils/idempotency.utils.d.ts +123 -0
  229. package/dist/utils/idempotency.utils.js +444 -0
  230. package/dist/utils/idempotency.utils.js.map +1 -0
  231. package/dist/utils/naming.utils.js +24 -5
  232. package/dist/utils/naming.utils.js.map +1 -1
  233. package/dist/utils/performance.utils.d.ts +37 -0
  234. package/dist/utils/performance.utils.js +158 -0
  235. package/dist/utils/performance.utils.js.map +1 -0
  236. package/dist/utils/relation.utils.d.ts +92 -0
  237. package/dist/utils/relation.utils.js +388 -0
  238. package/dist/utils/relation.utils.js.map +1 -0
  239. package/dist/utils/rollback.utils.d.ts +49 -0
  240. package/dist/utils/rollback.utils.js +306 -0
  241. package/dist/utils/rollback.utils.js.map +1 -0
  242. package/dist/utils/schema.utils.d.ts +123 -0
  243. package/dist/utils/schema.utils.js +419 -0
  244. package/dist/utils/schema.utils.js.map +1 -0
  245. package/dist/utils/security.utils.d.ts +57 -0
  246. package/dist/utils/security.utils.js +315 -0
  247. package/dist/utils/security.utils.js.map +1 -0
  248. package/dist/utils/template-engine.utils.d.ts +80 -0
  249. package/dist/utils/template-engine.utils.js +463 -0
  250. package/dist/utils/template-engine.utils.js.map +1 -0
  251. package/dist/utils/validation-registry.utils.d.ts +160 -0
  252. package/dist/utils/validation-registry.utils.js +526 -0
  253. package/dist/utils/validation-registry.utils.js.map +1 -0
  254. package/package.json +3 -1
@@ -0,0 +1,158 @@
1
+ import { Test, TestingModule } from "@nestjs/testing";
2
+ import { getRepositoryToken } from "@nestjs/typeorm";
3
+ import { Repository } from "typeorm";
4
+ import { {{entityNamePascal}}Repository } from "../{{entityNameKebab}}.repository";
5
+ import { {{entityNamePascal}}OrmEntity } from "../orm-entities/{{entityNameKebab}}.orm-entity";
6
+ import { {{entityNamePascal}}Mapper } from "../mappers/{{entityNameKebab}}.mapper";
7
+ import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/domain/entities/{{entityNameKebab}}.entity";
8
+
9
+ describe("{{entityNamePascal}}Repository", () => {
10
+ let repository: {{entityNamePascal}}Repository;
11
+ let typeOrmRepo: jest.Mocked<Repository<{{entityNamePascal}}OrmEntity>>;
12
+ let mapper: jest.Mocked<{{entityNamePascal}}Mapper>;
13
+
14
+ const mockOrmEntity: {{entityNamePascal}}OrmEntity = {
15
+ id: "test-uuid",
16
+ isActive: true,
17
+ createdAt: new Date(),
18
+ updatedAt: new Date(),
19
+ deletedAt: null,
20
+ };
21
+
22
+ const mockDomainEntity = new {{entityNamePascal}}Entity({
23
+ id: "test-uuid",
24
+ isActive: true,
25
+ createdAt: new Date(),
26
+ updatedAt: new Date(),
27
+ });
28
+
29
+ beforeEach(async () => {
30
+ const module: TestingModule = await Test.createTestingModule({
31
+ providers: [
32
+ {{entityNamePascal}}Repository,
33
+ {
34
+ provide: getRepositoryToken({{entityNamePascal}}OrmEntity),
35
+ useValue: {
36
+ save: jest.fn(),
37
+ findOne: jest.fn(),
38
+ find: jest.fn(),
39
+ findAndCount: jest.fn(),
40
+ update: jest.fn(),
41
+ delete: jest.fn(),
42
+ count: jest.fn(),
43
+ },
44
+ },
45
+ {
46
+ provide: {{entityNamePascal}}Mapper,
47
+ useValue: {
48
+ toOrmEntity: jest.fn(),
49
+ toDomainEntity: jest.fn(),
50
+ toResponseDto: jest.fn(),
51
+ },
52
+ },
53
+ ],
54
+ }).compile();
55
+
56
+ repository = module.get<{{entityNamePascal}}Repository>({{entityNamePascal}}Repository);
57
+ typeOrmRepo = module.get(getRepositoryToken({{entityNamePascal}}OrmEntity));
58
+ mapper = module.get({{entityNamePascal}}Mapper);
59
+ });
60
+
61
+ describe("create", () => {
62
+ it("should create and return a domain entity", async () => {
63
+ mapper.toOrmEntity.mockReturnValue(mockOrmEntity as any);
64
+ typeOrmRepo.save.mockResolvedValue(mockOrmEntity);
65
+ mapper.toDomainEntity.mockReturnValue(mockDomainEntity);
66
+
67
+ const result = await repository.create(mockDomainEntity);
68
+
69
+ expect(mapper.toOrmEntity).toHaveBeenCalledWith(mockDomainEntity);
70
+ expect(typeOrmRepo.save).toHaveBeenCalled();
71
+ expect(mapper.toDomainEntity).toHaveBeenCalledWith(mockOrmEntity);
72
+ expect(result).toEqual(mockDomainEntity);
73
+ });
74
+ });
75
+
76
+ describe("findById", () => {
77
+ it("should return a domain entity when found", async () => {
78
+ typeOrmRepo.findOne.mockResolvedValue(mockOrmEntity);
79
+ mapper.toDomainEntity.mockReturnValue(mockDomainEntity);
80
+
81
+ const result = await repository.findById("test-uuid");
82
+
83
+ expect(typeOrmRepo.findOne).toHaveBeenCalledWith({
84
+ where: { id: "test-uuid", deletedAt: null },
85
+ });
86
+ expect(result).toEqual(mockDomainEntity);
87
+ });
88
+
89
+ it("should return null when entity is not found", async () => {
90
+ typeOrmRepo.findOne.mockResolvedValue(null);
91
+
92
+ const result = await repository.findById("non-existent-uuid");
93
+
94
+ expect(result).toBeNull();
95
+ });
96
+ });
97
+
98
+ describe("findAllPaginated", () => {
99
+ it("should return paginated entities with total count", async () => {
100
+ const mockEntities = [mockOrmEntity];
101
+ typeOrmRepo.findAndCount.mockResolvedValue([mockEntities, 1]);
102
+ mapper.toDomainEntity.mockReturnValue(mockDomainEntity);
103
+
104
+ const result = await repository.findAllPaginated({
105
+ skip: 0,
106
+ take: 10,
107
+ orderBy: "createdAt",
108
+ orderDirection: "DESC",
109
+ });
110
+
111
+ expect(result[0]).toHaveLength(1);
112
+ expect(result[1]).toBe(1);
113
+ });
114
+ });
115
+
116
+ describe("update", () => {
117
+ it("should update and return the entity", async () => {
118
+ mapper.toOrmEntity.mockReturnValue(mockOrmEntity as any);
119
+ typeOrmRepo.update.mockResolvedValue({ affected: 1 } as any);
120
+
121
+ const result = await repository.update("test-uuid", mockDomainEntity);
122
+
123
+ expect(typeOrmRepo.update).toHaveBeenCalled();
124
+ expect(result).toEqual(mockDomainEntity);
125
+ });
126
+ });
127
+
128
+ describe("delete", () => {
129
+ it("should soft delete the entity", async () => {
130
+ typeOrmRepo.update.mockResolvedValue({ affected: 1 } as any);
131
+
132
+ await repository.delete("test-uuid");
133
+
134
+ expect(typeOrmRepo.update).toHaveBeenCalledWith(
135
+ "test-uuid",
136
+ expect.objectContaining({ deletedAt: expect.any(Date) })
137
+ );
138
+ });
139
+ });
140
+
141
+ describe("exists", () => {
142
+ it("should return true when entity exists", async () => {
143
+ typeOrmRepo.count.mockResolvedValue(1);
144
+
145
+ const result = await repository.exists("test-uuid");
146
+
147
+ expect(result).toBe(true);
148
+ });
149
+
150
+ it("should return false when entity does not exist", async () => {
151
+ typeOrmRepo.count.mockResolvedValue(0);
152
+
153
+ const result = await repository.exists("non-existent-uuid");
154
+
155
+ expect(result).toBe(false);
156
+ });
157
+ });
158
+ });
@@ -0,0 +1,116 @@
1
+ import { Test, TestingModule } from "@nestjs/testing";
2
+ import { NotFoundException } from "@nestjs/common";
3
+ import { Create{{entityNamePascal}}UseCase } from "../create-{{entityNameKebab}}.use-case";
4
+ import { Update{{entityNamePascal}}UseCase } from "../update-{{entityNameKebab}}.use-case";
5
+ import { Delete{{entityNamePascal}}UseCase } from "../delete-{{entityNameKebab}}.use-case";
6
+ import { {{entityNamePascal}}Repository } from "@modules/{{moduleNameKebab}}/infrastructure/repositories/{{entityNameKebab}}.repository";
7
+ import { {{entityNamePascal}}Mapper } from "@modules/{{moduleNameKebab}}/infrastructure/mappers/{{entityNameKebab}}.mapper";
8
+ import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/domain/entities/{{entityNameKebab}}.entity";
9
+
10
+ describe("{{entityNamePascal}} Use Cases", () => {
11
+ let createUseCase: Create{{entityNamePascal}}UseCase;
12
+ let updateUseCase: Update{{entityNamePascal}}UseCase;
13
+ let deleteUseCase: Delete{{entityNamePascal}}UseCase;
14
+ let repository: jest.Mocked<{{entityNamePascal}}Repository>;
15
+ let mapper: jest.Mocked<{{entityNamePascal}}Mapper>;
16
+
17
+ const mockEntity = new {{entityNamePascal}}Entity({
18
+ id: "test-uuid",
19
+ isActive: true,
20
+ createdAt: new Date(),
21
+ updatedAt: new Date(),
22
+ });
23
+
24
+ const mockResponseDto = {
25
+ id: "test-uuid",
26
+ isActive: true,
27
+ createdAt: new Date(),
28
+ updatedAt: new Date(),
29
+ };
30
+
31
+ beforeEach(async () => {
32
+ const module: TestingModule = await Test.createTestingModule({
33
+ providers: [
34
+ Create{{entityNamePascal}}UseCase,
35
+ Update{{entityNamePascal}}UseCase,
36
+ Delete{{entityNamePascal}}UseCase,
37
+ {
38
+ provide: {{entityNamePascal}}Repository,
39
+ useValue: {
40
+ create: jest.fn(),
41
+ findById: jest.fn(),
42
+ update: jest.fn(),
43
+ delete: jest.fn(),
44
+ },
45
+ },
46
+ {
47
+ provide: {{entityNamePascal}}Mapper,
48
+ useValue: {
49
+ toResponseDto: jest.fn(),
50
+ },
51
+ },
52
+ ],
53
+ }).compile();
54
+
55
+ createUseCase = module.get<Create{{entityNamePascal}}UseCase>(Create{{entityNamePascal}}UseCase);
56
+ updateUseCase = module.get<Update{{entityNamePascal}}UseCase>(Update{{entityNamePascal}}UseCase);
57
+ deleteUseCase = module.get<Delete{{entityNamePascal}}UseCase>(Delete{{entityNamePascal}}UseCase);
58
+ repository = module.get({{entityNamePascal}}Repository);
59
+ mapper = module.get({{entityNamePascal}}Mapper);
60
+ });
61
+
62
+ describe("Create{{entityNamePascal}}UseCase", () => {
63
+ it("should create a new {{entityNameCamel}} and return response DTO", async () => {
64
+ const createDto = {};
65
+ repository.create.mockResolvedValue(mockEntity);
66
+ mapper.toResponseDto.mockReturnValue(mockResponseDto as any);
67
+
68
+ const result = await createUseCase.execute(createDto as any);
69
+
70
+ expect(repository.create).toHaveBeenCalled();
71
+ expect(mapper.toResponseDto).toHaveBeenCalledWith(mockEntity);
72
+ expect(result).toEqual(mockResponseDto);
73
+ });
74
+ });
75
+
76
+ describe("Update{{entityNamePascal}}UseCase", () => {
77
+ it("should update an existing {{entityNameCamel}}", async () => {
78
+ const updateDto = {};
79
+ repository.findById.mockResolvedValue(mockEntity);
80
+ repository.update.mockResolvedValue(mockEntity);
81
+ mapper.toResponseDto.mockReturnValue(mockResponseDto as any);
82
+
83
+ const result = await updateUseCase.execute("test-uuid", updateDto as any);
84
+
85
+ expect(repository.findById).toHaveBeenCalledWith("test-uuid");
86
+ expect(repository.update).toHaveBeenCalled();
87
+ expect(result).toEqual(mockResponseDto);
88
+ });
89
+
90
+ it("should throw NotFoundException when {{entityNameCamel}} does not exist", async () => {
91
+ repository.findById.mockResolvedValue(null);
92
+
93
+ await expect(updateUseCase.execute("non-existent", {} as any)).rejects.toThrow(
94
+ NotFoundException
95
+ );
96
+ });
97
+ });
98
+
99
+ describe("Delete{{entityNamePascal}}UseCase", () => {
100
+ it("should delete an existing {{entityNameCamel}}", async () => {
101
+ repository.findById.mockResolvedValue(mockEntity);
102
+ repository.delete.mockResolvedValue(undefined);
103
+
104
+ await deleteUseCase.execute("test-uuid");
105
+
106
+ expect(repository.findById).toHaveBeenCalledWith("test-uuid");
107
+ expect(repository.delete).toHaveBeenCalledWith("test-uuid");
108
+ });
109
+
110
+ it("should throw NotFoundException when {{entityNameCamel}} does not exist", async () => {
111
+ repository.findById.mockResolvedValue(null);
112
+
113
+ await expect(deleteUseCase.execute("non-existent")).rejects.toThrow(NotFoundException);
114
+ });
115
+ });
116
+ });
@@ -1,14 +1,26 @@
1
+ import { Injectable } from "@nestjs/common";
1
2
  import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/domain/entities/{{entityNameKebab}}.entity";
2
3
  import { {{entityNamePascal}}Repository } from "@modules/{{moduleNameKebab}}/infrastructure/repositories/{{entityNameKebab}}.repository";
3
- import { Create{{entityNamePascal}}Command } from "@modules/{{moduleNameKebab}}/application/commands/create-{{entityNameKebab}}.command";
4
- import { Injectable } from "@nestjs/common";
4
+ import { {{entityNamePascal}}Mapper } from "@modules/{{moduleNameKebab}}/infrastructure/mappers/{{entityNameKebab}}.mapper";
5
+ import { Create{{entityNamePascal}}Dto } from "@modules/{{moduleNameKebab}}/application/dto/requests/create-{{entityNameKebab}}.dto";
6
+ import { {{entityNamePascal}}ResponseDto } from "@modules/{{moduleNameKebab}}/application/dto/responses/{{entityNameKebab}}.response.dto";
5
7
 
6
8
  @Injectable()
7
9
  export class Create{{entityNamePascal}}UseCase {
8
- constructor(private readonly repository: {{entityNamePascal}}Repository) {}
10
+ constructor(
11
+ private readonly repository: {{entityNamePascal}}Repository,
12
+ private readonly mapper: {{entityNamePascal}}Mapper,
13
+ ) {}
14
+
15
+ async execute(dto: Create{{entityNamePascal}}Dto): Promise<{{entityNamePascal}}ResponseDto> {
16
+ const entity = new {{entityNamePascal}}Entity({
17
+ ...dto,
18
+ isActive: true,
19
+ createdAt: new Date(),
20
+ updatedAt: new Date(),
21
+ });
9
22
 
10
- async execute(command: Create{{entityNamePascal}}Command) {
11
- const entity = new {{entityNamePascal}}Entity(command);
12
- return this.repository.create(entity);
23
+ const savedEntity = await this.repository.create(entity);
24
+ return this.mapper.toResponseDto(savedEntity);
13
25
  }
14
- }
26
+ }
@@ -0,0 +1,17 @@
1
+ import { Injectable, NotFoundException } from "@nestjs/common";
2
+ import { {{entityNamePascal}}Repository } from "@modules/{{moduleNameKebab}}/infrastructure/repositories/{{entityNameKebab}}.repository";
3
+
4
+ @Injectable()
5
+ export class Delete{{entityNamePascal}}UseCase {
6
+ constructor(private readonly repository: {{entityNamePascal}}Repository) {}
7
+
8
+ async execute(id: string): Promise<void> {
9
+ const existingEntity = await this.repository.findById(id);
10
+
11
+ if (!existingEntity) {
12
+ throw new NotFoundException(`{{entityNamePascal}} with id '${id}' not found`);
13
+ }
14
+
15
+ await this.repository.delete(id);
16
+ }
17
+ }
@@ -0,0 +1,31 @@
1
+ import { Injectable, NotFoundException } from "@nestjs/common";
2
+ import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/domain/entities/{{entityNameKebab}}.entity";
3
+ import { {{entityNamePascal}}Repository } from "@modules/{{moduleNameKebab}}/infrastructure/repositories/{{entityNameKebab}}.repository";
4
+ import { {{entityNamePascal}}Mapper } from "@modules/{{moduleNameKebab}}/infrastructure/mappers/{{entityNameKebab}}.mapper";
5
+ import { Update{{entityNamePascal}}Dto } from "@modules/{{moduleNameKebab}}/application/dto/requests/update-{{entityNameKebab}}.dto";
6
+ import { {{entityNamePascal}}ResponseDto } from "@modules/{{moduleNameKebab}}/application/dto/responses/{{entityNameKebab}}.response.dto";
7
+
8
+ @Injectable()
9
+ export class Update{{entityNamePascal}}UseCase {
10
+ constructor(
11
+ private readonly repository: {{entityNamePascal}}Repository,
12
+ private readonly mapper: {{entityNamePascal}}Mapper,
13
+ ) {}
14
+
15
+ async execute(id: string, dto: Update{{entityNamePascal}}Dto): Promise<{{entityNamePascal}}ResponseDto> {
16
+ const existingEntity = await this.repository.findById(id);
17
+
18
+ if (!existingEntity) {
19
+ throw new NotFoundException(`{{entityNamePascal}} with id '${id}' not found`);
20
+ }
21
+
22
+ const updatedEntity = new {{entityNamePascal}}Entity({
23
+ ...existingEntity,
24
+ ...dto,
25
+ updatedAt: new Date(),
26
+ });
27
+
28
+ const savedEntity = await this.repository.update(id, updatedEntity);
29
+ return this.mapper.toResponseDto(savedEntity);
30
+ }
31
+ }
@@ -0,0 +1,45 @@
1
+ export interface DddConfig {
2
+ orm: 'typeorm' | 'prisma' | 'mikro-orm';
3
+ database: 'postgres' | 'mysql' | 'mongodb' | 'sqlite';
4
+ naming: {
5
+ table: 'snake_case' | 'camelCase' | 'PascalCase';
6
+ dto: 'snake_case' | 'camelCase';
7
+ file: 'kebab-case' | 'snake_case';
8
+ };
9
+ features: {
10
+ swagger: boolean;
11
+ pagination: boolean;
12
+ softDelete: boolean;
13
+ timestamps: boolean;
14
+ tests: boolean;
15
+ events: boolean;
16
+ };
17
+ paths: {
18
+ modules: string;
19
+ migrations: string;
20
+ shared: string;
21
+ };
22
+ templates: {
23
+ custom?: string;
24
+ };
25
+ }
26
+ /**
27
+ * Load configuration from .dddrc.json or ddd.config.js
28
+ */
29
+ export declare function loadConfig(basePath?: string): Promise<DddConfig>;
30
+ /**
31
+ * Reset cached config (useful for testing)
32
+ */
33
+ export declare function resetConfigCache(): void;
34
+ /**
35
+ * Get a specific config value
36
+ */
37
+ export declare function getConfigValue<K extends keyof DddConfig>(key: K, basePath?: string): Promise<DddConfig[K]>;
38
+ /**
39
+ * Create a default .dddrc.json file in the specified directory
40
+ */
41
+ export declare function createDefaultConfig(basePath: string): Promise<void>;
42
+ /**
43
+ * Generate JSON schema for configuration validation
44
+ */
45
+ export declare function getConfigSchema(): object;
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadConfig = loadConfig;
37
+ exports.resetConfigCache = resetConfigCache;
38
+ exports.getConfigValue = getConfigValue;
39
+ exports.createDefaultConfig = createDefaultConfig;
40
+ exports.getConfigSchema = getConfigSchema;
41
+ const fs = __importStar(require("fs-extra"));
42
+ const path = __importStar(require("path"));
43
+ const cosmiconfig_1 = require("cosmiconfig");
44
+ const DEFAULT_CONFIG = {
45
+ orm: 'typeorm',
46
+ database: 'postgres',
47
+ naming: {
48
+ table: 'snake_case',
49
+ dto: 'snake_case',
50
+ file: 'kebab-case',
51
+ },
52
+ features: {
53
+ swagger: true,
54
+ pagination: true,
55
+ softDelete: true,
56
+ timestamps: true,
57
+ tests: false,
58
+ events: false,
59
+ },
60
+ paths: {
61
+ modules: 'src/modules',
62
+ migrations: 'src/migrations',
63
+ shared: 'src/shared',
64
+ },
65
+ templates: {},
66
+ };
67
+ let cachedConfig = null;
68
+ /**
69
+ * Load configuration from .dddrc.json or ddd.config.js
70
+ */
71
+ async function loadConfig(basePath) {
72
+ if (cachedConfig) {
73
+ return cachedConfig;
74
+ }
75
+ const searchPath = basePath || process.cwd();
76
+ try {
77
+ const explorer = (0, cosmiconfig_1.cosmiconfig)('ddd');
78
+ const result = await explorer.search(searchPath);
79
+ if (result && result.config) {
80
+ cachedConfig = mergeConfig(DEFAULT_CONFIG, result.config);
81
+ return cachedConfig;
82
+ }
83
+ }
84
+ catch (error) {
85
+ // Ignore errors, use defaults
86
+ }
87
+ cachedConfig = DEFAULT_CONFIG;
88
+ return cachedConfig;
89
+ }
90
+ /**
91
+ * Reset cached config (useful for testing)
92
+ */
93
+ function resetConfigCache() {
94
+ cachedConfig = null;
95
+ }
96
+ /**
97
+ * Deep merge configuration objects
98
+ */
99
+ function mergeConfig(defaults, overrides) {
100
+ return {
101
+ orm: overrides.orm || defaults.orm,
102
+ database: overrides.database || defaults.database,
103
+ naming: {
104
+ ...defaults.naming,
105
+ ...(overrides.naming || {}),
106
+ },
107
+ features: {
108
+ ...defaults.features,
109
+ ...(overrides.features || {}),
110
+ },
111
+ paths: {
112
+ ...defaults.paths,
113
+ ...(overrides.paths || {}),
114
+ },
115
+ templates: {
116
+ ...defaults.templates,
117
+ ...(overrides.templates || {}),
118
+ },
119
+ };
120
+ }
121
+ /**
122
+ * Get a specific config value
123
+ */
124
+ async function getConfigValue(key, basePath) {
125
+ const config = await loadConfig(basePath);
126
+ return config[key];
127
+ }
128
+ /**
129
+ * Create a default .dddrc.json file in the specified directory
130
+ */
131
+ async function createDefaultConfig(basePath) {
132
+ const configPath = path.join(basePath, '.dddrc.json');
133
+ const configContent = {
134
+ $schema: 'https://unpkg.com/nestjs-ddd-cli/ddd.schema.json',
135
+ ...DEFAULT_CONFIG,
136
+ };
137
+ await fs.writeJson(configPath, configContent, { spaces: 2 });
138
+ }
139
+ /**
140
+ * Generate JSON schema for configuration validation
141
+ */
142
+ function getConfigSchema() {
143
+ return {
144
+ $schema: 'http://json-schema.org/draft-07/schema#',
145
+ title: 'NestJS DDD CLI Configuration',
146
+ type: 'object',
147
+ properties: {
148
+ orm: {
149
+ type: 'string',
150
+ enum: ['typeorm', 'prisma', 'mikro-orm'],
151
+ default: 'typeorm',
152
+ description: 'ORM to use for database operations',
153
+ },
154
+ database: {
155
+ type: 'string',
156
+ enum: ['postgres', 'mysql', 'mongodb', 'sqlite'],
157
+ default: 'postgres',
158
+ description: 'Database type',
159
+ },
160
+ naming: {
161
+ type: 'object',
162
+ properties: {
163
+ table: {
164
+ type: 'string',
165
+ enum: ['snake_case', 'camelCase', 'PascalCase'],
166
+ default: 'snake_case',
167
+ },
168
+ dto: {
169
+ type: 'string',
170
+ enum: ['snake_case', 'camelCase'],
171
+ default: 'snake_case',
172
+ },
173
+ file: {
174
+ type: 'string',
175
+ enum: ['kebab-case', 'snake_case'],
176
+ default: 'kebab-case',
177
+ },
178
+ },
179
+ },
180
+ features: {
181
+ type: 'object',
182
+ properties: {
183
+ swagger: { type: 'boolean', default: true },
184
+ pagination: { type: 'boolean', default: true },
185
+ softDelete: { type: 'boolean', default: true },
186
+ timestamps: { type: 'boolean', default: true },
187
+ tests: { type: 'boolean', default: false },
188
+ events: { type: 'boolean', default: false },
189
+ },
190
+ },
191
+ paths: {
192
+ type: 'object',
193
+ properties: {
194
+ modules: { type: 'string', default: 'src/modules' },
195
+ migrations: { type: 'string', default: 'src/migrations' },
196
+ shared: { type: 'string', default: 'src/shared' },
197
+ },
198
+ },
199
+ templates: {
200
+ type: 'object',
201
+ properties: {
202
+ custom: {
203
+ type: 'string',
204
+ description: 'Path to custom templates directory',
205
+ },
206
+ },
207
+ },
208
+ },
209
+ };
210
+ }
211
+ //# sourceMappingURL=config.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.utils.js","sourceRoot":"","sources":["../../src/utils/config.utils.ts"],"names":[],"mappings":"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"}