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,687 @@
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.setupDbOptimization = setupDbOptimization;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const naming_utils_1 = require("../utils/naming.utils");
44
+ async function setupDbOptimization(basePath, options = {}) {
45
+ console.log(chalk_1.default.bold.blue('\n🗄️ Setting up Database Optimization\n'));
46
+ const moduleName = options.module || 'shared';
47
+ const pascalName = (0, naming_utils_1.toPascalCase)(moduleName);
48
+ const camelName = (0, naming_utils_1.toCamelCase)(moduleName);
49
+ const kebabName = (0, naming_utils_1.toKebabCase)(moduleName);
50
+ const orm = options.orm || 'typeorm';
51
+ const includeDataLoader = options.includeDataLoader !== false;
52
+ const includeQueryAnalyzer = options.includeQueryAnalyzer !== false;
53
+ const baseDir = path.join(basePath, 'src', kebabName, 'infrastructure', 'database');
54
+ fs.mkdirSync(baseDir, { recursive: true });
55
+ // DataLoader for N+1 prevention
56
+ if (includeDataLoader) {
57
+ const dataLoaderContent = `import { Injectable, Scope } from '@nestjs/common';
58
+ import DataLoader from 'dataloader';
59
+
60
+ /**
61
+ * Generic DataLoader factory for preventing N+1 queries
62
+ * Creates request-scoped DataLoader instances
63
+ */
64
+ @Injectable({ scope: Scope.REQUEST })
65
+ export class DataLoaderFactory {
66
+ private loaders: Map<string, DataLoader<any, any>> = new Map();
67
+
68
+ /**
69
+ * Get or create a DataLoader for the specified key
70
+ */
71
+ getLoader<K, V>(
72
+ key: string,
73
+ batchFn: (keys: readonly K[]) => Promise<(V | Error)[]>,
74
+ options?: DataLoader.Options<K, V>,
75
+ ): DataLoader<K, V> {
76
+ if (!this.loaders.has(key)) {
77
+ this.loaders.set(
78
+ key,
79
+ new DataLoader<K, V>(batchFn, {
80
+ cache: true,
81
+ maxBatchSize: 100,
82
+ ...options,
83
+ }),
84
+ );
85
+ }
86
+ return this.loaders.get(key) as DataLoader<K, V>;
87
+ }
88
+
89
+ /**
90
+ * Clear all loaders (useful for mutations)
91
+ */
92
+ clearAll(): void {
93
+ this.loaders.forEach((loader) => loader.clearAll());
94
+ }
95
+
96
+ /**
97
+ * Clear specific loader
98
+ */
99
+ clear(key: string): void {
100
+ const loader = this.loaders.get(key);
101
+ if (loader) {
102
+ loader.clearAll();
103
+ }
104
+ }
105
+ }
106
+
107
+ /**
108
+ * DataLoader decorator for automatic batching
109
+ */
110
+ export function BatchLoad(loaderKey: string): MethodDecorator {
111
+ return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
112
+ const originalMethod = descriptor.value;
113
+
114
+ descriptor.value = async function (...args: any[]) {
115
+ const dataLoaderFactory = (this as any).dataLoaderFactory as DataLoaderFactory;
116
+
117
+ if (!dataLoaderFactory) {
118
+ // Fallback to original method if no DataLoader available
119
+ return originalMethod.apply(this, args);
120
+ }
121
+
122
+ const loader = dataLoaderFactory.getLoader(
123
+ loaderKey,
124
+ async (keys: readonly any[]) => {
125
+ // Call original method with all keys
126
+ return originalMethod.call(this, keys);
127
+ },
128
+ );
129
+
130
+ // If single ID, use load; if array, use loadMany
131
+ const id = args[0];
132
+ if (Array.isArray(id)) {
133
+ return loader.loadMany(id);
134
+ }
135
+ return loader.load(id);
136
+ };
137
+
138
+ return descriptor;
139
+ };
140
+ }
141
+
142
+ /**
143
+ * ${pascalName} specific DataLoader service
144
+ */
145
+ @Injectable({ scope: Scope.REQUEST })
146
+ export class ${pascalName}DataLoader {
147
+ constructor(
148
+ private readonly dataLoaderFactory: DataLoaderFactory,
149
+ // Inject your repository here
150
+ // private readonly ${camelName}Repository: ${pascalName}Repository,
151
+ ) {}
152
+
153
+ /**
154
+ * Batch load ${camelName} by IDs
155
+ */
156
+ async loadById(id: string): Promise<any> {
157
+ const loader = this.dataLoaderFactory.getLoader<string, any>(
158
+ '${camelName}ById',
159
+ async (ids: readonly string[]) => {
160
+ // Replace with actual repository call
161
+ // const entities = await this.${camelName}Repository.findByIds([...ids]);
162
+ // return ids.map(id => entities.find(e => e.id === id) || new Error(\`${pascalName} \${id} not found\`));
163
+ return ids.map(() => null);
164
+ },
165
+ );
166
+ return loader.load(id);
167
+ }
168
+
169
+ /**
170
+ * Batch load ${camelName} by foreign key
171
+ */
172
+ async loadByForeignKey(foreignKeyId: string): Promise<any[]> {
173
+ const loader = this.dataLoaderFactory.getLoader<string, any[]>(
174
+ '${camelName}ByForeignKey',
175
+ async (foreignKeyIds: readonly string[]) => {
176
+ // Replace with actual repository call
177
+ // const entities = await this.${camelName}Repository.findByForeignKeys([...foreignKeyIds]);
178
+ // return foreignKeyIds.map(fkId => entities.filter(e => e.foreignKeyId === fkId));
179
+ return foreignKeyIds.map(() => []);
180
+ },
181
+ );
182
+ return loader.load(foreignKeyId);
183
+ }
184
+
185
+ /**
186
+ * Prime cache with known data
187
+ */
188
+ prime(id: string, data: any): void {
189
+ const loader = this.dataLoaderFactory.getLoader<string, any>(
190
+ '${camelName}ById',
191
+ async () => [],
192
+ );
193
+ loader.prime(id, data);
194
+ }
195
+
196
+ /**
197
+ * Clear cache after mutations
198
+ */
199
+ clearCache(id?: string): void {
200
+ if (id) {
201
+ const loader = this.dataLoaderFactory.getLoader<string, any>(
202
+ '${camelName}ById',
203
+ async () => [],
204
+ );
205
+ loader.clear(id);
206
+ } else {
207
+ this.dataLoaderFactory.clear('${camelName}ById');
208
+ this.dataLoaderFactory.clear('${camelName}ByForeignKey');
209
+ }
210
+ }
211
+ }
212
+ `;
213
+ fs.writeFileSync(path.join(baseDir, 'data-loader.ts'), dataLoaderContent);
214
+ }
215
+ // Query Analyzer
216
+ if (includeQueryAnalyzer) {
217
+ const queryAnalyzerContent = `import { Injectable, Logger } from '@nestjs/common';
218
+ ${orm === 'typeorm' ? "import { DataSource, QueryRunner } from 'typeorm';" : ''}
219
+
220
+ interface QueryMetrics {
221
+ query: string;
222
+ duration: number;
223
+ rowsAffected?: number;
224
+ timestamp: Date;
225
+ explain?: ExplainResult;
226
+ }
227
+
228
+ interface ExplainResult {
229
+ type: string;
230
+ possibleKeys?: string[];
231
+ key?: string;
232
+ rows?: number;
233
+ filtered?: number;
234
+ extra?: string;
235
+ }
236
+
237
+ interface SlowQueryReport {
238
+ query: string;
239
+ avgDuration: number;
240
+ maxDuration: number;
241
+ count: number;
242
+ suggestion: string;
243
+ }
244
+
245
+ interface IndexSuggestion {
246
+ table: string;
247
+ columns: string[];
248
+ reason: string;
249
+ impact: 'high' | 'medium' | 'low';
250
+ }
251
+
252
+ /**
253
+ * Query performance analyzer for identifying slow queries and optimization opportunities
254
+ */
255
+ @Injectable()
256
+ export class QueryAnalyzerService {
257
+ private readonly logger = new Logger(QueryAnalyzerService.name);
258
+ private readonly queryMetrics: Map<string, QueryMetrics[]> = new Map();
259
+ private readonly slowQueryThreshold: number;
260
+ private readonly maxStoredQueries: number;
261
+
262
+ constructor(
263
+ ${orm === 'typeorm' ? ' private readonly dataSource: DataSource,' : ''}
264
+ ) {
265
+ this.slowQueryThreshold = parseInt(process.env.SLOW_QUERY_THRESHOLD_MS || '100', 10);
266
+ this.maxStoredQueries = parseInt(process.env.MAX_STORED_QUERIES || '1000', 10);
267
+ }
268
+
269
+ /**
270
+ * Record query execution metrics
271
+ */
272
+ recordQuery(query: string, duration: number, rowsAffected?: number): void {
273
+ const normalizedQuery = this.normalizeQuery(query);
274
+
275
+ if (!this.queryMetrics.has(normalizedQuery)) {
276
+ this.queryMetrics.set(normalizedQuery, []);
277
+ }
278
+
279
+ const metrics = this.queryMetrics.get(normalizedQuery)!;
280
+ metrics.push({
281
+ query,
282
+ duration,
283
+ rowsAffected,
284
+ timestamp: new Date(),
285
+ });
286
+
287
+ // Keep only recent queries
288
+ if (metrics.length > this.maxStoredQueries) {
289
+ metrics.shift();
290
+ }
291
+
292
+ // Log slow queries
293
+ if (duration > this.slowQueryThreshold) {
294
+ this.logger.warn(\`Slow query detected (\${duration}ms): \${query.substring(0, 200)}...\`);
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Normalize query for grouping (remove specific values)
300
+ */
301
+ private normalizeQuery(query: string): string {
302
+ return query
303
+ .replace(/= \\d+/g, '= ?')
304
+ .replace(/= '[^']*'/g, "= '?'")
305
+ .replace(/IN \\([^)]+\\)/gi, 'IN (?)')
306
+ .replace(/LIMIT \\d+/gi, 'LIMIT ?')
307
+ .replace(/OFFSET \\d+/gi, 'OFFSET ?')
308
+ .trim();
309
+ }
310
+
311
+ /**
312
+ * Get slow query report
313
+ */
314
+ getSlowQueryReport(thresholdMs?: number): SlowQueryReport[] {
315
+ const threshold = thresholdMs || this.slowQueryThreshold;
316
+ const reports: SlowQueryReport[] = [];
317
+
318
+ this.queryMetrics.forEach((metrics, normalizedQuery) => {
319
+ const slowQueries = metrics.filter((m) => m.duration > threshold);
320
+
321
+ if (slowQueries.length > 0) {
322
+ const durations = slowQueries.map((m) => m.duration);
323
+ const avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length;
324
+ const maxDuration = Math.max(...durations);
325
+
326
+ reports.push({
327
+ query: normalizedQuery,
328
+ avgDuration: Math.round(avgDuration),
329
+ maxDuration,
330
+ count: slowQueries.length,
331
+ suggestion: this.generateSuggestion(normalizedQuery, avgDuration),
332
+ });
333
+ }
334
+ });
335
+
336
+ return reports.sort((a, b) => b.avgDuration - a.avgDuration);
337
+ }
338
+
339
+ /**
340
+ * Generate optimization suggestion for a query
341
+ */
342
+ private generateSuggestion(query: string, avgDuration: number): string {
343
+ const suggestions: string[] = [];
344
+ const upperQuery = query.toUpperCase();
345
+
346
+ // Check for SELECT *
347
+ if (upperQuery.includes('SELECT *')) {
348
+ suggestions.push('Avoid SELECT *, specify only needed columns');
349
+ }
350
+
351
+ // Check for missing WHERE clause
352
+ if (!upperQuery.includes('WHERE') && (upperQuery.includes('UPDATE') || upperQuery.includes('DELETE'))) {
353
+ suggestions.push('Missing WHERE clause - full table scan');
354
+ }
355
+
356
+ // Check for LIKE with leading wildcard
357
+ if (upperQuery.includes("LIKE '%") || upperQuery.includes("LIKE '?%")) {
358
+ suggestions.push('Leading wildcard in LIKE prevents index usage');
359
+ }
360
+
361
+ // Check for OR conditions
362
+ if (upperQuery.includes(' OR ')) {
363
+ suggestions.push('Consider using UNION instead of OR for better index usage');
364
+ }
365
+
366
+ // Check for NOT IN
367
+ if (upperQuery.includes('NOT IN')) {
368
+ suggestions.push('Consider using NOT EXISTS instead of NOT IN');
369
+ }
370
+
371
+ // Check for functions on indexed columns
372
+ if (/WHERE\\s+\\w+\\s*\\(/.test(query)) {
373
+ suggestions.push('Functions on columns prevent index usage');
374
+ }
375
+
376
+ // Check for ORDER BY without LIMIT
377
+ if (upperQuery.includes('ORDER BY') && !upperQuery.includes('LIMIT')) {
378
+ suggestions.push('ORDER BY without LIMIT may cause full result set sorting');
379
+ }
380
+
381
+ // Duration-based suggestions
382
+ if (avgDuration > 1000) {
383
+ suggestions.push('Consider query restructuring or adding composite index');
384
+ } else if (avgDuration > 500) {
385
+ suggestions.push('Review indexes on filtered/joined columns');
386
+ }
387
+
388
+ return suggestions.length > 0 ? suggestions.join('; ') : 'Profile query execution plan for detailed analysis';
389
+ }
390
+ ${orm === 'typeorm' ? `
391
+ /**
392
+ * Analyze query with EXPLAIN
393
+ */
394
+ async explainQuery(query: string): Promise<ExplainResult | null> {
395
+ try {
396
+ const result = await this.dataSource.query(\`EXPLAIN \${query}\`);
397
+ if (result && result.length > 0) {
398
+ return {
399
+ type: result[0].type || result[0].select_type,
400
+ possibleKeys: result[0].possible_keys?.split(','),
401
+ key: result[0].key,
402
+ rows: result[0].rows,
403
+ filtered: result[0].filtered,
404
+ extra: result[0].Extra,
405
+ };
406
+ }
407
+ return null;
408
+ } catch (error) {
409
+ this.logger.error(\`Failed to explain query: \${error}\`);
410
+ return null;
411
+ }
412
+ }
413
+ ` : ''}
414
+ /**
415
+ * Suggest indexes based on query patterns
416
+ */
417
+ suggestIndexes(): IndexSuggestion[] {
418
+ const suggestions: IndexSuggestion[] = [];
419
+ const tableColumns: Map<string, Set<string>> = new Map();
420
+
421
+ // Analyze WHERE and JOIN clauses
422
+ this.queryMetrics.forEach((metrics, normalizedQuery) => {
423
+ const avgDuration = metrics.reduce((a, m) => a + m.duration, 0) / metrics.length;
424
+
425
+ if (avgDuration > this.slowQueryThreshold) {
426
+ // Extract table and column from WHERE clauses
427
+ const whereMatches = normalizedQuery.matchAll(/FROM\\s+(\\w+).*?WHERE.*?(\\w+)\\s*=/gi);
428
+ for (const match of whereMatches) {
429
+ const table = match[1];
430
+ const column = match[2];
431
+
432
+ if (!tableColumns.has(table)) {
433
+ tableColumns.set(table, new Set());
434
+ }
435
+ tableColumns.get(table)!.add(column);
436
+ }
437
+
438
+ // Extract JOIN conditions
439
+ const joinMatches = normalizedQuery.matchAll(/JOIN\\s+(\\w+).*?ON.*?(\\w+)\\s*=/gi);
440
+ for (const match of joinMatches) {
441
+ const table = match[1];
442
+ const column = match[2];
443
+
444
+ if (!tableColumns.has(table)) {
445
+ tableColumns.set(table, new Set());
446
+ }
447
+ tableColumns.get(table)!.add(column);
448
+ }
449
+ }
450
+ });
451
+
452
+ // Generate index suggestions
453
+ tableColumns.forEach((columns, table) => {
454
+ if (columns.size > 0) {
455
+ suggestions.push({
456
+ table,
457
+ columns: Array.from(columns),
458
+ reason: \`Frequently used in WHERE/JOIN conditions on slow queries\`,
459
+ impact: columns.size > 2 ? 'high' : columns.size > 1 ? 'medium' : 'low',
460
+ });
461
+ }
462
+ });
463
+
464
+ return suggestions.sort((a, b) => {
465
+ const impactOrder = { high: 0, medium: 1, low: 2 };
466
+ return impactOrder[a.impact] - impactOrder[b.impact];
467
+ });
468
+ }
469
+
470
+ /**
471
+ * Get query statistics
472
+ */
473
+ getStatistics(): {
474
+ totalQueries: number;
475
+ uniqueQueries: number;
476
+ slowQueries: number;
477
+ avgDuration: number;
478
+ } {
479
+ let totalQueries = 0;
480
+ let slowQueries = 0;
481
+ let totalDuration = 0;
482
+
483
+ this.queryMetrics.forEach((metrics) => {
484
+ totalQueries += metrics.length;
485
+ metrics.forEach((m) => {
486
+ totalDuration += m.duration;
487
+ if (m.duration > this.slowQueryThreshold) {
488
+ slowQueries++;
489
+ }
490
+ });
491
+ });
492
+
493
+ return {
494
+ totalQueries,
495
+ uniqueQueries: this.queryMetrics.size,
496
+ slowQueries,
497
+ avgDuration: totalQueries > 0 ? Math.round(totalDuration / totalQueries) : 0,
498
+ };
499
+ }
500
+
501
+ /**
502
+ * Clear collected metrics
503
+ */
504
+ clearMetrics(): void {
505
+ this.queryMetrics.clear();
506
+ }
507
+ }
508
+ `;
509
+ fs.writeFileSync(path.join(baseDir, 'query-analyzer.ts'), queryAnalyzerContent);
510
+ // Query interceptor for automatic tracking
511
+ const queryInterceptorContent = `import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
512
+ import { Observable } from 'rxjs';
513
+ import { tap } from 'rxjs/operators';
514
+ import { QueryAnalyzerService } from './query-analyzer';
515
+
516
+ /**
517
+ * Interceptor to automatically track query execution times
518
+ */
519
+ @Injectable()
520
+ export class QueryTrackingInterceptor implements NestInterceptor {
521
+ constructor(private readonly queryAnalyzer: QueryAnalyzerService) {}
522
+
523
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
524
+ const startTime = Date.now();
525
+
526
+ return next.handle().pipe(
527
+ tap({
528
+ next: () => {
529
+ const duration = Date.now() - startTime;
530
+ const request = context.switchToHttp().getRequest();
531
+ const query = \`\${request.method} \${request.url}\`;
532
+
533
+ // Track as a pseudo-query for endpoint performance
534
+ this.queryAnalyzer.recordQuery(query, duration);
535
+ },
536
+ error: () => {
537
+ const duration = Date.now() - startTime;
538
+ const request = context.switchToHttp().getRequest();
539
+ const query = \`\${request.method} \${request.url} [ERROR]\`;
540
+
541
+ this.queryAnalyzer.recordQuery(query, duration);
542
+ },
543
+ }),
544
+ );
545
+ }
546
+ }
547
+ `;
548
+ fs.writeFileSync(path.join(baseDir, 'query-tracking.interceptor.ts'), queryInterceptorContent);
549
+ }
550
+ // Connection pool optimizer
551
+ const connectionPoolContent = `import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
552
+
553
+ interface PoolConfig {
554
+ min: number;
555
+ max: number;
556
+ acquireTimeoutMs: number;
557
+ idleTimeoutMs: number;
558
+ reapIntervalMs: number;
559
+ }
560
+
561
+ interface PoolMetrics {
562
+ totalConnections: number;
563
+ activeConnections: number;
564
+ idleConnections: number;
565
+ waitingRequests: number;
566
+ avgAcquireTime: number;
567
+ }
568
+
569
+ /**
570
+ * Connection pool optimizer with adaptive sizing
571
+ */
572
+ @Injectable()
573
+ export class ConnectionPoolOptimizer implements OnModuleInit {
574
+ private readonly logger = new Logger(ConnectionPoolOptimizer.name);
575
+ private metrics: PoolMetrics = {
576
+ totalConnections: 0,
577
+ activeConnections: 0,
578
+ idleConnections: 0,
579
+ waitingRequests: 0,
580
+ avgAcquireTime: 0,
581
+ };
582
+ private acquireTimes: number[] = [];
583
+ private readonly maxAcquireTimeSamples = 100;
584
+
585
+ async onModuleInit(): Promise<void> {
586
+ this.logger.log('Connection pool optimizer initialized');
587
+ }
588
+
589
+ /**
590
+ * Get optimal pool configuration based on workload
591
+ */
592
+ getOptimalConfig(currentConfig: PoolConfig, cpuCount: number = 4): PoolConfig {
593
+ // Formula: connections = (core_count * 2) + effective_spindle_count
594
+ // For SSDs, effective_spindle_count is typically 1
595
+ const optimalMax = Math.min(cpuCount * 2 + 1, 20);
596
+ const optimalMin = Math.max(Math.floor(optimalMax / 4), 2);
597
+
598
+ return {
599
+ min: optimalMin,
600
+ max: optimalMax,
601
+ acquireTimeoutMs: Math.max(currentConfig.acquireTimeoutMs, 10000),
602
+ idleTimeoutMs: currentConfig.idleTimeoutMs || 30000,
603
+ reapIntervalMs: currentConfig.reapIntervalMs || 1000,
604
+ };
605
+ }
606
+
607
+ /**
608
+ * Record connection acquire time
609
+ */
610
+ recordAcquireTime(timeMs: number): void {
611
+ this.acquireTimes.push(timeMs);
612
+
613
+ if (this.acquireTimes.length > this.maxAcquireTimeSamples) {
614
+ this.acquireTimes.shift();
615
+ }
616
+
617
+ this.metrics.avgAcquireTime =
618
+ this.acquireTimes.reduce((a, b) => a + b, 0) / this.acquireTimes.length;
619
+
620
+ // Warn if acquire time is high
621
+ if (timeMs > 1000) {
622
+ this.logger.warn(\`High connection acquire time: \${timeMs}ms. Consider increasing pool size.\`);
623
+ }
624
+ }
625
+
626
+ /**
627
+ * Update pool metrics
628
+ */
629
+ updateMetrics(metrics: Partial<PoolMetrics>): void {
630
+ this.metrics = { ...this.metrics, ...metrics };
631
+
632
+ // Log warnings based on metrics
633
+ if (this.metrics.waitingRequests > 0) {
634
+ this.logger.warn(\`\${this.metrics.waitingRequests} requests waiting for connections\`);
635
+ }
636
+
637
+ if (this.metrics.activeConnections === this.metrics.totalConnections) {
638
+ this.logger.warn('Connection pool exhausted - all connections in use');
639
+ }
640
+ }
641
+
642
+ /**
643
+ * Get current metrics
644
+ */
645
+ getMetrics(): PoolMetrics {
646
+ return { ...this.metrics };
647
+ }
648
+
649
+ /**
650
+ * Should pool be scaled up?
651
+ */
652
+ shouldScaleUp(currentMax: number): boolean {
653
+ const utilizationRatio = this.metrics.activeConnections / this.metrics.totalConnections;
654
+ return (
655
+ utilizationRatio > 0.8 ||
656
+ this.metrics.waitingRequests > 0 ||
657
+ this.metrics.avgAcquireTime > 500
658
+ );
659
+ }
660
+
661
+ /**
662
+ * Should pool be scaled down?
663
+ */
664
+ shouldScaleDown(currentMin: number): boolean {
665
+ const utilizationRatio = this.metrics.activeConnections / this.metrics.totalConnections;
666
+ return (
667
+ utilizationRatio < 0.2 &&
668
+ this.metrics.waitingRequests === 0 &&
669
+ this.metrics.idleConnections > currentMin
670
+ );
671
+ }
672
+ }
673
+ `;
674
+ fs.writeFileSync(path.join(baseDir, 'connection-pool-optimizer.ts'), connectionPoolContent);
675
+ console.log(chalk_1.default.green(` ✓ Created connection pool optimizer`));
676
+ console.log(chalk_1.default.bold.green(`\n✅ Database optimization setup complete for ${pascalName}`));
677
+ console.log(chalk_1.default.cyan(`Generated files in: ${baseDir}`));
678
+ if (includeDataLoader) {
679
+ console.log(chalk_1.default.gray(' - data-loader.ts (DataLoader factory and decorators)'));
680
+ }
681
+ if (includeQueryAnalyzer) {
682
+ console.log(chalk_1.default.gray(' - query-analyzer.ts (Query performance analysis)'));
683
+ console.log(chalk_1.default.gray(' - query-tracking.interceptor.ts (Automatic query tracking)'));
684
+ }
685
+ console.log(chalk_1.default.gray(' - connection-pool-optimizer.ts (Adaptive pool sizing)'));
686
+ }
687
+ //# sourceMappingURL=db-optimization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-optimization.js","sourceRoot":"","sources":["../../src/commands/db-optimization.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface DependencyGraphOptions {
2
+ output?: string;
3
+ format?: 'text' | 'json' | 'mermaid' | 'dot';
4
+ showCircular?: boolean;
5
+ }
6
+ export declare function analyzeDependencies(basePath: string, options?: DependencyGraphOptions): Promise<void>;