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,706 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.applyMessageQueueRecipe = applyMessageQueueRecipe;
40
+ const path = __importStar(require("path"));
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const file_utils_1 = require("../../utils/file.utils");
43
+ async function applyMessageQueueRecipe(basePath) {
44
+ const sharedPath = path.join(basePath, 'src/shared');
45
+ const mqPath = path.join(sharedPath, 'messaging');
46
+ await (0, file_utils_1.ensureDir)(mqPath);
47
+ await (0, file_utils_1.ensureDir)(path.join(mqPath, 'producers'));
48
+ await (0, file_utils_1.ensureDir)(path.join(mqPath, 'consumers'));
49
+ await (0, file_utils_1.ensureDir)(path.join(mqPath, 'decorators'));
50
+ // Message types
51
+ const messageTypesContent = `export interface Message<T = any> {
52
+ id: string;
53
+ type: string;
54
+ payload: T;
55
+ metadata: MessageMetadata;
56
+ timestamp: Date;
57
+ }
58
+
59
+ export interface MessageMetadata {
60
+ correlationId?: string;
61
+ causationId?: string;
62
+ userId?: string;
63
+ tenantId?: string;
64
+ retryCount?: number;
65
+ maxRetries?: number;
66
+ priority?: number;
67
+ headers?: Record<string, string>;
68
+ }
69
+
70
+ export interface MessageHandler<T = any> {
71
+ handle(message: Message<T>): Promise<void>;
72
+ }
73
+
74
+ export interface PublishOptions {
75
+ exchange?: string;
76
+ routingKey?: string;
77
+ persistent?: boolean;
78
+ priority?: number;
79
+ expiration?: number;
80
+ headers?: Record<string, any>;
81
+ delay?: number;
82
+ }
83
+
84
+ export interface ConsumeOptions {
85
+ queue: string;
86
+ prefetch?: number;
87
+ noAck?: boolean;
88
+ exclusive?: boolean;
89
+ deadLetterExchange?: string;
90
+ deadLetterRoutingKey?: string;
91
+ retryDelay?: number;
92
+ maxRetries?: number;
93
+ }
94
+
95
+ export type ExchangeType = "direct" | "topic" | "fanout" | "headers";
96
+
97
+ export interface ExchangeConfig {
98
+ name: string;
99
+ type: ExchangeType;
100
+ durable?: boolean;
101
+ autoDelete?: boolean;
102
+ }
103
+
104
+ export interface QueueConfig {
105
+ name: string;
106
+ durable?: boolean;
107
+ exclusive?: boolean;
108
+ autoDelete?: boolean;
109
+ deadLetterExchange?: string;
110
+ deadLetterRoutingKey?: string;
111
+ messageTtl?: number;
112
+ maxLength?: number;
113
+ }
114
+ `;
115
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'message.types.ts'), messageTypesContent);
116
+ // RabbitMQ Connection
117
+ const connectionContent = `import { Injectable, Logger, OnModuleInit, OnModuleDestroy } from "@nestjs/common";
118
+ import * as amqp from "amqplib";
119
+
120
+ export interface RabbitMQConfig {
121
+ url: string;
122
+ heartbeat?: number;
123
+ reconnectDelay?: number;
124
+ maxReconnectAttempts?: number;
125
+ }
126
+
127
+ @Injectable()
128
+ export class RabbitMQConnection implements OnModuleInit, OnModuleDestroy {
129
+ private readonly logger = new Logger(RabbitMQConnection.name);
130
+ private connection: amqp.Connection | null = null;
131
+ private channel: amqp.Channel | null = null;
132
+ private reconnectAttempts = 0;
133
+ private isConnecting = false;
134
+
135
+ private config: RabbitMQConfig = {
136
+ url: process.env.RABBITMQ_URL || "amqp://localhost:5672",
137
+ heartbeat: 60,
138
+ reconnectDelay: 5000,
139
+ maxReconnectAttempts: 10,
140
+ };
141
+
142
+ async onModuleInit() {
143
+ await this.connect();
144
+ }
145
+
146
+ async onModuleDestroy() {
147
+ await this.disconnect();
148
+ }
149
+
150
+ async connect(): Promise<void> {
151
+ if (this.isConnecting) return;
152
+ this.isConnecting = true;
153
+
154
+ try {
155
+ this.connection = await amqp.connect(this.config.url, {
156
+ heartbeat: this.config.heartbeat,
157
+ });
158
+
159
+ this.connection.on("error", (err) => {
160
+ this.logger.error("RabbitMQ connection error:", err.message);
161
+ });
162
+
163
+ this.connection.on("close", () => {
164
+ this.logger.warn("RabbitMQ connection closed, attempting reconnect...");
165
+ this.scheduleReconnect();
166
+ });
167
+
168
+ this.channel = await this.connection.createChannel();
169
+ this.reconnectAttempts = 0;
170
+ this.logger.log("Connected to RabbitMQ");
171
+ } catch (error) {
172
+ this.logger.error("Failed to connect to RabbitMQ:", error);
173
+ this.scheduleReconnect();
174
+ } finally {
175
+ this.isConnecting = false;
176
+ }
177
+ }
178
+
179
+ private scheduleReconnect() {
180
+ if (this.reconnectAttempts >= (this.config.maxReconnectAttempts || 10)) {
181
+ this.logger.error("Max reconnection attempts reached");
182
+ return;
183
+ }
184
+
185
+ this.reconnectAttempts++;
186
+ setTimeout(() => this.connect(), this.config.reconnectDelay);
187
+ }
188
+
189
+ async disconnect(): Promise<void> {
190
+ try {
191
+ if (this.channel) {
192
+ await this.channel.close();
193
+ this.channel = null;
194
+ }
195
+ if (this.connection) {
196
+ await this.connection.close();
197
+ this.connection = null;
198
+ }
199
+ this.logger.log("Disconnected from RabbitMQ");
200
+ } catch (error) {
201
+ this.logger.error("Error disconnecting from RabbitMQ:", error);
202
+ }
203
+ }
204
+
205
+ getChannel(): amqp.Channel {
206
+ if (!this.channel) {
207
+ throw new Error("RabbitMQ channel not available");
208
+ }
209
+ return this.channel;
210
+ }
211
+
212
+ isConnected(): boolean {
213
+ return this.channel !== null;
214
+ }
215
+ }
216
+ `;
217
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'rabbitmq.connection.ts'), connectionContent);
218
+ // Message Producer
219
+ const producerContent = `import { Injectable, Logger } from "@nestjs/common";
220
+ import { v4 as uuid } from "uuid";
221
+ import { RabbitMQConnection } from "../rabbitmq.connection";
222
+ import { Message, MessageMetadata, PublishOptions, ExchangeConfig, ExchangeType } from "../message.types";
223
+
224
+ @Injectable()
225
+ export class MessageProducer {
226
+ private readonly logger = new Logger(MessageProducer.name);
227
+ private declaredExchanges: Set<string> = new Set();
228
+
229
+ constructor(private connection: RabbitMQConnection) {}
230
+
231
+ /**
232
+ * Publish a message to an exchange
233
+ */
234
+ async publish<T>(
235
+ type: string,
236
+ payload: T,
237
+ options: PublishOptions = {}
238
+ ): Promise<string> {
239
+ const channel = this.connection.getChannel();
240
+ const messageId = uuid();
241
+
242
+ const message: Message<T> = {
243
+ id: messageId,
244
+ type,
245
+ payload,
246
+ metadata: {
247
+ correlationId: options.headers?.correlationId,
248
+ priority: options.priority,
249
+ },
250
+ timestamp: new Date(),
251
+ };
252
+
253
+ const exchange = options.exchange || "events";
254
+ const routingKey = options.routingKey || type;
255
+
256
+ await this.ensureExchange(exchange, "topic");
257
+
258
+ const content = Buffer.from(JSON.stringify(message));
259
+
260
+ channel.publish(exchange, routingKey, content, {
261
+ persistent: options.persistent !== false,
262
+ messageId,
263
+ timestamp: Date.now(),
264
+ contentType: "application/json",
265
+ priority: options.priority,
266
+ expiration: options.expiration?.toString(),
267
+ headers: options.headers,
268
+ });
269
+
270
+ this.logger.debug(\`Published message \${messageId} to \${exchange}:\${routingKey}\`);
271
+ return messageId;
272
+ }
273
+
274
+ /**
275
+ * Publish directly to a queue
276
+ */
277
+ async sendToQueue<T>(
278
+ queue: string,
279
+ type: string,
280
+ payload: T,
281
+ metadata?: Partial<MessageMetadata>
282
+ ): Promise<string> {
283
+ const channel = this.connection.getChannel();
284
+ const messageId = uuid();
285
+
286
+ const message: Message<T> = {
287
+ id: messageId,
288
+ type,
289
+ payload,
290
+ metadata: {
291
+ ...metadata,
292
+ },
293
+ timestamp: new Date(),
294
+ };
295
+
296
+ const content = Buffer.from(JSON.stringify(message));
297
+
298
+ channel.sendToQueue(queue, content, {
299
+ persistent: true,
300
+ messageId,
301
+ timestamp: Date.now(),
302
+ contentType: "application/json",
303
+ });
304
+
305
+ this.logger.debug(\`Sent message \${messageId} to queue \${queue}\`);
306
+ return messageId;
307
+ }
308
+
309
+ /**
310
+ * Publish with delay using dead-letter exchange
311
+ */
312
+ async publishDelayed<T>(
313
+ type: string,
314
+ payload: T,
315
+ delayMs: number,
316
+ options: PublishOptions = {}
317
+ ): Promise<string> {
318
+ const channel = this.connection.getChannel();
319
+ const messageId = uuid();
320
+ const delayQueue = \`delay.\${delayMs}.\${options.routingKey || type}\`;
321
+ const targetExchange = options.exchange || "events";
322
+
323
+ // Create delay queue that forwards to target exchange after TTL
324
+ await channel.assertQueue(delayQueue, {
325
+ durable: true,
326
+ deadLetterExchange: targetExchange,
327
+ deadLetterRoutingKey: options.routingKey || type,
328
+ messageTtl: delayMs,
329
+ expires: delayMs + 60000,
330
+ });
331
+
332
+ const message: Message<T> = {
333
+ id: messageId,
334
+ type,
335
+ payload,
336
+ metadata: {
337
+ correlationId: options.headers?.correlationId,
338
+ },
339
+ timestamp: new Date(),
340
+ };
341
+
342
+ const content = Buffer.from(JSON.stringify(message));
343
+
344
+ channel.sendToQueue(delayQueue, content, {
345
+ persistent: true,
346
+ messageId,
347
+ contentType: "application/json",
348
+ });
349
+
350
+ this.logger.debug(\`Published delayed message \${messageId} (delay: \${delayMs}ms)\`);
351
+ return messageId;
352
+ }
353
+
354
+ /**
355
+ * Ensure exchange exists
356
+ */
357
+ private async ensureExchange(name: string, type: ExchangeType): Promise<void> {
358
+ if (this.declaredExchanges.has(name)) return;
359
+
360
+ const channel = this.connection.getChannel();
361
+ await channel.assertExchange(name, type, { durable: true });
362
+ this.declaredExchanges.add(name);
363
+ }
364
+
365
+ /**
366
+ * Create exchange with config
367
+ */
368
+ async createExchange(config: ExchangeConfig): Promise<void> {
369
+ const channel = this.connection.getChannel();
370
+ await channel.assertExchange(config.name, config.type, {
371
+ durable: config.durable !== false,
372
+ autoDelete: config.autoDelete || false,
373
+ });
374
+ this.declaredExchanges.add(config.name);
375
+ }
376
+ }
377
+ `;
378
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'producers/message.producer.ts'), producerContent);
379
+ // Message Consumer
380
+ const consumerContent = `import { Injectable, Logger, OnModuleInit } from "@nestjs/common";
381
+ import * as amqp from "amqplib";
382
+ import { RabbitMQConnection } from "../rabbitmq.connection";
383
+ import { Message, ConsumeOptions, QueueConfig } from "../message.types";
384
+
385
+ export type MessageHandlerFn<T = any> = (message: Message<T>) => Promise<void>;
386
+
387
+ interface RegisteredHandler {
388
+ queue: string;
389
+ handler: MessageHandlerFn;
390
+ options: ConsumeOptions;
391
+ }
392
+
393
+ @Injectable()
394
+ export class MessageConsumer implements OnModuleInit {
395
+ private readonly logger = new Logger(MessageConsumer.name);
396
+ private handlers: Map<string, RegisteredHandler[]> = new Map();
397
+ private declaredQueues: Set<string> = new Set();
398
+
399
+ constructor(private connection: RabbitMQConnection) {}
400
+
401
+ async onModuleInit() {
402
+ // Start consuming after connection is established
403
+ setTimeout(() => this.startConsuming(), 1000);
404
+ }
405
+
406
+ /**
407
+ * Register a message handler
408
+ */
409
+ registerHandler(
410
+ messageType: string,
411
+ handler: MessageHandlerFn,
412
+ options: ConsumeOptions
413
+ ): void {
414
+ if (!this.handlers.has(messageType)) {
415
+ this.handlers.set(messageType, []);
416
+ }
417
+ this.handlers.get(messageType)!.push({ queue: options.queue, handler, options });
418
+ }
419
+
420
+ /**
421
+ * Create and configure a queue
422
+ */
423
+ async createQueue(config: QueueConfig): Promise<void> {
424
+ const channel = this.connection.getChannel();
425
+
426
+ await channel.assertQueue(config.name, {
427
+ durable: config.durable !== false,
428
+ exclusive: config.exclusive || false,
429
+ autoDelete: config.autoDelete || false,
430
+ deadLetterExchange: config.deadLetterExchange,
431
+ deadLetterRoutingKey: config.deadLetterRoutingKey,
432
+ messageTtl: config.messageTtl,
433
+ maxLength: config.maxLength,
434
+ });
435
+
436
+ this.declaredQueues.add(config.name);
437
+ }
438
+
439
+ /**
440
+ * Bind queue to exchange
441
+ */
442
+ async bindQueue(queue: string, exchange: string, routingKey: string): Promise<void> {
443
+ const channel = this.connection.getChannel();
444
+ await channel.bindQueue(queue, exchange, routingKey);
445
+ }
446
+
447
+ /**
448
+ * Start consuming from all registered handlers
449
+ */
450
+ private async startConsuming(): Promise<void> {
451
+ if (!this.connection.isConnected()) {
452
+ this.logger.warn("Connection not ready, retrying in 1s...");
453
+ setTimeout(() => this.startConsuming(), 1000);
454
+ return;
455
+ }
456
+
457
+ for (const [messageType, handlers] of this.handlers) {
458
+ for (const { queue, handler, options } of handlers) {
459
+ await this.consume(queue, handler, options);
460
+ }
461
+ }
462
+ }
463
+
464
+ /**
465
+ * Consume messages from a queue
466
+ */
467
+ private async consume(
468
+ queue: string,
469
+ handler: MessageHandlerFn,
470
+ options: ConsumeOptions
471
+ ): Promise<void> {
472
+ const channel = this.connection.getChannel();
473
+
474
+ // Ensure queue exists
475
+ await channel.assertQueue(queue, { durable: true });
476
+
477
+ // Set prefetch
478
+ if (options.prefetch) {
479
+ await channel.prefetch(options.prefetch);
480
+ }
481
+
482
+ // Set up dead letter queue if configured
483
+ if (options.deadLetterExchange) {
484
+ const dlqName = \`\${queue}.dlq\`;
485
+ await channel.assertQueue(dlqName, { durable: true });
486
+ await channel.bindQueue(
487
+ dlqName,
488
+ options.deadLetterExchange,
489
+ options.deadLetterRoutingKey || queue
490
+ );
491
+ }
492
+
493
+ this.logger.log(\`Starting consumer for queue: \${queue}\`);
494
+
495
+ channel.consume(
496
+ queue,
497
+ async (msg: amqp.ConsumeMessage | null) => {
498
+ if (!msg) return;
499
+
500
+ try {
501
+ const message: Message = JSON.parse(msg.content.toString());
502
+ await handler(message);
503
+ channel.ack(msg);
504
+ this.logger.debug(\`Processed message \${message.id} from \${queue}\`);
505
+ } catch (error) {
506
+ this.logger.error(\`Error processing message from \${queue}:\`, error);
507
+ await this.handleFailure(channel, msg, options);
508
+ }
509
+ },
510
+ { noAck: options.noAck || false }
511
+ );
512
+ }
513
+
514
+ /**
515
+ * Handle message processing failure
516
+ */
517
+ private async handleFailure(
518
+ channel: amqp.Channel,
519
+ msg: amqp.ConsumeMessage,
520
+ options: ConsumeOptions
521
+ ): Promise<void> {
522
+ const retryCount = (msg.properties.headers?.["x-retry-count"] || 0) + 1;
523
+ const maxRetries = options.maxRetries || 3;
524
+
525
+ if (retryCount <= maxRetries) {
526
+ // Retry with delay
527
+ const retryDelay = options.retryDelay || 5000;
528
+ const retryQueue = \`\${options.queue}.retry\`;
529
+
530
+ await channel.assertQueue(retryQueue, {
531
+ durable: true,
532
+ deadLetterExchange: "",
533
+ deadLetterRoutingKey: options.queue,
534
+ messageTtl: retryDelay * retryCount,
535
+ });
536
+
537
+ channel.sendToQueue(retryQueue, msg.content, {
538
+ persistent: true,
539
+ headers: {
540
+ ...msg.properties.headers,
541
+ "x-retry-count": retryCount,
542
+ "x-original-queue": options.queue,
543
+ },
544
+ });
545
+
546
+ this.logger.warn(\`Retrying message (attempt \${retryCount}/\${maxRetries})\`);
547
+ } else {
548
+ // Send to dead letter queue
549
+ this.logger.error(\`Message exceeded max retries, sending to DLQ\`);
550
+ }
551
+
552
+ channel.ack(msg);
553
+ }
554
+ }
555
+ `;
556
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'consumers/message.consumer.ts'), consumerContent);
557
+ // Subscribe decorator
558
+ const subscribeDecoratorContent = `import { SetMetadata } from "@nestjs/common";
559
+ import { ConsumeOptions } from "../message.types";
560
+
561
+ export const SUBSCRIBE_METADATA = "message:subscribe";
562
+
563
+ export interface SubscribeConfig extends Partial<ConsumeOptions> {
564
+ messageType: string;
565
+ queue: string;
566
+ exchange?: string;
567
+ routingKey?: string;
568
+ }
569
+
570
+ /**
571
+ * Decorator to subscribe a method to a message type
572
+ */
573
+ export function Subscribe(config: SubscribeConfig): MethodDecorator {
574
+ return SetMetadata(SUBSCRIBE_METADATA, config);
575
+ }
576
+
577
+ /**
578
+ * Decorator to mark a class as a message handler
579
+ */
580
+ export function MessageHandler(): ClassDecorator {
581
+ return (target) => {
582
+ Reflect.defineMetadata("message:handler", true, target);
583
+ };
584
+ }
585
+ `;
586
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'decorators/subscribe.decorator.ts'), subscribeDecoratorContent);
587
+ // Messaging module
588
+ const moduleContent = `import { Module, Global, DynamicModule, OnModuleInit } from "@nestjs/common";
589
+ import { DiscoveryModule, DiscoveryService, MetadataScanner } from "@nestjs/core";
590
+ import { RabbitMQConnection, RabbitMQConfig } from "./rabbitmq.connection";
591
+ import { MessageProducer } from "./producers/message.producer";
592
+ import { MessageConsumer } from "./consumers/message.consumer";
593
+ import { SUBSCRIBE_METADATA, SubscribeConfig } from "./decorators/subscribe.decorator";
594
+
595
+ export interface MessagingModuleOptions {
596
+ config?: Partial<RabbitMQConfig>;
597
+ exchanges?: Array<{ name: string; type: "direct" | "topic" | "fanout" }>;
598
+ queues?: Array<{ name: string; exchange: string; routingKey: string }>;
599
+ }
600
+
601
+ @Global()
602
+ @Module({})
603
+ export class MessagingModule implements OnModuleInit {
604
+ static options: MessagingModuleOptions;
605
+
606
+ constructor(
607
+ private discovery: DiscoveryService,
608
+ private scanner: MetadataScanner,
609
+ private consumer: MessageConsumer,
610
+ private producer: MessageProducer
611
+ ) {}
612
+
613
+ static forRoot(options: MessagingModuleOptions = {}): DynamicModule {
614
+ MessagingModule.options = options;
615
+
616
+ return {
617
+ module: MessagingModule,
618
+ imports: [DiscoveryModule],
619
+ providers: [
620
+ RabbitMQConnection,
621
+ MessageProducer,
622
+ MessageConsumer,
623
+ ],
624
+ exports: [MessageProducer, MessageConsumer, RabbitMQConnection],
625
+ };
626
+ }
627
+
628
+ async onModuleInit() {
629
+ // Set up exchanges
630
+ for (const exchange of MessagingModule.options.exchanges || []) {
631
+ await this.producer.createExchange({
632
+ name: exchange.name,
633
+ type: exchange.type,
634
+ });
635
+ }
636
+
637
+ // Set up queues and bindings
638
+ for (const queue of MessagingModule.options.queues || []) {
639
+ await this.consumer.createQueue({ name: queue.name });
640
+ await this.consumer.bindQueue(queue.name, queue.exchange, queue.routingKey);
641
+ }
642
+
643
+ // Discover and register handlers
644
+ this.discoverHandlers();
645
+ }
646
+
647
+ private discoverHandlers() {
648
+ const providers = this.discovery.getProviders();
649
+
650
+ providers
651
+ .filter((wrapper) => wrapper.instance && wrapper.metatype)
652
+ .forEach((wrapper) => {
653
+ const { instance } = wrapper;
654
+
655
+ this.scanner.scanFromPrototype(
656
+ instance,
657
+ Object.getPrototypeOf(instance),
658
+ (methodName) => {
659
+ const methodRef = instance[methodName];
660
+ const metadata = Reflect.getMetadata(
661
+ SUBSCRIBE_METADATA,
662
+ methodRef
663
+ ) as SubscribeConfig | undefined;
664
+
665
+ if (metadata) {
666
+ this.consumer.registerHandler(
667
+ metadata.messageType,
668
+ methodRef.bind(instance),
669
+ {
670
+ queue: metadata.queue,
671
+ prefetch: metadata.prefetch,
672
+ maxRetries: metadata.maxRetries,
673
+ retryDelay: metadata.retryDelay,
674
+ deadLetterExchange: metadata.deadLetterExchange,
675
+ }
676
+ );
677
+ }
678
+ }
679
+ );
680
+ });
681
+ }
682
+ }
683
+ `;
684
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'messaging.module.ts'), moduleContent);
685
+ // Index exports
686
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'index.ts'), `export * from "./message.types";
687
+ export * from "./rabbitmq.connection";
688
+ export * from "./producers/message.producer";
689
+ export * from "./consumers/message.consumer";
690
+ export * from "./decorators/subscribe.decorator";
691
+ export * from "./messaging.module";
692
+ `);
693
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'producers/index.ts'), `export * from "./message.producer";
694
+ `);
695
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'consumers/index.ts'), `export * from "./message.consumer";
696
+ `);
697
+ await (0, file_utils_1.writeFile)(path.join(mqPath, 'decorators/index.ts'), `export * from "./subscribe.decorator";
698
+ `);
699
+ console.log(chalk_1.default.green(' ✓ Message types and interfaces'));
700
+ console.log(chalk_1.default.green(' ✓ RabbitMQ connection manager with reconnection'));
701
+ console.log(chalk_1.default.green(' ✓ Message producer (publish, sendToQueue, delayed)'));
702
+ console.log(chalk_1.default.green(' ✓ Message consumer with retry and DLQ'));
703
+ console.log(chalk_1.default.green(' ✓ @Subscribe decorator'));
704
+ console.log(chalk_1.default.green(' ✓ Messaging module with auto-discovery'));
705
+ }
706
+ //# sourceMappingURL=message-queue.recipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-queue.recipe.js","sourceRoot":"","sources":["../../../src/commands/recipes/message-queue.recipe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function applyMiddlewareRecipe(basePath: string): Promise<void>;