@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,339 @@
|
|
|
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 ErrorCategorizerService_1;
|
|
11
|
+
import { Injectable } from '@nestjs/common';
|
|
12
|
+
import { ModuleRef } from '@nestjs/core';
|
|
13
|
+
import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_UNAUTHORIZED, HTTP_STATUS_FORBIDDEN, HTTP_STATUS_NOT_FOUND, HTTP_STATUS_TOO_MANY_REQUESTS, HTTP_STATUS_BAD_GATEWAY, HTTP_STATUS_SERVICE_UNAVAILABLE, HTTP_STATUS_GATEWAY_TIMEOUT, HTTP_STATUS_UNPROCESSABLE_ENTITY, } from '../constants/http-status.constants.js';
|
|
14
|
+
import { AppLogger } from './logger.service.js';
|
|
15
|
+
// Backoff times in milliseconds
|
|
16
|
+
const BACKOFF_RETRY_MS = 1000;
|
|
17
|
+
const BACKOFF_TIMEOUT_MS = 2000;
|
|
18
|
+
const BACKOFF_DATABASE_MS = 5000;
|
|
19
|
+
const BACKOFF_RATE_LIMIT_MS = 10000;
|
|
20
|
+
/**
|
|
21
|
+
* Error Categorizer Service.
|
|
22
|
+
* Classifies errors as transient or permanent and recommends recovery strategies.
|
|
23
|
+
*
|
|
24
|
+
* Categories:
|
|
25
|
+
* - **Transient** (retryable): Network errors, timeouts, database connection errors, rate limits, server errors (5xx)
|
|
26
|
+
* - **Permanent** (not retryable): Validation errors, bad requests (4xx), authentication/authorization, not found
|
|
27
|
+
*
|
|
28
|
+
* Recovery strategies:
|
|
29
|
+
* - **retry**: Immediate retry (for network errors)
|
|
30
|
+
* - **backoff**: Exponential backoff retry (for timeouts, database, rate limits)
|
|
31
|
+
* - **fail**: Fast failure without retry (for validation, authentication, not found)
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* - Node.js error codes (ECONNRESET, ECONNREFUSED, ETIMEDOUT, ENOTFOUND, EAI_AGAIN) are always transient
|
|
35
|
+
* - Database connection errors are always transient with long backoff (5s)
|
|
36
|
+
* - Timeout errors get medium backoff (2s)
|
|
37
|
+
* - Rate limit errors get maximum backoff (10s)
|
|
38
|
+
* - Unknown errors default to permanent/fail strategy
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const category = errorCategorizer.categorizeError(error);
|
|
43
|
+
* if (category.retryable) {
|
|
44
|
+
* // Retry with backoff: category.backoffMs
|
|
45
|
+
* } else {
|
|
46
|
+
* // Fail fast
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
let ErrorCategorizerService = ErrorCategorizerService_1 = class ErrorCategorizerService {
|
|
51
|
+
_contextualLogger;
|
|
52
|
+
Module;
|
|
53
|
+
constructor(module) {
|
|
54
|
+
this.Module = module;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get contextual logger for error categorizer
|
|
58
|
+
*/
|
|
59
|
+
get Logger() {
|
|
60
|
+
if (!this._contextualLogger) {
|
|
61
|
+
const baseLogger = this.Module.get(AppLogger);
|
|
62
|
+
this._contextualLogger = baseLogger.createContextualLogger(ErrorCategorizerService_1.name);
|
|
63
|
+
}
|
|
64
|
+
return this._contextualLogger;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check if an error is retryable
|
|
68
|
+
*/
|
|
69
|
+
isRetryable(error) {
|
|
70
|
+
const category = this.categorizeError(error);
|
|
71
|
+
return category.retryable;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Categorize an error and determine recovery strategy
|
|
75
|
+
*/
|
|
76
|
+
categorizeError(error) {
|
|
77
|
+
const err = error;
|
|
78
|
+
const errorMessage = err?.message ?? String(error);
|
|
79
|
+
const errorCode = err?.code ?? err?.status;
|
|
80
|
+
// Node.js network error codes are always transient (checked first before pattern matching)
|
|
81
|
+
const NODE_TRANSIENT_CODES = new Set(['ECONNRESET', 'ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND', 'EAI_AGAIN']);
|
|
82
|
+
if (error && NODE_TRANSIENT_CODES.has(error.code ?? '')) {
|
|
83
|
+
this.Logger.debug('Categorized as transient network error (Node.js error code)', {
|
|
84
|
+
error: errorMessage,
|
|
85
|
+
code: errorCode,
|
|
86
|
+
category: 'transient',
|
|
87
|
+
strategy: 'backoff',
|
|
88
|
+
});
|
|
89
|
+
return {
|
|
90
|
+
type: 'transient',
|
|
91
|
+
retryable: true,
|
|
92
|
+
strategy: 'backoff',
|
|
93
|
+
backoffMs: BACKOFF_RETRY_MS,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// Database connection errors (transient) - check before timeout since "timeout" may be in message
|
|
97
|
+
if (this.isDatabaseError(error)) {
|
|
98
|
+
this.Logger.debug('Categorized as transient database error', {
|
|
99
|
+
error: errorMessage,
|
|
100
|
+
category: 'transient',
|
|
101
|
+
strategy: 'backoff',
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
type: 'transient',
|
|
105
|
+
retryable: true,
|
|
106
|
+
strategy: 'backoff',
|
|
107
|
+
backoffMs: BACKOFF_DATABASE_MS,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Timeout errors (transient) - check before generic network errors since ETIMEDOUT is in networkCodes
|
|
111
|
+
if (this.isTimeoutError(error)) {
|
|
112
|
+
this.Logger.debug('Categorized as transient timeout error', {
|
|
113
|
+
error: errorMessage,
|
|
114
|
+
category: 'transient',
|
|
115
|
+
strategy: 'backoff',
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
type: 'transient',
|
|
119
|
+
retryable: true,
|
|
120
|
+
strategy: 'backoff',
|
|
121
|
+
backoffMs: BACKOFF_TIMEOUT_MS,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Network errors (transient)
|
|
125
|
+
if (this.isNetworkError(error)) {
|
|
126
|
+
this.Logger.debug('Categorized as transient network error', {
|
|
127
|
+
error: errorMessage,
|
|
128
|
+
category: 'transient',
|
|
129
|
+
strategy: 'retry',
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
type: 'transient',
|
|
133
|
+
retryable: true,
|
|
134
|
+
strategy: 'retry',
|
|
135
|
+
backoffMs: BACKOFF_RETRY_MS,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Server errors (transient) - 502, 503, 504
|
|
139
|
+
if (this.isServerError(error)) {
|
|
140
|
+
this.Logger.debug('Categorized as transient server error', {
|
|
141
|
+
error: errorMessage,
|
|
142
|
+
status: errorCode,
|
|
143
|
+
category: 'transient',
|
|
144
|
+
strategy: 'backoff',
|
|
145
|
+
});
|
|
146
|
+
return {
|
|
147
|
+
type: 'transient',
|
|
148
|
+
retryable: true,
|
|
149
|
+
strategy: 'backoff',
|
|
150
|
+
backoffMs: BACKOFF_TIMEOUT_MS,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// Rate limit errors (transient) - 429
|
|
154
|
+
if (this.isRateLimitError(error)) {
|
|
155
|
+
this.Logger.debug('Categorized as transient rate limit error', {
|
|
156
|
+
error: errorMessage,
|
|
157
|
+
category: 'transient',
|
|
158
|
+
strategy: 'backoff',
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
type: 'transient',
|
|
162
|
+
retryable: true,
|
|
163
|
+
strategy: 'backoff',
|
|
164
|
+
backoffMs: BACKOFF_RATE_LIMIT_MS,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// Bad request errors (permanent) - 400, 422
|
|
168
|
+
if (this.isBadRequestError(error)) {
|
|
169
|
+
this.Logger.debug('Categorized as permanent bad request error', {
|
|
170
|
+
error: errorMessage,
|
|
171
|
+
category: 'permanent',
|
|
172
|
+
strategy: 'fail',
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
type: 'permanent',
|
|
176
|
+
retryable: false,
|
|
177
|
+
strategy: 'fail',
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// Validation errors (permanent)
|
|
181
|
+
if (this.isValidationError(error)) {
|
|
182
|
+
this.Logger.debug('Categorized as permanent validation error', {
|
|
183
|
+
error: errorMessage,
|
|
184
|
+
category: 'permanent',
|
|
185
|
+
strategy: 'fail',
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
type: 'permanent',
|
|
189
|
+
retryable: false,
|
|
190
|
+
strategy: 'fail',
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// Authentication errors (permanent) - 401
|
|
194
|
+
if (this.isAuthError(error)) {
|
|
195
|
+
this.Logger.debug('Categorized as permanent authentication error', {
|
|
196
|
+
error: errorMessage,
|
|
197
|
+
category: 'permanent',
|
|
198
|
+
strategy: 'fail',
|
|
199
|
+
});
|
|
200
|
+
return {
|
|
201
|
+
type: 'permanent',
|
|
202
|
+
retryable: false,
|
|
203
|
+
strategy: 'fail',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// Authorization errors (permanent) - 403
|
|
207
|
+
if (this.isAuthzError(error)) {
|
|
208
|
+
this.Logger.debug('Categorized as permanent authorization error', {
|
|
209
|
+
error: errorMessage,
|
|
210
|
+
category: 'permanent',
|
|
211
|
+
strategy: 'fail',
|
|
212
|
+
});
|
|
213
|
+
return {
|
|
214
|
+
type: 'permanent',
|
|
215
|
+
retryable: false,
|
|
216
|
+
strategy: 'fail',
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// Not found errors (permanent) - 404
|
|
220
|
+
if (this.isNotFoundError(error)) {
|
|
221
|
+
this.Logger.debug('Categorized as permanent not found error', {
|
|
222
|
+
error: errorMessage,
|
|
223
|
+
category: 'permanent',
|
|
224
|
+
strategy: 'fail',
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
type: 'permanent',
|
|
228
|
+
retryable: false,
|
|
229
|
+
strategy: 'fail',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
// Default to permanent error
|
|
233
|
+
this.Logger.warn('Uncategorized error treated as permanent', {
|
|
234
|
+
error: errorMessage,
|
|
235
|
+
code: errorCode,
|
|
236
|
+
category: 'permanent',
|
|
237
|
+
strategy: 'fail',
|
|
238
|
+
});
|
|
239
|
+
return {
|
|
240
|
+
type: 'permanent',
|
|
241
|
+
retryable: false,
|
|
242
|
+
strategy: 'fail',
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Log error recovery attempt
|
|
247
|
+
*/
|
|
248
|
+
logRecoveryAttempt(error, attempt, maxAttempts) {
|
|
249
|
+
const category = this.categorizeError(error);
|
|
250
|
+
this.Logger.info('Error recovery attempt', {
|
|
251
|
+
attempt,
|
|
252
|
+
maxAttempts,
|
|
253
|
+
errorType: category.type,
|
|
254
|
+
strategy: category.strategy,
|
|
255
|
+
backoffMs: category.backoffMs,
|
|
256
|
+
error: error?.message ?? String(error),
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Log successful recovery
|
|
261
|
+
*/
|
|
262
|
+
logRecoverySuccess(error, attempts) {
|
|
263
|
+
this.Logger.info('Error recovery successful', {
|
|
264
|
+
attempts,
|
|
265
|
+
error: error?.message ?? String(error),
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Log failed recovery
|
|
270
|
+
*/
|
|
271
|
+
logRecoveryFailed(error, attempts) {
|
|
272
|
+
const err = error;
|
|
273
|
+
const category = this.categorizeError(error);
|
|
274
|
+
this.Logger.error('Error recovery failed', undefined, undefined, {
|
|
275
|
+
attempts,
|
|
276
|
+
errorType: category.type,
|
|
277
|
+
retryable: category.retryable,
|
|
278
|
+
error: err?.message ?? String(error),
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
isNetworkError(error) {
|
|
282
|
+
const err = error;
|
|
283
|
+
const networkCodes = ['ECONNREFUSED', 'ENOTFOUND', 'ECONNRESET', 'EPIPE'];
|
|
284
|
+
return networkCodes.includes(err?.code) || /\bnetwork\b/i.test(err?.message) || /\bconnection\b/i.test(err?.message);
|
|
285
|
+
}
|
|
286
|
+
isTimeoutError(error) {
|
|
287
|
+
const err = error;
|
|
288
|
+
return err?.code === 'ETIMEDOUT' ||
|
|
289
|
+
/\btimeout\b|\btimed out\b/i.test(err?.message);
|
|
290
|
+
}
|
|
291
|
+
isDatabaseError(error) {
|
|
292
|
+
const err = error;
|
|
293
|
+
return /\bconnection\b/i.test(err?.message) &&
|
|
294
|
+
(/\bdatabase\b/i.test(err?.message) ||
|
|
295
|
+
/\bmongodb\b/i.test(err?.message) ||
|
|
296
|
+
/\bredis\b/i.test(err?.message));
|
|
297
|
+
}
|
|
298
|
+
isBadRequestError(error) {
|
|
299
|
+
const err = error;
|
|
300
|
+
return err?.status === HTTP_STATUS_BAD_REQUEST ||
|
|
301
|
+
err?.status === HTTP_STATUS_UNPROCESSABLE_ENTITY;
|
|
302
|
+
}
|
|
303
|
+
isValidationError(error) {
|
|
304
|
+
const err = error;
|
|
305
|
+
return /\bvalidation\b/i.test(err?.message) ||
|
|
306
|
+
err?.name === 'ValidationError';
|
|
307
|
+
}
|
|
308
|
+
isAuthError(error) {
|
|
309
|
+
const err = error;
|
|
310
|
+
return err?.status === HTTP_STATUS_UNAUTHORIZED || /\bunauthorized\b/i.test(err?.message) ||
|
|
311
|
+
/\bauthentication\b/i.test(err?.message);
|
|
312
|
+
}
|
|
313
|
+
isAuthzError(error) {
|
|
314
|
+
const err = error;
|
|
315
|
+
return err?.status === HTTP_STATUS_FORBIDDEN || /\bforbidden\b/i.test(err?.message) ||
|
|
316
|
+
/\bauthorization\b/i.test(err?.message);
|
|
317
|
+
}
|
|
318
|
+
isNotFoundError(error) {
|
|
319
|
+
const err = error;
|
|
320
|
+
return err?.status === HTTP_STATUS_NOT_FOUND || /\bnot found\b/i.test(err?.message);
|
|
321
|
+
}
|
|
322
|
+
isServerError(error) {
|
|
323
|
+
const err = error;
|
|
324
|
+
return err?.status === HTTP_STATUS_BAD_GATEWAY ||
|
|
325
|
+
err?.status === HTTP_STATUS_SERVICE_UNAVAILABLE ||
|
|
326
|
+
err?.status === HTTP_STATUS_GATEWAY_TIMEOUT;
|
|
327
|
+
}
|
|
328
|
+
isRateLimitError(error) {
|
|
329
|
+
const err = error;
|
|
330
|
+
return err?.status === HTTP_STATUS_TOO_MANY_REQUESTS || /\brate limit\b/i.test(err?.message) ||
|
|
331
|
+
/\btoo many requests\b/i.test(err?.message);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
ErrorCategorizerService = ErrorCategorizerService_1 = __decorate([
|
|
335
|
+
Injectable(),
|
|
336
|
+
__metadata("design:paramtypes", [ModuleRef])
|
|
337
|
+
], ErrorCategorizerService);
|
|
338
|
+
export { ErrorCategorizerService };
|
|
339
|
+
//# sourceMappingURL=error-categorizer.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-categorizer.service.js","sourceRoot":"","sources":["../../../src/common/services/error-categorizer.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { ModuleRef } from '@nestjs/core';
|
|
2
|
+
import { LazyModuleRefService } from '../utils/lazy-getter.types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Options for configuring the ErrorSanitizerService.
|
|
5
|
+
*/
|
|
6
|
+
export interface ErrorSanitizerOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Additional regex patterns to apply for message sanitization.
|
|
9
|
+
*/
|
|
10
|
+
additionalPatterns?: RegExp[];
|
|
11
|
+
/**
|
|
12
|
+
* Additional field names to treat as sensitive and redact.
|
|
13
|
+
*/
|
|
14
|
+
additionalSensitiveKeys?: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Injection token for ErrorSanitizerService configuration.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ERROR_SANITIZER_OPTIONS = "ERROR_SANITIZER_OPTIONS";
|
|
20
|
+
/**
|
|
21
|
+
* Error Sanitizer Service.
|
|
22
|
+
* Sanitizes error responses and error context to prevent information disclosure in production.
|
|
23
|
+
* Removes sensitive information like stack traces, file paths, database URIs, API keys, email addresses,
|
|
24
|
+
* IP addresses, and custom sensitive fields.
|
|
25
|
+
*
|
|
26
|
+
* Implements defense-in-depth by sanitizing:
|
|
27
|
+
* - Error messages (via regex patterns)
|
|
28
|
+
* - Nested context objects (via field name matching)
|
|
29
|
+
* - Stack traces (removed in production)
|
|
30
|
+
*
|
|
31
|
+
* Sensitive patterns redacted:
|
|
32
|
+
* - File paths (e.g., `/home/user/app.ts` -> `[FILE]`)
|
|
33
|
+
* - Database URIs (e.g., `mongodb://...` -> `[REDACTED]`)
|
|
34
|
+
* - API keys and tokens (e.g., `Bearer sk_live_...` -> `Bearer [REDACTED]`)
|
|
35
|
+
* - Email addresses (e.g., `user@example.com` -> `[EMAIL]`)
|
|
36
|
+
* - IP addresses (IPv4 and IPv6) -> `[IP]`
|
|
37
|
+
* - Sensitive field values (passwords, tokens, API keys, etc.) -> `***REDACTED***`
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* - Maximum message length: 5000 chars (prevents ReDoS attacks on regex patterns)
|
|
41
|
+
* - Maximum context depth: 5 levels (prevents deeply nested structure processing)
|
|
42
|
+
* - Circular reference detection prevents infinite loops
|
|
43
|
+
* - Case-insensitive field name matching for sensitivity
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const error = {
|
|
48
|
+
* message: 'Error at /home/user/app.ts, Bearer sk_live_abc123',
|
|
49
|
+
* context: { password: 'secret123', userId: '456' }
|
|
50
|
+
* };
|
|
51
|
+
* const sanitized = errorSanitizer.sanitizeErrorResponse(error, false);
|
|
52
|
+
* // message: 'Error at [FILE], Bearer [REDACTED]'
|
|
53
|
+
* // context: { password: '***REDACTED***', userId: '456' }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare class ErrorSanitizerService implements LazyModuleRefService {
|
|
57
|
+
/**
|
|
58
|
+
* Maximum length for error messages before truncation.
|
|
59
|
+
* Prevents ReDoS (Regular Expression Denial of Service) attacks by limiting
|
|
60
|
+
* the input size to regex patterns used in message sanitization.
|
|
61
|
+
*/
|
|
62
|
+
private static readonly MAX_MESSAGE_LENGTH;
|
|
63
|
+
/**
|
|
64
|
+
* Maximum nesting depth for context object serialization.
|
|
65
|
+
* Prevents deeply nested structures from causing performance issues.
|
|
66
|
+
*/
|
|
67
|
+
private static readonly MAX_CONTEXT_DEPTH;
|
|
68
|
+
/**
|
|
69
|
+
* Precompiled regex pattern for matching file paths with code extensions
|
|
70
|
+
* Used to redact file paths from error messages
|
|
71
|
+
*/
|
|
72
|
+
private static readonly FILE_PATH_REGEX;
|
|
73
|
+
/**
|
|
74
|
+
* Precompiled regex pattern for matching IPv4 addresses
|
|
75
|
+
*/
|
|
76
|
+
private static readonly IPV4_REGEX;
|
|
77
|
+
/**
|
|
78
|
+
* Precompiled regex pattern for matching IPv6 addresses
|
|
79
|
+
* Covers various IPv6 formats: full form, compressed form, ::1, ::ffff:IPv4, bare ::
|
|
80
|
+
* Uses a simpler, non-backtracking pattern to avoid ReDoS (Regular Expression Denial of Service)
|
|
81
|
+
*/
|
|
82
|
+
private static readonly IPV6_REGEX;
|
|
83
|
+
/**
|
|
84
|
+
* Default sensitive field names that are always redacted from context
|
|
85
|
+
* Stored as lowercase for case-insensitive matching
|
|
86
|
+
*/
|
|
87
|
+
private static readonly DEFAULT_SENSITIVE_KEYS;
|
|
88
|
+
readonly Module: ModuleRef;
|
|
89
|
+
constructor(module: ModuleRef);
|
|
90
|
+
private get Options();
|
|
91
|
+
/**
|
|
92
|
+
* Sanitize error response for client
|
|
93
|
+
* Removes sensitive information like stack traces, file paths, etc.
|
|
94
|
+
*/
|
|
95
|
+
sanitizeErrorResponse(error: Record<string, any>, isDevelopment?: boolean): Record<string, any>;
|
|
96
|
+
/**
|
|
97
|
+
* Sanitize an error message to remove sensitive information.
|
|
98
|
+
* Redacts file paths, database connection strings, API keys, Bearer tokens,
|
|
99
|
+
* email addresses, and IP addresses. Truncates overly long messages to prevent
|
|
100
|
+
* ReDoS attacks and ensure reasonable log sizes.
|
|
101
|
+
*
|
|
102
|
+
* @param message - The error message string to sanitize
|
|
103
|
+
* @returns Sanitized message with sensitive patterns replaced by placeholder strings
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const msg = 'Error at /home/user/app.ts, Bearer sk_live_abc123';
|
|
108
|
+
* const sanitized = sanitizeMessage(msg);
|
|
109
|
+
* // Returns: 'Error at [FILE], Bearer [REDACTED]'
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
private sanitizeMessage;
|
|
113
|
+
/**
|
|
114
|
+
* Recursively sanitize an error context object to remove sensitive field values.
|
|
115
|
+
* Identifies sensitive fields by name (e.g., password, token, secret) and replaces
|
|
116
|
+
* their values with a redaction marker. Handles nested objects and arrays while
|
|
117
|
+
* detecting circular references to prevent infinite loops.
|
|
118
|
+
*
|
|
119
|
+
* @param context - The context object to sanitize
|
|
120
|
+
* @returns Sanitized context with sensitive field values replaced
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const ctx = { user: 'john', password: 'secret123', nested: { apiKey: 'sk_live' } };
|
|
125
|
+
* const sanitized = sanitizeContext(ctx);
|
|
126
|
+
* // Returns: { user: 'john', password: '***REDACTED***', nested: { apiKey: '***REDACTED***' } }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
private sanitizeContext;
|
|
130
|
+
/**
|
|
131
|
+
* Recursively serialize an object with depth limiting and circular reference detection.
|
|
132
|
+
* Handles nested objects and arrays while preventing infinite loops.
|
|
133
|
+
*
|
|
134
|
+
* @param obj - The object to serialize
|
|
135
|
+
* @param maxDepth - Maximum nesting depth (default 5)
|
|
136
|
+
* @param currentDepth - Current recursion depth
|
|
137
|
+
* @param seen - Set of already-visited objects to detect cycles
|
|
138
|
+
* @returns Serialized object with sensitive fields redacted
|
|
139
|
+
*/
|
|
140
|
+
private serializeWithDepthLimit;
|
|
141
|
+
/**
|
|
142
|
+
* Check if field is sensitive (case-insensitive comparison)
|
|
143
|
+
*/
|
|
144
|
+
private isSensitiveField;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=error-sanitizer.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-sanitizer.service.d.ts","sourceRoot":"","sources":["../../../src/common/services/error-sanitizer.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;OAEG;IACH,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;CACnC;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,qBACa,qBAAsB,YAAW,oBAAoB;IACjE;;;;OAIG;IAEH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAElD;;;OAGG;IAEH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAK;IAE9C;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAqE;IAE5G;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAEpE;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAqgB;IAEviB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CA+B5C;IAEF,SAAgB,MAAM,EAAE,SAAS,CAAC;gBAEtB,MAAM,EAAE,SAAS;IAI7B,OAAO,KAAK,OAAO,GAMlB;IAED;;;OAGG;IACI,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,aAAa,GAAE,OAAe,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAoB7G;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,eAAe;IAkDvB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,eAAe;IAWvB;;;;;;;;;OASG;IACH,OAAO,CAAC,uBAAuB;IA6D/B;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAWxB"}
|