@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,165 @@
|
|
|
1
|
+
import { performance } from 'node:perf_hooks';
|
|
2
|
+
/**
|
|
3
|
+
* Module-level singleton holder for InstrumentationRegistry.
|
|
4
|
+
*
|
|
5
|
+
* The @Instrument() decorator uses this holder to access the registry
|
|
6
|
+
* without requiring direct DI into every decorated method.
|
|
7
|
+
*
|
|
8
|
+
* Set during application bootstrap by CommonModule.onModuleInit().
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // In CommonModule.onModuleInit()
|
|
13
|
+
* InstrumentationRegistryHolder.setInstance(this.registry);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export class InstrumentationRegistryHolder {
|
|
17
|
+
/**
|
|
18
|
+
* Singleton instance of InstrumentationRegistry
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
21
|
+
static instance = null;
|
|
22
|
+
/**
|
|
23
|
+
* Set the singleton instance.
|
|
24
|
+
* Called during application bootstrap.
|
|
25
|
+
*
|
|
26
|
+
* @param registry - The InstrumentationRegistry instance
|
|
27
|
+
*/
|
|
28
|
+
static setInstance(registry) {
|
|
29
|
+
InstrumentationRegistryHolder.instance = registry;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the singleton instance.
|
|
33
|
+
*
|
|
34
|
+
* @returns The InstrumentationRegistry instance, or null if not yet set
|
|
35
|
+
*/
|
|
36
|
+
static getInstance() {
|
|
37
|
+
return InstrumentationRegistryHolder.instance;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Method decorator for automatic metrics instrumentation.
|
|
42
|
+
*
|
|
43
|
+
* Automatically records method timing (histogram), success counters, and error counters
|
|
44
|
+
* using the InstrumentationRegistry. Metric descriptors are auto-registered on first use.
|
|
45
|
+
*
|
|
46
|
+
* Supports both synchronous and asynchronous (Promise-returning) methods.
|
|
47
|
+
*
|
|
48
|
+
* @param options - Instrumentation configuration (timing, counters, errorCounters, labels)
|
|
49
|
+
* @returns MethodDecorator
|
|
50
|
+
*
|
|
51
|
+
* @throws Error if a metric name is not registered (only if registry is available)
|
|
52
|
+
* @throws The original error if the decorated method throws/rejects
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* class UserService {
|
|
57
|
+
* @Instrument({
|
|
58
|
+
* timing: 'user_service_create_duration_seconds',
|
|
59
|
+
* counters: ['user_service_create_total'],
|
|
60
|
+
* errorCounters: ['user_service_create_errors'],
|
|
61
|
+
* labels: { service: 'user' },
|
|
62
|
+
* })
|
|
63
|
+
* async create(userData: CreateUserDto): Promise<User> {
|
|
64
|
+
* return this.repository.save(userData);
|
|
65
|
+
* }
|
|
66
|
+
*
|
|
67
|
+
* @Instrument({
|
|
68
|
+
* timing: 'user_service_find_by_id_duration_seconds',
|
|
69
|
+
* counters: ['user_service_find_by_id_total'],
|
|
70
|
+
* errorCounters: ['user_service_find_by_id_errors'],
|
|
71
|
+
* labels: (id: string) => ({ userId: id }),
|
|
72
|
+
* })
|
|
73
|
+
* async findById(id: string): Promise<User | null> {
|
|
74
|
+
* return this.repository.findOne(id);
|
|
75
|
+
* }
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function Instrument(options) {
|
|
80
|
+
return (target, propertyKey, descriptor) => {
|
|
81
|
+
const originalMethod = descriptor.value;
|
|
82
|
+
descriptor.value = function instrumentMethod(...args) {
|
|
83
|
+
// Resolve labels: static object or computed from arguments
|
|
84
|
+
const labels = typeof options.labels === 'function'
|
|
85
|
+
? options.labels(...args)
|
|
86
|
+
: options.labels ?? {};
|
|
87
|
+
// Get registry from singleton holder
|
|
88
|
+
const registry = InstrumentationRegistryHolder.getInstance();
|
|
89
|
+
// If registry not available (e.g., during early bootstrap), just call original
|
|
90
|
+
if (!registry) {
|
|
91
|
+
return originalMethod.apply(this, args);
|
|
92
|
+
}
|
|
93
|
+
// Auto-register metric descriptors on first invocation
|
|
94
|
+
if (options.timing) {
|
|
95
|
+
registry.registerDescriptor({
|
|
96
|
+
name: options.timing,
|
|
97
|
+
type: 'histogram',
|
|
98
|
+
help: `Duration of ${String(propertyKey)}`,
|
|
99
|
+
labelNames: Object.keys(labels),
|
|
100
|
+
unit: 'seconds',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
for (const counterName of options.counters ?? []) {
|
|
104
|
+
registry.registerDescriptor({
|
|
105
|
+
name: counterName,
|
|
106
|
+
type: 'counter',
|
|
107
|
+
help: `${String(propertyKey)} invocation count`,
|
|
108
|
+
labelNames: Object.keys(labels),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
for (const errorCounterName of options.errorCounters ?? []) {
|
|
112
|
+
registry.registerDescriptor({
|
|
113
|
+
name: errorCounterName,
|
|
114
|
+
type: 'counter',
|
|
115
|
+
help: `${String(propertyKey)} error count`,
|
|
116
|
+
labelNames: Object.keys(labels),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
// Record start time
|
|
120
|
+
const startTime = performance.now();
|
|
121
|
+
/**
|
|
122
|
+
* Handle successful completion.
|
|
123
|
+
* Records timing and success counters.
|
|
124
|
+
*/
|
|
125
|
+
const handleSuccess = () => {
|
|
126
|
+
// eslint-disable-next-line no-magic-numbers
|
|
127
|
+
const durationSeconds = (performance.now() - startTime) / 1000; // Convert to seconds
|
|
128
|
+
if (options.timing) {
|
|
129
|
+
registry.recordMetric(options.timing, durationSeconds, labels);
|
|
130
|
+
}
|
|
131
|
+
for (const counterName of options.counters ?? []) {
|
|
132
|
+
registry.recordMetric(counterName, 1, labels);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Handle error.
|
|
137
|
+
* Records error counters and rethrows the error.
|
|
138
|
+
*/
|
|
139
|
+
const handleError = (err) => {
|
|
140
|
+
for (const errorCounterName of options.errorCounters ?? []) {
|
|
141
|
+
registry.recordMetric(errorCounterName, 1, labels);
|
|
142
|
+
}
|
|
143
|
+
throw err; // Always rethrow original error
|
|
144
|
+
};
|
|
145
|
+
try {
|
|
146
|
+
const result = originalMethod.apply(this, args);
|
|
147
|
+
// Check if result is a Promise (async method)
|
|
148
|
+
if (result instanceof Promise) {
|
|
149
|
+
return result.then((value) => {
|
|
150
|
+
handleSuccess();
|
|
151
|
+
return value;
|
|
152
|
+
}, (err) => handleError(err));
|
|
153
|
+
}
|
|
154
|
+
// Synchronous method
|
|
155
|
+
handleSuccess();
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
return handleError(err);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
return descriptor;
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=instrument.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument.decorator.js","sourceRoot":"","sources":["../../../src/common/decorators/instrument.decorator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Counter, Gauge, Histogram, Summary } from 'prom-client';
|
|
2
|
+
/**
|
|
3
|
+
* Metric decorators for easy injection of Prometheus metrics
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Inject a Counter metric
|
|
7
|
+
*/
|
|
8
|
+
export declare const InjectCounter: (name: string) => ParameterDecorator;
|
|
9
|
+
/**
|
|
10
|
+
* Inject a Gauge metric
|
|
11
|
+
*/
|
|
12
|
+
export declare const InjectGauge: (name: string) => ParameterDecorator;
|
|
13
|
+
/**
|
|
14
|
+
* Inject a Histogram metric
|
|
15
|
+
*/
|
|
16
|
+
export declare const InjectHistogram: (name: string) => ParameterDecorator;
|
|
17
|
+
/**
|
|
18
|
+
* Inject a Summary metric
|
|
19
|
+
*/
|
|
20
|
+
export declare const InjectSummary: (name: string) => ParameterDecorator;
|
|
21
|
+
/**
|
|
22
|
+
* Metric creation utilities
|
|
23
|
+
*/
|
|
24
|
+
export declare class MetricFactory {
|
|
25
|
+
/**
|
|
26
|
+
* Create a counter metric
|
|
27
|
+
*/
|
|
28
|
+
static createCounter(name: string, help: string, labelNames?: string[]): Counter<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Create a gauge metric
|
|
31
|
+
*/
|
|
32
|
+
static createGauge(name: string, help: string, labelNames?: string[]): Gauge<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Create a histogram metric
|
|
35
|
+
*/
|
|
36
|
+
static createHistogram(name: string, help: string, labelNames?: string[], buckets?: number[]): Histogram<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Create a summary metric
|
|
39
|
+
*/
|
|
40
|
+
static createSummary(name: string, help: string, labelNames?: string[], percentiles?: number[]): Summary<string>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=metric.decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric.decorators.d.ts","sourceRoot":"","sources":["../../../src/common/decorators/metric.decorators.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEjE;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,kBAA2D,CAAC;AAEzG;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,kBAAyD,CAAC;AAErG;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,kBAA6D,CAAC;AAE7G;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,kBAA2D,CAAC;AAEzG;;GAEG;AACH,qBAAa,aAAa;IACzB;;OAEG;WACW,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAW/F;;OAEG;WACW,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;IAW3F;;OAEG;WACW,eAAe,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,EAAE,EACrB,OAAO,CAAC,EAAE,MAAM,EAAE,GAChB,SAAS,CAAC,MAAM,CAAC;IAcpB;;OAEG;WACW,aAAa,CAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,EAAE,EACrB,WAAW,CAAC,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,MAAM,CAAC;CAalB"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Inject } from '@nestjs/common';
|
|
2
|
+
import { Counter, Gauge, Histogram, Summary } from 'prom-client';
|
|
3
|
+
/**
|
|
4
|
+
* Metric decorators for easy injection of Prometheus metrics
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Inject a Counter metric
|
|
8
|
+
*/
|
|
9
|
+
export const InjectCounter = (name) => Inject(`PROM_METRIC_COUNTER_${name}`);
|
|
10
|
+
/**
|
|
11
|
+
* Inject a Gauge metric
|
|
12
|
+
*/
|
|
13
|
+
export const InjectGauge = (name) => Inject(`PROM_METRIC_GAUGE_${name}`);
|
|
14
|
+
/**
|
|
15
|
+
* Inject a Histogram metric
|
|
16
|
+
*/
|
|
17
|
+
export const InjectHistogram = (name) => Inject(`PROM_METRIC_HISTOGRAM_${name}`);
|
|
18
|
+
/**
|
|
19
|
+
* Inject a Summary metric
|
|
20
|
+
*/
|
|
21
|
+
export const InjectSummary = (name) => Inject(`PROM_METRIC_SUMMARY_${name}`);
|
|
22
|
+
/**
|
|
23
|
+
* Metric creation utilities
|
|
24
|
+
*/
|
|
25
|
+
export class MetricFactory {
|
|
26
|
+
/**
|
|
27
|
+
* Create a counter metric
|
|
28
|
+
*/
|
|
29
|
+
static createCounter(name, help, labelNames) {
|
|
30
|
+
const config = {
|
|
31
|
+
name,
|
|
32
|
+
help,
|
|
33
|
+
};
|
|
34
|
+
if (labelNames !== undefined) {
|
|
35
|
+
config.labelNames = labelNames;
|
|
36
|
+
}
|
|
37
|
+
return new Counter(config);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create a gauge metric
|
|
41
|
+
*/
|
|
42
|
+
static createGauge(name, help, labelNames) {
|
|
43
|
+
const config = {
|
|
44
|
+
name,
|
|
45
|
+
help,
|
|
46
|
+
};
|
|
47
|
+
if (labelNames !== undefined) {
|
|
48
|
+
config.labelNames = labelNames;
|
|
49
|
+
}
|
|
50
|
+
return new Gauge(config);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a histogram metric
|
|
54
|
+
*/
|
|
55
|
+
static createHistogram(name, help, labelNames, buckets) {
|
|
56
|
+
const config = {
|
|
57
|
+
name,
|
|
58
|
+
help,
|
|
59
|
+
};
|
|
60
|
+
if (labelNames !== undefined) {
|
|
61
|
+
config.labelNames = labelNames;
|
|
62
|
+
}
|
|
63
|
+
if (buckets !== undefined) {
|
|
64
|
+
config.buckets = buckets;
|
|
65
|
+
}
|
|
66
|
+
return new Histogram(config);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Create a summary metric
|
|
70
|
+
*/
|
|
71
|
+
static createSummary(name, help, labelNames, percentiles) {
|
|
72
|
+
const config = {
|
|
73
|
+
name,
|
|
74
|
+
help,
|
|
75
|
+
};
|
|
76
|
+
if (labelNames !== undefined) {
|
|
77
|
+
config.labelNames = labelNames;
|
|
78
|
+
}
|
|
79
|
+
if (percentiles !== undefined) {
|
|
80
|
+
config.percentiles = percentiles;
|
|
81
|
+
}
|
|
82
|
+
return new Summary(config);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=metric.decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric.decorators.js","sourceRoot":"","sources":["../../../src/common/decorators/metric.decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEjE;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAsB,EAAE,CAAC,MAAM,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;AAEzG;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAsB,EAAE,CAAC,MAAM,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;AAErG;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAY,EAAsB,EAAE,CAAC,MAAM,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;AAE7G;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAsB,EAAE,CAAC,MAAM,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;AAEzG;;GAEG;AACH,MAAM,OAAO,aAAa;IACzB;;OAEG;IACI,MAAM,CAAC,aAAa,CAAC,IAAY,EAAE,IAAY,EAAE,UAAqB;QAC5E,MAAM,MAAM,GAA0D;YACrE,IAAI;YACJ,IAAI;SACJ,CAAC;QACF,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAChC,CAAC;QACD,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,WAAW,CAAC,IAAY,EAAE,IAAY,EAAE,UAAqB;QAC1E,MAAM,MAAM,GAA0D;YACrE,IAAI;YACJ,IAAI;SACJ,CAAC;QACF,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAChC,CAAC;QACD,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,eAAe,CAC5B,IAAY,EACZ,IAAY,EACZ,UAAqB,EACrB,OAAkB;QAElB,MAAM,MAAM,GAA8E;YACzF,IAAI;YACJ,IAAI;SACJ,CAAC;QACF,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAChC,CAAC;QACD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,aAAa,CAC1B,IAAY,EACZ,IAAY,EACZ,UAAqB,EACrB,WAAsB;QAEtB,MAAM,MAAM,GAAkF;YAC7F,IAAI;YACJ,IAAI;SACJ,CAAC;QACF,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAChC,CAAC;QACD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;CACD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { AppLogger } from '../services/logger.service.js';
|
|
2
|
+
/**
|
|
3
|
+
* Options for the RequestProperty decorator
|
|
4
|
+
*/
|
|
5
|
+
export interface RequestPropertyOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Default value to return if the property is not found
|
|
8
|
+
*/
|
|
9
|
+
defaultValue?: any;
|
|
10
|
+
/**
|
|
11
|
+
* Whether to throw an error if the property is not found (overrides defaultValue)
|
|
12
|
+
*/
|
|
13
|
+
required?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Transform function to apply to the extracted value
|
|
16
|
+
*/
|
|
17
|
+
transform?: (value: any) => any;
|
|
18
|
+
/**
|
|
19
|
+
* Fallback paths to try if the primary path is not found
|
|
20
|
+
*/
|
|
21
|
+
fallbackPaths?: string[];
|
|
22
|
+
/**
|
|
23
|
+
* Whether to log missing properties (for debugging)
|
|
24
|
+
*/
|
|
25
|
+
logMissing?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Sets the AppLogger instance for use in the decorator
|
|
29
|
+
* This should be called during module initialization
|
|
30
|
+
* @param logger - The AppLogger instance
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export declare function SetRequestPropertyDecoratorLogger(logger: AppLogger): void;
|
|
34
|
+
/**
|
|
35
|
+
* Generic Request Property Decorator Factory
|
|
36
|
+
*
|
|
37
|
+
* Extracts any property from the HTTP request object using dot notation paths.
|
|
38
|
+
* Supports nested property access, type safety, and transformations.
|
|
39
|
+
*
|
|
40
|
+
* @param path - Dot-notation path to the property (e.g., 'user', 'query.id', 'body.data.name')
|
|
41
|
+
* @param options - Configuration options
|
|
42
|
+
* @returns Parameter decorator function
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // Extract user from request
|
|
46
|
+
* @Get()
|
|
47
|
+
* getProfile(@RequestProperty('user') user: User) {}
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // Extract nested property with default
|
|
51
|
+
* @Get()
|
|
52
|
+
* getData(@RequestProperty('query.limit', { defaultValue: 10 }) limit: number) {}
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // Extract with transformation
|
|
56
|
+
* @Post()
|
|
57
|
+
* createItem(@RequestProperty('body', { transform: (data) => validateData(data) }) data: ValidatedData) {}
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* // Required property (throws if missing)
|
|
61
|
+
* @Get()
|
|
62
|
+
* getUser(@RequestProperty('user', { required: true }) user: User) {}
|
|
63
|
+
*/
|
|
64
|
+
export declare function RequestProperty<T = any>(path: string, options?: RequestPropertyOptions): ParameterDecorator;
|
|
65
|
+
//# sourceMappingURL=request-property.decorator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-property.decorator.d.ts","sourceRoot":"","sources":["../../../src/common/decorators/request-property.decorator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAU/D;;GAEG;AAEH,MAAM,WAAW,sBAAsB;IACtC;;MAEK;IACL,YAAY,CAAC,EAAE,GAAG,CAAC;IAEnB;;MAEK;IACL,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;MAEK;IACL,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;IAEhC;;MAEK;IACL,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;MAEK;IACL,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAEzE;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,CAAC,GAAG,GAAG,EACtC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,sBAA2B,GAClC,kBAAkB,CA+CpB"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { createParamDecorator, Logger } from '@nestjs/common';
|
|
2
|
+
import { ObjectGetPropertyByPath } from '@pawells/typescript-common';
|
|
3
|
+
import { getErrorMessage } from '../utils/error.utils.js';
|
|
4
|
+
// Logger instance for decorator warnings
|
|
5
|
+
// Note: We can't use AppLogger directly here since decorators don't have DI context
|
|
6
|
+
// Instead, we use a Logger instance from @nestjs/common
|
|
7
|
+
const logger = new Logger('RequestPropertyDecorator');
|
|
8
|
+
let appLogger;
|
|
9
|
+
/**
|
|
10
|
+
* Sets the AppLogger instance for use in the decorator
|
|
11
|
+
* This should be called during module initialization
|
|
12
|
+
* @param logger - The AppLogger instance
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export function SetRequestPropertyDecoratorLogger(logger) {
|
|
16
|
+
appLogger = logger;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Logs a warning message using AppLogger if available, falls back to NestJS Logger
|
|
20
|
+
* This ensures observability capture when AppLogger is initialized
|
|
21
|
+
* @param message - The message to log
|
|
22
|
+
*/
|
|
23
|
+
function logWarning(message) {
|
|
24
|
+
// Try to use AppLogger if available, otherwise use NestJS Logger
|
|
25
|
+
if (appLogger) {
|
|
26
|
+
appLogger.warn(message);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Fallback to NestJS Logger when AppLogger is not yet initialized
|
|
30
|
+
logger.warn(message);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generic Request Property Decorator Factory
|
|
35
|
+
*
|
|
36
|
+
* Extracts any property from the HTTP request object using dot notation paths.
|
|
37
|
+
* Supports nested property access, type safety, and transformations.
|
|
38
|
+
*
|
|
39
|
+
* @param path - Dot-notation path to the property (e.g., 'user', 'query.id', 'body.data.name')
|
|
40
|
+
* @param options - Configuration options
|
|
41
|
+
* @returns Parameter decorator function
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // Extract user from request
|
|
45
|
+
* @Get()
|
|
46
|
+
* getProfile(@RequestProperty('user') user: User) {}
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // Extract nested property with default
|
|
50
|
+
* @Get()
|
|
51
|
+
* getData(@RequestProperty('query.limit', { defaultValue: 10 }) limit: number) {}
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // Extract with transformation
|
|
55
|
+
* @Post()
|
|
56
|
+
* createItem(@RequestProperty('body', { transform: (data) => validateData(data) }) data: ValidatedData) {}
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Required property (throws if missing)
|
|
60
|
+
* @Get()
|
|
61
|
+
* getUser(@RequestProperty('user', { required: true }) user: User) {}
|
|
62
|
+
*/
|
|
63
|
+
export function RequestProperty(path, options = {}) {
|
|
64
|
+
return createParamDecorator((_data, ctx) => {
|
|
65
|
+
const request = ctx.switchToHttp().getRequest();
|
|
66
|
+
// Try primary path first
|
|
67
|
+
let value = ObjectGetPropertyByPath(request, path);
|
|
68
|
+
// Try fallback paths if primary path didn't work
|
|
69
|
+
if (value === undefined && options.fallbackPaths) {
|
|
70
|
+
for (const fallbackPath of options.fallbackPaths) {
|
|
71
|
+
value = ObjectGetPropertyByPath(request, fallbackPath);
|
|
72
|
+
if (value !== undefined) {
|
|
73
|
+
if (options.logMissing) {
|
|
74
|
+
logWarning(`RequestProperty: Primary path '${path}' not found, using fallback '${fallbackPath}'`);
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Handle missing values
|
|
81
|
+
if (value === undefined) {
|
|
82
|
+
if (options.required) {
|
|
83
|
+
throw new Error(`Required property '${path}' not found in HTTP request`);
|
|
84
|
+
}
|
|
85
|
+
if (options.logMissing) {
|
|
86
|
+
logWarning(`RequestProperty: Property '${path}' not found, using default value`);
|
|
87
|
+
}
|
|
88
|
+
value = options.defaultValue;
|
|
89
|
+
}
|
|
90
|
+
// Apply transformation if provided
|
|
91
|
+
if (options.transform && value !== undefined) {
|
|
92
|
+
try {
|
|
93
|
+
value = options.transform(value);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
throw new Error(`RequestProperty transform failed for path '${path}': ${getErrorMessage(error)}`, { cause: error });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return value;
|
|
100
|
+
})();
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=request-property.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-property.decorator.js","sourceRoot":"","sources":["../../../src/common/decorators/request-property.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAEhF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,yCAAyC;AACzC,oFAAoF;AACpF,wDAAwD;AACxD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,0BAA0B,CAAC,CAAC;AACtD,IAAI,SAAgC,CAAC;AAiCrC;;;;;GAKG;AACH,MAAM,UAAU,iCAAiC,CAAC,MAAiB;IAClE,SAAS,GAAG,MAAM,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,OAAe;IAClC,iEAAiE;IACjE,IAAI,SAAS,EAAE,CAAC;QACf,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACP,kEAAkE;QAClE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,eAAe,CAC9B,IAAY,EACZ,UAAkC,EAAE;IAEpC,OAAO,oBAAoB,CAC1B,CAAC,KAAc,EAAE,GAAqB,EAAK,EAAE;QAC5C,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAEhD,yBAAyB;QACzB,IAAI,KAAK,GAAG,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAEnD,iDAAiD;QACjD,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAClD,KAAK,MAAM,YAAY,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAClD,KAAK,GAAG,uBAAuB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;gBACvD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBACzB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;wBACxB,UAAU,CAAC,kCAAkC,IAAI,gCAAgC,YAAY,GAAG,CAAC,CAAC;oBACnG,CAAC;oBACD,MAAM;gBACP,CAAC;YACF,CAAC;QACF,CAAC;QAED,wBAAwB;QACxB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,6BAA6B,CAAC,CAAC;YAC1E,CAAC;YACD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;gBACxB,UAAU,CAAC,8BAA8B,IAAI,kCAAkC,CAAC,CAAC;YAClF,CAAC;YACD,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC;QAC9B,CAAC;QAED,mCAAmC;QACnC,IAAI,OAAO,CAAC,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACJ,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CACd,8CAA8C,IAAI,MAAM,eAAe,CAAC,KAAK,CAAC,EAAE,EAChF,EAAE,KAAK,EAAE,KAAK,EAAE,CAChB,CAAC;YACH,CAAC;QACF,CAAC;QAED,OAAO,KAAU,CAAC;IACnB,CAAC,CACD,EAAE,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Application Error
|
|
3
|
+
*
|
|
4
|
+
* Provides a standardized error structure for NestJS applications with consistent
|
|
5
|
+
* properties and methods for error handling, serialization, and context management.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* throw new BaseApplicationError('User not found', {
|
|
10
|
+
* code: 'USER_NOT_FOUND',
|
|
11
|
+
* statusCode: 404,
|
|
12
|
+
* context: { userId: '123' }
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare class BaseApplicationError extends Error {
|
|
17
|
+
/**
|
|
18
|
+
* The HTTP status code associated with this error
|
|
19
|
+
*/
|
|
20
|
+
readonly statusCode: number;
|
|
21
|
+
/**
|
|
22
|
+
* The error code for programmatic error identification
|
|
23
|
+
*/
|
|
24
|
+
readonly code: string;
|
|
25
|
+
/**
|
|
26
|
+
* Additional context information for debugging and logging
|
|
27
|
+
*/
|
|
28
|
+
readonly context: Record<string, any>;
|
|
29
|
+
/**
|
|
30
|
+
* Timestamp when the error was created
|
|
31
|
+
*/
|
|
32
|
+
readonly timestamp: Date;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new BaseApplicationError instance
|
|
35
|
+
*
|
|
36
|
+
* @param message - The error message
|
|
37
|
+
* @param options - Configuration options for the error
|
|
38
|
+
* @param options.code - The error code (defaults to 'INTERNAL_SERVER_ERROR')
|
|
39
|
+
* @param options.statusCode - The HTTP status code (defaults to 500)
|
|
40
|
+
* @param options.context - Additional context information (defaults to empty object)
|
|
41
|
+
*/
|
|
42
|
+
constructor(message: string, options?: {
|
|
43
|
+
code?: string;
|
|
44
|
+
statusCode?: number;
|
|
45
|
+
context?: Record<string, any>;
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Serializes the error to a plain object for JSON responses or logging
|
|
49
|
+
*
|
|
50
|
+
* @returns A plain object representation of the error
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const error = new BaseApplicationError('Test error');
|
|
55
|
+
* console.log(error.toJSON());
|
|
56
|
+
* // {
|
|
57
|
+
* // name: 'BaseApplicationError',
|
|
58
|
+
* // message: 'Test error',
|
|
59
|
+
* // code: 'INTERNAL_SERVER_ERROR',
|
|
60
|
+
* // statusCode: 500,
|
|
61
|
+
* // context: {},
|
|
62
|
+
* // timestamp: '2023-01-01T00:00:00.000Z'
|
|
63
|
+
* // }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
toJSON(): Record<string, any>;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a new error instance with additional context merged into the existing context.
|
|
69
|
+
* Note: Returns a new instance, not the same instance, so instanceof checks will still work.
|
|
70
|
+
*
|
|
71
|
+
* @param additionalContext - Additional context to merge
|
|
72
|
+
* @returns A new error instance of the same type with merged context
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const error = new BaseApplicationError('User error', { code: 'USER_ERROR' });
|
|
77
|
+
* const errorWithContext = error.withContext({ userId: '123', action: 'login' });
|
|
78
|
+
* // errorWithContext is a new instance but still instanceof BaseApplicationError
|
|
79
|
+
* // errorWithContext.context = { userId: '123', action: 'login' }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
withContext(additionalContext: Record<string, any>): this;
|
|
83
|
+
/**
|
|
84
|
+
* Creates a new error instance with a different message
|
|
85
|
+
*
|
|
86
|
+
* @param newMessage - The new error message
|
|
87
|
+
* @returns A new error instance with the updated message
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const error = new BaseApplicationError('Generic error');
|
|
92
|
+
* const specificError = error.withMessage('User not found');
|
|
93
|
+
* // specificError.message = 'User not found'
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
withMessage(newMessage: string): this;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=base-application-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-application-error.d.ts","sourceRoot":"","sources":["../../../src/common/errors/base-application-error.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C;;OAEG;IACH,SAAgB,UAAU,EAAE,MAAM,CAAC;IAEnC;;OAEG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,SAAgB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE7C;;OAEG;IACH,SAAgB,SAAS,EAAE,IAAI,CAAC;IAEhC;;;;;;;;OAQG;gBAEF,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACzB;IAkBP;;;;;;;;;;;;;;;;;;OAkBG;IACI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAapC;;;;;;;;;;;;;;OAcG;IACI,WAAW,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAchE;;;;;;;;;;;;OAYG;IACI,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAY5C"}
|