@rsdk/core 5.7.0-next.3 → 6.0.0-next.0
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/dist/config/index.d.ts +0 -1
- package/dist/config/index.js +0 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/metadata/decorators/declare-property.decorator.d.ts +2 -1
- package/dist/config/metadata/decorators/declare-property.decorator.js.map +1 -1
- package/dist/config/metadata/decorators/property.decorator.d.ts +2 -1
- package/dist/config/metadata/decorators/property.decorator.js.map +1 -1
- package/dist/config/sources/implementations/json-file.source.js +1 -2
- package/dist/config/sources/implementations/json-file.source.js.map +1 -1
- package/dist/config/sources/implementations/relodable-json-file.source.js +1 -2
- package/dist/config/sources/implementations/relodable-json-file.source.js.map +1 -1
- package/dist/config/types.d.ts +1 -20
- package/dist/config/types.js.map +1 -1
- package/dist/exceptions.handling/default.formatter.d.ts +6 -0
- package/dist/exceptions.handling/default.formatter.js +12 -0
- package/dist/exceptions.handling/default.formatter.js.map +1 -0
- package/dist/exceptions.handling/default.sender.d.ts +8 -0
- package/dist/exceptions.handling/default.sender.js +13 -0
- package/dist/exceptions.handling/default.sender.js.map +1 -0
- package/dist/exceptions.handling/global-exceptions.config.js +1 -1
- package/dist/exceptions.handling/global-exceptions.config.js.map +1 -1
- package/dist/exceptions.handling/global-exceptions.filter.d.ts +8 -11
- package/dist/exceptions.handling/global-exceptions.filter.js +38 -56
- package/dist/exceptions.handling/global-exceptions.filter.js.map +1 -1
- package/dist/exceptions.handling/global-exceptions.interceptor.d.ts +18 -0
- package/dist/exceptions.handling/global-exceptions.interceptor.js +57 -0
- package/dist/exceptions.handling/global-exceptions.interceptor.js.map +1 -0
- package/dist/exceptions.handling/global-exceptions.module.d.ts +2 -23
- package/dist/exceptions.handling/global-exceptions.module.js +38 -3
- package/dist/exceptions.handling/global-exceptions.module.js.map +1 -1
- package/dist/exceptions.handling/types.d.ts +2 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +34 -1
- package/dist/index.js.map +1 -1
- package/dist/logging/constants.d.ts +1 -0
- package/dist/logging/constants.js +5 -0
- package/dist/logging/constants.js.map +1 -0
- package/dist/logging/decorators/inject-logger.decorator.js +2 -2
- package/dist/logging/decorators/inject-logger.decorator.js.map +1 -1
- package/dist/logging/formatters/default.formatter.d.ts +7 -0
- package/dist/logging/formatters/default.formatter.js +17 -0
- package/dist/logging/formatters/default.formatter.js.map +1 -0
- package/dist/logging/formatters/index.d.ts +2 -0
- package/dist/{config/parsers/array → logging/formatters}/index.js +2 -1
- package/dist/logging/formatters/index.js.map +1 -0
- package/dist/logging/formatters/interfaces.d.ts +23 -0
- package/dist/logging/formatters/interfaces.js +3 -0
- package/dist/logging/formatters/interfaces.js.map +1 -0
- package/dist/logging/index.d.ts +3 -2
- package/dist/logging/index.js +6 -4
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/logging-core.module.d.ts +10 -0
- package/dist/logging/{logger-initializing.module.js → logging-core.module.js} +46 -10
- package/dist/logging/logging-core.module.js.map +1 -0
- package/dist/logging/{logging.module.d.ts → logging-instances.module.d.ts} +1 -1
- package/dist/logging/{logging.module.js → logging-instances.module.js} +8 -9
- package/dist/logging/logging-instances.module.js.map +1 -0
- package/dist/logging/logging.config.d.ts +3 -0
- package/dist/logging/logging.config.js +29 -4
- package/dist/logging/logging.config.js.map +1 -1
- package/dist/logging/logging.interceptor.d.ts +37 -0
- package/dist/logging/logging.interceptor.js +124 -0
- package/dist/logging/logging.interceptor.js.map +1 -0
- package/dist/metrics/metrics.config.js +3 -2
- package/dist/metrics/metrics.config.js.map +1 -1
- package/dist/platform.context.d.ts +1 -1
- package/dist/platform.context.js +3 -2
- package/dist/platform.context.js.map +1 -1
- package/dist/platform.module.js +19 -6
- package/dist/platform.module.js.map +1 -1
- package/dist/tracing/constants.d.ts +4 -5
- package/dist/tracing/constants.js +9 -7
- package/dist/tracing/constants.js.map +1 -1
- package/dist/tracing/index.d.ts +1 -0
- package/dist/tracing/index.js +1 -0
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/request-id/index.d.ts +4 -0
- package/dist/{config/parsers/enum → tracing/request-id}/index.js +4 -1
- package/dist/tracing/request-id/index.js.map +1 -0
- package/dist/tracing/request-id/metadata.helpers.d.ts +13 -0
- package/dist/tracing/request-id/metadata.helpers.js +23 -0
- package/dist/tracing/request-id/metadata.helpers.js.map +1 -0
- package/dist/tracing/request-id/request-id-gen.decorator.d.ts +8 -0
- package/dist/tracing/request-id/request-id-gen.decorator.js +17 -0
- package/dist/tracing/request-id/request-id-gen.decorator.js.map +1 -0
- package/dist/tracing/request-id/types.d.ts +2 -0
- package/dist/tracing/request-id/types.js +3 -0
- package/dist/tracing/request-id/types.js.map +1 -0
- package/dist/tracing/request-id/with-prefix.fn.d.ts +30 -0
- package/dist/tracing/request-id/with-prefix.fn.js +36 -0
- package/dist/tracing/request-id/with-prefix.fn.js.map +1 -0
- package/dist/tracing/tracing.config.d.ts +5 -0
- package/dist/tracing/tracing.config.js +42 -0
- package/dist/tracing/tracing.config.js.map +1 -0
- package/dist/tracing/tracing.interceptor.d.ts +7 -9
- package/dist/tracing/tracing.interceptor.js +30 -28
- package/dist/tracing/tracing.interceptor.js.map +1 -1
- package/dist/tracing/tracing.module.d.ts +13 -2
- package/dist/tracing/tracing.module.js +60 -17
- package/dist/tracing/tracing.module.js.map +1 -1
- package/dist/transport/protocol.detector.d.ts +1 -1
- package/dist/transport/protocol.detector.js +17 -2
- package/dist/transport/protocol.detector.js.map +1 -1
- package/dist/transport/transport.module.d.ts +0 -1
- package/dist/transport/transport.module.js +0 -20
- package/dist/transport/transport.module.js.map +1 -1
- package/dist/types/plugins.d.ts +2 -15
- package/dist/types/plugins.js.map +1 -1
- package/dist/types/transports.d.ts +23 -13
- package/dist/types/transports.js.map +1 -1
- package/dist/unhandled-rejection.handler.js +8 -13
- package/dist/unhandled-rejection.handler.js.map +1 -1
- package/package.json +3 -2
- package/src/config/index.ts +0 -1
- package/src/config/metadata/decorators/declare-property.decorator.ts +3 -1
- package/src/config/metadata/decorators/property.decorator.ts +3 -5
- package/src/config/sources/implementations/json-file.source.ts +1 -2
- package/src/config/sources/implementations/relodable-json-file.source.ts +1 -2
- package/src/config/types.ts +2 -23
- package/src/exceptions.handling/default.formatter.ts +11 -0
- package/src/exceptions.handling/default.sender.ts +15 -0
- package/src/exceptions.handling/global-exceptions.config.ts +2 -2
- package/src/exceptions.handling/global-exceptions.filter.ts +45 -77
- package/src/exceptions.handling/global-exceptions.interceptor.ts +57 -0
- package/src/exceptions.handling/global-exceptions.module.ts +46 -33
- package/src/exceptions.handling/types.ts +2 -2
- package/src/index.ts +53 -2
- package/src/logging/constants.ts +1 -0
- package/src/logging/decorators/inject-logger.decorator.ts +2 -2
- package/src/logging/formatters/default.formatter.ts +17 -0
- package/src/logging/formatters/index.ts +2 -0
- package/src/logging/formatters/interfaces.ts +34 -0
- package/src/logging/index.ts +3 -2
- package/src/logging/logging-core.module.ts +102 -0
- package/src/logging/{logging.module.ts → logging-instances.module.ts} +2 -4
- package/src/logging/logging.config.ts +22 -6
- package/src/logging/logging.interceptor.ts +138 -0
- package/src/metrics/metrics.config.ts +3 -1
- package/src/platform.context.ts +5 -2
- package/src/platform.module.ts +28 -7
- package/src/tracing/constants.ts +8 -7
- package/src/tracing/index.ts +1 -0
- package/src/tracing/request-id/index.ts +4 -0
- package/src/tracing/request-id/metadata.helpers.ts +24 -0
- package/src/tracing/request-id/request-id-gen.decorator.ts +16 -0
- package/src/tracing/request-id/types.ts +6 -0
- package/src/tracing/request-id/with-prefix.fn.ts +44 -0
- package/src/tracing/tracing.config.ts +23 -0
- package/src/tracing/tracing.interceptor.ts +36 -31
- package/src/tracing/tracing.module.ts +68 -19
- package/src/transport/protocol.detector.ts +24 -4
- package/src/transport/transport.module.ts +0 -25
- package/src/types/plugins.ts +11 -22
- package/src/types/transports.ts +32 -16
- package/src/unhandled-rejection.handler.ts +10 -18
- package/test/logging.interceptor.spec.ts +292 -0
- package/dist/config/parsers/array/array.parser.d.ts +0 -11
- package/dist/config/parsers/array/array.parser.js +0 -33
- package/dist/config/parsers/array/array.parser.js.map +0 -1
- package/dist/config/parsers/array/index.d.ts +0 -1
- package/dist/config/parsers/array/index.js.map +0 -1
- package/dist/config/parsers/boolean/bool.parser.d.ts +0 -6
- package/dist/config/parsers/boolean/bool.parser.js +0 -20
- package/dist/config/parsers/boolean/bool.parser.js.map +0 -1
- package/dist/config/parsers/boolean/index.d.ts +0 -1
- package/dist/config/parsers/boolean/index.js +0 -18
- package/dist/config/parsers/boolean/index.js.map +0 -1
- package/dist/config/parsers/enum/enum.parser.d.ts +0 -9
- package/dist/config/parsers/enum/enum.parser.js +0 -24
- package/dist/config/parsers/enum/enum.parser.js.map +0 -1
- package/dist/config/parsers/enum/index.d.ts +0 -1
- package/dist/config/parsers/enum/index.js.map +0 -1
- package/dist/config/parsers/index.d.ts +0 -11
- package/dist/config/parsers/index.js +0 -28
- package/dist/config/parsers/index.js.map +0 -1
- package/dist/config/parsers/int/index.d.ts +0 -1
- package/dist/config/parsers/int/index.js +0 -18
- package/dist/config/parsers/int/index.js.map +0 -1
- package/dist/config/parsers/int/int.parser.d.ts +0 -6
- package/dist/config/parsers/int/int.parser.js +0 -20
- package/dist/config/parsers/int/int.parser.js.map +0 -1
- package/dist/config/parsers/json/index.d.ts +0 -1
- package/dist/config/parsers/json/index.js +0 -18
- package/dist/config/parsers/json/index.js.map +0 -1
- package/dist/config/parsers/json/json.parser.d.ts +0 -6
- package/dist/config/parsers/json/json.parser.js +0 -16
- package/dist/config/parsers/json/json.parser.js.map +0 -1
- package/dist/config/parsers/number/index.d.ts +0 -1
- package/dist/config/parsers/number/index.js +0 -18
- package/dist/config/parsers/number/index.js.map +0 -1
- package/dist/config/parsers/number/number.parser.d.ts +0 -6
- package/dist/config/parsers/number/number.parser.js +0 -23
- package/dist/config/parsers/number/number.parser.js.map +0 -1
- package/dist/config/parsers/path/fspath.parser.d.ts +0 -8
- package/dist/config/parsers/path/fspath.parser.js +0 -59
- package/dist/config/parsers/path/fspath.parser.js.map +0 -1
- package/dist/config/parsers/path/index.d.ts +0 -1
- package/dist/config/parsers/path/index.js +0 -18
- package/dist/config/parsers/path/index.js.map +0 -1
- package/dist/config/parsers/size/index.d.ts +0 -1
- package/dist/config/parsers/size/index.js +0 -18
- package/dist/config/parsers/size/index.js.map +0 -1
- package/dist/config/parsers/size/size.parser.d.ts +0 -7
- package/dist/config/parsers/size/size.parser.js +0 -21
- package/dist/config/parsers/size/size.parser.js.map +0 -1
- package/dist/config/parsers/string/index.d.ts +0 -1
- package/dist/config/parsers/string/index.js +0 -18
- package/dist/config/parsers/string/index.js.map +0 -1
- package/dist/config/parsers/string/string.parser.d.ts +0 -8
- package/dist/config/parsers/string/string.parser.js +0 -29
- package/dist/config/parsers/string/string.parser.js.map +0 -1
- package/dist/config/parsers/timespan/index.d.ts +0 -1
- package/dist/config/parsers/timespan/index.js +0 -18
- package/dist/config/parsers/timespan/index.js.map +0 -1
- package/dist/config/parsers/timespan/timespan.parser.d.ts +0 -7
- package/dist/config/parsers/timespan/timespan.parser.js +0 -21
- package/dist/config/parsers/timespan/timespan.parser.js.map +0 -1
- package/dist/config/parsers/url/exception.d.ts +0 -7
- package/dist/config/parsers/url/exception.js +0 -25
- package/dist/config/parsers/url/exception.js.map +0 -1
- package/dist/config/parsers/url/index.d.ts +0 -2
- package/dist/config/parsers/url/index.js +0 -21
- package/dist/config/parsers/url/index.js.map +0 -1
- package/dist/config/parsers/url/url.parser.d.ts +0 -9
- package/dist/config/parsers/url/url.parser.js +0 -38
- package/dist/config/parsers/url/url.parser.js.map +0 -1
- package/dist/logging/logger-initializing.module.d.ts +0 -6
- package/dist/logging/logger-initializing.module.js.map +0 -1
- package/dist/logging/logging.module.js.map +0 -1
- package/src/config/parsers/array/array.parser.ts +0 -34
- package/src/config/parsers/array/index.ts +0 -1
- package/src/config/parsers/boolean/bool.parser.ts +0 -20
- package/src/config/parsers/boolean/bool.spec.ts +0 -4
- package/src/config/parsers/boolean/index.ts +0 -1
- package/src/config/parsers/enum/enum.parser.ts +0 -23
- package/src/config/parsers/enum/enum.spec.ts +0 -5
- package/src/config/parsers/enum/index.ts +0 -1
- package/src/config/parsers/index.ts +0 -11
- package/src/config/parsers/int/index.ts +0 -1
- package/src/config/parsers/int/int.parser.ts +0 -20
- package/src/config/parsers/int/int.spec.ts +0 -5
- package/src/config/parsers/json/index.ts +0 -1
- package/src/config/parsers/json/json.parser.ts +0 -15
- package/src/config/parsers/number/index.ts +0 -1
- package/src/config/parsers/number/number.parser.ts +0 -23
- package/src/config/parsers/number/number.spec.ts +0 -5
- package/src/config/parsers/path/fspath.parser.ts +0 -64
- package/src/config/parsers/path/index.ts +0 -1
- package/src/config/parsers/size/index.ts +0 -1
- package/src/config/parsers/size/size.parser.ts +0 -22
- package/src/config/parsers/size/size.spec.ts +0 -4
- package/src/config/parsers/string/index.ts +0 -1
- package/src/config/parsers/string/string.parser.ts +0 -26
- package/src/config/parsers/string/string.spec.ts +0 -10
- package/src/config/parsers/timespan/index.ts +0 -1
- package/src/config/parsers/timespan/timespan.parser.ts +0 -22
- package/src/config/parsers/timespan/timespan.spec.ts +0 -5
- package/src/config/parsers/url/exception.ts +0 -21
- package/src/config/parsers/url/index.ts +0 -2
- package/src/config/parsers/url/url.parser.ts +0 -44
- package/src/logging/logger-initializing.module.ts +0 -55
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
DynamicModule,
|
|
3
|
+
FactoryProvider,
|
|
4
|
+
OnModuleInit,
|
|
5
|
+
ValueProvider,
|
|
6
|
+
} from '@nestjs/common';
|
|
2
7
|
import { Module } from '@nestjs/common';
|
|
3
8
|
import { APP_INTERCEPTOR } from '@nestjs/core';
|
|
4
9
|
import type { ContextAPI, TraceAPI } from '@opentelemetry/api';
|
|
@@ -6,19 +11,19 @@ import { text } from '@rsdk/common';
|
|
|
6
11
|
import { ILogger, LoggerFactory } from '@rsdk/logging';
|
|
7
12
|
|
|
8
13
|
import { InjectLogger } from '../logging';
|
|
9
|
-
import type { PlatformOptions } from '../types';
|
|
14
|
+
import type { PlatformOptions, WithGenericHeaders } from '../types';
|
|
10
15
|
|
|
11
16
|
import {
|
|
12
|
-
|
|
13
|
-
DEFAULT_TRACING_OPTIONS,
|
|
17
|
+
HEADER_EXTRACTORS,
|
|
14
18
|
HEADER_MAPPINGS,
|
|
19
|
+
REQUEST_ID_HEADERS,
|
|
15
20
|
} from './constants';
|
|
16
21
|
import { TracingHeaders } from './tracing.actx';
|
|
22
|
+
import { TracingConfig } from './tracing.config';
|
|
17
23
|
import { TracingInterceptor } from './tracing.interceptor';
|
|
18
24
|
import type { TracingHeaderMappings } from './types';
|
|
19
25
|
|
|
20
26
|
export interface TracingOptions {
|
|
21
|
-
includeDefault: boolean;
|
|
22
27
|
additionalMappings?: TracingHeaderMappings[];
|
|
23
28
|
}
|
|
24
29
|
|
|
@@ -30,31 +35,75 @@ export class TracingModule implements OnModuleInit {
|
|
|
30
35
|
constructor(@InjectLogger(TracingModule) private readonly logger: ILogger) {}
|
|
31
36
|
|
|
32
37
|
static forRoot({
|
|
33
|
-
tracing
|
|
34
|
-
plugins
|
|
38
|
+
tracing,
|
|
39
|
+
plugins,
|
|
40
|
+
transports,
|
|
35
41
|
}: PlatformOptions): DynamicModule {
|
|
36
|
-
|
|
42
|
+
return {
|
|
43
|
+
global: true,
|
|
44
|
+
module: TracingModule,
|
|
45
|
+
providers: [
|
|
46
|
+
{ provide: APP_INTERCEPTOR, useClass: TracingInterceptor },
|
|
47
|
+
this.createHeaderExtractorsProvider(transports, plugins),
|
|
48
|
+
this.createHeaderMappingsProvider(tracing, plugins),
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
37
52
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Creates a provider for header mappings configuration.
|
|
55
|
+
* Combines default headers, plugin-provided headers and additional custom mappings
|
|
56
|
+
* into a single collection.
|
|
57
|
+
*/
|
|
58
|
+
private static createHeaderMappingsProvider(
|
|
59
|
+
options: TracingOptions = {},
|
|
60
|
+
plugins: PlatformOptions['plugins'],
|
|
61
|
+
): FactoryProvider {
|
|
62
|
+
const mappings: TracingHeaderMappings[] = [];
|
|
41
63
|
|
|
42
|
-
for (const plugin of plugins) {
|
|
64
|
+
for (const plugin of plugins ?? []) {
|
|
43
65
|
mappings.push(...(plugin.additionalTracingHeaders?.() ?? []));
|
|
44
66
|
}
|
|
45
67
|
|
|
46
|
-
mappings.push(...(
|
|
68
|
+
mappings.push(...(options.additionalMappings ?? []));
|
|
47
69
|
|
|
48
70
|
return {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
71
|
+
provide: HEADER_MAPPINGS,
|
|
72
|
+
inject: [TracingConfig],
|
|
73
|
+
useFactory: (config: TracingConfig): TracingHeaderMappings[] => {
|
|
74
|
+
if (config.traceRequestId) {
|
|
75
|
+
mappings.push(REQUEST_ID_HEADERS);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return mappings;
|
|
79
|
+
},
|
|
55
80
|
};
|
|
56
81
|
}
|
|
57
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Creates a provider for header extractors from different transport protocols.
|
|
85
|
+
* Collects extractors from both transport implementations and plugins to handle
|
|
86
|
+
* protocol-specific header extraction.
|
|
87
|
+
*/
|
|
88
|
+
private static createHeaderExtractorsProvider(
|
|
89
|
+
transports: PlatformOptions['transports'],
|
|
90
|
+
plugins: PlatformOptions['plugins'],
|
|
91
|
+
): ValueProvider {
|
|
92
|
+
const extractors = new Map<string, WithGenericHeaders>();
|
|
93
|
+
|
|
94
|
+
for (const transport of transports ?? []) {
|
|
95
|
+
extractors.set(transport.getProtocol(), transport);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for (const plugin of plugins ?? []) {
|
|
99
|
+
for (const x of plugin.tracingHeadersExtractors?.() ?? []) {
|
|
100
|
+
extractors.set(x.protocol, x.extractor);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return { provide: HEADER_EXTRACTORS, useValue: extractors };
|
|
105
|
+
}
|
|
106
|
+
|
|
58
107
|
// Можно добавить включение и выключение при изменении конфига.
|
|
59
108
|
async onModuleInit(): Promise<void> {
|
|
60
109
|
if (!this.context || !this.trace) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ArgumentsHost } from '@nestjs/common';
|
|
2
2
|
|
|
3
|
+
import { InternalException } from '../exceptions';
|
|
3
4
|
import type { ITransport } from '../types';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -12,8 +13,17 @@ export class ProtocolDetector {
|
|
|
12
13
|
/**
|
|
13
14
|
* Detects transport's protocol by ArgumentHost (context)
|
|
14
15
|
*/
|
|
15
|
-
getProtocol(context: ArgumentsHost): string
|
|
16
|
-
|
|
16
|
+
getProtocol(context: ArgumentsHost): string {
|
|
17
|
+
/**
|
|
18
|
+
* FIXME: Грязный хак, который можно исправить только
|
|
19
|
+
* "прицепив" к транспорту. А ещё учесть, что на http-транспорте
|
|
20
|
+
* может быть и обычный http!
|
|
21
|
+
*/
|
|
22
|
+
if ((context.getType() as any) === 'graphql') {
|
|
23
|
+
return 'graphql';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return this.getTransport(context).getProtocol();
|
|
17
27
|
}
|
|
18
28
|
|
|
19
29
|
/**
|
|
@@ -24,7 +34,17 @@ export class ProtocolDetector {
|
|
|
24
34
|
return this.getProtocol(context) === protocol;
|
|
25
35
|
}
|
|
26
36
|
|
|
27
|
-
private getTransport(context: ArgumentsHost): ITransport
|
|
28
|
-
|
|
37
|
+
private getTransport(context: ArgumentsHost): ITransport {
|
|
38
|
+
const transport = this.transports.findLast((x) =>
|
|
39
|
+
x.matchByContext(context),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (!transport) {
|
|
43
|
+
throw new InternalException('Cant detect transport protocol', {
|
|
44
|
+
details: { context },
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return transport;
|
|
29
49
|
}
|
|
30
50
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { DynamicModule } from '@nestjs/common';
|
|
2
2
|
import type { NestModuleDefinition } from '@rsdk/common.nestjs';
|
|
3
|
-
import { flatten } from 'lodash';
|
|
4
3
|
|
|
5
|
-
import type { IErrorsFormatter, IErrorsSender } from '../exceptions.handling';
|
|
6
|
-
import { GlobalExceptionsModule } from '../exceptions.handling';
|
|
7
4
|
import { HealthModule } from '../health/health.module';
|
|
8
5
|
import { MetricsModule } from '../metrics';
|
|
9
6
|
import type { PlatformExtendedOptions } from '../types';
|
|
@@ -18,7 +15,6 @@ export class PlatformTransportModule {
|
|
|
18
15
|
PlatformTransportModule.initProtocolDetector(options),
|
|
19
16
|
PlatformTransportModule.initHealthchecks(options),
|
|
20
17
|
PlatformTransportModule.initMetrics(options),
|
|
21
|
-
PlatformTransportModule.initExceptionsHandling(options),
|
|
22
18
|
...PlatformTransportModule.getTransportModules(options),
|
|
23
19
|
],
|
|
24
20
|
module: PlatformTransportModule,
|
|
@@ -72,25 +68,4 @@ export class PlatformTransportModule {
|
|
|
72
68
|
.map((x) => x.getHealthController()),
|
|
73
69
|
});
|
|
74
70
|
}
|
|
75
|
-
|
|
76
|
-
private static initExceptionsHandling(
|
|
77
|
-
options: PlatformExtendedOptions,
|
|
78
|
-
): DynamicModule {
|
|
79
|
-
const transports = options.transports ?? [];
|
|
80
|
-
|
|
81
|
-
return GlobalExceptionsModule.forRoot({
|
|
82
|
-
formatters: [
|
|
83
|
-
...transports.map((x) => x.getErrorsFormatter()),
|
|
84
|
-
...(options.plugins?.map((x) => x.errorFormatter?.()) || []),
|
|
85
|
-
].filter((x): x is IErrorsFormatter => Boolean(x)),
|
|
86
|
-
senders: [
|
|
87
|
-
...transports.map((x) => x.getErrorsSender?.()),
|
|
88
|
-
...(options.plugins?.map((x) => x.errorSender?.()) || []),
|
|
89
|
-
].filter((x): x is IErrorsSender => Boolean(x)),
|
|
90
|
-
transformers: [
|
|
91
|
-
...flatten(transports.map((x) => x.getErrorTransformers())),
|
|
92
|
-
...flatten(options.plugins?.map((x) => x.errorTransformers?.() || [])),
|
|
93
|
-
],
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
71
|
}
|
package/src/types/plugins.ts
CHANGED
|
@@ -2,14 +2,15 @@ import type { DynamicModule, MiddlewareConsumer } from '@nestjs/common';
|
|
|
2
2
|
import type { Constructor } from '@rsdk/common';
|
|
3
3
|
import type { ResourceExtractor } from '@rsdk/metadata';
|
|
4
4
|
|
|
5
|
-
import type {
|
|
6
|
-
IErrorsFormatter,
|
|
7
|
-
IErrorsSender,
|
|
8
|
-
IErrorsTransformer,
|
|
9
|
-
} from '../exceptions.handling';
|
|
10
5
|
import type { TracingHeaderMappings } from '../tracing';
|
|
11
6
|
|
|
12
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
WithErrorFormatting,
|
|
9
|
+
WithErrorSending,
|
|
10
|
+
WithErrorTransforming,
|
|
11
|
+
WithGenericHeaders,
|
|
12
|
+
WithLogFormatting,
|
|
13
|
+
} from './transports';
|
|
13
14
|
|
|
14
15
|
export type SpecifiedTransports = Readonly<string[]>;
|
|
15
16
|
export type AppropriateTransports = SpecifiedTransports | 'any';
|
|
@@ -26,7 +27,10 @@ export const hasSpecifiedTransports = (
|
|
|
26
27
|
*/
|
|
27
28
|
export interface PlatformAppPlugin<
|
|
28
29
|
T extends AppropriateTransports = AppropriateTransports,
|
|
29
|
-
>
|
|
30
|
+
> extends Partial<WithErrorFormatting>,
|
|
31
|
+
Partial<WithErrorSending>,
|
|
32
|
+
Partial<WithErrorTransforming>,
|
|
33
|
+
Partial<WithLogFormatting> {
|
|
30
34
|
/**
|
|
31
35
|
* Additional resource extractors
|
|
32
36
|
* Maybe used with custom plugin entity
|
|
@@ -58,21 +62,6 @@ export interface PlatformAppPlugin<
|
|
|
58
62
|
*/
|
|
59
63
|
modules?(): (Constructor | DynamicModule)[];
|
|
60
64
|
|
|
61
|
-
/**
|
|
62
|
-
* Additional error transformers
|
|
63
|
-
*/
|
|
64
|
-
errorTransformers?(): IErrorsTransformer[];
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Additional error formatter
|
|
68
|
-
*/
|
|
69
|
-
errorFormatter?(): IErrorsFormatter;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Additional errors sender
|
|
73
|
-
*/
|
|
74
|
-
errorSender?(): IErrorsSender;
|
|
75
|
-
|
|
76
65
|
/**
|
|
77
66
|
* Apply additional middleware (using MiddlewareConsumer).
|
|
78
67
|
* Will work only if application has HttpAdapter
|
package/src/types/transports.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
IErrorsSender,
|
|
15
15
|
IErrorsTransformer,
|
|
16
16
|
} from '../exceptions.handling';
|
|
17
|
+
import type { LogFormatter } from '../logging';
|
|
17
18
|
|
|
18
19
|
import type { NestModuleDefinitions } from './options';
|
|
19
20
|
|
|
@@ -36,10 +37,40 @@ export interface WithGenericHeaders {
|
|
|
36
37
|
export const hasGenericHeaders = (x: unknown): x is WithGenericHeaders =>
|
|
37
38
|
typeof (x as any)?.getHeaders === 'function';
|
|
38
39
|
|
|
40
|
+
export interface WithErrorFormatting {
|
|
41
|
+
errorFormatter(): IErrorsFormatter;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface WithErrorSending {
|
|
45
|
+
/**
|
|
46
|
+
* @returns sending error algorithm
|
|
47
|
+
*/
|
|
48
|
+
errorSender(): IErrorsSender;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface WithErrorTransforming {
|
|
52
|
+
/**
|
|
53
|
+
* @returns error transformers or empty array
|
|
54
|
+
*/
|
|
55
|
+
errorTransformers(): IErrorsTransformer[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface WithLogFormatting {
|
|
59
|
+
/**
|
|
60
|
+
* @returns logging formatter
|
|
61
|
+
*/
|
|
62
|
+
logFormatter(): LogFormatter;
|
|
63
|
+
}
|
|
64
|
+
|
|
39
65
|
/**
|
|
40
66
|
* Base functionality of HTTP or microservice transport
|
|
41
67
|
*/
|
|
42
|
-
export interface ITransport
|
|
68
|
+
export interface ITransport
|
|
69
|
+
extends WithGenericHeaders,
|
|
70
|
+
WithErrorFormatting,
|
|
71
|
+
WithErrorTransforming,
|
|
72
|
+
WithLogFormatting,
|
|
73
|
+
Partial<WithErrorSending> {
|
|
43
74
|
/**
|
|
44
75
|
* @returns protocol in text format
|
|
45
76
|
*/
|
|
@@ -57,21 +88,6 @@ export interface ITransport extends WithGenericHeaders {
|
|
|
57
88
|
*/
|
|
58
89
|
matchByContext(ctx: ArgumentsHost): boolean;
|
|
59
90
|
|
|
60
|
-
/**
|
|
61
|
-
* @returns error formatting algorithm
|
|
62
|
-
*/
|
|
63
|
-
getErrorsFormatter(): IErrorsFormatter;
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @returns error transformers or empty array
|
|
67
|
-
*/
|
|
68
|
-
getErrorTransformers(): IErrorsTransformer[];
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @returns sending error algorithm
|
|
72
|
-
*/
|
|
73
|
-
getErrorsSender?(): IErrorsSender;
|
|
74
|
-
|
|
75
91
|
/**
|
|
76
92
|
* Modules for register metrics, healthchecks, configs and supporting tools, such as clients
|
|
77
93
|
*/
|
|
@@ -1,31 +1,23 @@
|
|
|
1
1
|
import { text } from '@rsdk/common';
|
|
2
2
|
import { LoggerFactory } from '@rsdk/logging';
|
|
3
3
|
|
|
4
|
-
const logger = LoggerFactory.create('
|
|
5
|
-
|
|
6
|
-
if (!process.env.RSDK_CLI_MODE) {
|
|
7
|
-
logger.info('Registering unhandled rejections handler...');
|
|
8
|
-
}
|
|
4
|
+
const logger = LoggerFactory.create('UnhandledRejectionHandler');
|
|
9
5
|
|
|
10
6
|
// This code enriches output if unhandled exceptions happen
|
|
11
|
-
process.on('unhandledRejection', (reason: any, promise) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
);
|
|
7
|
+
process.on('unhandledRejection', (reason: any, promise: Promise<any>) => {
|
|
8
|
+
const message = text`
|
|
9
|
+
Unhandled promise rejection happened! Process is shutting down
|
|
10
|
+
with exit code 1. See: https://github.com/nodejs/node/issues/20392
|
|
11
|
+
and https://nodejs.org/api/process.html#event-unhandledrejection
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
logger.error(message, { promise, reason });
|
|
20
15
|
|
|
21
16
|
/**
|
|
22
17
|
* Additionally writes to standard console, because both <promise> and <reason>
|
|
23
18
|
* can be not serializable
|
|
24
19
|
*/
|
|
25
|
-
console.error(
|
|
26
|
-
promise,
|
|
27
|
-
reason,
|
|
28
|
-
});
|
|
20
|
+
console.error(message, { promise, reason });
|
|
29
21
|
|
|
30
22
|
process.exit(1);
|
|
31
23
|
});
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import type { ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import type { ILogger } from '@rsdk/logging';
|
|
3
|
+
import { DEFAULT_LEVEL } from '@rsdk/logging';
|
|
4
|
+
import { ApiZone } from '@rsdk/zones';
|
|
5
|
+
import { of, throwError } from 'rxjs';
|
|
6
|
+
|
|
7
|
+
import type { Config } from '../src/config';
|
|
8
|
+
import { InternalException } from '../src/exceptions';
|
|
9
|
+
import type { LogFormatter } from '../src/logging/formatters';
|
|
10
|
+
import type { LoggingConfig } from '../src/logging/logging.config';
|
|
11
|
+
import { LoggingInterceptor } from '../src/logging/logging.interceptor';
|
|
12
|
+
import type { ProtocolDetector } from '../src/transport/protocol.detector';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* TODO: Надо куда-то вынести, но @rsdk/testing зависит
|
|
16
|
+
* от @rsdk/core, так что возникает цикл. Разобраться!
|
|
17
|
+
*/
|
|
18
|
+
export const createMockLogger = (): jest.Mocked<ILogger> => {
|
|
19
|
+
return {
|
|
20
|
+
debug: jest.fn(),
|
|
21
|
+
info: jest.fn(),
|
|
22
|
+
warn: jest.fn(),
|
|
23
|
+
error: jest.fn(),
|
|
24
|
+
fatal: jest.fn(),
|
|
25
|
+
trace: jest.fn(),
|
|
26
|
+
log: jest.fn(),
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* TODO: Надо куда-то вынести, но @rsdk/testing зависит
|
|
32
|
+
* от @rsdk/core, так что возникает цикл. Разобраться!
|
|
33
|
+
*/
|
|
34
|
+
export const createMockExecutionContext = (): jest.Mocked<ExecutionContext> => {
|
|
35
|
+
return {
|
|
36
|
+
getClass: jest.fn().mockReturnValue(class TestController {}),
|
|
37
|
+
getHandler: jest.fn(),
|
|
38
|
+
getArgs: jest.fn(),
|
|
39
|
+
getArgByIndex: jest.fn(),
|
|
40
|
+
switchToRpc: jest.fn(),
|
|
41
|
+
switchToHttp: jest.fn(),
|
|
42
|
+
switchToWs: jest.fn(),
|
|
43
|
+
getType: jest.fn(),
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
describe('LoggingInterceptor', () => {
|
|
48
|
+
let mockLogger: jest.Mocked<ILogger>;
|
|
49
|
+
let mockDetector: jest.Mocked<ProtocolDetector>;
|
|
50
|
+
let mockFormatter: jest.Mocked<LogFormatter>;
|
|
51
|
+
|
|
52
|
+
const makeInterceptor = (
|
|
53
|
+
configOverrides: Partial<Omit<LoggingConfig, keyof Config>> = {},
|
|
54
|
+
): LoggingInterceptor => {
|
|
55
|
+
const config: Omit<LoggingConfig, keyof Config> = {
|
|
56
|
+
/**
|
|
57
|
+
* Defaults
|
|
58
|
+
*/
|
|
59
|
+
logRequestBody: false,
|
|
60
|
+
logResponseBody: false,
|
|
61
|
+
excludeZones: [],
|
|
62
|
+
level: DEFAULT_LEVEL,
|
|
63
|
+
redact: [],
|
|
64
|
+
sync: false,
|
|
65
|
+
otelEnabled: false,
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Overrides
|
|
69
|
+
*/
|
|
70
|
+
...configOverrides,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return new LoggingInterceptor(
|
|
74
|
+
mockLogger,
|
|
75
|
+
new Map([[mockFormatter.protocol, mockFormatter]]),
|
|
76
|
+
mockDetector,
|
|
77
|
+
config as LoggingConfig,
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* TODO: Чтобы вот такого не делать, нужно будет убрать базовый класс
|
|
83
|
+
* config в принципе. Это можно сделать, привязывая функциональность
|
|
84
|
+
* обновления и прочего к ссылкам на созданные инстансы
|
|
85
|
+
*/
|
|
86
|
+
beforeEach(async () => {
|
|
87
|
+
mockLogger = createMockLogger();
|
|
88
|
+
|
|
89
|
+
mockDetector = {
|
|
90
|
+
getProtocol: jest.fn(),
|
|
91
|
+
} as unknown as jest.Mocked<ProtocolDetector>;
|
|
92
|
+
|
|
93
|
+
mockFormatter = {
|
|
94
|
+
protocol: 'test',
|
|
95
|
+
getPath: jest.fn().mockReturnValue('/test/path'),
|
|
96
|
+
formatRequest: jest.fn().mockReturnValue({}),
|
|
97
|
+
formatResponse: jest.fn().mockReturnValue({}),
|
|
98
|
+
shouldLog: jest.fn().mockReturnValue(true),
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('no error', () => {
|
|
103
|
+
it('should log request and response for non-excluded zone', (done) => {
|
|
104
|
+
// Arrange
|
|
105
|
+
mockDetector.getProtocol.mockReturnValue('test');
|
|
106
|
+
const mockContext = createMockExecutionContext();
|
|
107
|
+
const interceptor = makeInterceptor();
|
|
108
|
+
|
|
109
|
+
// Act & Assert
|
|
110
|
+
interceptor
|
|
111
|
+
.intercept(mockContext, { handle: () => of('response data') })
|
|
112
|
+
.subscribe({
|
|
113
|
+
complete: () => {
|
|
114
|
+
/* eslint-disable prettier/prettier */
|
|
115
|
+
expect(mockLogger.debug).toHaveBeenCalledTimes(2);
|
|
116
|
+
expect(mockLogger.debug).toHaveBeenNthCalledWith(1, '>>> Received [TEST] /test/path', expect.any(Object));
|
|
117
|
+
expect(mockLogger.debug).toHaveBeenNthCalledWith(2, '<<< Handled [TEST] /test/path', expect.objectContaining({
|
|
118
|
+
executionTime: expect.any(Number),
|
|
119
|
+
}));
|
|
120
|
+
/* eslint-enable prettier/prettier */
|
|
121
|
+
|
|
122
|
+
done();
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should not log request and response for excluded zone', (done) => {
|
|
128
|
+
// Arrange
|
|
129
|
+
mockDetector.getProtocol.mockReturnValue('test');
|
|
130
|
+
const mockContext = createMockExecutionContext();
|
|
131
|
+
|
|
132
|
+
// Mock zone metadata
|
|
133
|
+
@ApiZone('excluded-zone')
|
|
134
|
+
class WithExcludedZone {}
|
|
135
|
+
|
|
136
|
+
mockContext.getClass.mockReturnValue(WithExcludedZone);
|
|
137
|
+
jest.spyOn(Reflect, 'getMetadata').mockReturnValue('excluded-zone');
|
|
138
|
+
|
|
139
|
+
const interceptor = makeInterceptor({
|
|
140
|
+
excludeZones: ['excluded-zone'],
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Act & Assert
|
|
144
|
+
interceptor
|
|
145
|
+
.intercept(mockContext, { handle: () => of('response data') })
|
|
146
|
+
.subscribe({
|
|
147
|
+
complete: () => {
|
|
148
|
+
expect(mockLogger.debug).toHaveBeenCalledTimes(0);
|
|
149
|
+
done();
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should include request body when logRequestBody is true', (done) => {
|
|
155
|
+
// Arrange
|
|
156
|
+
mockDetector.getProtocol.mockReturnValue('test');
|
|
157
|
+
const mockContext = createMockExecutionContext();
|
|
158
|
+
const interceptor = makeInterceptor({ logRequestBody: true });
|
|
159
|
+
|
|
160
|
+
// Act & Assert
|
|
161
|
+
interceptor
|
|
162
|
+
.intercept(mockContext, { handle: () => of('response data') })
|
|
163
|
+
.subscribe({
|
|
164
|
+
complete: () => {
|
|
165
|
+
expect(mockFormatter.formatRequest).toHaveBeenCalledWith(
|
|
166
|
+
mockContext,
|
|
167
|
+
true,
|
|
168
|
+
);
|
|
169
|
+
done();
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should include response body when logResponseBody is true', (done) => {
|
|
175
|
+
// Arrange
|
|
176
|
+
mockDetector.getProtocol.mockReturnValue('test');
|
|
177
|
+
const mockContext = createMockExecutionContext();
|
|
178
|
+
const interceptor = makeInterceptor({ logResponseBody: true });
|
|
179
|
+
|
|
180
|
+
// Act & Assert
|
|
181
|
+
interceptor
|
|
182
|
+
.intercept(mockContext, { handle: () => of('response data') })
|
|
183
|
+
.subscribe({
|
|
184
|
+
complete: () => {
|
|
185
|
+
expect(mockFormatter.formatResponse).toHaveBeenCalledWith(
|
|
186
|
+
mockContext,
|
|
187
|
+
'response data',
|
|
188
|
+
);
|
|
189
|
+
done();
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should use default formatter for unknown protocol', (done) => {
|
|
195
|
+
// Arrange
|
|
196
|
+
mockDetector.getProtocol.mockReturnValue('unknown');
|
|
197
|
+
const mockContext = createMockExecutionContext();
|
|
198
|
+
const interceptor = makeInterceptor();
|
|
199
|
+
|
|
200
|
+
// Act & Assert
|
|
201
|
+
interceptor
|
|
202
|
+
.intercept(mockContext, { handle: () => of('response data') })
|
|
203
|
+
.subscribe({
|
|
204
|
+
complete: () => {
|
|
205
|
+
expect(mockLogger.warn).toHaveBeenCalledWith(
|
|
206
|
+
'no formatter for protocol <unknown>...',
|
|
207
|
+
);
|
|
208
|
+
done();
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should not log if formatter.shouldLog returns false', (done) => {
|
|
214
|
+
// Arrange
|
|
215
|
+
mockDetector.getProtocol.mockReturnValue('test');
|
|
216
|
+
const mockContext = createMockExecutionContext();
|
|
217
|
+
|
|
218
|
+
mockFormatter.shouldLog = jest.fn().mockReturnValue(false);
|
|
219
|
+
const interceptor = makeInterceptor();
|
|
220
|
+
|
|
221
|
+
// Act & Assert
|
|
222
|
+
interceptor
|
|
223
|
+
.intercept(mockContext, { handle: () => of('response data') })
|
|
224
|
+
.subscribe({
|
|
225
|
+
complete: () => {
|
|
226
|
+
expect(mockLogger.debug).not.toHaveBeenCalled();
|
|
227
|
+
done();
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe('with error', () => {
|
|
234
|
+
it('should log errors even for excluded zones', (done) => {
|
|
235
|
+
// Arrange
|
|
236
|
+
mockDetector.getProtocol.mockReturnValue('test');
|
|
237
|
+
const mockContext = createMockExecutionContext();
|
|
238
|
+
|
|
239
|
+
// Mock zone metadata
|
|
240
|
+
jest.spyOn(Reflect, 'getMetadata').mockReturnValue('excluded-zone');
|
|
241
|
+
|
|
242
|
+
const interceptor = makeInterceptor({
|
|
243
|
+
excludeZones: ['excluded-zone'],
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const error = new InternalException('Test error');
|
|
247
|
+
|
|
248
|
+
// Act & Assert
|
|
249
|
+
interceptor
|
|
250
|
+
.intercept(mockContext, { handle: () => throwError(() => error) })
|
|
251
|
+
.subscribe({
|
|
252
|
+
error: () => {
|
|
253
|
+
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
254
|
+
'Failed [TEST] /test/path',
|
|
255
|
+
expect.objectContaining({
|
|
256
|
+
request: {},
|
|
257
|
+
cause: error,
|
|
258
|
+
path: '/test/path',
|
|
259
|
+
zone: 'excluded-zone',
|
|
260
|
+
}),
|
|
261
|
+
);
|
|
262
|
+
done();
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should log error with request details', (done) => {
|
|
268
|
+
// Arrange
|
|
269
|
+
mockDetector.getProtocol.mockReturnValue('test');
|
|
270
|
+
const mockContext = createMockExecutionContext();
|
|
271
|
+
const error = new InternalException('Test error');
|
|
272
|
+
const interceptor = makeInterceptor();
|
|
273
|
+
|
|
274
|
+
// Act & Assert
|
|
275
|
+
interceptor
|
|
276
|
+
.intercept(mockContext, { handle: () => throwError(() => error) })
|
|
277
|
+
.subscribe({
|
|
278
|
+
error: () => {
|
|
279
|
+
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
280
|
+
'Failed [TEST] /test/path',
|
|
281
|
+
expect.objectContaining({
|
|
282
|
+
request: '[ALREADY LOGGED]',
|
|
283
|
+
cause: error,
|
|
284
|
+
path: '/test/path',
|
|
285
|
+
}),
|
|
286
|
+
);
|
|
287
|
+
done();
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { PropertyParser } from '../../types';
|
|
2
|
-
export declare class ArrayParser<T> implements PropertyParser<T[]> {
|
|
3
|
-
private readonly singleValueParser;
|
|
4
|
-
private readonly options;
|
|
5
|
-
constructor(singleValueParser: PropertyParser<T>, options?: {
|
|
6
|
-
separator: string;
|
|
7
|
-
});
|
|
8
|
-
type(): string;
|
|
9
|
-
description(): string;
|
|
10
|
-
parse(value: unknown): T[];
|
|
11
|
-
}
|