nestjs-ddd-cli 2.2.0 → 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 +26 -3
- 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,655 @@
|
|
|
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.setupHealthProbesAdvanced = setupHealthProbesAdvanced;
|
|
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 setupHealthProbesAdvanced(basePath, options = {}) {
|
|
45
|
+
console.log(chalk_1.default.bold.blue('\n🏥 Setting up Advanced Health Probes\n'));
|
|
46
|
+
const moduleName = options.module || 'shared';
|
|
47
|
+
const pascalName = (0, naming_utils_1.toPascalCase)(moduleName);
|
|
48
|
+
const kebabName = (0, naming_utils_1.toKebabCase)(moduleName);
|
|
49
|
+
const dependencies = options.dependencies || ['database', 'redis', 'external-api'];
|
|
50
|
+
const includeKubernetes = options.includeKubernetes !== false;
|
|
51
|
+
const baseDir = path.join(basePath, 'src', kebabName, 'infrastructure', 'health');
|
|
52
|
+
fs.mkdirSync(baseDir, { recursive: true });
|
|
53
|
+
// Health indicator registry
|
|
54
|
+
const healthRegistryContent = `import { Injectable, Logger } from '@nestjs/common';
|
|
55
|
+
import { HealthIndicator, HealthIndicatorResult, HealthCheckError } from '@nestjs/terminus';
|
|
56
|
+
|
|
57
|
+
export type HealthStatus = 'healthy' | 'degraded' | 'unhealthy';
|
|
58
|
+
|
|
59
|
+
export interface DependencyHealth {
|
|
60
|
+
name: string;
|
|
61
|
+
status: HealthStatus;
|
|
62
|
+
responseTimeMs?: number;
|
|
63
|
+
message?: string;
|
|
64
|
+
lastCheck: Date;
|
|
65
|
+
consecutiveFailures: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface HealthCheckConfig {
|
|
69
|
+
name: string;
|
|
70
|
+
critical: boolean;
|
|
71
|
+
timeout: number;
|
|
72
|
+
interval: number;
|
|
73
|
+
healthyThreshold: number;
|
|
74
|
+
unhealthyThreshold: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Custom health indicator with circuit breaker pattern
|
|
79
|
+
*/
|
|
80
|
+
@Injectable()
|
|
81
|
+
export class DependencyHealthIndicator extends HealthIndicator {
|
|
82
|
+
private readonly logger = new Logger(DependencyHealthIndicator.name);
|
|
83
|
+
private readonly healthStates: Map<string, DependencyHealth> = new Map();
|
|
84
|
+
private readonly configs: Map<string, HealthCheckConfig> = new Map();
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Register a dependency health check
|
|
88
|
+
*/
|
|
89
|
+
registerDependency(config: HealthCheckConfig): void {
|
|
90
|
+
this.configs.set(config.name, config);
|
|
91
|
+
this.healthStates.set(config.name, {
|
|
92
|
+
name: config.name,
|
|
93
|
+
status: 'healthy',
|
|
94
|
+
lastCheck: new Date(),
|
|
95
|
+
consecutiveFailures: 0,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Check a dependency's health
|
|
101
|
+
*/
|
|
102
|
+
async checkDependency(
|
|
103
|
+
name: string,
|
|
104
|
+
checkFn: () => Promise<boolean>,
|
|
105
|
+
): Promise<HealthIndicatorResult> {
|
|
106
|
+
const config = this.configs.get(name);
|
|
107
|
+
const state = this.healthStates.get(name);
|
|
108
|
+
|
|
109
|
+
if (!config || !state) {
|
|
110
|
+
throw new HealthCheckError(
|
|
111
|
+
\`Dependency \${name} not registered\`,
|
|
112
|
+
this.getStatus(name, false),
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const startTime = Date.now();
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
// Add timeout to health check
|
|
120
|
+
const result = await Promise.race([
|
|
121
|
+
checkFn(),
|
|
122
|
+
new Promise<boolean>((_, reject) =>
|
|
123
|
+
setTimeout(() => reject(new Error('Health check timeout')), config.timeout),
|
|
124
|
+
),
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
const responseTime = Date.now() - startTime;
|
|
128
|
+
|
|
129
|
+
if (result) {
|
|
130
|
+
state.consecutiveFailures = 0;
|
|
131
|
+
state.status = 'healthy';
|
|
132
|
+
state.responseTimeMs = responseTime;
|
|
133
|
+
state.message = undefined;
|
|
134
|
+
state.lastCheck = new Date();
|
|
135
|
+
|
|
136
|
+
return this.getStatus(name, true, { responseTimeMs: responseTime });
|
|
137
|
+
} else {
|
|
138
|
+
throw new Error('Health check returned false');
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
state.consecutiveFailures++;
|
|
142
|
+
state.lastCheck = new Date();
|
|
143
|
+
state.message = error instanceof Error ? error.message : 'Unknown error';
|
|
144
|
+
state.responseTimeMs = Date.now() - startTime;
|
|
145
|
+
|
|
146
|
+
// Determine status based on consecutive failures
|
|
147
|
+
if (state.consecutiveFailures >= config.unhealthyThreshold) {
|
|
148
|
+
state.status = 'unhealthy';
|
|
149
|
+
} else if (state.consecutiveFailures >= Math.ceil(config.unhealthyThreshold / 2)) {
|
|
150
|
+
state.status = 'degraded';
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
this.logger.warn(
|
|
154
|
+
\`Health check failed for \${name}: \${state.message} (failures: \${state.consecutiveFailures})\`,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
if (config.critical && state.status === 'unhealthy') {
|
|
158
|
+
throw new HealthCheckError(
|
|
159
|
+
\`Critical dependency \${name} is unhealthy\`,
|
|
160
|
+
this.getStatus(name, false, { error: state.message }),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return this.getStatus(name, state.status !== 'unhealthy', {
|
|
165
|
+
status: state.status,
|
|
166
|
+
error: state.message,
|
|
167
|
+
consecutiveFailures: state.consecutiveFailures,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Get all dependency health states
|
|
174
|
+
*/
|
|
175
|
+
getAllHealthStates(): DependencyHealth[] {
|
|
176
|
+
return Array.from(this.healthStates.values());
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get overall health status
|
|
181
|
+
*/
|
|
182
|
+
getOverallStatus(): HealthStatus {
|
|
183
|
+
const states = this.getAllHealthStates();
|
|
184
|
+
|
|
185
|
+
if (states.some((s) => s.status === 'unhealthy')) {
|
|
186
|
+
return 'unhealthy';
|
|
187
|
+
}
|
|
188
|
+
if (states.some((s) => s.status === 'degraded')) {
|
|
189
|
+
return 'degraded';
|
|
190
|
+
}
|
|
191
|
+
return 'healthy';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Database health indicator
|
|
197
|
+
*/
|
|
198
|
+
@Injectable()
|
|
199
|
+
export class DatabaseHealthIndicator extends HealthIndicator {
|
|
200
|
+
async check(key: string, pingFn: () => Promise<boolean>): Promise<HealthIndicatorResult> {
|
|
201
|
+
try {
|
|
202
|
+
const isHealthy = await pingFn();
|
|
203
|
+
return this.getStatus(key, isHealthy);
|
|
204
|
+
} catch (error) {
|
|
205
|
+
throw new HealthCheckError(
|
|
206
|
+
\`Database \${key} health check failed\`,
|
|
207
|
+
this.getStatus(key, false, { error: error instanceof Error ? error.message : 'Unknown' }),
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Memory health indicator
|
|
215
|
+
*/
|
|
216
|
+
@Injectable()
|
|
217
|
+
export class MemoryHealthIndicator extends HealthIndicator {
|
|
218
|
+
check(
|
|
219
|
+
key: string,
|
|
220
|
+
options: { heapUsedThreshold: number; rssThreshold: number },
|
|
221
|
+
): HealthIndicatorResult {
|
|
222
|
+
const memUsage = process.memoryUsage();
|
|
223
|
+
const heapUsedMB = memUsage.heapUsed / 1024 / 1024;
|
|
224
|
+
const rssMB = memUsage.rss / 1024 / 1024;
|
|
225
|
+
|
|
226
|
+
const isHealthy = heapUsedMB < options.heapUsedThreshold && rssMB < options.rssThreshold;
|
|
227
|
+
|
|
228
|
+
return this.getStatus(key, isHealthy, {
|
|
229
|
+
heapUsedMB: Math.round(heapUsedMB),
|
|
230
|
+
rssMB: Math.round(rssMB),
|
|
231
|
+
heapTotalMB: Math.round(memUsage.heapTotal / 1024 / 1024),
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Disk health indicator
|
|
238
|
+
*/
|
|
239
|
+
@Injectable()
|
|
240
|
+
export class DiskHealthIndicator extends HealthIndicator {
|
|
241
|
+
async check(
|
|
242
|
+
key: string,
|
|
243
|
+
options: { path: string; thresholdPercent: number },
|
|
244
|
+
): Promise<HealthIndicatorResult> {
|
|
245
|
+
// This is a placeholder - in production, use a library like 'diskusage'
|
|
246
|
+
// or call df command
|
|
247
|
+
return this.getStatus(key, true, {
|
|
248
|
+
path: options.path,
|
|
249
|
+
threshold: options.thresholdPercent,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
`;
|
|
254
|
+
fs.writeFileSync(path.join(baseDir, 'health-indicators.ts'), healthRegistryContent);
|
|
255
|
+
// Health controller with Kubernetes probes
|
|
256
|
+
const healthControllerContent = `import { Controller, Get, HttpCode, HttpStatus, Res } from '@nestjs/common';
|
|
257
|
+
import { Response } from 'express';
|
|
258
|
+
import {
|
|
259
|
+
HealthCheck,
|
|
260
|
+
HealthCheckService,
|
|
261
|
+
HealthCheckResult,
|
|
262
|
+
} from '@nestjs/terminus';
|
|
263
|
+
import {
|
|
264
|
+
DependencyHealthIndicator,
|
|
265
|
+
DatabaseHealthIndicator,
|
|
266
|
+
MemoryHealthIndicator,
|
|
267
|
+
HealthStatus,
|
|
268
|
+
} from './health-indicators';
|
|
269
|
+
|
|
270
|
+
interface ProbeResponse {
|
|
271
|
+
status: HealthStatus;
|
|
272
|
+
timestamp: string;
|
|
273
|
+
uptime: number;
|
|
274
|
+
checks?: Record<string, any>;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Health check controller with Kubernetes probe support
|
|
279
|
+
*/
|
|
280
|
+
@Controller('health')
|
|
281
|
+
export class HealthController {
|
|
282
|
+
private startTime: Date;
|
|
283
|
+
private ready: boolean = false;
|
|
284
|
+
|
|
285
|
+
constructor(
|
|
286
|
+
private readonly health: HealthCheckService,
|
|
287
|
+
private readonly dependencyHealth: DependencyHealthIndicator,
|
|
288
|
+
private readonly dbHealth: DatabaseHealthIndicator,
|
|
289
|
+
private readonly memoryHealth: MemoryHealthIndicator,
|
|
290
|
+
) {
|
|
291
|
+
this.startTime = new Date();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Liveness probe - Is the application running?
|
|
296
|
+
* Returns 200 if the process is alive, regardless of dependency health
|
|
297
|
+
*/
|
|
298
|
+
@Get('live')
|
|
299
|
+
@HttpCode(HttpStatus.OK)
|
|
300
|
+
async liveness(@Res() res: Response): Promise<void> {
|
|
301
|
+
const response: ProbeResponse = {
|
|
302
|
+
status: 'healthy',
|
|
303
|
+
timestamp: new Date().toISOString(),
|
|
304
|
+
uptime: this.getUptimeSeconds(),
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
res.status(HttpStatus.OK).json(response);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Readiness probe - Is the application ready to receive traffic?
|
|
312
|
+
* Returns 200 only if all critical dependencies are healthy
|
|
313
|
+
*/
|
|
314
|
+
@Get('ready')
|
|
315
|
+
async readiness(@Res() res: Response): Promise<void> {
|
|
316
|
+
const checks = this.dependencyHealth.getAllHealthStates();
|
|
317
|
+
const overallStatus = this.dependencyHealth.getOverallStatus();
|
|
318
|
+
|
|
319
|
+
const response: ProbeResponse = {
|
|
320
|
+
status: overallStatus,
|
|
321
|
+
timestamp: new Date().toISOString(),
|
|
322
|
+
uptime: this.getUptimeSeconds(),
|
|
323
|
+
checks: checks.reduce((acc, check) => {
|
|
324
|
+
acc[check.name] = {
|
|
325
|
+
status: check.status,
|
|
326
|
+
responseTimeMs: check.responseTimeMs,
|
|
327
|
+
lastCheck: check.lastCheck,
|
|
328
|
+
};
|
|
329
|
+
return acc;
|
|
330
|
+
}, {} as Record<string, any>),
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const httpStatus = overallStatus === 'unhealthy'
|
|
334
|
+
? HttpStatus.SERVICE_UNAVAILABLE
|
|
335
|
+
: HttpStatus.OK;
|
|
336
|
+
|
|
337
|
+
res.status(httpStatus).json(response);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Startup probe - Has the application finished initialization?
|
|
342
|
+
* Kubernetes uses this to know when to start liveness/readiness checks
|
|
343
|
+
*/
|
|
344
|
+
@Get('startup')
|
|
345
|
+
async startup(@Res() res: Response): Promise<void> {
|
|
346
|
+
const response: ProbeResponse = {
|
|
347
|
+
status: this.ready ? 'healthy' : 'unhealthy',
|
|
348
|
+
timestamp: new Date().toISOString(),
|
|
349
|
+
uptime: this.getUptimeSeconds(),
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const httpStatus = this.ready
|
|
353
|
+
? HttpStatus.OK
|
|
354
|
+
: HttpStatus.SERVICE_UNAVAILABLE;
|
|
355
|
+
|
|
356
|
+
res.status(httpStatus).json(response);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Mark application as ready (call after initialization)
|
|
361
|
+
*/
|
|
362
|
+
markReady(): void {
|
|
363
|
+
this.ready = true;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Mark application as not ready (e.g., during graceful shutdown)
|
|
368
|
+
*/
|
|
369
|
+
markNotReady(): void {
|
|
370
|
+
this.ready = false;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Detailed health check with all indicators
|
|
375
|
+
*/
|
|
376
|
+
@Get()
|
|
377
|
+
@HealthCheck()
|
|
378
|
+
async check(): Promise<HealthCheckResult> {
|
|
379
|
+
return this.health.check([
|
|
380
|
+
// Memory check
|
|
381
|
+
() => this.memoryHealth.check('memory', {
|
|
382
|
+
heapUsedThreshold: 500, // MB
|
|
383
|
+
rssThreshold: 1000, // MB
|
|
384
|
+
}),
|
|
385
|
+
// Add more checks here
|
|
386
|
+
]);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Deep health check - checks all dependencies
|
|
391
|
+
*/
|
|
392
|
+
@Get('deep')
|
|
393
|
+
async deepCheck(@Res() res: Response): Promise<void> {
|
|
394
|
+
const startTime = Date.now();
|
|
395
|
+
const checks = this.dependencyHealth.getAllHealthStates();
|
|
396
|
+
const overallStatus = this.dependencyHealth.getOverallStatus();
|
|
397
|
+
|
|
398
|
+
const response = {
|
|
399
|
+
status: overallStatus,
|
|
400
|
+
timestamp: new Date().toISOString(),
|
|
401
|
+
uptime: this.getUptimeSeconds(),
|
|
402
|
+
checkDurationMs: Date.now() - startTime,
|
|
403
|
+
dependencies: checks.map((check) => ({
|
|
404
|
+
name: check.name,
|
|
405
|
+
status: check.status,
|
|
406
|
+
responseTimeMs: check.responseTimeMs,
|
|
407
|
+
message: check.message,
|
|
408
|
+
lastCheck: check.lastCheck,
|
|
409
|
+
consecutiveFailures: check.consecutiveFailures,
|
|
410
|
+
})),
|
|
411
|
+
system: {
|
|
412
|
+
memory: process.memoryUsage(),
|
|
413
|
+
cpu: process.cpuUsage(),
|
|
414
|
+
nodeVersion: process.version,
|
|
415
|
+
pid: process.pid,
|
|
416
|
+
},
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
const httpStatus = overallStatus === 'unhealthy'
|
|
420
|
+
? HttpStatus.SERVICE_UNAVAILABLE
|
|
421
|
+
: HttpStatus.OK;
|
|
422
|
+
|
|
423
|
+
res.status(httpStatus).json(response);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private getUptimeSeconds(): number {
|
|
427
|
+
return Math.floor((Date.now() - this.startTime.getTime()) / 1000);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
`;
|
|
431
|
+
fs.writeFileSync(path.join(baseDir, 'health.controller.ts'), healthControllerContent);
|
|
432
|
+
// Graceful shutdown handler
|
|
433
|
+
const gracefulShutdownContent = `import { Injectable, Logger, OnModuleDestroy, OnApplicationShutdown } from '@nestjs/common';
|
|
434
|
+
import { HealthController } from './health.controller';
|
|
435
|
+
|
|
436
|
+
interface ShutdownHook {
|
|
437
|
+
name: string;
|
|
438
|
+
priority: number;
|
|
439
|
+
handler: () => Promise<void>;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Graceful shutdown manager for Kubernetes
|
|
444
|
+
*/
|
|
445
|
+
@Injectable()
|
|
446
|
+
export class GracefulShutdownService implements OnModuleDestroy, OnApplicationShutdown {
|
|
447
|
+
private readonly logger = new Logger(GracefulShutdownService.name);
|
|
448
|
+
private readonly hooks: ShutdownHook[] = [];
|
|
449
|
+
private isShuttingDown: boolean = false;
|
|
450
|
+
private readonly shutdownTimeout: number;
|
|
451
|
+
private readonly preShutdownWait: number;
|
|
452
|
+
|
|
453
|
+
constructor(private readonly healthController: HealthController) {
|
|
454
|
+
this.shutdownTimeout = parseInt(process.env.SHUTDOWN_TIMEOUT_MS || '30000', 10);
|
|
455
|
+
this.preShutdownWait = parseInt(process.env.PRE_SHUTDOWN_WAIT_MS || '5000', 10);
|
|
456
|
+
|
|
457
|
+
// Handle process signals
|
|
458
|
+
process.on('SIGTERM', () => this.handleSignal('SIGTERM'));
|
|
459
|
+
process.on('SIGINT', () => this.handleSignal('SIGINT'));
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Register a shutdown hook
|
|
464
|
+
*/
|
|
465
|
+
registerHook(name: string, handler: () => Promise<void>, priority: number = 10): void {
|
|
466
|
+
this.hooks.push({ name, handler, priority });
|
|
467
|
+
this.hooks.sort((a, b) => a.priority - b.priority);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Handle shutdown signal
|
|
472
|
+
*/
|
|
473
|
+
private async handleSignal(signal: string): Promise<void> {
|
|
474
|
+
if (this.isShuttingDown) {
|
|
475
|
+
this.logger.warn(\`Already shutting down, ignoring \${signal}\`);
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
this.isShuttingDown = true;
|
|
480
|
+
this.logger.log(\`Received \${signal}, starting graceful shutdown...\`);
|
|
481
|
+
|
|
482
|
+
// Mark as not ready immediately
|
|
483
|
+
this.healthController.markNotReady();
|
|
484
|
+
|
|
485
|
+
// Wait for in-flight requests to complete
|
|
486
|
+
this.logger.log(\`Waiting \${this.preShutdownWait}ms for in-flight requests...\`);
|
|
487
|
+
await this.sleep(this.preShutdownWait);
|
|
488
|
+
|
|
489
|
+
// Run shutdown hooks with timeout
|
|
490
|
+
await this.runHooksWithTimeout();
|
|
491
|
+
|
|
492
|
+
this.logger.log('Graceful shutdown complete');
|
|
493
|
+
process.exit(0);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Run all hooks with overall timeout
|
|
498
|
+
*/
|
|
499
|
+
private async runHooksWithTimeout(): Promise<void> {
|
|
500
|
+
const timeoutPromise = new Promise<void>((_, reject) => {
|
|
501
|
+
setTimeout(() => reject(new Error('Shutdown timeout exceeded')), this.shutdownTimeout);
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
try {
|
|
505
|
+
await Promise.race([this.runHooks(), timeoutPromise]);
|
|
506
|
+
} catch (error) {
|
|
507
|
+
this.logger.error(\`Shutdown error: \${error}\`);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Run all registered hooks
|
|
513
|
+
*/
|
|
514
|
+
private async runHooks(): Promise<void> {
|
|
515
|
+
for (const hook of this.hooks) {
|
|
516
|
+
try {
|
|
517
|
+
this.logger.log(\`Running shutdown hook: \${hook.name}\`);
|
|
518
|
+
await hook.handler();
|
|
519
|
+
this.logger.log(\`Completed shutdown hook: \${hook.name}\`);
|
|
520
|
+
} catch (error) {
|
|
521
|
+
this.logger.error(\`Shutdown hook \${hook.name} failed: \${error}\`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* NestJS lifecycle hook
|
|
528
|
+
*/
|
|
529
|
+
async onModuleDestroy(): Promise<void> {
|
|
530
|
+
this.logger.log('Module destroying...');
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* NestJS lifecycle hook
|
|
535
|
+
*/
|
|
536
|
+
async onApplicationShutdown(signal?: string): Promise<void> {
|
|
537
|
+
this.logger.log(\`Application shutdown: \${signal}\`);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
private sleep(ms: number): Promise<void> {
|
|
541
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
`;
|
|
545
|
+
fs.writeFileSync(path.join(baseDir, 'graceful-shutdown.service.ts'), gracefulShutdownContent);
|
|
546
|
+
// Kubernetes configuration examples
|
|
547
|
+
if (includeKubernetes) {
|
|
548
|
+
const k8sConfigContent = `# Kubernetes Health Probe Configuration
|
|
549
|
+
# Add these to your deployment spec
|
|
550
|
+
|
|
551
|
+
# Example deployment.yaml probes configuration:
|
|
552
|
+
#
|
|
553
|
+
# spec:
|
|
554
|
+
# containers:
|
|
555
|
+
# - name: ${kebabName}
|
|
556
|
+
# livenessProbe:
|
|
557
|
+
# httpGet:
|
|
558
|
+
# path: /health/live
|
|
559
|
+
# port: 3000
|
|
560
|
+
# initialDelaySeconds: 10
|
|
561
|
+
# periodSeconds: 10
|
|
562
|
+
# timeoutSeconds: 5
|
|
563
|
+
# failureThreshold: 3
|
|
564
|
+
#
|
|
565
|
+
# readinessProbe:
|
|
566
|
+
# httpGet:
|
|
567
|
+
# path: /health/ready
|
|
568
|
+
# port: 3000
|
|
569
|
+
# initialDelaySeconds: 5
|
|
570
|
+
# periodSeconds: 5
|
|
571
|
+
# timeoutSeconds: 3
|
|
572
|
+
# failureThreshold: 3
|
|
573
|
+
#
|
|
574
|
+
# startupProbe:
|
|
575
|
+
# httpGet:
|
|
576
|
+
# path: /health/startup
|
|
577
|
+
# port: 3000
|
|
578
|
+
# initialDelaySeconds: 0
|
|
579
|
+
# periodSeconds: 5
|
|
580
|
+
# timeoutSeconds: 3
|
|
581
|
+
# failureThreshold: 30 # 30 * 5s = 150s max startup time
|
|
582
|
+
#
|
|
583
|
+
# Environment variables for graceful shutdown:
|
|
584
|
+
# - name: SHUTDOWN_TIMEOUT_MS
|
|
585
|
+
# value: "30000"
|
|
586
|
+
# - name: PRE_SHUTDOWN_WAIT_MS
|
|
587
|
+
# value: "5000"
|
|
588
|
+
#
|
|
589
|
+
# Lifecycle hooks for graceful shutdown:
|
|
590
|
+
# lifecycle:
|
|
591
|
+
# preStop:
|
|
592
|
+
# exec:
|
|
593
|
+
# command: ["sh", "-c", "sleep 5"] # Allow time for service mesh to drain
|
|
594
|
+
#
|
|
595
|
+
# Pod disruption budget (optional):
|
|
596
|
+
# apiVersion: policy/v1
|
|
597
|
+
# kind: PodDisruptionBudget
|
|
598
|
+
# metadata:
|
|
599
|
+
# name: ${kebabName}-pdb
|
|
600
|
+
# spec:
|
|
601
|
+
# minAvailable: 1
|
|
602
|
+
# selector:
|
|
603
|
+
# matchLabels:
|
|
604
|
+
# app: ${kebabName}
|
|
605
|
+
`;
|
|
606
|
+
fs.writeFileSync(path.join(baseDir, 'k8s-probes.yaml'), k8sConfigContent);
|
|
607
|
+
}
|
|
608
|
+
// Health module
|
|
609
|
+
const healthModuleContent = `import { Module } from '@nestjs/common';
|
|
610
|
+
import { TerminusModule } from '@nestjs/terminus';
|
|
611
|
+
import { HealthController } from './health.controller';
|
|
612
|
+
import {
|
|
613
|
+
DependencyHealthIndicator,
|
|
614
|
+
DatabaseHealthIndicator,
|
|
615
|
+
MemoryHealthIndicator,
|
|
616
|
+
DiskHealthIndicator,
|
|
617
|
+
} from './health-indicators';
|
|
618
|
+
import { GracefulShutdownService } from './graceful-shutdown.service';
|
|
619
|
+
|
|
620
|
+
@Module({
|
|
621
|
+
imports: [TerminusModule],
|
|
622
|
+
controllers: [HealthController],
|
|
623
|
+
providers: [
|
|
624
|
+
DependencyHealthIndicator,
|
|
625
|
+
DatabaseHealthIndicator,
|
|
626
|
+
MemoryHealthIndicator,
|
|
627
|
+
DiskHealthIndicator,
|
|
628
|
+
GracefulShutdownService,
|
|
629
|
+
],
|
|
630
|
+
exports: [
|
|
631
|
+
DependencyHealthIndicator,
|
|
632
|
+
GracefulShutdownService,
|
|
633
|
+
],
|
|
634
|
+
})
|
|
635
|
+
export class ${pascalName}HealthModule {}
|
|
636
|
+
`;
|
|
637
|
+
fs.writeFileSync(path.join(baseDir, 'health.module.ts'), healthModuleContent);
|
|
638
|
+
console.log(chalk_1.default.green(` ✓ Created health indicators`));
|
|
639
|
+
console.log(chalk_1.default.green(` ✓ Created health controller`));
|
|
640
|
+
console.log(chalk_1.default.green(` ✓ Created graceful shutdown service`));
|
|
641
|
+
console.log(chalk_1.default.green(` ✓ Created health module`));
|
|
642
|
+
if (includeKubernetes) {
|
|
643
|
+
console.log(chalk_1.default.green(` ✓ Created Kubernetes configuration`));
|
|
644
|
+
}
|
|
645
|
+
console.log(chalk_1.default.bold.green(`\n✅ Advanced health probes setup complete for ${pascalName}`));
|
|
646
|
+
console.log(chalk_1.default.cyan(`Generated files in: ${baseDir}`));
|
|
647
|
+
console.log(chalk_1.default.gray(' - health-indicators.ts (Custom health indicators)'));
|
|
648
|
+
console.log(chalk_1.default.gray(' - health.controller.ts (K8s probe endpoints)'));
|
|
649
|
+
console.log(chalk_1.default.gray(' - graceful-shutdown.service.ts (Graceful shutdown)'));
|
|
650
|
+
console.log(chalk_1.default.gray(' - health.module.ts (Health module)'));
|
|
651
|
+
if (includeKubernetes) {
|
|
652
|
+
console.log(chalk_1.default.gray(' - k8s-probes.yaml (Kubernetes configuration)'));
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
//# sourceMappingURL=health-probes-advanced.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-probes-advanced.js","sourceRoot":"","sources":["../../src/commands/health-probes-advanced.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,8DA8mBC;AAznBD,uCAAyB;AACzB,2CAA6B;AAC7B,kDAA0B;AAC1B,wDAAkE;AAQ3D,KAAK,UAAU,yBAAyB,CAC7C,QAAgB,EAChB,UAA+B,EAAE;IAEjC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC,CAAC;IAEzE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAA,2BAAY,EAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAA,0BAAW,EAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;IACnF,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,KAAK,KAAK,CAAC;IAE9D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAClF,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3C,4BAA4B;IAC5B,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuM/B,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC,EAAE,qBAAqB,CAAC,CAAC;IAEpF,2CAA2C;IAC3C,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8KjC,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC,EAAE,uBAAuB,CAAC,CAAC;IAEtF,4BAA4B;IAC5B,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+GjC,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,8BAA8B,CAAC,EAAE,uBAAuB,CAAC,CAAC;IAE9F,oCAAoC;IACpC,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,gBAAgB,GAAG;;;;;;;cAOf,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YA4CX,SAAS;;;;;eAKN,SAAS;CACvB,CAAC;QACE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC5E,CAAC;IAED,gBAAgB;IAChB,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;eA0Bf,UAAU;CACxB,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAE9E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACtD,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,iDAAiD,UAAU,EAAE,CAAC,CAAC,CAAC;IAC7F,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC,CAAC;IAChE,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internationalization (i18n) & Localization Engine Generator
|
|
3
|
+
* Generates comprehensive i18n infrastructure
|
|
4
|
+
*/
|
|
5
|
+
export interface I18nOptions {
|
|
6
|
+
path?: string;
|
|
7
|
+
defaultLocale?: string;
|
|
8
|
+
supportedLocales?: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare function setupI18n(basePath: string, options?: I18nOptions): Promise<void>;
|