@pawells/nestjs-shared 1.0.0-dev.3052c75
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/LICENSE +21 -0
- package/README.md +802 -0
- package/build/LICENSE +21 -0
- package/build/README.md +802 -0
- package/build/common/common.module.d.ts +49 -0
- package/build/common/common.module.d.ts.map +1 -0
- package/build/common/common.module.js +178 -0
- package/build/common/common.module.js.map +1 -0
- package/build/common/constants/histogram-buckets.constants.d.ts +12 -0
- package/build/common/constants/histogram-buckets.constants.d.ts.map +1 -0
- package/build/common/constants/histogram-buckets.constants.js +51 -0
- package/build/common/constants/histogram-buckets.constants.js.map +1 -0
- package/build/common/constants/http-status.constants.d.ts +27 -0
- package/build/common/constants/http-status.constants.d.ts.map +1 -0
- package/build/common/constants/http-status.constants.js +27 -0
- package/build/common/constants/http-status.constants.js.map +1 -0
- package/build/common/constants/timeout.constants.d.ts +29 -0
- package/build/common/constants/timeout.constants.d.ts.map +1 -0
- package/build/common/constants/timeout.constants.js +45 -0
- package/build/common/constants/timeout.constants.js.map +1 -0
- package/build/common/controllers/metrics.controller.d.ts +23 -0
- package/build/common/controllers/metrics.controller.d.ts.map +1 -0
- package/build/common/controllers/metrics.controller.js +66 -0
- package/build/common/controllers/metrics.controller.js.map +1 -0
- package/build/common/decorators/common-decorators.d.ts +90 -0
- package/build/common/decorators/common-decorators.d.ts.map +1 -0
- package/build/common/decorators/common-decorators.js +101 -0
- package/build/common/decorators/common-decorators.js.map +1 -0
- package/build/common/decorators/decorator-factory.d.ts +108 -0
- package/build/common/decorators/decorator-factory.d.ts.map +1 -0
- package/build/common/decorators/decorator-factory.js +104 -0
- package/build/common/decorators/decorator-factory.js.map +1 -0
- package/build/common/decorators/guard.decorators.d.ts +48 -0
- package/build/common/decorators/guard.decorators.d.ts.map +1 -0
- package/build/common/decorators/guard.decorators.js +49 -0
- package/build/common/decorators/guard.decorators.js.map +1 -0
- package/build/common/decorators/index.d.ts +10 -0
- package/build/common/decorators/index.d.ts.map +1 -0
- package/build/common/decorators/index.js +11 -0
- package/build/common/decorators/index.js.map +1 -0
- package/build/common/decorators/instrument.decorator.d.ts +128 -0
- package/build/common/decorators/instrument.decorator.d.ts.map +1 -0
- package/build/common/decorators/instrument.decorator.js +165 -0
- package/build/common/decorators/instrument.decorator.js.map +1 -0
- package/build/common/decorators/metric.decorators.d.ts +42 -0
- package/build/common/decorators/metric.decorators.d.ts.map +1 -0
- package/build/common/decorators/metric.decorators.js +85 -0
- package/build/common/decorators/metric.decorators.js.map +1 -0
- package/build/common/decorators/request-property.decorator.d.ts +65 -0
- package/build/common/decorators/request-property.decorator.d.ts.map +1 -0
- package/build/common/decorators/request-property.decorator.js +102 -0
- package/build/common/decorators/request-property.decorator.js.map +1 -0
- package/build/common/errors/base-application-error.d.ts +98 -0
- package/build/common/errors/base-application-error.d.ts.map +1 -0
- package/build/common/errors/base-application-error.js +133 -0
- package/build/common/errors/base-application-error.js.map +1 -0
- package/build/common/errors/error-factory.d.ts +93 -0
- package/build/common/errors/error-factory.d.ts.map +1 -0
- package/build/common/errors/error-factory.js +105 -0
- package/build/common/errors/error-factory.js.map +1 -0
- package/build/common/errors/index.d.ts +13 -0
- package/build/common/errors/index.d.ts.map +1 -0
- package/build/common/errors/index.js +15 -0
- package/build/common/errors/index.js.map +1 -0
- package/build/common/factories/index.d.ts +5 -0
- package/build/common/factories/index.d.ts.map +1 -0
- package/build/common/factories/index.js +3 -0
- package/build/common/factories/index.js.map +1 -0
- package/build/common/factories/module-factory.d.ts +178 -0
- package/build/common/factories/module-factory.d.ts.map +1 -0
- package/build/common/factories/module-factory.js +253 -0
- package/build/common/factories/module-factory.js.map +1 -0
- package/build/common/factories/rate-limit-config.factory.d.ts +79 -0
- package/build/common/factories/rate-limit-config.factory.d.ts.map +1 -0
- package/build/common/factories/rate-limit-config.factory.js +115 -0
- package/build/common/factories/rate-limit-config.factory.js.map +1 -0
- package/build/common/factories/security-bootstrap.factory.d.ts +77 -0
- package/build/common/factories/security-bootstrap.factory.d.ts.map +1 -0
- package/build/common/factories/security-bootstrap.factory.js +222 -0
- package/build/common/factories/security-bootstrap.factory.js.map +1 -0
- package/build/common/filters/global-exception.filter.d.ts +78 -0
- package/build/common/filters/global-exception.filter.d.ts.map +1 -0
- package/build/common/filters/global-exception.filter.js +192 -0
- package/build/common/filters/global-exception.filter.js.map +1 -0
- package/build/common/filters/http-exception.filter.d.ts +37 -0
- package/build/common/filters/http-exception.filter.d.ts.map +1 -0
- package/build/common/filters/http-exception.filter.js +91 -0
- package/build/common/filters/http-exception.filter.js.map +1 -0
- package/build/common/guards/csrf.guard.d.ts +53 -0
- package/build/common/guards/csrf.guard.d.ts.map +1 -0
- package/build/common/guards/csrf.guard.js +109 -0
- package/build/common/guards/csrf.guard.js.map +1 -0
- package/build/common/guards/metrics.guard.d.ts +42 -0
- package/build/common/guards/metrics.guard.d.ts.map +1 -0
- package/build/common/guards/metrics.guard.js +124 -0
- package/build/common/guards/metrics.guard.js.map +1 -0
- package/build/common/index.d.ts +43 -0
- package/build/common/index.d.ts.map +1 -0
- package/build/common/index.js +50 -0
- package/build/common/index.js.map +1 -0
- package/build/common/interceptors/http-client.interceptor.d.ts +11 -0
- package/build/common/interceptors/http-client.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-client.interceptor.js +69 -0
- package/build/common/interceptors/http-client.interceptor.js.map +1 -0
- package/build/common/interceptors/http-instrumentation.interceptor.d.ts +64 -0
- package/build/common/interceptors/http-instrumentation.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-instrumentation.interceptor.js +148 -0
- package/build/common/interceptors/http-instrumentation.interceptor.js.map +1 -0
- package/build/common/interceptors/http-metrics.interceptor.d.ts +46 -0
- package/build/common/interceptors/http-metrics.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-metrics.interceptor.js +120 -0
- package/build/common/interceptors/http-metrics.interceptor.js.map +1 -0
- package/build/common/interceptors/logging.interceptor.d.ts +22 -0
- package/build/common/interceptors/logging.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/logging.interceptor.js +67 -0
- package/build/common/interceptors/logging.interceptor.js.map +1 -0
- package/build/common/interfaces/cache-provider.interface.d.ts +54 -0
- package/build/common/interfaces/cache-provider.interface.d.ts.map +1 -0
- package/build/common/interfaces/cache-provider.interface.js +6 -0
- package/build/common/interfaces/cache-provider.interface.js.map +1 -0
- package/build/common/interfaces/index.d.ts +7 -0
- package/build/common/interfaces/index.d.ts.map +1 -0
- package/build/common/interfaces/index.js +3 -0
- package/build/common/interfaces/index.js.map +1 -0
- package/build/common/interfaces/log-context.interface.d.ts +77 -0
- package/build/common/interfaces/log-context.interface.d.ts.map +1 -0
- package/build/common/interfaces/log-context.interface.js +2 -0
- package/build/common/interfaces/log-context.interface.js.map +1 -0
- package/build/common/interfaces/log-entry.interface.d.ts +26 -0
- package/build/common/interfaces/log-entry.interface.d.ts.map +1 -0
- package/build/common/interfaces/log-entry.interface.js +33 -0
- package/build/common/interfaces/log-entry.interface.js.map +1 -0
- package/build/common/interfaces/logger.interface.d.ts +62 -0
- package/build/common/interfaces/logger.interface.d.ts.map +1 -0
- package/build/common/interfaces/logger.interface.js +2 -0
- package/build/common/interfaces/logger.interface.js.map +1 -0
- package/build/common/interfaces/metrics-exporter.interface.d.ts +275 -0
- package/build/common/interfaces/metrics-exporter.interface.d.ts.map +1 -0
- package/build/common/interfaces/metrics-exporter.interface.js +8 -0
- package/build/common/interfaces/metrics-exporter.interface.js.map +1 -0
- package/build/common/metrics/base-metrics-collector.d.ts +81 -0
- package/build/common/metrics/base-metrics-collector.d.ts.map +1 -0
- package/build/common/metrics/base-metrics-collector.js +88 -0
- package/build/common/metrics/base-metrics-collector.js.map +1 -0
- package/build/common/metrics/index.d.ts +2 -0
- package/build/common/metrics/index.d.ts.map +1 -0
- package/build/common/metrics/index.js +2 -0
- package/build/common/metrics/index.js.map +1 -0
- package/build/common/metrics.module.d.ts +50 -0
- package/build/common/metrics.module.d.ts.map +1 -0
- package/build/common/metrics.module.js +77 -0
- package/build/common/metrics.module.js.map +1 -0
- package/build/common/modules/throttler.module.d.ts +69 -0
- package/build/common/modules/throttler.module.d.ts.map +1 -0
- package/build/common/modules/throttler.module.js +117 -0
- package/build/common/modules/throttler.module.js.map +1 -0
- package/build/common/pipes/base-validation.pipe.d.ts +67 -0
- package/build/common/pipes/base-validation.pipe.d.ts.map +1 -0
- package/build/common/pipes/base-validation.pipe.js +95 -0
- package/build/common/pipes/base-validation.pipe.js.map +1 -0
- package/build/common/pipes/validation.pipe.d.ts +32 -0
- package/build/common/pipes/validation.pipe.d.ts.map +1 -0
- package/build/common/pipes/validation.pipe.js +60 -0
- package/build/common/pipes/validation.pipe.js.map +1 -0
- package/build/common/registry/instrumentation-registry.d.ts +227 -0
- package/build/common/registry/instrumentation-registry.d.ts.map +1 -0
- package/build/common/registry/instrumentation-registry.js +414 -0
- package/build/common/registry/instrumentation-registry.js.map +1 -0
- package/build/common/services/audit-logger.service.d.ts +91 -0
- package/build/common/services/audit-logger.service.d.ts.map +1 -0
- package/build/common/services/audit-logger.service.js +180 -0
- package/build/common/services/audit-logger.service.js.map +1 -0
- package/build/common/services/csrf.service.d.ts +202 -0
- package/build/common/services/csrf.service.d.ts.map +1 -0
- package/build/common/services/csrf.service.js +478 -0
- package/build/common/services/csrf.service.js.map +1 -0
- package/build/common/services/error-categorizer.service.d.ts +82 -0
- package/build/common/services/error-categorizer.service.d.ts.map +1 -0
- package/build/common/services/error-categorizer.service.js +339 -0
- package/build/common/services/error-categorizer.service.js.map +1 -0
- package/build/common/services/error-sanitizer.service.d.ts +146 -0
- package/build/common/services/error-sanitizer.service.d.ts.map +1 -0
- package/build/common/services/error-sanitizer.service.js +287 -0
- package/build/common/services/error-sanitizer.service.js.map +1 -0
- package/build/common/services/health-check.service.d.ts +86 -0
- package/build/common/services/health-check.service.d.ts.map +1 -0
- package/build/common/services/health-check.service.js +132 -0
- package/build/common/services/health-check.service.js.map +1 -0
- package/build/common/services/http-client.service.d.ts +113 -0
- package/build/common/services/http-client.service.d.ts.map +1 -0
- package/build/common/services/http-client.service.js +294 -0
- package/build/common/services/http-client.service.js.map +1 -0
- package/build/common/services/logger.service.d.ts +189 -0
- package/build/common/services/logger.service.d.ts.map +1 -0
- package/build/common/services/logger.service.js +423 -0
- package/build/common/services/logger.service.js.map +1 -0
- package/build/common/services/metrics-registry.service.d.ts +98 -0
- package/build/common/services/metrics-registry.service.d.ts.map +1 -0
- package/build/common/services/metrics-registry.service.js +262 -0
- package/build/common/services/metrics-registry.service.js.map +1 -0
- package/build/common/services/nest-logger-adapter.service.d.ts +62 -0
- package/build/common/services/nest-logger-adapter.service.d.ts.map +1 -0
- package/build/common/services/nest-logger-adapter.service.js +120 -0
- package/build/common/services/nest-logger-adapter.service.js.map +1 -0
- package/build/common/utils/error.utils.d.ts +16 -0
- package/build/common/utils/error.utils.d.ts.map +1 -0
- package/build/common/utils/error.utils.js +26 -0
- package/build/common/utils/error.utils.js.map +1 -0
- package/build/common/utils/lazy-getter.types.d.ts +190 -0
- package/build/common/utils/lazy-getter.types.d.ts.map +1 -0
- package/build/common/utils/lazy-getter.types.js +114 -0
- package/build/common/utils/lazy-getter.types.js.map +1 -0
- package/build/common/utils/module.utils.d.ts +33 -0
- package/build/common/utils/module.utils.d.ts.map +1 -0
- package/build/common/utils/module.utils.js +48 -0
- package/build/common/utils/module.utils.js.map +1 -0
- package/build/common/utils/sanitization.utils.d.ts +69 -0
- package/build/common/utils/sanitization.utils.d.ts.map +1 -0
- package/build/common/utils/sanitization.utils.js +141 -0
- package/build/common/utils/sanitization.utils.js.map +1 -0
- package/build/config/config.module.d.ts +30 -0
- package/build/config/config.module.d.ts.map +1 -0
- package/build/config/config.module.js +49 -0
- package/build/config/config.module.js.map +1 -0
- package/build/config/config.service.d.ts +74 -0
- package/build/config/config.service.d.ts.map +1 -0
- package/build/config/config.service.js +145 -0
- package/build/config/config.service.js.map +1 -0
- package/build/config/config.types.d.ts +143 -0
- package/build/config/config.types.d.ts.map +1 -0
- package/build/config/config.types.js +2 -0
- package/build/config/config.types.js.map +1 -0
- package/build/config/decorators/config.decorators.d.ts +43 -0
- package/build/config/decorators/config.decorators.d.ts.map +1 -0
- package/build/config/decorators/config.decorators.js +68 -0
- package/build/config/decorators/config.decorators.js.map +1 -0
- package/build/config/decorators/index.d.ts +2 -0
- package/build/config/decorators/index.d.ts.map +1 -0
- package/build/config/decorators/index.js +2 -0
- package/build/config/decorators/index.js.map +1 -0
- package/build/config/index.d.ts +7 -0
- package/build/config/index.d.ts.map +1 -0
- package/build/config/index.js +9 -0
- package/build/config/index.js.map +1 -0
- package/build/config/validation.utils.d.ts +136 -0
- package/build/config/validation.utils.d.ts.map +1 -0
- package/build/config/validation.utils.js +263 -0
- package/build/config/validation.utils.js.map +1 -0
- package/build/errors/index.d.ts +9 -0
- package/build/errors/index.d.ts.map +1 -0
- package/build/errors/index.js +12 -0
- package/build/errors/index.js.map +1 -0
- package/build/guards/custom-throttle.guard.d.ts +28 -0
- package/build/guards/custom-throttle.guard.d.ts.map +1 -0
- package/build/guards/custom-throttle.guard.js +52 -0
- package/build/guards/custom-throttle.guard.js.map +1 -0
- package/build/guards/index.d.ts +2 -0
- package/build/guards/index.d.ts.map +1 -0
- package/build/guards/index.js +2 -0
- package/build/guards/index.js.map +1 -0
- package/build/index.d.ts +53 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +61 -0
- package/build/index.js.map +1 -0
- package/build/logging/index.d.ts +7 -0
- package/build/logging/index.d.ts.map +1 -0
- package/build/logging/index.js +7 -0
- package/build/logging/index.js.map +1 -0
- package/build/metrics/index.d.ts +6 -0
- package/build/metrics/index.d.ts.map +1 -0
- package/build/metrics/index.js +11 -0
- package/build/metrics/index.js.map +1 -0
- package/build/package.json +72 -0
- package/build/security/index.d.ts +8 -0
- package/build/security/index.d.ts.map +1 -0
- package/build/security/index.js +11 -0
- package/build/security/index.js.map +1 -0
- package/build/test-setup.d.ts +2 -0
- package/build/test-setup.d.ts.map +1 -0
- package/build/test-setup.js +40 -0
- package/build/test-setup.js.map +1 -0
- package/build/validation/index.d.ts +6 -0
- package/build/validation/index.d.ts.map +1 -0
- package/build/validation/index.js +8 -0
- package/build/validation/index.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var ErrorSanitizerService_1;
|
|
11
|
+
import { Injectable } from '@nestjs/common';
|
|
12
|
+
import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '../constants/http-status.constants.js';
|
|
13
|
+
import { ModuleRef } from '@nestjs/core';
|
|
14
|
+
/**
|
|
15
|
+
* Injection token for ErrorSanitizerService configuration.
|
|
16
|
+
*/
|
|
17
|
+
export const ERROR_SANITIZER_OPTIONS = 'ERROR_SANITIZER_OPTIONS';
|
|
18
|
+
/**
|
|
19
|
+
* Error Sanitizer Service.
|
|
20
|
+
* Sanitizes error responses and error context to prevent information disclosure in production.
|
|
21
|
+
* Removes sensitive information like stack traces, file paths, database URIs, API keys, email addresses,
|
|
22
|
+
* IP addresses, and custom sensitive fields.
|
|
23
|
+
*
|
|
24
|
+
* Implements defense-in-depth by sanitizing:
|
|
25
|
+
* - Error messages (via regex patterns)
|
|
26
|
+
* - Nested context objects (via field name matching)
|
|
27
|
+
* - Stack traces (removed in production)
|
|
28
|
+
*
|
|
29
|
+
* Sensitive patterns redacted:
|
|
30
|
+
* - File paths (e.g., `/home/user/app.ts` -> `[FILE]`)
|
|
31
|
+
* - Database URIs (e.g., `mongodb://...` -> `[REDACTED]`)
|
|
32
|
+
* - API keys and tokens (e.g., `Bearer sk_live_...` -> `Bearer [REDACTED]`)
|
|
33
|
+
* - Email addresses (e.g., `user@example.com` -> `[EMAIL]`)
|
|
34
|
+
* - IP addresses (IPv4 and IPv6) -> `[IP]`
|
|
35
|
+
* - Sensitive field values (passwords, tokens, API keys, etc.) -> `***REDACTED***`
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* - Maximum message length: 5000 chars (prevents ReDoS attacks on regex patterns)
|
|
39
|
+
* - Maximum context depth: 5 levels (prevents deeply nested structure processing)
|
|
40
|
+
* - Circular reference detection prevents infinite loops
|
|
41
|
+
* - Case-insensitive field name matching for sensitivity
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const error = {
|
|
46
|
+
* message: 'Error at /home/user/app.ts, Bearer sk_live_abc123',
|
|
47
|
+
* context: { password: 'secret123', userId: '456' }
|
|
48
|
+
* };
|
|
49
|
+
* const sanitized = errorSanitizer.sanitizeErrorResponse(error, false);
|
|
50
|
+
* // message: 'Error at [FILE], Bearer [REDACTED]'
|
|
51
|
+
* // context: { password: '***REDACTED***', userId: '456' }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
let ErrorSanitizerService = class ErrorSanitizerService {
|
|
55
|
+
static { ErrorSanitizerService_1 = this; }
|
|
56
|
+
/**
|
|
57
|
+
* Maximum length for error messages before truncation.
|
|
58
|
+
* Prevents ReDoS (Regular Expression Denial of Service) attacks by limiting
|
|
59
|
+
* the input size to regex patterns used in message sanitization.
|
|
60
|
+
*/
|
|
61
|
+
// eslint-disable-next-line no-magic-numbers
|
|
62
|
+
static MAX_MESSAGE_LENGTH = 5000;
|
|
63
|
+
/**
|
|
64
|
+
* Maximum nesting depth for context object serialization.
|
|
65
|
+
* Prevents deeply nested structures from causing performance issues.
|
|
66
|
+
*/
|
|
67
|
+
// eslint-disable-next-line no-magic-numbers
|
|
68
|
+
static MAX_CONTEXT_DEPTH = 5;
|
|
69
|
+
/**
|
|
70
|
+
* Precompiled regex pattern for matching file paths with code extensions
|
|
71
|
+
* Used to redact file paths from error messages
|
|
72
|
+
*/
|
|
73
|
+
static FILE_PATH_REGEX = /\/[a-zA-Z0-9_./:-]{0,200}\.(?:ts|js|json|py|go|rb|java|cs|php)/g;
|
|
74
|
+
/**
|
|
75
|
+
* Precompiled regex pattern for matching IPv4 addresses
|
|
76
|
+
*/
|
|
77
|
+
static IPV4_REGEX = /\b(?:\d{1,3}\.){3}\d{1,3}\b/g;
|
|
78
|
+
/**
|
|
79
|
+
* Precompiled regex pattern for matching IPv6 addresses
|
|
80
|
+
* Covers various IPv6 formats: full form, compressed form, ::1, ::ffff:IPv4, bare ::
|
|
81
|
+
* Uses a simpler, non-backtracking pattern to avoid ReDoS (Regular Expression Denial of Service)
|
|
82
|
+
*/
|
|
83
|
+
static IPV6_REGEX = /(?:::(?:ffff(?::0{1,4})?:)?(?:25[0-5]|(?:2[0-4]|1?[0-9])?[0-9])(?:\.(?:25[0-5]|(?:2[0-4]|1?[0-9])?[0-9])){3}|(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|:(?::[0-9a-fA-F]{1,4}){1,7}|::)/gi;
|
|
84
|
+
/**
|
|
85
|
+
* Default sensitive field names that are always redacted from context
|
|
86
|
+
* Stored as lowercase for case-insensitive matching
|
|
87
|
+
*/
|
|
88
|
+
static DEFAULT_SENSITIVE_KEYS = [
|
|
89
|
+
'password',
|
|
90
|
+
'pwd',
|
|
91
|
+
'passwd',
|
|
92
|
+
'pass',
|
|
93
|
+
'token',
|
|
94
|
+
'secret',
|
|
95
|
+
'key',
|
|
96
|
+
'credential',
|
|
97
|
+
'apikey',
|
|
98
|
+
'api_key',
|
|
99
|
+
'api-key',
|
|
100
|
+
'authorization',
|
|
101
|
+
'auth',
|
|
102
|
+
'jwt',
|
|
103
|
+
'refreshtoken',
|
|
104
|
+
'accesstoken',
|
|
105
|
+
'private_key',
|
|
106
|
+
'privatekey',
|
|
107
|
+
'secret_key',
|
|
108
|
+
'client_secret',
|
|
109
|
+
'access_token',
|
|
110
|
+
'refresh_token',
|
|
111
|
+
'bearer',
|
|
112
|
+
'ssn',
|
|
113
|
+
'credit_card',
|
|
114
|
+
'creditcard',
|
|
115
|
+
'card_number',
|
|
116
|
+
'cardnumber',
|
|
117
|
+
'cvv',
|
|
118
|
+
'pin',
|
|
119
|
+
];
|
|
120
|
+
Module;
|
|
121
|
+
constructor(module) {
|
|
122
|
+
this.Module = module;
|
|
123
|
+
}
|
|
124
|
+
get Options() {
|
|
125
|
+
try {
|
|
126
|
+
return this.Module.get(ERROR_SANITIZER_OPTIONS, { strict: false });
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Sanitize error response for client
|
|
134
|
+
* Removes sensitive information like stack traces, file paths, etc.
|
|
135
|
+
*/
|
|
136
|
+
sanitizeErrorResponse(error, isDevelopment = false) {
|
|
137
|
+
const sanitized = {
|
|
138
|
+
message: this.sanitizeMessage(error.message),
|
|
139
|
+
statusCode: error.statusCode ?? HTTP_STATUS_INTERNAL_SERVER_ERROR,
|
|
140
|
+
timestamp: new Date().toISOString(),
|
|
141
|
+
};
|
|
142
|
+
// Only include stack trace in development
|
|
143
|
+
if (isDevelopment && error.stack) {
|
|
144
|
+
sanitized.stack = error.stack;
|
|
145
|
+
}
|
|
146
|
+
// Sanitize context if present
|
|
147
|
+
if (error.context) {
|
|
148
|
+
sanitized.context = this.sanitizeContext(error.context);
|
|
149
|
+
}
|
|
150
|
+
return sanitized;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Sanitize an error message to remove sensitive information.
|
|
154
|
+
* Redacts file paths, database connection strings, API keys, Bearer tokens,
|
|
155
|
+
* email addresses, and IP addresses. Truncates overly long messages to prevent
|
|
156
|
+
* ReDoS attacks and ensure reasonable log sizes.
|
|
157
|
+
*
|
|
158
|
+
* @param message - The error message string to sanitize
|
|
159
|
+
* @returns Sanitized message with sensitive patterns replaced by placeholder strings
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* const msg = 'Error at /home/user/app.ts, Bearer sk_live_abc123';
|
|
164
|
+
* const sanitized = sanitizeMessage(msg);
|
|
165
|
+
* // Returns: 'Error at [FILE], Bearer [REDACTED]'
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
sanitizeMessage(message) {
|
|
169
|
+
if (!message)
|
|
170
|
+
return 'An error occurred';
|
|
171
|
+
// Ensure message is a string
|
|
172
|
+
let safeMessage = message;
|
|
173
|
+
if (typeof safeMessage !== 'string') {
|
|
174
|
+
safeMessage = String(safeMessage);
|
|
175
|
+
}
|
|
176
|
+
// Truncate message to prevent ReDoS attacks on regex patterns
|
|
177
|
+
const truncated = safeMessage.length > ErrorSanitizerService_1.MAX_MESSAGE_LENGTH
|
|
178
|
+
? `${safeMessage.substring(0, ErrorSanitizerService_1.MAX_MESSAGE_LENGTH)}... [truncated]`
|
|
179
|
+
: safeMessage;
|
|
180
|
+
// Remove file paths - match paths with code file extensions
|
|
181
|
+
let sanitized = truncated.replace(ErrorSanitizerService_1.FILE_PATH_REGEX, '[FILE]');
|
|
182
|
+
// Remove database connection strings
|
|
183
|
+
sanitized = sanitized.replace(/mongodb:\/\/[^\s/]+/gi, '[REDACTED]');
|
|
184
|
+
sanitized = sanitized.replace(/postgres(?:ql)?:\/\/[^\s/]+/gi, '[REDACTED]');
|
|
185
|
+
// Remove API keys and tokens
|
|
186
|
+
sanitized = sanitized.replace(/Bearer\s+[a-zA-Z0-9._-]+/gi, 'Bearer [REDACTED]');
|
|
187
|
+
sanitized = sanitized.replace(/(?:api[_-]?key|sk_live|sk_test|pk_live|pk_test)[\s=:]*[a-zA-Z0-9._-]+/gi, '[REDACTED]');
|
|
188
|
+
// Remove email addresses - more restrictive pattern
|
|
189
|
+
sanitized = sanitized.replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, '[EMAIL]');
|
|
190
|
+
// Remove IP addresses (both IPv4 and IPv6)
|
|
191
|
+
sanitized = sanitized.replace(ErrorSanitizerService_1.IPV4_REGEX, '[IP]');
|
|
192
|
+
sanitized = sanitized.replace(ErrorSanitizerService_1.IPV6_REGEX, '[IP]');
|
|
193
|
+
return sanitized;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Recursively sanitize an error context object to remove sensitive field values.
|
|
197
|
+
* Identifies sensitive fields by name (e.g., password, token, secret) and replaces
|
|
198
|
+
* their values with a redaction marker. Handles nested objects and arrays while
|
|
199
|
+
* detecting circular references to prevent infinite loops.
|
|
200
|
+
*
|
|
201
|
+
* @param context - The context object to sanitize
|
|
202
|
+
* @returns Sanitized context with sensitive field values replaced
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```typescript
|
|
206
|
+
* const ctx = { user: 'john', password: 'secret123', nested: { apiKey: 'sk_live' } };
|
|
207
|
+
* const sanitized = sanitizeContext(ctx);
|
|
208
|
+
* // Returns: { user: 'john', password: '***REDACTED***', nested: { apiKey: '***REDACTED***' } }
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
sanitizeContext(context) {
|
|
212
|
+
const seen = new Set();
|
|
213
|
+
const result = this.serializeWithDepthLimit(context, ErrorSanitizerService_1.MAX_CONTEXT_DEPTH, 0, seen);
|
|
214
|
+
return result ?? {};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Recursively serialize an object with depth limiting and circular reference detection.
|
|
218
|
+
* Handles nested objects and arrays while preventing infinite loops.
|
|
219
|
+
*
|
|
220
|
+
* @param obj - The object to serialize
|
|
221
|
+
* @param maxDepth - Maximum nesting depth (default 5)
|
|
222
|
+
* @param currentDepth - Current recursion depth
|
|
223
|
+
* @param seen - Set of already-visited objects to detect cycles
|
|
224
|
+
* @returns Serialized object with sensitive fields redacted
|
|
225
|
+
*/
|
|
226
|
+
serializeWithDepthLimit(obj, maxDepth, currentDepth, seen) {
|
|
227
|
+
// Return non-object values as-is
|
|
228
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
229
|
+
if (typeof obj === 'string') {
|
|
230
|
+
return this.sanitizeMessage(obj);
|
|
231
|
+
}
|
|
232
|
+
return obj;
|
|
233
|
+
}
|
|
234
|
+
// Check for circular reference
|
|
235
|
+
if (seen.has(obj)) {
|
|
236
|
+
return '[CIRCULAR_REF]';
|
|
237
|
+
}
|
|
238
|
+
// Check for max depth
|
|
239
|
+
if (currentDepth >= maxDepth) {
|
|
240
|
+
return '[MAX_DEPTH]';
|
|
241
|
+
}
|
|
242
|
+
// Mark object as visited immediately after circular check, before recursing
|
|
243
|
+
seen.add(obj);
|
|
244
|
+
// Handle arrays
|
|
245
|
+
if (Array.isArray(obj)) {
|
|
246
|
+
return obj.map(item => this.serializeWithDepthLimit(item, maxDepth, currentDepth + 1, seen));
|
|
247
|
+
}
|
|
248
|
+
// Handle objects
|
|
249
|
+
const sanitized = {};
|
|
250
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
251
|
+
// Skip sensitive fields
|
|
252
|
+
if (this.isSensitiveField(key)) {
|
|
253
|
+
sanitized[key] = '***REDACTED***';
|
|
254
|
+
}
|
|
255
|
+
else if (typeof value === 'object' && value !== null) {
|
|
256
|
+
// For objects and arrays, recurse with depth check
|
|
257
|
+
sanitized[key] = this.serializeWithDepthLimit(value, maxDepth, currentDepth + 1, seen);
|
|
258
|
+
}
|
|
259
|
+
else if (typeof value === 'string') {
|
|
260
|
+
// Sanitize string values
|
|
261
|
+
sanitized[key] = this.sanitizeMessage(value);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// Return primitive values as-is
|
|
265
|
+
sanitized[key] = value;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return sanitized;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Check if field is sensitive (case-insensitive comparison)
|
|
272
|
+
*/
|
|
273
|
+
isSensitiveField(fieldName) {
|
|
274
|
+
const fieldNameLower = fieldName.toLowerCase();
|
|
275
|
+
const allSensitiveFields = [
|
|
276
|
+
...ErrorSanitizerService_1.DEFAULT_SENSITIVE_KEYS,
|
|
277
|
+
...(this.Options?.additionalSensitiveKeys ?? []),
|
|
278
|
+
];
|
|
279
|
+
return allSensitiveFields.some(field => fieldNameLower.includes(field.toLowerCase()));
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
ErrorSanitizerService = ErrorSanitizerService_1 = __decorate([
|
|
283
|
+
Injectable(),
|
|
284
|
+
__metadata("design:paramtypes", [ModuleRef])
|
|
285
|
+
], ErrorSanitizerService);
|
|
286
|
+
export { ErrorSanitizerService };
|
|
287
|
+
//# sourceMappingURL=error-sanitizer.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-sanitizer.service.js","sourceRoot":"","sources":["../../../src/common/services/error-sanitizer.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ModuleRef } from '@nestjs/core';
|
|
2
|
+
import { LazyModuleRefService } from '../utils/lazy-getter.types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Health status enumeration for standardized health check responses.
|
|
5
|
+
*/
|
|
6
|
+
export declare enum HealthStatus {
|
|
7
|
+
OK = "ok",
|
|
8
|
+
READY = "ready",
|
|
9
|
+
ALIVE = "alive"
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Health check response interface.
|
|
13
|
+
*/
|
|
14
|
+
export interface IHealthCheck {
|
|
15
|
+
status: string;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
service?: string;
|
|
18
|
+
version?: string;
|
|
19
|
+
checks?: Record<string, string>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Health Check Service.
|
|
23
|
+
* Provides standardized health, readiness, and liveness checks for Kubernetes probes and monitoring.
|
|
24
|
+
*
|
|
25
|
+
* Probe types:
|
|
26
|
+
* - **Health/Status**: General application health (used by load balancers)
|
|
27
|
+
* - **Readiness**: Determines if service should receive traffic (Kubernetes readiness probe)
|
|
28
|
+
* - **Liveness**: Confirms service is alive and responsive (Kubernetes liveness probe)
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* - All responses include ISO timestamps for log correlation
|
|
32
|
+
* - Supports optional service name and version strings
|
|
33
|
+
* - Readiness probe can include custom checks (database, cache, etc.)
|
|
34
|
+
* - All checks automatically logged via AppLogger for monitoring
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* // In a health controller
|
|
39
|
+
* @Get('/')
|
|
40
|
+
* health() {
|
|
41
|
+
* return this.healthService.getHealth('my-service', '1.0.0');
|
|
42
|
+
* }
|
|
43
|
+
*
|
|
44
|
+
* @Get('/ready')
|
|
45
|
+
* readiness() {
|
|
46
|
+
* const checks = {
|
|
47
|
+
* database: HealthStatus.OK,
|
|
48
|
+
* cache: HealthStatus.OK,
|
|
49
|
+
* };
|
|
50
|
+
* return this.healthService.getReadiness(checks);
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* @Get('/live')
|
|
54
|
+
* liveness() {
|
|
55
|
+
* return this.healthService.getLiveness();
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare class HealthCheckService implements LazyModuleRefService {
|
|
60
|
+
private _contextualLogger;
|
|
61
|
+
readonly Module: ModuleRef;
|
|
62
|
+
constructor(module: ModuleRef);
|
|
63
|
+
private get Logger();
|
|
64
|
+
/**
|
|
65
|
+
* Get application health status
|
|
66
|
+
* Used for general health checks
|
|
67
|
+
* @param serviceName - Optional service name
|
|
68
|
+
* @param version - Optional version string
|
|
69
|
+
* @returns Health check response
|
|
70
|
+
*/
|
|
71
|
+
getHealth(serviceName?: string, version?: string): IHealthCheck;
|
|
72
|
+
/**
|
|
73
|
+
* Get application readiness status
|
|
74
|
+
* Used for Kubernetes readiness probes to determine if service should receive traffic
|
|
75
|
+
* @param checks - Optional custom health checks (e.g., database, cache status)
|
|
76
|
+
* @returns Readiness check response
|
|
77
|
+
*/
|
|
78
|
+
getReadiness(checks?: Record<string, string>): IHealthCheck;
|
|
79
|
+
/**
|
|
80
|
+
* Get application liveness status
|
|
81
|
+
* Used for Kubernetes liveness probes to determine if service is alive
|
|
82
|
+
* @returns Liveness check response
|
|
83
|
+
*/
|
|
84
|
+
getLiveness(): IHealthCheck;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=health-check.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-check.service.d.ts","sourceRoot":"","sources":["../../../src/common/services/health-check.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE;;GAEG;AACH,oBAAY,YAAY;IACvB,EAAE,OAAO;IACT,KAAK,UAAU;IACf,KAAK,UAAU;CACf;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,qBACa,kBAAmB,YAAW,oBAAoB;IAC9D,OAAO,CAAC,iBAAiB,CAAwB;IAEjD,SAAgB,MAAM,EAAE,SAAS,CAAC;gBAEtB,MAAM,EAAE,SAAS;IAI7B,OAAO,KAAK,MAAM,GAMjB;IAED;;;;;;OAMG;IACI,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY;IAoBtE;;;;;OAKG;IACI,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY;IAalE;;;;OAIG;IACI,WAAW,IAAI,YAAY;CAWlC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var HealthCheckService_1;
|
|
11
|
+
import { Injectable } from '@nestjs/common';
|
|
12
|
+
import { ModuleRef } from '@nestjs/core';
|
|
13
|
+
import { AppLogger } from './logger.service.js';
|
|
14
|
+
/**
|
|
15
|
+
* Health status enumeration for standardized health check responses.
|
|
16
|
+
*/
|
|
17
|
+
export var HealthStatus;
|
|
18
|
+
(function (HealthStatus) {
|
|
19
|
+
HealthStatus["OK"] = "ok";
|
|
20
|
+
HealthStatus["READY"] = "ready";
|
|
21
|
+
HealthStatus["ALIVE"] = "alive";
|
|
22
|
+
})(HealthStatus || (HealthStatus = {}));
|
|
23
|
+
/**
|
|
24
|
+
* Health Check Service.
|
|
25
|
+
* Provides standardized health, readiness, and liveness checks for Kubernetes probes and monitoring.
|
|
26
|
+
*
|
|
27
|
+
* Probe types:
|
|
28
|
+
* - **Health/Status**: General application health (used by load balancers)
|
|
29
|
+
* - **Readiness**: Determines if service should receive traffic (Kubernetes readiness probe)
|
|
30
|
+
* - **Liveness**: Confirms service is alive and responsive (Kubernetes liveness probe)
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* - All responses include ISO timestamps for log correlation
|
|
34
|
+
* - Supports optional service name and version strings
|
|
35
|
+
* - Readiness probe can include custom checks (database, cache, etc.)
|
|
36
|
+
* - All checks automatically logged via AppLogger for monitoring
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // In a health controller
|
|
41
|
+
* @Get('/')
|
|
42
|
+
* health() {
|
|
43
|
+
* return this.healthService.getHealth('my-service', '1.0.0');
|
|
44
|
+
* }
|
|
45
|
+
*
|
|
46
|
+
* @Get('/ready')
|
|
47
|
+
* readiness() {
|
|
48
|
+
* const checks = {
|
|
49
|
+
* database: HealthStatus.OK,
|
|
50
|
+
* cache: HealthStatus.OK,
|
|
51
|
+
* };
|
|
52
|
+
* return this.healthService.getReadiness(checks);
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* @Get('/live')
|
|
56
|
+
* liveness() {
|
|
57
|
+
* return this.healthService.getLiveness();
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
let HealthCheckService = HealthCheckService_1 = class HealthCheckService {
|
|
62
|
+
_contextualLogger;
|
|
63
|
+
Module;
|
|
64
|
+
constructor(module) {
|
|
65
|
+
this.Module = module;
|
|
66
|
+
}
|
|
67
|
+
get Logger() {
|
|
68
|
+
if (!this._contextualLogger) {
|
|
69
|
+
const baseLogger = this.Module.get(AppLogger);
|
|
70
|
+
this._contextualLogger = baseLogger.createContextualLogger(HealthCheckService_1.name);
|
|
71
|
+
}
|
|
72
|
+
return this._contextualLogger;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get application health status
|
|
76
|
+
* Used for general health checks
|
|
77
|
+
* @param serviceName - Optional service name
|
|
78
|
+
* @param version - Optional version string
|
|
79
|
+
* @returns Health check response
|
|
80
|
+
*/
|
|
81
|
+
getHealth(serviceName, version) {
|
|
82
|
+
this.Logger.debug('Health check requested');
|
|
83
|
+
const response = {
|
|
84
|
+
status: HealthStatus.OK,
|
|
85
|
+
timestamp: new Date().toISOString(),
|
|
86
|
+
};
|
|
87
|
+
if (serviceName) {
|
|
88
|
+
response.service = serviceName;
|
|
89
|
+
}
|
|
90
|
+
if (version) {
|
|
91
|
+
response.version = version;
|
|
92
|
+
}
|
|
93
|
+
this.Logger.debug(`Health check response: ${JSON.stringify(response)}`);
|
|
94
|
+
return response;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get application readiness status
|
|
98
|
+
* Used for Kubernetes readiness probes to determine if service should receive traffic
|
|
99
|
+
* @param checks - Optional custom health checks (e.g., database, cache status)
|
|
100
|
+
* @returns Readiness check response
|
|
101
|
+
*/
|
|
102
|
+
getReadiness(checks) {
|
|
103
|
+
this.Logger.debug('Readiness check requested');
|
|
104
|
+
const response = {
|
|
105
|
+
status: HealthStatus.READY,
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
checks: checks ?? {},
|
|
108
|
+
};
|
|
109
|
+
this.Logger.debug(`Readiness check response: ${JSON.stringify(response)}`);
|
|
110
|
+
return response;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get application liveness status
|
|
114
|
+
* Used for Kubernetes liveness probes to determine if service is alive
|
|
115
|
+
* @returns Liveness check response
|
|
116
|
+
*/
|
|
117
|
+
getLiveness() {
|
|
118
|
+
this.Logger.debug('Liveness check requested');
|
|
119
|
+
const response = {
|
|
120
|
+
status: HealthStatus.ALIVE,
|
|
121
|
+
timestamp: new Date().toISOString(),
|
|
122
|
+
};
|
|
123
|
+
this.Logger.debug(`Liveness check response: ${JSON.stringify(response)}`);
|
|
124
|
+
return response;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
HealthCheckService = HealthCheckService_1 = __decorate([
|
|
128
|
+
Injectable(),
|
|
129
|
+
__metadata("design:paramtypes", [ModuleRef])
|
|
130
|
+
], HealthCheckService);
|
|
131
|
+
export { HealthCheckService };
|
|
132
|
+
//# sourceMappingURL=health-check.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-check.service.js","sourceRoot":"","sources":["../../../src/common/services/health-check.service.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD;;GAEG;AACH,MAAM,CAAN,IAAY,YAIX;AAJD,WAAY,YAAY;IACvB,yBAAS,CAAA;IACT,+BAAe,CAAA;IACf,+BAAe,CAAA;AAChB,CAAC,EAJW,YAAY,KAAZ,YAAY,QAIvB;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEI,IAAM,kBAAkB,0BAAxB,MAAM,kBAAkB;IACtB,iBAAiB,CAAwB;IAEjC,MAAM,CAAY;IAElC,YAAY,MAAiB;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAED,IAAY,MAAM;QACjB,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC9C,IAAI,CAAC,iBAAiB,GAAG,UAAU,CAAC,sBAAsB,CAAC,oBAAkB,CAAC,IAAI,CAAC,CAAC;QACrF,CAAC;QACD,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAC/B,CAAC;IAED;;;;;;OAMG;IACI,SAAS,CAAC,WAAoB,EAAE,OAAgB;QACtD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAE5C,MAAM,QAAQ,GAAiB;YAC9B,MAAM,EAAE,YAAY,CAAC,EAAE;YACvB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACnC,CAAC;QAEF,IAAI,WAAW,EAAE,CAAC;YACjB,QAAQ,CAAC,OAAO,GAAG,WAAW,CAAC;QAChC,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACxE,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED;;;;;OAKG;IACI,YAAY,CAAC,MAA+B;QAClD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAE/C,MAAM,QAAQ,GAAiB;YAC9B,MAAM,EAAE,YAAY,CAAC,KAAK;YAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,MAAM,IAAI,EAAE;SACpB,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC3E,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACI,WAAW;QACjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAE9C,MAAM,QAAQ,GAAiB;YAC9B,MAAM,EAAE,YAAY,CAAC,KAAK;YAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACnC,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1E,OAAO,QAAQ,CAAC;IACjB,CAAC;CACD,CAAA;AA/EY,kBAAkB;IAD9B,UAAU,EAAE;qCAMQ,SAAS;GALjB,kBAAkB,CA+E9B"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { ModuleRef } from '@nestjs/core';
|
|
2
|
+
import { LazyModuleRefService } from '../utils/lazy-getter.types.js';
|
|
3
|
+
import { AppLogger } from './logger.service.js';
|
|
4
|
+
/**
|
|
5
|
+
* HTTP request options.
|
|
6
|
+
*/
|
|
7
|
+
interface HttpRequestOptions {
|
|
8
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
9
|
+
url: string;
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
data?: Record<string, unknown> | string;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
correlationId?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Whether to reject unauthorized (self-signed) SSL/TLS certificates.
|
|
16
|
+
* Default: true (recommended for production)
|
|
17
|
+
*
|
|
18
|
+
* Security Warning: Setting this to false allows Man-in-the-Middle (MITM) attacks
|
|
19
|
+
* in production environments. Only use for development or testing with known certificates.
|
|
20
|
+
*
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
rejectUnauthorized?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Custom Certificate Authority (CA) certificate for SSL/TLS validation.
|
|
26
|
+
* Can be a PEM-encoded certificate as a string or Buffer.
|
|
27
|
+
* Useful for environments using self-signed or internal CAs.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const cert = fs.readFileSync('/path/to/ca.pem');
|
|
32
|
+
* await client.request({
|
|
33
|
+
* url: 'https://internal-api.local',
|
|
34
|
+
* ca: cert,
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
ca?: Buffer | string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* HTTP response wrapper.
|
|
42
|
+
*/
|
|
43
|
+
interface HttpResponse<T = Record<string, unknown>> {
|
|
44
|
+
data: T;
|
|
45
|
+
status: number;
|
|
46
|
+
statusText: string;
|
|
47
|
+
headers: Record<string, string>;
|
|
48
|
+
duration: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* HTTP Client Service.
|
|
52
|
+
* Provides a robust HTTP client with timeout handling, SSL/TLS configuration, payload size limits,
|
|
53
|
+
* and comprehensive logging with sensitive data redaction.
|
|
54
|
+
*
|
|
55
|
+
* Features:
|
|
56
|
+
* - Configurable timeouts (default: HTTP_CLIENT_TIMEOUT)
|
|
57
|
+
* - SSL/TLS certificate validation (default: strict)
|
|
58
|
+
* - Custom CA certificate support for self-signed certs
|
|
59
|
+
* - Payload size limit enforcement (10MB default)
|
|
60
|
+
* - Automatic content-type parsing (JSON, text)
|
|
61
|
+
* - Correlation ID support for request tracing
|
|
62
|
+
* - Sensitive data redaction in logs (passwords, tokens, auth headers)
|
|
63
|
+
* - Request/response duration tracking
|
|
64
|
+
*
|
|
65
|
+
* @remarks
|
|
66
|
+
* - Maximum payload size: 10MB (prevents memory exhaustion from large responses)
|
|
67
|
+
* - Timeout error handling with clear error messages
|
|
68
|
+
* - Content-type validation before JSON parsing
|
|
69
|
+
* - All sensitive headers (Authorization, Cookie, X-API-Key) redacted in logs
|
|
70
|
+
* - URLs with embedded credentials are sanitized before logging
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* // Simple GET request
|
|
75
|
+
* const response = await client.get('https://api.example.com/users');
|
|
76
|
+
*
|
|
77
|
+
* // POST with custom timeout and correlation ID
|
|
78
|
+
* const response = await client.post('https://api.example.com/users',
|
|
79
|
+
* { name: 'John', email: 'john@example.com' },
|
|
80
|
+
* { timeout: 5000, correlationId: 'req-123' }
|
|
81
|
+
* );
|
|
82
|
+
*
|
|
83
|
+
* // HTTPS with custom CA certificate
|
|
84
|
+
* const cert = fs.readFileSync('/path/to/ca.pem');
|
|
85
|
+
* const response = await client.get('https://internal-api.local/data', { ca: cert });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare class HttpClientService implements LazyModuleRefService {
|
|
89
|
+
private _contextualLogger;
|
|
90
|
+
readonly Module: ModuleRef;
|
|
91
|
+
constructor(module: ModuleRef);
|
|
92
|
+
get Logger(): AppLogger;
|
|
93
|
+
/**
|
|
94
|
+
* Makes an HTTP request. URLs with embedded credentials and sensitive headers
|
|
95
|
+
* are sanitized before logging.
|
|
96
|
+
*/
|
|
97
|
+
request<T = Record<string, unknown>>(options: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
98
|
+
get<T = Record<string, unknown>>(url: string, options?: Omit<HttpRequestOptions, 'method' | 'url'>): Promise<HttpResponse<T>>;
|
|
99
|
+
post<T = Record<string, unknown>>(url: string, data?: Record<string, unknown> | string, options?: Omit<HttpRequestOptions, 'method' | 'url' | 'data'>): Promise<HttpResponse<T>>;
|
|
100
|
+
put<T = Record<string, unknown>>(url: string, data?: Record<string, unknown> | string, options?: Omit<HttpRequestOptions, 'method' | 'url' | 'data'>): Promise<HttpResponse<T>>;
|
|
101
|
+
delete<T = Record<string, unknown>>(url: string, options?: Omit<HttpRequestOptions, 'method' | 'url'>): Promise<HttpResponse<T>>;
|
|
102
|
+
/**
|
|
103
|
+
* Sanitize a URL to remove embedded credentials (e.g., https://user:pass@host/)
|
|
104
|
+
*/
|
|
105
|
+
private sanitizeUrl;
|
|
106
|
+
/**
|
|
107
|
+
* Redacts sensitive headers (authorization, cookies, API keys, CSRF tokens)
|
|
108
|
+
* before logging.
|
|
109
|
+
*/
|
|
110
|
+
private sanitizeHeaders;
|
|
111
|
+
}
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=http-client.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.service.d.ts","sourceRoot":"","sources":["../../../src/common/services/http-client.service.ts"],"names":[],"mappings":"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"}
|