@pawells/nestjs-shared 1.0.0-dev.4c8c698
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,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pawells/nestjs-shared - Lazy Module Ref Pattern Utilities
|
|
3
|
+
*
|
|
4
|
+
* This file provides type definitions and utilities for implementing the lazy ModuleRef
|
|
5
|
+
* dependency injection pattern. This pattern enables deferred dependency resolution,
|
|
6
|
+
* reducing constructor complexity and enabling circular dependency handling.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link .claude/skills/lazy-module-ref-pattern.md} - Comprehensive pattern guide
|
|
9
|
+
*/
|
|
10
|
+
import { ModuleRef } from '@nestjs/core';
|
|
11
|
+
/**
|
|
12
|
+
* Type for a lazy-loaded getter that retrieves a dependency from ModuleRef
|
|
13
|
+
*
|
|
14
|
+
* @template T - The type of dependency being retrieved
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* public get Logger(): AppLogger {
|
|
19
|
+
* return this.Module.get(AppLogger);
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export type LazyGetter<T> = () => T;
|
|
24
|
+
/**
|
|
25
|
+
* Type for an optional lazy-loaded getter that may return undefined
|
|
26
|
+
*
|
|
27
|
+
* @template T - The type of dependency being retrieved
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* public get OptionalConfig(): ConfigService | undefined {
|
|
32
|
+
* try {
|
|
33
|
+
* return this.Module.get(ConfigService, { strict: false });
|
|
34
|
+
* } catch {
|
|
35
|
+
* return undefined;
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export type OptionalLazyGetter<T> = () => T | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Type for a lazy-loaded getter using a string-based injection token
|
|
43
|
+
*
|
|
44
|
+
* @template T - The type of dependency being retrieved
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* public get PubSub(): PubSub {
|
|
49
|
+
* return this.Module.get('PUB_SUB');
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export type TokenLazyGetter<T> = (token: string) => T;
|
|
54
|
+
/**
|
|
55
|
+
* Interface for a service using lazy ModuleRef pattern
|
|
56
|
+
*
|
|
57
|
+
* Services implementing this pattern should have ModuleRef as their only
|
|
58
|
+
* constructor dependency and provide typed getters for accessing other services.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* @Injectable()
|
|
63
|
+
* export class ExampleService implements LazyModuleRefService {
|
|
64
|
+
* constructor(public readonly Module: ModuleRef) {}
|
|
65
|
+
*
|
|
66
|
+
* public get SomeService(): SomeServiceType {
|
|
67
|
+
* return this.Module.get(SomeServiceType);
|
|
68
|
+
* }
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export interface LazyModuleRefService {
|
|
73
|
+
/**
|
|
74
|
+
* The ModuleRef instance for lazy dependency resolution
|
|
75
|
+
* This should be the ONLY injected dependency
|
|
76
|
+
*/
|
|
77
|
+
Module: ModuleRef;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Utility type to extract dependencies from a service with lazy getters
|
|
81
|
+
*
|
|
82
|
+
* Maps getter names to their return types for documentation and type inference.
|
|
83
|
+
*
|
|
84
|
+
* @template S - The service type with lazy getters
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* type AuthServiceDeps = LazyGetterDependencies<AuthService>;
|
|
89
|
+
* // Results in: { Config: ConfigService, Logger: AppLogger }
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export type LazyGetterDependencies<S> = {
|
|
93
|
+
[K in keyof S as S[K] extends LazyGetter<any> ? K : never]: S[K] extends LazyGetter<infer T> ? T : never;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Configuration for optional dependency resolution
|
|
97
|
+
* Used when a service may not be registered in the module
|
|
98
|
+
*/
|
|
99
|
+
export interface OptionalGetterConfig {
|
|
100
|
+
/**
|
|
101
|
+
* Set to false to return undefined instead of throwing if not found
|
|
102
|
+
* @default true
|
|
103
|
+
*/
|
|
104
|
+
strict?: boolean;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Utility function to create a memoized lazy getter
|
|
108
|
+
* Caches the resolved dependency to avoid repeated lookups
|
|
109
|
+
*
|
|
110
|
+
* @template T - The type of dependency
|
|
111
|
+
* @param getterFn - Function that retrieves the dependency
|
|
112
|
+
* @returns A memoized getter function
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* private _cachedService: ServiceType | undefined;
|
|
117
|
+
*
|
|
118
|
+
* public get Service(): ServiceType {
|
|
119
|
+
* if (!this._cachedService) {
|
|
120
|
+
* this._cachedService = this.Module.get(ServiceType);
|
|
121
|
+
* }
|
|
122
|
+
* return this._cachedService;
|
|
123
|
+
* }
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
export declare function CreateMemoizedLazyGetter<T>(getterFn: () => T): () => T;
|
|
127
|
+
/**
|
|
128
|
+
* Utility function to create a lazy getter with error handling for optional dependencies
|
|
129
|
+
*
|
|
130
|
+
* @template T - The type of dependency
|
|
131
|
+
* @param module - The ModuleRef instance
|
|
132
|
+
* @param token - The dependency token
|
|
133
|
+
* @param config - Optional configuration
|
|
134
|
+
* @returns The dependency or undefined
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* public get OptionalService(): ServiceType | undefined {
|
|
139
|
+
* return createOptionalLazyGetter(this.Module, ServiceType);
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export declare function CreateOptionalLazyGetter<T>(module: ModuleRef, token: string | Function, config?: OptionalGetterConfig): T | undefined;
|
|
144
|
+
/**
|
|
145
|
+
* Type guard to check if a value is a LazyModuleRefService
|
|
146
|
+
*
|
|
147
|
+
* @param value - The value to check
|
|
148
|
+
* @returns True if the value has a Module property of type ModuleRef
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* if (isLazyModuleRefService(service)) {
|
|
153
|
+
* // service.Module is available
|
|
154
|
+
* }
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
export declare function IsLazyModuleRefService(value: any): value is LazyModuleRefService;
|
|
158
|
+
/**
|
|
159
|
+
* Pattern naming convention constants
|
|
160
|
+
* Use these as documentation helpers for your lazy getter implementations
|
|
161
|
+
*/
|
|
162
|
+
export declare const LazyGetterNamingConventions: {
|
|
163
|
+
/**
|
|
164
|
+
* Getter names should use PascalCase matching the service/type name
|
|
165
|
+
* Examples: Config, Logger, CacheService, OrderModel
|
|
166
|
+
*/
|
|
167
|
+
NAMING_PATTERN: string;
|
|
168
|
+
/**
|
|
169
|
+
* Getter names should NOT include 'get' prefix or 'Service' suffix if redundant
|
|
170
|
+
* Example: public get Config() NOT public get getConfigService()
|
|
171
|
+
*/
|
|
172
|
+
AVOID_REDUNDANCY: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* For Mongoose models, use PascalCase + 'Model' suffix
|
|
175
|
+
* Example: public get OrderModel()
|
|
176
|
+
*/
|
|
177
|
+
MODEL_SUFFIX: string;
|
|
178
|
+
/**
|
|
179
|
+
* For string-based tokens, use meaningful names representing the service
|
|
180
|
+
* Example: public get PubSub() for 'PUB_SUB' token
|
|
181
|
+
*/
|
|
182
|
+
TOKEN_MAPPING: string;
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Backwards compatibility aliases - exported functions use PascalCase per project conventions
|
|
186
|
+
*/
|
|
187
|
+
export declare const createMemoizedLazyGetter: typeof CreateMemoizedLazyGetter;
|
|
188
|
+
export declare const createOptionalLazyGetter: typeof CreateOptionalLazyGetter;
|
|
189
|
+
export declare const isLazyModuleRefService: typeof IsLazyModuleRefService;
|
|
190
|
+
//# sourceMappingURL=lazy-getter.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy-getter.types.d.ts","sourceRoot":"","sources":["../../../src/common/utils/lazy-getter.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAEpC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;AAEtD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,MAAM,EAAE,SAAS,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,IAAI;KACtC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GACzF,CAAC,GACD,KAAK;CACR,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACzC,QAAQ,EAAE,MAAM,CAAC,GACf,MAAM,CAAC,CAWT;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACzC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,GAAG,QAAQ,EACxB,MAAM,CAAC,EAAE,oBAAoB,GAC3B,CAAC,GAAG,SAAS,CAMf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,oBAAoB,CAEhF;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B;IACvC;;;OAGG;;IAGH;;;OAGG;;IAGH;;;OAGG;;IAGH;;;OAGG;;CAEH,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,iCAA2B,CAAC;AACjE,eAAO,MAAM,wBAAwB,iCAA2B,CAAC;AACjE,eAAO,MAAM,sBAAsB,+BAAyB,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pawells/nestjs-shared - Lazy Module Ref Pattern Utilities
|
|
3
|
+
*
|
|
4
|
+
* This file provides type definitions and utilities for implementing the lazy ModuleRef
|
|
5
|
+
* dependency injection pattern. This pattern enables deferred dependency resolution,
|
|
6
|
+
* reducing constructor complexity and enabling circular dependency handling.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link .claude/skills/lazy-module-ref-pattern.md} - Comprehensive pattern guide
|
|
9
|
+
*/
|
|
10
|
+
import { ModuleRef } from '@nestjs/core';
|
|
11
|
+
/**
|
|
12
|
+
* Utility function to create a memoized lazy getter
|
|
13
|
+
* Caches the resolved dependency to avoid repeated lookups
|
|
14
|
+
*
|
|
15
|
+
* @template T - The type of dependency
|
|
16
|
+
* @param getterFn - Function that retrieves the dependency
|
|
17
|
+
* @returns A memoized getter function
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* private _cachedService: ServiceType | undefined;
|
|
22
|
+
*
|
|
23
|
+
* public get Service(): ServiceType {
|
|
24
|
+
* if (!this._cachedService) {
|
|
25
|
+
* this._cachedService = this.Module.get(ServiceType);
|
|
26
|
+
* }
|
|
27
|
+
* return this._cachedService;
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function CreateMemoizedLazyGetter(getterFn) {
|
|
32
|
+
let cached;
|
|
33
|
+
let initialized = false;
|
|
34
|
+
return () => {
|
|
35
|
+
if (!initialized) {
|
|
36
|
+
cached = getterFn();
|
|
37
|
+
initialized = true;
|
|
38
|
+
}
|
|
39
|
+
return cached;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Utility function to create a lazy getter with error handling for optional dependencies
|
|
44
|
+
*
|
|
45
|
+
* @template T - The type of dependency
|
|
46
|
+
* @param module - The ModuleRef instance
|
|
47
|
+
* @param token - The dependency token
|
|
48
|
+
* @param config - Optional configuration
|
|
49
|
+
* @returns The dependency or undefined
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* public get OptionalService(): ServiceType | undefined {
|
|
54
|
+
* return createOptionalLazyGetter(this.Module, ServiceType);
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function CreateOptionalLazyGetter(module, token, config) {
|
|
59
|
+
try {
|
|
60
|
+
return module.get(token, { strict: config?.strict ?? true });
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Type guard to check if a value is a LazyModuleRefService
|
|
68
|
+
*
|
|
69
|
+
* @param value - The value to check
|
|
70
|
+
* @returns True if the value has a Module property of type ModuleRef
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* if (isLazyModuleRefService(service)) {
|
|
75
|
+
* // service.Module is available
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function IsLazyModuleRefService(value) {
|
|
80
|
+
return !!(value && typeof value === 'object' && 'Module' in value && value.Module instanceof ModuleRef);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Pattern naming convention constants
|
|
84
|
+
* Use these as documentation helpers for your lazy getter implementations
|
|
85
|
+
*/
|
|
86
|
+
export const LazyGetterNamingConventions = {
|
|
87
|
+
/**
|
|
88
|
+
* Getter names should use PascalCase matching the service/type name
|
|
89
|
+
* Examples: Config, Logger, CacheService, OrderModel
|
|
90
|
+
*/
|
|
91
|
+
NAMING_PATTERN: 'PascalCase (matching service/type name)',
|
|
92
|
+
/**
|
|
93
|
+
* Getter names should NOT include 'get' prefix or 'Service' suffix if redundant
|
|
94
|
+
* Example: public get Config() NOT public get getConfigService()
|
|
95
|
+
*/
|
|
96
|
+
AVOID_REDUNDANCY: true,
|
|
97
|
+
/**
|
|
98
|
+
* For Mongoose models, use PascalCase + 'Model' suffix
|
|
99
|
+
* Example: public get OrderModel()
|
|
100
|
+
*/
|
|
101
|
+
MODEL_SUFFIX: 'Model',
|
|
102
|
+
/**
|
|
103
|
+
* For string-based tokens, use meaningful names representing the service
|
|
104
|
+
* Example: public get PubSub() for 'PUB_SUB' token
|
|
105
|
+
*/
|
|
106
|
+
TOKEN_MAPPING: 'Meaningful name for token string',
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Backwards compatibility aliases - exported functions use PascalCase per project conventions
|
|
110
|
+
*/
|
|
111
|
+
export const createMemoizedLazyGetter = CreateMemoizedLazyGetter;
|
|
112
|
+
export const createOptionalLazyGetter = CreateOptionalLazyGetter;
|
|
113
|
+
export const isLazyModuleRefService = IsLazyModuleRefService;
|
|
114
|
+
//# sourceMappingURL=lazy-getter.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy-getter.types.js","sourceRoot":"","sources":["../../../src/common/utils/lazy-getter.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAyGzC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,wBAAwB,CACvC,QAAiB;IAEjB,IAAI,MAAqB,CAAC;IAC1B,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,OAAO,GAAG,EAAE;QACX,IAAI,CAAC,WAAW,EAAE,CAAC;YAClB,MAAM,GAAG,QAAQ,EAAE,CAAC;YACpB,WAAW,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,OAAO,MAAW,CAAC;IACpB,CAAC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,wBAAwB,CACvC,MAAiB,EACjB,KAAwB,EACxB,MAA6B;IAE7B,IAAI,CAAC;QACJ,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAU;IAChD,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,YAAY,SAAS,CAAC,CAAC;AACzG,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG;IAC1C;;;OAGG;IACH,cAAc,EAAE,yCAAyC;IAEzD;;;OAGG;IACH,gBAAgB,EAAE,IAAI;IAEtB;;;OAGG;IACH,YAAY,EAAE,OAAO;IAErB;;;OAGG;IACH,aAAa,EAAE,kCAAkC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AACjE,MAAM,CAAC,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AACjE,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { InjectionToken, OptionalFactoryDependency, Provider, Type } from '@nestjs/common';
|
|
2
|
+
/**
|
|
3
|
+
* Generic shape for forRootAsync() options.
|
|
4
|
+
*
|
|
5
|
+
* F is the factory interface (e.g. NatsOptionsFactory, QdrantModuleOptionsFactory).
|
|
6
|
+
* T is the resolved options type.
|
|
7
|
+
*/
|
|
8
|
+
export interface AsyncModuleOptions<T, F = unknown> {
|
|
9
|
+
useFactory?: (...args: unknown[]) => T | Promise<T>;
|
|
10
|
+
useClass?: Type<F>;
|
|
11
|
+
useExisting?: Type<F>;
|
|
12
|
+
inject?: Array<InjectionToken | OptionalFactoryDependency>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Creates the single async options provider (the injection-token → resolved-options
|
|
16
|
+
* mapping) for a forRootAsync() module.
|
|
17
|
+
*
|
|
18
|
+
* @param options The async options passed to forRootAsync()
|
|
19
|
+
* @param token Injection token to provide the resolved options under
|
|
20
|
+
* @param factoryFn Calls the factory method on the options-factory instance,
|
|
21
|
+
* e.g. `(f) => f.createNatsOptions()`
|
|
22
|
+
*/
|
|
23
|
+
export declare function createAsyncOptionsProvider<T, F>(options: AsyncModuleOptions<T, F>, token: InjectionToken, factoryFn: (factory: F) => T | Promise<T>): Provider<T>;
|
|
24
|
+
/**
|
|
25
|
+
* Creates the full provider array for a forRootAsync() module — the options
|
|
26
|
+
* provider plus an optional self-binding for useClass.
|
|
27
|
+
*
|
|
28
|
+
* @param options The async options passed to forRootAsync()
|
|
29
|
+
* @param token Injection token to provide the resolved options under
|
|
30
|
+
* @param factoryFn Calls the factory method on the options-factory instance
|
|
31
|
+
*/
|
|
32
|
+
export declare function createAsyncProviders<T, F>(options: AsyncModuleOptions<T, F>, token: InjectionToken, factoryFn: (factory: F) => T | Promise<T>): Provider[];
|
|
33
|
+
//# sourceMappingURL=module.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils/module.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,yBAAyB,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEhG;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO;IACjD,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACnB,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,CAAC,EAAE,KAAK,CAAC,cAAc,GAAG,yBAAyB,CAAC,CAAC;CAC3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,CAAC,EAC9C,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EACjC,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvC,QAAQ,CAAC,CAAC,CAAC,CAmBb;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EACxC,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EACjC,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvC,QAAQ,EAAE,CAaZ"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the single async options provider (the injection-token → resolved-options
|
|
3
|
+
* mapping) for a forRootAsync() module.
|
|
4
|
+
*
|
|
5
|
+
* @param options The async options passed to forRootAsync()
|
|
6
|
+
* @param token Injection token to provide the resolved options under
|
|
7
|
+
* @param factoryFn Calls the factory method on the options-factory instance,
|
|
8
|
+
* e.g. `(f) => f.createNatsOptions()`
|
|
9
|
+
*/
|
|
10
|
+
export function createAsyncOptionsProvider(options, token, factoryFn) {
|
|
11
|
+
if (options.useFactory !== undefined) {
|
|
12
|
+
return {
|
|
13
|
+
provide: token,
|
|
14
|
+
useFactory: options.useFactory,
|
|
15
|
+
inject: (options.inject ?? []),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const factoryToken = options.useExisting ?? options.useClass;
|
|
19
|
+
if (factoryToken === undefined) {
|
|
20
|
+
throw new Error('Invalid async module options: must specify useFactory, useClass, or useExisting.');
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
provide: token,
|
|
24
|
+
useFactory: factoryFn,
|
|
25
|
+
inject: [factoryToken],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates the full provider array for a forRootAsync() module — the options
|
|
30
|
+
* provider plus an optional self-binding for useClass.
|
|
31
|
+
*
|
|
32
|
+
* @param options The async options passed to forRootAsync()
|
|
33
|
+
* @param token Injection token to provide the resolved options under
|
|
34
|
+
* @param factoryFn Calls the factory method on the options-factory instance
|
|
35
|
+
*/
|
|
36
|
+
export function createAsyncProviders(options, token, factoryFn) {
|
|
37
|
+
if (options.useExisting !== undefined || options.useFactory !== undefined) {
|
|
38
|
+
return [createAsyncOptionsProvider(options, token, factoryFn)];
|
|
39
|
+
}
|
|
40
|
+
if (options.useClass !== undefined) {
|
|
41
|
+
return [
|
|
42
|
+
createAsyncOptionsProvider(options, token, factoryFn),
|
|
43
|
+
{ provide: options.useClass, useClass: options.useClass },
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
throw new Error('Invalid async module options: must specify useFactory, useClass, or useExisting.');
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=module.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.utils.js","sourceRoot":"","sources":["../../../src/common/utils/module.utils.ts"],"names":[],"mappings":"AAeA;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CACzC,OAAiC,EACjC,KAAqB,EACrB,SAAyC;IAEzC,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO;YACN,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAsD;SACnF,CAAC;IACH,CAAC;IACD,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;IAC7D,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACd,kFAAkF,CAClF,CAAC;IACH,CAAC;IACD,OAAO;QACN,OAAO,EAAE,KAAK;QACd,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,CAAC,YAAY,CAAC;KACtB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CACnC,OAAiC,EACjC,KAAqB,EACrB,SAAyC;IAEzC,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QAC3E,OAAO,CAAC,0BAA0B,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO;YACN,0BAA0B,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC;YACrD,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;SACzD,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACd,kFAAkF,CAClF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Logger } from '@nestjs/common';
|
|
2
|
+
/**
|
|
3
|
+
* Maximum recursion depth for sanitization operations.
|
|
4
|
+
* Prevents stack overflow attacks and infinite loops on circular references.
|
|
5
|
+
*/
|
|
6
|
+
export declare const MAX_SANITIZE_DEPTH = 20;
|
|
7
|
+
/**
|
|
8
|
+
* Escapes newline characters and other special characters that could be used for log injection attacks.
|
|
9
|
+
* Replaces newlines with \n literal strings to prevent log forging where an attacker might inject
|
|
10
|
+
* a newline to create fake log entries.
|
|
11
|
+
*
|
|
12
|
+
* @param str The string to escape
|
|
13
|
+
* @returns String with newlines and carriage returns escaped
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* escapeNewlines('Hello\nWorld') // Returns: 'Hello\\nWorld'
|
|
18
|
+
* escapeNewlines('foo\rbar') // Returns: 'foo\\rbar'
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function escapeNewlines(str: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Recursively sanitizes object keys to prevent MongoDB injection attacks.
|
|
24
|
+
* This function only sanitizes keys (property names), not values, to prevent
|
|
25
|
+
* destruction of legitimate data like email addresses or S3 paths.
|
|
26
|
+
*
|
|
27
|
+
* CRITICAL: This function must be applied to the complete root request object.
|
|
28
|
+
* Extracting a sub-object and passing it separately bypasses sanitization for
|
|
29
|
+
* parent levels. Always sanitize at the entry point (request body, params, query).
|
|
30
|
+
*
|
|
31
|
+
* Behavior at max depth: Throws an error to prevent bypass of sanitization.
|
|
32
|
+
* A highly nested object may indicate an attack or data structure issue.
|
|
33
|
+
*
|
|
34
|
+
* @param value The value to sanitize (keys only)
|
|
35
|
+
* @param depth Current recursion depth (internal use)
|
|
36
|
+
* @param logger Optional logger instance for warnings
|
|
37
|
+
* @returns Sanitized value with dangerous characters in keys replaced
|
|
38
|
+
* @throws Error if maximum sanitization depth is exceeded
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* // CORRECT: Sanitize at entry point
|
|
43
|
+
* app.use((req, res, next) => {
|
|
44
|
+
* req.body = sanitizeObject(req.body);
|
|
45
|
+
* next();
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* // WRONG: Don't extract sub-object and sanitize separately
|
|
49
|
+
* const user = sanitizeObject(req.body.user); // Misses req.body itself
|
|
50
|
+
*
|
|
51
|
+
* // CORRECT: Sanitize complete object first
|
|
52
|
+
* const sanitized = sanitizeObject(req.body);
|
|
53
|
+
* const user = sanitized.user; // Now safe
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function sanitizeObject(value: any, depth?: number, logger?: Logger): any;
|
|
57
|
+
/**
|
|
58
|
+
* Recursively sanitizes object values to prevent XSS attacks.
|
|
59
|
+
* Strips dangerous HTML tags, JavaScript event handlers, and protocol handlers
|
|
60
|
+
* from string values while preserving legitimate data.
|
|
61
|
+
*
|
|
62
|
+
* Uses the xss library for server-side HTML string sanitization.
|
|
63
|
+
*
|
|
64
|
+
* @param value The value to sanitize (strings and nested objects)
|
|
65
|
+
* @param logger Optional logger instance for warnings
|
|
66
|
+
* @returns Sanitized value with XSS vectors removed
|
|
67
|
+
*/
|
|
68
|
+
export declare function sanitizeXss(value: unknown, logger?: Logger): unknown;
|
|
69
|
+
//# sourceMappingURL=sanitization.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitization.utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils/sanitization.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAIxC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,GAAE,MAAU,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,CAyClF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAqCpE"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import xss from 'xss';
|
|
2
|
+
import { getErrorMessage } from './error.utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Maximum recursion depth for sanitization operations.
|
|
5
|
+
* Prevents stack overflow attacks and infinite loops on circular references.
|
|
6
|
+
*/
|
|
7
|
+
export const MAX_SANITIZE_DEPTH = 20;
|
|
8
|
+
/**
|
|
9
|
+
* Escapes newline characters and other special characters that could be used for log injection attacks.
|
|
10
|
+
* Replaces newlines with \n literal strings to prevent log forging where an attacker might inject
|
|
11
|
+
* a newline to create fake log entries.
|
|
12
|
+
*
|
|
13
|
+
* @param str The string to escape
|
|
14
|
+
* @returns String with newlines and carriage returns escaped
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* escapeNewlines('Hello\nWorld') // Returns: 'Hello\\nWorld'
|
|
19
|
+
* escapeNewlines('foo\rbar') // Returns: 'foo\\rbar'
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function escapeNewlines(str) {
|
|
23
|
+
if (typeof str !== 'string') {
|
|
24
|
+
return String(str);
|
|
25
|
+
}
|
|
26
|
+
return str
|
|
27
|
+
.replace(/\n/g, '\\n')
|
|
28
|
+
.replace(/\r/g, '\\r')
|
|
29
|
+
.replace(/\t/g, '\\t');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Recursively sanitizes object keys to prevent MongoDB injection attacks.
|
|
33
|
+
* This function only sanitizes keys (property names), not values, to prevent
|
|
34
|
+
* destruction of legitimate data like email addresses or S3 paths.
|
|
35
|
+
*
|
|
36
|
+
* CRITICAL: This function must be applied to the complete root request object.
|
|
37
|
+
* Extracting a sub-object and passing it separately bypasses sanitization for
|
|
38
|
+
* parent levels. Always sanitize at the entry point (request body, params, query).
|
|
39
|
+
*
|
|
40
|
+
* Behavior at max depth: Throws an error to prevent bypass of sanitization.
|
|
41
|
+
* A highly nested object may indicate an attack or data structure issue.
|
|
42
|
+
*
|
|
43
|
+
* @param value The value to sanitize (keys only)
|
|
44
|
+
* @param depth Current recursion depth (internal use)
|
|
45
|
+
* @param logger Optional logger instance for warnings
|
|
46
|
+
* @returns Sanitized value with dangerous characters in keys replaced
|
|
47
|
+
* @throws Error if maximum sanitization depth is exceeded
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // CORRECT: Sanitize at entry point
|
|
52
|
+
* app.use((req, res, next) => {
|
|
53
|
+
* req.body = sanitizeObject(req.body);
|
|
54
|
+
* next();
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* // WRONG: Don't extract sub-object and sanitize separately
|
|
58
|
+
* const user = sanitizeObject(req.body.user); // Misses req.body itself
|
|
59
|
+
*
|
|
60
|
+
* // CORRECT: Sanitize complete object first
|
|
61
|
+
* const sanitized = sanitizeObject(req.body);
|
|
62
|
+
* const user = sanitized.user; // Now safe
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function sanitizeObject(value, depth = 0, logger) {
|
|
66
|
+
if (depth >= MAX_SANITIZE_DEPTH) {
|
|
67
|
+
if (logger) {
|
|
68
|
+
logger.error(`Sanitization depth limit exceeded at depth ${MAX_SANITIZE_DEPTH}`);
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`Input object exceeds maximum sanitization depth of ${MAX_SANITIZE_DEPTH}. Deeply nested objects may be malicious.`);
|
|
71
|
+
}
|
|
72
|
+
if (typeof value === 'object' && value !== null) {
|
|
73
|
+
if (Array.isArray(value)) {
|
|
74
|
+
return value.map(item => sanitizeObject(item, depth + 1, logger));
|
|
75
|
+
}
|
|
76
|
+
const sanitized = {};
|
|
77
|
+
for (const [key, val] of Object.entries(value)) {
|
|
78
|
+
// Sanitize keys to prevent MongoDB operator injection
|
|
79
|
+
// MongoDB operators start with '$', and command expressions with 'eval', 'function', etc.
|
|
80
|
+
// Replace dangerous key patterns: $ at start, eval, function in keys
|
|
81
|
+
let sanitizedKey = key;
|
|
82
|
+
// Prevent MongoDB operators (e.g., $where, $regex, etc.)
|
|
83
|
+
if (sanitizedKey.startsWith('$')) {
|
|
84
|
+
sanitizedKey = '_' + sanitizedKey.slice(1);
|
|
85
|
+
}
|
|
86
|
+
// Prevent arbitrary code execution patterns in key names
|
|
87
|
+
const dangerousKeyPatterns = ['eval', 'function', '__proto__', 'constructor', 'prototype'];
|
|
88
|
+
for (const pattern of dangerousKeyPatterns) {
|
|
89
|
+
if (sanitizedKey.toLowerCase().includes(pattern)) {
|
|
90
|
+
sanitizedKey = sanitizedKey.replace(new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi'), '_redacted_');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Recursively sanitize nested objects/arrays, but preserve string values
|
|
94
|
+
sanitized[sanitizedKey] = typeof val === 'object' ? sanitizeObject(val, depth + 1, logger) : val;
|
|
95
|
+
}
|
|
96
|
+
return sanitized;
|
|
97
|
+
}
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Recursively sanitizes object values to prevent XSS attacks.
|
|
102
|
+
* Strips dangerous HTML tags, JavaScript event handlers, and protocol handlers
|
|
103
|
+
* from string values while preserving legitimate data.
|
|
104
|
+
*
|
|
105
|
+
* Uses the xss library for server-side HTML string sanitization.
|
|
106
|
+
*
|
|
107
|
+
* @param value The value to sanitize (strings and nested objects)
|
|
108
|
+
* @param logger Optional logger instance for warnings
|
|
109
|
+
* @returns Sanitized value with XSS vectors removed
|
|
110
|
+
*/
|
|
111
|
+
export function sanitizeXss(value, logger) {
|
|
112
|
+
if (typeof value === 'string') {
|
|
113
|
+
// Use xss library for server-side HTML string sanitization
|
|
114
|
+
// Removes common XSS patterns: script tags, event handlers, dangerous protocols
|
|
115
|
+
// Static import ensures dependency is resolved at module load time and fails fast if missing
|
|
116
|
+
let sanitized = value;
|
|
117
|
+
try {
|
|
118
|
+
// xss is statically imported at module top to ensure TypeScript and bundlers
|
|
119
|
+
// can properly resolve the dependency at build time
|
|
120
|
+
sanitized = xss(sanitized);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (logger) {
|
|
124
|
+
logger.warn(`XSS sanitization (xss library) failed: ${getErrorMessage(error)}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Final protocol stripping as defense-in-depth
|
|
128
|
+
sanitized = sanitized
|
|
129
|
+
.replace(/javascript:/gi, '')
|
|
130
|
+
.replace(/vbscript:/gi, '');
|
|
131
|
+
return sanitized;
|
|
132
|
+
}
|
|
133
|
+
if (Array.isArray(value)) {
|
|
134
|
+
return value.map(v => sanitizeXss(v, logger));
|
|
135
|
+
}
|
|
136
|
+
if (value && typeof value === 'object') {
|
|
137
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, sanitizeXss(v, logger)]));
|
|
138
|
+
}
|
|
139
|
+
return value;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=sanitization.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitization.utils.js","sourceRoot":"","sources":["../../../src/common/utils/sanitization.utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Module.
|
|
3
|
+
* Provides configuration services with environment variable access, validation, and logging.
|
|
4
|
+
* MUST be imported before CommonModule in your application.
|
|
5
|
+
*
|
|
6
|
+
* Exports:
|
|
7
|
+
* - ConfigService: Typed configuration accessor
|
|
8
|
+
* - ValidationService: Configuration validation utilities
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* - ConfigService is required by CommonModule and other @pawells packages
|
|
12
|
+
* - Initializes logging for configuration operations
|
|
13
|
+
* - Import order critical: ConfigModule must come BEFORE CommonModule
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* @Module({
|
|
18
|
+
* imports: [
|
|
19
|
+
* ConfigModule, // FIRST
|
|
20
|
+
* CommonModule, // SECOND (depends on ConfigModule)
|
|
21
|
+
* MetricsModule.forRoot(),
|
|
22
|
+
* // ... other modules
|
|
23
|
+
* ]
|
|
24
|
+
* })
|
|
25
|
+
* export class AppModule {}
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare class ConfigModule {
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=config.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.module.d.ts","sourceRoot":"","sources":["../../src/config/config.module.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,qBAOa,YAAY;CAAG"}
|