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.
- package/README.md +247 -408
- package/ddd.schema.json +111 -0
- package/dist/commands/aggregate-validator.d.ts +9 -0
- package/dist/commands/aggregate-validator.js +953 -0
- package/dist/commands/aggregate-validator.js.map +1 -0
- package/dist/commands/ai-assist.d.ts +8 -0
- package/dist/commands/ai-assist.js +337 -0
- package/dist/commands/ai-assist.js.map +1 -0
- package/dist/commands/api-contracts.d.ts +9 -0
- package/dist/commands/api-contracts.js +1368 -0
- package/dist/commands/api-contracts.js.map +1 -0
- package/dist/commands/api-docs.d.ts +8 -0
- package/dist/commands/api-docs.js +408 -0
- package/dist/commands/api-docs.js.map +1 -0
- package/dist/commands/api-versioning.d.ts +11 -0
- package/dist/commands/api-versioning.js +643 -0
- package/dist/commands/api-versioning.js.map +1 -0
- package/dist/commands/audit-logging.d.ts +9 -0
- package/dist/commands/audit-logging.js +1129 -0
- package/dist/commands/audit-logging.js.map +1 -0
- package/dist/commands/batch-generate.d.ts +10 -0
- package/dist/commands/batch-generate.js +405 -0
- package/dist/commands/batch-generate.js.map +1 -0
- package/dist/commands/caching-strategies.d.ts +9 -0
- package/dist/commands/caching-strategies.js +874 -0
- package/dist/commands/caching-strategies.js.map +1 -0
- package/dist/commands/code-analyzer.d.ts +42 -0
- package/dist/commands/code-analyzer.js +474 -0
- package/dist/commands/code-analyzer.js.map +1 -0
- package/dist/commands/database-seeding.d.ts +6 -0
- package/dist/commands/database-seeding.js +621 -0
- package/dist/commands/database-seeding.js.map +1 -0
- package/dist/commands/db-optimization.d.ts +7 -0
- package/dist/commands/db-optimization.js +687 -0
- package/dist/commands/db-optimization.js.map +1 -0
- package/dist/commands/dependency-graph.d.ts +6 -0
- package/dist/commands/dependency-graph.js +329 -0
- package/dist/commands/dependency-graph.js.map +1 -0
- package/dist/commands/doctor-enhanced.d.ts +22 -0
- package/dist/commands/doctor-enhanced.js +543 -0
- package/dist/commands/doctor-enhanced.js.map +1 -0
- package/dist/commands/doctor.d.ts +4 -0
- package/dist/commands/doctor.js +151 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/env-manager.d.ts +6 -0
- package/dist/commands/env-manager.js +419 -0
- package/dist/commands/env-manager.js.map +1 -0
- package/dist/commands/event-sourcing-full.d.ts +10 -0
- package/dist/commands/event-sourcing-full.js +1107 -0
- package/dist/commands/event-sourcing-full.js.map +1 -0
- package/dist/commands/feature-flags.d.ts +9 -0
- package/dist/commands/feature-flags.js +824 -0
- package/dist/commands/feature-flags.js.map +1 -0
- package/dist/commands/filter-dsl.d.ts +10 -0
- package/dist/commands/filter-dsl.js +1407 -0
- package/dist/commands/filter-dsl.js.map +1 -0
- package/dist/commands/generate-all.js +485 -32
- package/dist/commands/generate-all.js.map +1 -1
- package/dist/commands/generate-deployment.d.ts +8 -0
- package/dist/commands/generate-deployment.js +746 -0
- package/dist/commands/generate-deployment.js.map +1 -0
- package/dist/commands/generate-domain-service.d.ts +14 -0
- package/dist/commands/generate-domain-service.js +796 -0
- package/dist/commands/generate-domain-service.js.map +1 -0
- package/dist/commands/generate-entity.js +82 -24
- package/dist/commands/generate-entity.js.map +1 -1
- package/dist/commands/generate-from-schema.d.ts +56 -0
- package/dist/commands/generate-from-schema.js +222 -0
- package/dist/commands/generate-from-schema.js.map +1 -0
- package/dist/commands/generate-orchestrator.d.ts +14 -0
- package/dist/commands/generate-orchestrator.js +887 -0
- package/dist/commands/generate-orchestrator.js.map +1 -0
- package/dist/commands/generate-repository.d.ts +14 -0
- package/dist/commands/generate-repository.js +1019 -0
- package/dist/commands/generate-repository.js.map +1 -0
- package/dist/commands/generate-shared.d.ts +4 -0
- package/dist/commands/generate-shared.js +388 -0
- package/dist/commands/generate-shared.js.map +1 -0
- package/dist/commands/generate-value-object.d.ts +32 -0
- package/dist/commands/generate-value-object.js +700 -0
- package/dist/commands/generate-value-object.js.map +1 -0
- package/dist/commands/graphql-subscriptions.d.ts +6 -0
- package/dist/commands/graphql-subscriptions.js +607 -0
- package/dist/commands/graphql-subscriptions.js.map +1 -0
- package/dist/commands/graphql-types.d.ts +5 -0
- package/dist/commands/graphql-types.js +423 -0
- package/dist/commands/graphql-types.js.map +1 -0
- package/dist/commands/health-probes-advanced.d.ts +6 -0
- package/dist/commands/health-probes-advanced.js +655 -0
- package/dist/commands/health-probes-advanced.js.map +1 -0
- package/dist/commands/i18n-setup.d.ts +10 -0
- package/dist/commands/i18n-setup.js +677 -0
- package/dist/commands/i18n-setup.js.map +1 -0
- package/dist/commands/init-config.d.ts +6 -0
- package/dist/commands/init-config.js +370 -0
- package/dist/commands/init-config.js.map +1 -0
- package/dist/commands/init-project.js +56 -6
- package/dist/commands/init-project.js.map +1 -1
- package/dist/commands/interactive-scaffold.d.ts +5 -0
- package/dist/commands/interactive-scaffold.js +271 -0
- package/dist/commands/interactive-scaffold.js.map +1 -0
- package/dist/commands/metrics-prometheus.d.ts +6 -0
- package/dist/commands/metrics-prometheus.js +681 -0
- package/dist/commands/metrics-prometheus.js.map +1 -0
- package/dist/commands/migration-engine.d.ts +6 -0
- package/dist/commands/migration-engine.js +446 -0
- package/dist/commands/migration-engine.js.map +1 -0
- package/dist/commands/migration.d.ts +12 -0
- package/dist/commands/migration.js +484 -0
- package/dist/commands/migration.js.map +1 -0
- package/dist/commands/monorepo.d.ts +8 -0
- package/dist/commands/monorepo.js +483 -0
- package/dist/commands/monorepo.js.map +1 -0
- package/dist/commands/multi-database.d.ts +5 -0
- package/dist/commands/multi-database.js +439 -0
- package/dist/commands/multi-database.js.map +1 -0
- package/dist/commands/observability-tracing.d.ts +10 -0
- package/dist/commands/observability-tracing.js +740 -0
- package/dist/commands/observability-tracing.js.map +1 -0
- package/dist/commands/openapi-export.d.ts +8 -0
- package/dist/commands/openapi-export.js +359 -0
- package/dist/commands/openapi-export.js.map +1 -0
- package/dist/commands/perf-analyzer.d.ts +8 -0
- package/dist/commands/perf-analyzer.js +423 -0
- package/dist/commands/perf-analyzer.js.map +1 -0
- package/dist/commands/rate-limiting.d.ts +10 -0
- package/dist/commands/rate-limiting.js +953 -0
- package/dist/commands/rate-limiting.js.map +1 -0
- package/dist/commands/recipe-plugin.d.ts +56 -0
- package/dist/commands/recipe-plugin.js +315 -0
- package/dist/commands/recipe-plugin.js.map +1 -0
- package/dist/commands/recipe.d.ts +6 -0
- package/dist/commands/recipe.js +3941 -0
- package/dist/commands/recipe.js.map +1 -0
- package/dist/commands/recipes/elasticsearch.recipe.d.ts +1 -0
- package/dist/commands/recipes/elasticsearch.recipe.js +761 -0
- package/dist/commands/recipes/elasticsearch.recipe.js.map +1 -0
- package/dist/commands/recipes/event-sourcing.recipe.d.ts +1 -0
- package/dist/commands/recipes/event-sourcing.recipe.js +889 -0
- package/dist/commands/recipes/event-sourcing.recipe.js.map +1 -0
- package/dist/commands/recipes/index.d.ts +7 -0
- package/dist/commands/recipes/index.js +24 -0
- package/dist/commands/recipes/index.js.map +1 -0
- package/dist/commands/recipes/message-queue.recipe.d.ts +1 -0
- package/dist/commands/recipes/message-queue.recipe.js +706 -0
- package/dist/commands/recipes/message-queue.recipe.js.map +1 -0
- package/dist/commands/recipes/middleware.recipe.d.ts +1 -0
- package/dist/commands/recipes/middleware.recipe.js +383 -0
- package/dist/commands/recipes/middleware.recipe.js.map +1 -0
- package/dist/commands/recipes/multi-tenancy.recipe.d.ts +1 -0
- package/dist/commands/recipes/multi-tenancy.recipe.js +520 -0
- package/dist/commands/recipes/multi-tenancy.recipe.js.map +1 -0
- package/dist/commands/recipes/oauth2.recipe.d.ts +1 -0
- package/dist/commands/recipes/oauth2.recipe.js +472 -0
- package/dist/commands/recipes/oauth2.recipe.js.map +1 -0
- package/dist/commands/recipes/websocket.recipe.d.ts +1 -0
- package/dist/commands/recipes/websocket.recipe.js +453 -0
- package/dist/commands/recipes/websocket.recipe.js.map +1 -0
- package/dist/commands/resilience-patterns.d.ts +13 -0
- package/dist/commands/resilience-patterns.js +1029 -0
- package/dist/commands/resilience-patterns.js.map +1 -0
- package/dist/commands/security-patterns.d.ts +11 -0
- package/dist/commands/security-patterns.js +2233 -0
- package/dist/commands/security-patterns.js.map +1 -0
- package/dist/commands/template-debug.d.ts +27 -0
- package/dist/commands/template-debug.js +388 -0
- package/dist/commands/template-debug.js.map +1 -0
- package/dist/commands/test-factory-full.d.ts +9 -0
- package/dist/commands/test-factory-full.js +1570 -0
- package/dist/commands/test-factory-full.js.map +1 -0
- package/dist/commands/test-scaffold.d.ts +7 -0
- package/dist/commands/test-scaffold.js +621 -0
- package/dist/commands/test-scaffold.js.map +1 -0
- package/dist/index.js +1088 -0
- package/dist/index.js.map +1 -1
- package/dist/templates/ai-context/CLAUDE.md.hbs +158 -0
- package/dist/templates/ai-context/conventions.md.hbs +154 -0
- package/dist/templates/command/create-command.hbs +6 -14
- package/dist/templates/command/delete-command.hbs +19 -0
- package/dist/templates/command/update-command.hbs +24 -0
- package/dist/templates/controller/controller.hbs +64 -17
- package/dist/templates/dto/create-dto.hbs +29 -5
- package/dist/templates/dto/filter-dto.hbs +52 -0
- package/dist/templates/dto/filter-query.dto.hbs +148 -0
- package/dist/templates/dto/paginated-response.dto.hbs +29 -0
- package/dist/templates/dto/pagination-query.dto.hbs +30 -0
- package/dist/templates/dto/response-dto.hbs +38 -0
- package/dist/templates/dto/update-dto.hbs +11 -0
- package/dist/templates/entity/entity.hbs +32 -1
- package/dist/templates/event/domain-event.hbs +33 -7
- package/dist/templates/event/event-handler.hbs +40 -0
- package/dist/templates/exception/base-exceptions.hbs +69 -0
- package/dist/templates/exception/entity-not-found.exception.hbs +7 -0
- package/dist/templates/mapper/mapper.hbs +49 -24
- package/dist/templates/module/module.hbs +34 -10
- package/dist/templates/orm-entity/orm-entity.hbs +63 -12
- package/dist/templates/prisma/prisma-mapper.hbs +71 -0
- package/dist/templates/prisma/prisma-repository.hbs +114 -0
- package/dist/templates/prisma/prisma-schema.hbs +20 -0
- package/dist/templates/prisma/prisma-service.hbs +51 -0
- package/dist/templates/query/get-all.query.hbs +50 -0
- package/dist/templates/query/get-by-id.query.hbs +31 -0
- package/dist/templates/repository/repository.hbs +55 -13
- package/dist/templates/resolver/graphql-input.hbs +54 -0
- package/dist/templates/resolver/graphql-type.hbs +58 -0
- package/dist/templates/resolver/pagination-args.hbs +33 -0
- package/dist/templates/resolver/resolver.hbs +62 -0
- package/dist/templates/shared/prisma-query-builder.util.hbs +189 -0
- package/dist/templates/shared/query-builder.util.hbs +218 -0
- package/dist/templates/test/controller.spec.hbs +124 -0
- package/dist/templates/test/repository.spec.hbs +158 -0
- package/dist/templates/test/usecase.spec.hbs +116 -0
- package/dist/templates/usecase/create-usecase.hbs +19 -7
- package/dist/templates/usecase/delete-usecase.hbs +17 -0
- package/dist/templates/usecase/update-usecase.hbs +31 -0
- package/dist/utils/config.utils.d.ts +45 -0
- package/dist/utils/config.utils.js +211 -0
- package/dist/utils/config.utils.js.map +1 -0
- package/dist/utils/error.utils.d.ts +145 -0
- package/dist/utils/error.utils.js +422 -0
- package/dist/utils/error.utils.js.map +1 -0
- package/dist/utils/field.utils.d.ts +54 -0
- package/dist/utils/field.utils.js +389 -0
- package/dist/utils/field.utils.js.map +1 -0
- package/dist/utils/file.utils.d.ts +19 -8
- package/dist/utils/file.utils.js +135 -4
- package/dist/utils/file.utils.js.map +1 -1
- package/dist/utils/idempotency.utils.d.ts +123 -0
- package/dist/utils/idempotency.utils.js +444 -0
- package/dist/utils/idempotency.utils.js.map +1 -0
- package/dist/utils/naming.utils.js +24 -5
- package/dist/utils/naming.utils.js.map +1 -1
- package/dist/utils/performance.utils.d.ts +37 -0
- package/dist/utils/performance.utils.js +158 -0
- package/dist/utils/performance.utils.js.map +1 -0
- package/dist/utils/relation.utils.d.ts +92 -0
- package/dist/utils/relation.utils.js +388 -0
- package/dist/utils/relation.utils.js.map +1 -0
- package/dist/utils/rollback.utils.d.ts +49 -0
- package/dist/utils/rollback.utils.js +306 -0
- package/dist/utils/rollback.utils.js.map +1 -0
- package/dist/utils/schema.utils.d.ts +123 -0
- package/dist/utils/schema.utils.js +419 -0
- package/dist/utils/schema.utils.js.map +1 -0
- package/dist/utils/security.utils.d.ts +57 -0
- package/dist/utils/security.utils.js +315 -0
- package/dist/utils/security.utils.js.map +1 -0
- package/dist/utils/template-engine.utils.d.ts +80 -0
- package/dist/utils/template-engine.utils.js +463 -0
- package/dist/utils/template-engine.utils.js.map +1 -0
- package/dist/utils/validation-registry.utils.d.ts +160 -0
- package/dist/utils/validation-registry.utils.js +526 -0
- package/dist/utils/validation-registry.utils.js.map +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,439 @@
|
|
|
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.setupMultiDatabase = setupMultiDatabase;
|
|
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 setupMultiDatabase(basePath, options = {}) {
|
|
44
|
+
console.log(chalk_1.default.bold.blue('\n🗄️ Setting up Multi-Database Support\n'));
|
|
45
|
+
const sharedPath = path.join(basePath, 'src/shared');
|
|
46
|
+
const dbPath = path.join(sharedPath, 'database');
|
|
47
|
+
await (0, file_utils_1.ensureDir)(dbPath);
|
|
48
|
+
await (0, file_utils_1.ensureDir)(path.join(dbPath, 'connections'));
|
|
49
|
+
await (0, file_utils_1.ensureDir)(path.join(dbPath, 'repositories'));
|
|
50
|
+
// Database configuration types
|
|
51
|
+
const typesContent = `export interface DatabaseConnectionConfig {
|
|
52
|
+
name: string;
|
|
53
|
+
type: 'postgres' | 'mysql' | 'mongodb' | 'sqlite';
|
|
54
|
+
host?: string;
|
|
55
|
+
port?: number;
|
|
56
|
+
username?: string;
|
|
57
|
+
password?: string;
|
|
58
|
+
database?: string;
|
|
59
|
+
url?: string;
|
|
60
|
+
synchronize?: boolean;
|
|
61
|
+
logging?: boolean;
|
|
62
|
+
entities?: string[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface MultiDatabaseConfig {
|
|
66
|
+
default: string;
|
|
67
|
+
connections: Record<string, DatabaseConnectionConfig>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type ConnectionName = string;
|
|
71
|
+
|
|
72
|
+
export interface DatabaseHealthStatus {
|
|
73
|
+
name: string;
|
|
74
|
+
connected: boolean;
|
|
75
|
+
latency?: number;
|
|
76
|
+
error?: string;
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
await (0, file_utils_1.writeFile)(path.join(dbPath, 'database.types.ts'), typesContent);
|
|
80
|
+
console.log(chalk_1.default.green(' ✓ Database types'));
|
|
81
|
+
// Connection manager
|
|
82
|
+
const connectionManagerContent = `import { Injectable, Logger, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
|
83
|
+
import { DataSource, DataSourceOptions } from 'typeorm';
|
|
84
|
+
import { DatabaseConnectionConfig, DatabaseHealthStatus } from './database.types';
|
|
85
|
+
|
|
86
|
+
@Injectable()
|
|
87
|
+
export class ConnectionManager implements OnModuleInit, OnModuleDestroy {
|
|
88
|
+
private readonly logger = new Logger(ConnectionManager.name);
|
|
89
|
+
private connections: Map<string, DataSource> = new Map();
|
|
90
|
+
private defaultConnection: string = 'default';
|
|
91
|
+
|
|
92
|
+
async onModuleInit() {
|
|
93
|
+
// Connections are lazy-loaded
|
|
94
|
+
this.logger.log('ConnectionManager initialized');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async onModuleDestroy() {
|
|
98
|
+
await this.closeAll();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get or create a connection
|
|
103
|
+
*/
|
|
104
|
+
async getConnection(name: string = 'default'): Promise<DataSource> {
|
|
105
|
+
if (this.connections.has(name)) {
|
|
106
|
+
const conn = this.connections.get(name)!;
|
|
107
|
+
if (conn.isInitialized) {
|
|
108
|
+
return conn;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
throw new Error(\`Connection "\${name}" not found. Register it first.\`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Register a new connection
|
|
117
|
+
*/
|
|
118
|
+
async registerConnection(config: DatabaseConnectionConfig): Promise<DataSource> {
|
|
119
|
+
if (this.connections.has(config.name)) {
|
|
120
|
+
return this.connections.get(config.name)!;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const options = this.buildDataSourceOptions(config);
|
|
124
|
+
const dataSource = new DataSource(options);
|
|
125
|
+
|
|
126
|
+
await dataSource.initialize();
|
|
127
|
+
this.connections.set(config.name, dataSource);
|
|
128
|
+
|
|
129
|
+
this.logger.log(\`Connected to database: \${config.name} (\${config.type})\`);
|
|
130
|
+
return dataSource;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Close a specific connection
|
|
135
|
+
*/
|
|
136
|
+
async closeConnection(name: string): Promise<void> {
|
|
137
|
+
const conn = this.connections.get(name);
|
|
138
|
+
if (conn?.isInitialized) {
|
|
139
|
+
await conn.destroy();
|
|
140
|
+
this.connections.delete(name);
|
|
141
|
+
this.logger.log(\`Closed connection: \${name}\`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Close all connections
|
|
147
|
+
*/
|
|
148
|
+
async closeAll(): Promise<void> {
|
|
149
|
+
for (const [name, conn] of this.connections) {
|
|
150
|
+
if (conn.isInitialized) {
|
|
151
|
+
await conn.destroy();
|
|
152
|
+
this.logger.log(\`Closed connection: \${name}\`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
this.connections.clear();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Check health of all connections
|
|
160
|
+
*/
|
|
161
|
+
async healthCheck(): Promise<DatabaseHealthStatus[]> {
|
|
162
|
+
const statuses: DatabaseHealthStatus[] = [];
|
|
163
|
+
|
|
164
|
+
for (const [name, conn] of this.connections) {
|
|
165
|
+
const status: DatabaseHealthStatus = { name, connected: false };
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const start = Date.now();
|
|
169
|
+
await conn.query('SELECT 1');
|
|
170
|
+
status.connected = true;
|
|
171
|
+
status.latency = Date.now() - start;
|
|
172
|
+
} catch (error) {
|
|
173
|
+
status.error = (error as Error).message;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
statuses.push(status);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return statuses;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Get list of registered connections
|
|
184
|
+
*/
|
|
185
|
+
getConnectionNames(): string[] {
|
|
186
|
+
return Array.from(this.connections.keys());
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Set default connection
|
|
191
|
+
*/
|
|
192
|
+
setDefaultConnection(name: string): void {
|
|
193
|
+
if (!this.connections.has(name)) {
|
|
194
|
+
throw new Error(\`Connection "\${name}" not found\`);
|
|
195
|
+
}
|
|
196
|
+
this.defaultConnection = name;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private buildDataSourceOptions(config: DatabaseConnectionConfig): DataSourceOptions {
|
|
200
|
+
const base: Partial<DataSourceOptions> = {
|
|
201
|
+
synchronize: config.synchronize ?? false,
|
|
202
|
+
logging: config.logging ?? false,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
switch (config.type) {
|
|
206
|
+
case 'postgres':
|
|
207
|
+
return {
|
|
208
|
+
...base,
|
|
209
|
+
type: 'postgres',
|
|
210
|
+
host: config.host || 'localhost',
|
|
211
|
+
port: config.port || 5432,
|
|
212
|
+
username: config.username,
|
|
213
|
+
password: config.password,
|
|
214
|
+
database: config.database,
|
|
215
|
+
entities: config.entities || [],
|
|
216
|
+
} as DataSourceOptions;
|
|
217
|
+
|
|
218
|
+
case 'mysql':
|
|
219
|
+
return {
|
|
220
|
+
...base,
|
|
221
|
+
type: 'mysql',
|
|
222
|
+
host: config.host || 'localhost',
|
|
223
|
+
port: config.port || 3306,
|
|
224
|
+
username: config.username,
|
|
225
|
+
password: config.password,
|
|
226
|
+
database: config.database,
|
|
227
|
+
entities: config.entities || [],
|
|
228
|
+
} as DataSourceOptions;
|
|
229
|
+
|
|
230
|
+
case 'mongodb':
|
|
231
|
+
return {
|
|
232
|
+
...base,
|
|
233
|
+
type: 'mongodb',
|
|
234
|
+
url: config.url || \`mongodb://\${config.host}:\${config.port}/\${config.database}\`,
|
|
235
|
+
useNewUrlParser: true,
|
|
236
|
+
useUnifiedTopology: true,
|
|
237
|
+
entities: config.entities || [],
|
|
238
|
+
} as DataSourceOptions;
|
|
239
|
+
|
|
240
|
+
case 'sqlite':
|
|
241
|
+
return {
|
|
242
|
+
...base,
|
|
243
|
+
type: 'sqlite',
|
|
244
|
+
database: config.database || ':memory:',
|
|
245
|
+
entities: config.entities || [],
|
|
246
|
+
} as DataSourceOptions;
|
|
247
|
+
|
|
248
|
+
default:
|
|
249
|
+
throw new Error(\`Unsupported database type: \${config.type}\`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
`;
|
|
254
|
+
await (0, file_utils_1.writeFile)(path.join(dbPath, 'connections/connection-manager.ts'), connectionManagerContent);
|
|
255
|
+
console.log(chalk_1.default.green(' ✓ Connection manager'));
|
|
256
|
+
// Multi-database repository base
|
|
257
|
+
const multiRepoContent = `import { DataSource, Repository, EntityTarget, ObjectLiteral } from 'typeorm';
|
|
258
|
+
import { ConnectionManager } from '../connections/connection-manager';
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Base repository that can work with multiple database connections
|
|
262
|
+
*/
|
|
263
|
+
export abstract class MultiDatabaseRepository<T extends ObjectLiteral> {
|
|
264
|
+
protected connectionManager: ConnectionManager;
|
|
265
|
+
protected connectionName: string;
|
|
266
|
+
protected entity: EntityTarget<T>;
|
|
267
|
+
|
|
268
|
+
constructor(
|
|
269
|
+
connectionManager: ConnectionManager,
|
|
270
|
+
entity: EntityTarget<T>,
|
|
271
|
+
connectionName: string = 'default'
|
|
272
|
+
) {
|
|
273
|
+
this.connectionManager = connectionManager;
|
|
274
|
+
this.entity = entity;
|
|
275
|
+
this.connectionName = connectionName;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Get TypeORM repository for the entity
|
|
280
|
+
*/
|
|
281
|
+
protected async getRepository(): Promise<Repository<T>> {
|
|
282
|
+
const connection = await this.connectionManager.getConnection(this.connectionName);
|
|
283
|
+
return connection.getRepository(this.entity);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get raw data source
|
|
288
|
+
*/
|
|
289
|
+
protected async getDataSource(): Promise<DataSource> {
|
|
290
|
+
return this.connectionManager.getConnection(this.connectionName);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Switch to a different connection
|
|
295
|
+
*/
|
|
296
|
+
useConnection(connectionName: string): this {
|
|
297
|
+
this.connectionName = connectionName;
|
|
298
|
+
return this;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Execute within a transaction
|
|
303
|
+
*/
|
|
304
|
+
async withTransaction<R>(work: (repo: Repository<T>) => Promise<R>): Promise<R> {
|
|
305
|
+
const dataSource = await this.getDataSource();
|
|
306
|
+
return dataSource.transaction(async (manager) => {
|
|
307
|
+
const repo = manager.getRepository(this.entity);
|
|
308
|
+
return work(repo);
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Standard CRUD operations
|
|
313
|
+
async findAll(): Promise<T[]> {
|
|
314
|
+
const repo = await this.getRepository();
|
|
315
|
+
return repo.find();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async findById(id: string | number): Promise<T | null> {
|
|
319
|
+
const repo = await this.getRepository();
|
|
320
|
+
return repo.findOne({ where: { id } as any });
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async create(data: Partial<T>): Promise<T> {
|
|
324
|
+
const repo = await this.getRepository();
|
|
325
|
+
const entity = repo.create(data as any);
|
|
326
|
+
return repo.save(entity);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async update(id: string | number, data: Partial<T>): Promise<T | null> {
|
|
330
|
+
const repo = await this.getRepository();
|
|
331
|
+
await repo.update(id, data as any);
|
|
332
|
+
return this.findById(id);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async delete(id: string | number): Promise<void> {
|
|
336
|
+
const repo = await this.getRepository();
|
|
337
|
+
await repo.delete(id);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
`;
|
|
341
|
+
await (0, file_utils_1.writeFile)(path.join(dbPath, 'repositories/multi-database.repository.ts'), multiRepoContent);
|
|
342
|
+
console.log(chalk_1.default.green(' ✓ Multi-database repository base'));
|
|
343
|
+
// Database decorator
|
|
344
|
+
const decoratorContent = `import { Inject } from '@nestjs/common';
|
|
345
|
+
|
|
346
|
+
export const CONNECTION_NAME = 'DATABASE_CONNECTION_NAME';
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Decorator to specify which database connection to use
|
|
350
|
+
*/
|
|
351
|
+
export function UseConnection(connectionName: string): ClassDecorator {
|
|
352
|
+
return (target) => {
|
|
353
|
+
Reflect.defineMetadata(CONNECTION_NAME, connectionName, target);
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Decorator to inject a specific database connection
|
|
359
|
+
*/
|
|
360
|
+
export function InjectConnection(connectionName: string = 'default') {
|
|
361
|
+
return Inject(\`DATABASE_CONNECTION_\${connectionName.toUpperCase()}\`);
|
|
362
|
+
}
|
|
363
|
+
`;
|
|
364
|
+
await (0, file_utils_1.writeFile)(path.join(dbPath, 'decorators.ts'), decoratorContent);
|
|
365
|
+
console.log(chalk_1.default.green(' ✓ Database decorators'));
|
|
366
|
+
// Database module
|
|
367
|
+
const moduleContent = `import { Module, Global, DynamicModule } from '@nestjs/common';
|
|
368
|
+
import { ConnectionManager } from './connections/connection-manager';
|
|
369
|
+
import { MultiDatabaseConfig, DatabaseConnectionConfig } from './database.types';
|
|
370
|
+
|
|
371
|
+
@Global()
|
|
372
|
+
@Module({})
|
|
373
|
+
export class MultiDatabaseModule {
|
|
374
|
+
static forRoot(config: MultiDatabaseConfig): DynamicModule {
|
|
375
|
+
const connectionProviders = Object.entries(config.connections).map(([name, connConfig]) => ({
|
|
376
|
+
provide: \`DATABASE_CONNECTION_\${name.toUpperCase()}\`,
|
|
377
|
+
useFactory: async (manager: ConnectionManager) => {
|
|
378
|
+
return manager.registerConnection({ ...connConfig, name });
|
|
379
|
+
},
|
|
380
|
+
inject: [ConnectionManager],
|
|
381
|
+
}));
|
|
382
|
+
|
|
383
|
+
return {
|
|
384
|
+
module: MultiDatabaseModule,
|
|
385
|
+
providers: [
|
|
386
|
+
ConnectionManager,
|
|
387
|
+
...connectionProviders,
|
|
388
|
+
{
|
|
389
|
+
provide: 'MULTI_DATABASE_CONFIG',
|
|
390
|
+
useValue: config,
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
exports: [ConnectionManager, ...connectionProviders.map(p => p.provide)],
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
static forFeature(connectionName: string = 'default'): DynamicModule {
|
|
398
|
+
return {
|
|
399
|
+
module: MultiDatabaseModule,
|
|
400
|
+
providers: [
|
|
401
|
+
{
|
|
402
|
+
provide: 'CURRENT_CONNECTION',
|
|
403
|
+
useFactory: (manager: ConnectionManager) => manager.getConnection(connectionName),
|
|
404
|
+
inject: [ConnectionManager],
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
exports: ['CURRENT_CONNECTION'],
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
`;
|
|
412
|
+
await (0, file_utils_1.writeFile)(path.join(dbPath, 'multi-database.module.ts'), moduleContent);
|
|
413
|
+
console.log(chalk_1.default.green(' ✓ Multi-database module'));
|
|
414
|
+
// Index exports
|
|
415
|
+
await (0, file_utils_1.writeFile)(path.join(dbPath, 'index.ts'), `export * from './database.types';
|
|
416
|
+
export * from './connections/connection-manager';
|
|
417
|
+
export * from './repositories/multi-database.repository';
|
|
418
|
+
export * from './decorators';
|
|
419
|
+
export * from './multi-database.module';
|
|
420
|
+
`);
|
|
421
|
+
await (0, file_utils_1.writeFile)(path.join(dbPath, 'connections/index.ts'), `export * from './connection-manager';
|
|
422
|
+
`);
|
|
423
|
+
await (0, file_utils_1.writeFile)(path.join(dbPath, 'repositories/index.ts'), `export * from './multi-database.repository';
|
|
424
|
+
`);
|
|
425
|
+
console.log(chalk_1.default.green('\n✅ Multi-database support configured!'));
|
|
426
|
+
console.log(chalk_1.default.gray('\nUsage example:'));
|
|
427
|
+
console.log(chalk_1.default.cyan(`
|
|
428
|
+
// In app.module.ts
|
|
429
|
+
MultiDatabaseModule.forRoot({
|
|
430
|
+
default: 'primary',
|
|
431
|
+
connections: {
|
|
432
|
+
primary: { type: 'postgres', host: 'localhost', ... },
|
|
433
|
+
analytics: { type: 'mysql', host: 'analytics-db', ... },
|
|
434
|
+
cache: { type: 'mongodb', url: 'mongodb://...', ... },
|
|
435
|
+
},
|
|
436
|
+
})
|
|
437
|
+
`));
|
|
438
|
+
}
|
|
439
|
+
//# sourceMappingURL=multi-database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-database.js","sourceRoot":"","sources":["../../src/commands/multi-database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distributed Tracing & Observability Generator
|
|
3
|
+
* OpenTelemetry integration for microservices
|
|
4
|
+
*/
|
|
5
|
+
export interface ObservabilityOptions {
|
|
6
|
+
path?: string;
|
|
7
|
+
provider?: 'jaeger' | 'zipkin' | 'datadog' | 'otlp';
|
|
8
|
+
serviceName?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function setupObservability(basePath: string, options?: ObservabilityOptions): Promise<void>;
|