@rsdk/core 1.0.12 → 2.0.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/CHANGELOG.md +50 -0
- package/dist/app/platform.app.d.ts +1 -1
- package/dist/app/platform.app.js +3 -25
- package/dist/app/platform.app.js.map +1 -1
- package/dist/app-metadata/app-metadata.module.js.map +1 -1
- package/dist/app-metadata/exceptions/app-name-validation.exception.js.map +1 -1
- package/dist/config/additional-source/additional-source.initializer.d.ts +6 -2
- package/dist/config/additional-source/additional-source.initializer.js +24 -18
- package/dist/config/additional-source/additional-source.initializer.js.map +1 -1
- package/dist/config/additional-source/additional-source.module.d.ts +1 -1
- package/dist/config/additional-source/additional-source.module.js +3 -1
- package/dist/config/additional-source/additional-source.module.js.map +1 -1
- package/dist/config/config-reload.indicator.d.ts +3 -2
- package/dist/config/config-reload.indicator.js +4 -3
- package/dist/config/config-reload.indicator.js.map +1 -1
- package/dist/config/config.abstract.d.ts +3 -2
- package/dist/config/config.abstract.js +3 -3
- package/dist/config/config.abstract.js.map +1 -1
- package/dist/config/config.module.d.ts +0 -81
- package/dist/config/config.module.js +26 -203
- package/dist/config/config.module.js.map +1 -1
- package/dist/config/context/config.context.d.ts +75 -0
- package/dist/config/context/config.context.js +159 -0
- package/dist/config/context/config.context.js.map +1 -0
- package/dist/config/context/module.d.ts +5 -0
- package/dist/config/context/module.js +26 -0
- package/dist/config/context/module.js.map +1 -0
- package/dist/config/exceptions/config-not-bootstrapped.exception.js.map +1 -1
- package/dist/config/exceptions/property.exception.d.ts +9 -2
- package/dist/config/exceptions/property.exception.js +4 -6
- package/dist/config/exceptions/property.exception.js.map +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.js +3 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/metadata/config-metadata.provider.d.ts +21 -0
- package/dist/config/metadata/config-metadata.provider.js +37 -0
- package/dist/config/metadata/config-metadata.provider.js.map +1 -0
- package/dist/config/metadata/config-metadata.registry.d.ts +1 -9
- package/dist/config/metadata/config-metadata.registry.js +9 -28
- package/dist/config/metadata/config-metadata.registry.js.map +1 -1
- package/dist/config/metadata/constants.d.ts +3 -0
- package/dist/config/metadata/constants.js +7 -0
- package/dist/config/metadata/constants.js.map +1 -0
- package/dist/config/metadata/decorators/declare-property.decorator.js +2 -2
- package/dist/config/metadata/decorators/declare-property.decorator.js.map +1 -1
- package/dist/config/metadata/decorators/inject-property.decorator.d.ts +1 -1
- package/dist/config/metadata/decorators/inject-property.decorator.js +1 -1
- package/dist/config/metadata/exceptions/duplicate-property.exception.js.map +1 -1
- package/dist/config/metadata/exceptions/duplicate-section.exception.js.map +1 -1
- package/dist/config/metadata/exceptions/duplicate-source.exception.js.map +1 -1
- package/dist/config/metadata/types.d.ts +16 -0
- package/dist/config/metadata/types.js +3 -0
- package/dist/config/metadata/types.js.map +1 -0
- package/dist/config/reload/config-reload.events.d.ts +0 -2
- package/dist/config/reload/config-reload.events.js +0 -8
- package/dist/config/reload/config-reload.events.js.map +1 -1
- package/dist/config/sources/base/reloadable-config-source.abstract.d.ts +3 -2
- package/dist/config/sources/base/reloadable-config-source.abstract.js +3 -3
- package/dist/config/sources/base/reloadable-config-source.abstract.js.map +1 -1
- package/dist/config/sources/exceptions/config-source-di.exception.js.map +1 -1
- package/dist/config/sources/implementations/json-file.source.js.map +1 -1
- package/dist/config/sources/implementations/relodable-json-file.source.d.ts +3 -1
- package/dist/config/sources/implementations/relodable-json-file.source.js +6 -3
- package/dist/config/sources/implementations/relodable-json-file.source.js.map +1 -1
- package/dist/config/vars.class.d.ts +1 -1
- package/dist/config/vars.class.js +6 -6
- package/dist/config/vars.class.js.map +1 -1
- package/dist/context.aggregator.d.ts +21 -0
- package/dist/context.aggregator.js +53 -0
- package/dist/context.aggregator.js.map +1 -0
- package/dist/exceptions/base/platform-exception.absract.d.ts +2 -2
- package/dist/exceptions/base/platform-exception.absract.js +4 -1
- package/dist/exceptions/base/platform-exception.absract.js.map +1 -1
- package/dist/exceptions/implementations/bootstrap/double-init.exception.js.map +1 -1
- package/dist/exceptions/implementations/bootstrap/duplicate-protocol.exception.js.map +1 -1
- package/dist/exceptions/implementations/bootstrap/no-http.exception.js.map +1 -1
- package/dist/exceptions/implementations/bootstrap/no-init.exception.js.map +1 -1
- package/dist/exceptions/implementations/bootstrap/no-matching-transport.exception.js.map +1 -1
- package/dist/exceptions/implementations/bootstrap/sequence.exception.js.map +1 -1
- package/dist/exceptions/implementations/bootstrap/symbol-key-decoration.exception.js.map +1 -1
- package/dist/exceptions/implementations/bootstrap/unknown-bootstrap.exception.js.map +1 -1
- package/dist/exceptions/implementations/pipeline/authentication.exception.js.map +1 -1
- package/dist/exceptions/implementations/pipeline/conflict.exception.js.map +1 -1
- package/dist/exceptions/implementations/pipeline/duplicate-entity.exception.js.map +1 -1
- package/dist/exceptions/implementations/pipeline/input.exception.js.map +1 -1
- package/dist/exceptions/implementations/pipeline/internal.exception.js.map +1 -1
- package/dist/exceptions/implementations/pipeline/not-allowed.exception.js.map +1 -1
- package/dist/exceptions/implementations/pipeline/not-found.exception.js.map +1 -1
- package/dist/exceptions/implementations/pipeline/timeout.exception.js.map +1 -1
- package/dist/exceptions.handling/global-exceptions.config.js.map +1 -1
- package/dist/exceptions.handling/global-exceptions.filter.js.map +1 -1
- package/dist/exceptions.handling/global-exceptions.module.js.map +1 -1
- package/dist/health/autodoc/heath.autodoc-resolver.d.ts +5 -15
- package/dist/health/autodoc/heath.autodoc-resolver.js +11 -13
- package/dist/health/autodoc/heath.autodoc-resolver.js.map +1 -1
- package/dist/health/exceptions/health-check.exception.js.map +1 -1
- package/dist/health/health.const.d.ts +1 -0
- package/dist/health/health.const.js +2 -1
- package/dist/health/health.const.js.map +1 -1
- package/dist/health/health.module.js.map +1 -1
- package/dist/health/health.service.d.ts +6 -2
- package/dist/health/health.service.js +19 -6
- package/dist/health/health.service.js.map +1 -1
- package/dist/health/metadata/constants.d.ts +1 -0
- package/dist/health/metadata/constants.js +5 -0
- package/dist/health/metadata/constants.js.map +1 -0
- package/dist/health/metadata/indicator.decorator.js +2 -12
- package/dist/health/metadata/indicator.decorator.js.map +1 -1
- package/dist/health/metadata/indicators.registry.d.ts +0 -7
- package/dist/health/metadata/indicators.registry.js +6 -14
- package/dist/health/metadata/indicators.registry.js.map +1 -1
- package/dist/health/metadata/types.d.ts +7 -0
- package/dist/health/metadata/types.js +3 -0
- package/dist/health/metadata/types.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/dist/logging/decorators/inject-logger.decorator.js +5 -3
- package/dist/logging/decorators/inject-logger.decorator.js.map +1 -1
- package/dist/logging/global-logger-provider.generator.d.ts +7 -0
- package/dist/logging/global-logger-provider.generator.js +22 -0
- package/dist/logging/global-logger-provider.generator.js.map +1 -0
- package/dist/logging/index.d.ts +2 -0
- package/dist/logging/index.js +3 -0
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/logging.config.js +1 -1
- package/dist/logging/logging.config.js.map +1 -1
- package/dist/logging/logging.module.d.ts +5 -3
- package/dist/logging/logging.module.js +25 -13
- package/dist/logging/logging.module.js.map +1 -1
- package/dist/logging/metadata/constants.d.ts +1 -0
- package/dist/logging/metadata/constants.js +5 -0
- package/dist/logging/metadata/constants.js.map +1 -0
- package/dist/logging/types.d.ts +6 -2
- package/dist/metrics/index.d.ts +1 -1
- package/dist/metrics/index.js +3 -3
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/metadata/autodoc/metrics.autodoc-resolver.d.ts +6 -7
- package/dist/metrics/metadata/autodoc/metrics.autodoc-resolver.js +8 -11
- package/dist/metrics/metadata/autodoc/metrics.autodoc-resolver.js.map +1 -1
- package/dist/metrics/metadata/constants.d.ts +1 -0
- package/dist/metrics/metadata/constants.js +5 -0
- package/dist/metrics/metadata/constants.js.map +1 -0
- package/dist/metrics/metadata/index.d.ts +0 -1
- package/dist/metrics/metadata/index.js +0 -3
- package/dist/metrics/metadata/index.js.map +1 -1
- package/dist/metrics/metadata/metrics.registry.d.ts +0 -3
- package/dist/metrics/metadata/metrics.registry.js +9 -16
- package/dist/metrics/metadata/metrics.registry.js.map +1 -1
- package/dist/metrics/metadata/types.d.ts +2 -4
- package/dist/metrics/metric.storage.d.ts +8 -0
- package/dist/metrics/metric.storage.js +11 -0
- package/dist/metrics/metric.storage.js.map +1 -0
- package/dist/metrics/metrics.config.js.map +1 -1
- package/dist/metrics/metrics.module.d.ts +1 -1
- package/dist/metrics/metrics.module.js +27 -21
- package/dist/metrics/metrics.module.js.map +1 -1
- package/dist/platform.context.d.ts +5 -3
- package/dist/platform.context.js +20 -19
- package/dist/platform.context.js.map +1 -1
- package/dist/platform.module.d.ts +5 -4
- package/dist/platform.module.js +24 -13
- package/dist/platform.module.js.map +1 -1
- package/dist/rsdk-metadata/constants.d.ts +3 -0
- package/dist/rsdk-metadata/constants.js +5 -0
- package/dist/rsdk-metadata/constants.js.map +1 -0
- package/dist/rsdk-metadata/rsdk-metadata.global-module.d.ts +6 -0
- package/dist/rsdk-metadata/rsdk-metadata.global-module.js +31 -0
- package/dist/rsdk-metadata/rsdk-metadata.global-module.js.map +1 -0
- package/dist/tracing/services/instrumentation.service.js.map +1 -1
- package/dist/tracing/services/metadata.scanner.js.map +1 -1
- package/dist/tracing/tracing.config.js.map +1 -1
- package/dist/tracing/tracing.module.js.map +1 -1
- package/dist/transport/transport.module.d.ts +1 -0
- package/dist/transport/transport.module.js +8 -2
- package/dist/transport/transport.module.js.map +1 -1
- package/dist/types/context-aggregated.d.ts +8 -0
- package/dist/types/context-aggregated.js +3 -0
- package/dist/types/context-aggregated.js.map +1 -0
- package/dist/types/options.d.ts +6 -6
- package/dist/types/transports.d.ts +10 -3
- package/dist/types/transports.js.map +1 -1
- package/dist/unhandled-rejection.handler.d.ts +1 -0
- package/dist/unhandled-rejection.handler.js +24 -0
- package/dist/unhandled-rejection.handler.js.map +1 -0
- package/package.json +8 -7
- package/src/app/platform.app.ts +6 -32
- package/src/config/additional-source/additional-source.initializer.ts +34 -25
- package/src/config/additional-source/additional-source.module.ts +5 -2
- package/src/config/config-reload.indicator.ts +3 -3
- package/src/config/config.abstract.ts +2 -3
- package/src/config/config.module.ts +23 -225
- package/src/config/context/config.context.ts +209 -0
- package/src/config/context/module.ts +25 -0
- package/src/config/exceptions/property.exception.ts +11 -6
- package/src/config/index.ts +1 -0
- package/src/config/metadata/config-metadata.provider.ts +79 -0
- package/src/config/metadata/config-metadata.registry.ts +36 -41
- package/src/config/metadata/constants.ts +6 -0
- package/src/config/metadata/decorators/declare-property.decorator.ts +2 -2
- package/src/config/metadata/decorators/inject-property.decorator.ts +1 -1
- package/src/config/metadata/types.ts +22 -0
- package/src/config/reload/config-reload.events.ts +1 -13
- package/src/config/sources/base/reloadable-config-source.abstract.ts +2 -3
- package/src/config/sources/implementations/relodable-json-file.source.ts +6 -2
- package/src/config/vars.class.ts +9 -7
- package/src/context.aggregator.ts +62 -0
- package/src/exceptions/base/platform-exception.absract.ts +8 -3
- package/src/health/autodoc/heath.autodoc-resolver.ts +15 -18
- package/src/health/health.const.ts +2 -0
- package/src/health/health.service.ts +23 -4
- package/src/health/metadata/constants.ts +1 -0
- package/src/health/metadata/indicator.decorator.ts +2 -18
- package/src/health/metadata/indicators.registry.ts +16 -23
- package/src/health/metadata/types.ts +9 -0
- package/src/index.ts +29 -12
- package/src/logging/decorators/inject-logger.decorator.ts +5 -4
- package/src/logging/global-logger-provider.generator.ts +28 -0
- package/src/logging/index.ts +2 -0
- package/src/logging/logging.config.ts +2 -1
- package/src/logging/logging.module.ts +42 -16
- package/src/logging/metadata/constants.ts +1 -0
- package/src/logging/types.ts +6 -2
- package/src/metrics/index.ts +1 -1
- package/src/metrics/metadata/autodoc/metrics.autodoc-resolver.ts +13 -9
- package/src/metrics/metadata/constants.ts +1 -0
- package/src/metrics/metadata/index.ts +0 -1
- package/src/metrics/metadata/metrics.registry.ts +19 -23
- package/src/metrics/metadata/types.ts +2 -5
- package/src/metrics/metric.storage.ts +10 -0
- package/src/metrics/metrics.module.ts +32 -31
- package/src/platform.context.ts +32 -20
- package/src/platform.module.ts +18 -20
- package/src/rsdk-metadata/constants.ts +5 -0
- package/src/rsdk-metadata/rsdk-metadata.global-module.ts +34 -0
- package/src/transport/transport.module.ts +13 -1
- package/src/types/context-aggregated.ts +10 -0
- package/src/types/options.ts +6 -5
- package/src/types/transports.ts +15 -3
- package/src/unhandled-rejection.handler.ts +29 -0
- package/dist/health/index.d.ts +0 -7
- package/dist/health/index.js +0 -26
- package/dist/health/index.js.map +0 -1
- package/dist/health/metadata/index.d.ts +0 -2
- package/dist/health/metadata/index.js +0 -19
- package/dist/health/metadata/index.js.map +0 -1
- package/src/health/index.ts +0 -7
- package/src/health/metadata/index.ts +0 -2
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration is loaded in predictable order. You should take
|
|
3
|
+
* into account chat all repeating keys will be overwritten on each step:
|
|
4
|
+
*
|
|
5
|
+
* 1. .env file if there is any
|
|
6
|
+
* 2. process environment
|
|
7
|
+
* 3. динамические source'ы (если сделать последовательно - то в порядке указания)
|
|
8
|
+
*/
|
|
9
|
+
import type { Constructor } from '@rsdk/common';
|
|
10
|
+
import { dotenv } from '@rsdk/common';
|
|
11
|
+
import { LoggerFactory } from '@rsdk/logging';
|
|
12
|
+
import type { RsdkMetadataProvider } from '@rsdk/metadata';
|
|
13
|
+
|
|
14
|
+
import type { Config } from '../config.abstract';
|
|
15
|
+
import type { ConfigModuleOptions } from '../config.module';
|
|
16
|
+
import { ConfigPropertyMetadataNotFound } from '../exceptions';
|
|
17
|
+
import type { PropertyToken } from '../metadata';
|
|
18
|
+
import { getPropertyToken } from '../metadata';
|
|
19
|
+
import { ConfigMetadataProvider } from '../metadata/config-metadata.provider';
|
|
20
|
+
import { ReloadEvents } from '../reload';
|
|
21
|
+
import type { ConfigValue, PropertyMetadata } from '../types';
|
|
22
|
+
import { Vars } from '../vars.class';
|
|
23
|
+
|
|
24
|
+
export class ConfigContext {
|
|
25
|
+
readonly events = new ReloadEvents();
|
|
26
|
+
readonly vars: Vars;
|
|
27
|
+
readonly prefix: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Метадата о необходимых приложению значениях конфигурации
|
|
31
|
+
* Зачем храним?
|
|
32
|
+
* Потому что пайплайн такой:
|
|
33
|
+
* 1. Собираем данные о том какие поля нам нужны
|
|
34
|
+
* 2. Приложение запрашивает поле из конфигурации
|
|
35
|
+
* 3. Ищем метаданные
|
|
36
|
+
* 4. По метаданным вытягиваем значение
|
|
37
|
+
* 5. Отдаём значение
|
|
38
|
+
|
|
39
|
+
*
|
|
40
|
+
* Это важно так как позволяет прозрачным образом контролировать этот процесс и инициализировать поля в тот момент когда они потребуются
|
|
41
|
+
* А не в тот момент когда их объявили
|
|
42
|
+
* Основной кейс, где это применяется - тесты
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
readonly standalonePropertyMetadata = new Map<string, PropertyMetadata>();
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Проинициализированные секции конфигов
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
private readonly initializedConfigs = new Map<Constructor<Config>, Config>();
|
|
52
|
+
/**
|
|
53
|
+
* undefined является валидным значением по умолчанию (`defaultValue`)
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
private readonly properties = new Map<
|
|
57
|
+
PropertyToken,
|
|
58
|
+
ConfigValue | undefined
|
|
59
|
+
>();
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* We don't use class as context here because it is undefined if
|
|
63
|
+
* tsc target is ES2022
|
|
64
|
+
*/
|
|
65
|
+
private readonly logger = LoggerFactory.create('PlatformConfigModule');
|
|
66
|
+
|
|
67
|
+
constructor(
|
|
68
|
+
rsdkMetadataProvider: RsdkMetadataProvider,
|
|
69
|
+
options?: ConfigModuleOptions,
|
|
70
|
+
) {
|
|
71
|
+
/**
|
|
72
|
+
* Should be invoked BEFORE bootstrapping nest application.
|
|
73
|
+
*
|
|
74
|
+
* It takes 2 main actions:
|
|
75
|
+
* - load environment variables
|
|
76
|
+
*
|
|
77
|
+
* - initialize storage from options and rsdkMetadataProvider
|
|
78
|
+
*
|
|
79
|
+
* If any of these actions fails - application should exit.
|
|
80
|
+
*
|
|
81
|
+
* ATTENTION: not load values from additional source
|
|
82
|
+
*/
|
|
83
|
+
this.prefix = options?.appName ?? '';
|
|
84
|
+
|
|
85
|
+
if (this.prefix) {
|
|
86
|
+
this.logger.info('Setting configuration keys prefix', {
|
|
87
|
+
prefix: this.prefix,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
this.vars = new Vars(this.prefix);
|
|
92
|
+
|
|
93
|
+
this.readEnvironment();
|
|
94
|
+
|
|
95
|
+
const properties = new ConfigMetadataProvider(
|
|
96
|
+
rsdkMetadataProvider,
|
|
97
|
+
).getPropertiesMap();
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Reading and validating standalone properties from env.
|
|
101
|
+
*
|
|
102
|
+
* NOTE: Splitting extraction if standalone properties into 2 phases
|
|
103
|
+
* is necessary, some configuration sources can need something
|
|
104
|
+
* from env to be instatiated.
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
this.extractStandaloneProperties(properties, 'expectedInEnv');
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* NOTE: That properties from .env already loaded.
|
|
111
|
+
* Now loading ones from other sources
|
|
112
|
+
*/
|
|
113
|
+
this.extractStandaloneProperties(properties, 'others');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Extracting specific instance of configuration section by
|
|
118
|
+
* its class reference. Throws error if called before .bootstrap()
|
|
119
|
+
*
|
|
120
|
+
* ATTENTION: Конфиг будет разрешен с доступными на данный момент переменными,
|
|
121
|
+
* то есть если дополнительные источники конфигурации ещё не были проинициализированы,
|
|
122
|
+
* они не будут учтены в разрешении конфигурации.
|
|
123
|
+
*
|
|
124
|
+
* @param ctor Pass constructor of configuration section class
|
|
125
|
+
* @returns T
|
|
126
|
+
*/
|
|
127
|
+
resolve<T extends Config>(ctor: Constructor<T>): T {
|
|
128
|
+
const instance = this.initializedConfigs.get(ctor);
|
|
129
|
+
if (!instance) {
|
|
130
|
+
const instantiateSection = this.instantiateSection(ctor);
|
|
131
|
+
|
|
132
|
+
this.initializedConfigs.set(ctor, instantiateSection);
|
|
133
|
+
return instantiateSection;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// We know exactly it is T
|
|
137
|
+
return instance as T;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
resolveProperty(
|
|
141
|
+
token: `STANDALONE_CONFIG_PROPERTY_${string}`,
|
|
142
|
+
): ConfigValue | undefined {
|
|
143
|
+
if (this.properties.has(token)) {
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
145
|
+
return this.properties.get(token)!;
|
|
146
|
+
}
|
|
147
|
+
const propMeta = this.standalonePropertyMetadata.get(token);
|
|
148
|
+
if (!propMeta) {
|
|
149
|
+
throw new ConfigPropertyMetadataNotFound(token);
|
|
150
|
+
}
|
|
151
|
+
const value = this.vars.extract(propMeta);
|
|
152
|
+
|
|
153
|
+
this.properties.set(token, value);
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private readEnvironment(): void {
|
|
158
|
+
this.logger.info('Loading variables from .env file if exists');
|
|
159
|
+
dotenv.config();
|
|
160
|
+
|
|
161
|
+
this.logger.info('Initializing raw parameters storage');
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Copying parameters from process.env, skipping entries
|
|
165
|
+
* for which value is undefined (not sure it's possible,
|
|
166
|
+
* but @types/node says it is).
|
|
167
|
+
*/
|
|
168
|
+
|
|
169
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
170
|
+
if (value !== undefined) {
|
|
171
|
+
this.vars.set(key, value);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private extractStandaloneProperties(
|
|
177
|
+
properties: Map<string, PropertyMetadata>,
|
|
178
|
+
subset: 'expectedInEnv' | 'others',
|
|
179
|
+
): void {
|
|
180
|
+
for (const [alias, metadata] of properties.entries()) {
|
|
181
|
+
if (subset === 'expectedInEnv' && !metadata.expectedInEnv) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
this.standalonePropertyMetadata.set(getPropertyToken(alias), metadata);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Инициализирует инстанс секции конфига
|
|
191
|
+
* ATTENTION: не проверяет есть ли ещё проинициализированные, будьте внимательны во избежание неожиданного поведение
|
|
192
|
+
* @param ctor
|
|
193
|
+
* @private
|
|
194
|
+
*/
|
|
195
|
+
private instantiateSection<T extends Config>(ctor: Constructor<T>): T {
|
|
196
|
+
const instance = new ctor(this.events);
|
|
197
|
+
|
|
198
|
+
this.logger.debug('Initializing configuration section instance', {
|
|
199
|
+
ctor: ctor.name,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
this.events.on('merge', () => {
|
|
203
|
+
instance.tryUpdate(this.vars);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
instance.read(this.vars);
|
|
207
|
+
return instance;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DynamicModule } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
import { ReloadEvents } from '../reload';
|
|
4
|
+
|
|
5
|
+
import { ConfigContext } from './config.context';
|
|
6
|
+
|
|
7
|
+
export class ConfigContextModule {
|
|
8
|
+
static forRoot(configContext: ConfigContext): DynamicModule {
|
|
9
|
+
return {
|
|
10
|
+
global: true,
|
|
11
|
+
module: ConfigContextModule,
|
|
12
|
+
providers: [
|
|
13
|
+
{
|
|
14
|
+
provide: ConfigContext,
|
|
15
|
+
useValue: configContext,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
provide: ReloadEvents,
|
|
19
|
+
useValue: configContext.events,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
exports: [ConfigContext],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { PlatformException } from '../../exceptions';
|
|
2
|
+
import type { PropertyMetadata } from '../types';
|
|
2
3
|
|
|
3
4
|
export class PropertyException extends PlatformException {
|
|
4
|
-
constructor(
|
|
5
|
+
constructor(
|
|
6
|
+
msg: string,
|
|
7
|
+
details: { propertyMetadata: PropertyMetadata; preparedKey: string },
|
|
8
|
+
) {
|
|
5
9
|
super('CONFIG:PROPERTY', msg, {
|
|
6
|
-
details
|
|
7
|
-
property,
|
|
8
|
-
},
|
|
10
|
+
details,
|
|
9
11
|
});
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
static fromError(
|
|
13
|
-
|
|
14
|
+
static fromError(
|
|
15
|
+
err: any,
|
|
16
|
+
details: { propertyMetadata: PropertyMetadata; preparedKey: string },
|
|
17
|
+
): PropertyException {
|
|
18
|
+
return new PropertyException(err.message || 'UNKNOWN ERROR', details);
|
|
14
19
|
}
|
|
15
20
|
}
|
package/src/config/index.ts
CHANGED
|
@@ -8,3 +8,4 @@ export * from './reload';
|
|
|
8
8
|
export { AdditionalSourceModule } from './additional-source/additional-source.module';
|
|
9
9
|
export { AdditionalSourceOptions } from './additional-source/additional-source.module';
|
|
10
10
|
export { ConfigPropertyMetadataNotFound } from './exceptions';
|
|
11
|
+
export { ConfigContext } from './context/config.context';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Constructor } from '@rsdk/common';
|
|
2
|
+
import type { Resource, RsdkMetadataProvider } from '@rsdk/metadata';
|
|
3
|
+
|
|
4
|
+
import type { Config } from '../config.abstract';
|
|
5
|
+
import type { ConfigSource } from '../sources';
|
|
6
|
+
import type {
|
|
7
|
+
PropertyMetadata,
|
|
8
|
+
SectionMetadata,
|
|
9
|
+
SourceMetadata,
|
|
10
|
+
} from '../types';
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
CONFIG_PROPERTIES_RSDK_METADATA_SCOPE,
|
|
14
|
+
CONFIG_SECTION_RSDK_METADATA_SCOPE,
|
|
15
|
+
CONFIG_SOURCE_RSDK_METADATA_SCOPE,
|
|
16
|
+
} from './constants';
|
|
17
|
+
import type {
|
|
18
|
+
PropertyRsdkMetadata,
|
|
19
|
+
SectionRsdkMetadata,
|
|
20
|
+
SourcesRsdkMetadata,
|
|
21
|
+
} from './types';
|
|
22
|
+
|
|
23
|
+
export class ConfigMetadataProvider {
|
|
24
|
+
constructor(private rsdkMetadataProvider: RsdkMetadataProvider) {}
|
|
25
|
+
|
|
26
|
+
getPropertiesMetadata(): Resource<PropertyRsdkMetadata>[] {
|
|
27
|
+
return this.rsdkMetadataProvider.get<PropertyRsdkMetadata>(
|
|
28
|
+
CONFIG_PROPERTIES_RSDK_METADATA_SCOPE,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getMetadata(): Readonly<{
|
|
33
|
+
sources: Map<Constructor<ConfigSource>, SourceMetadata>;
|
|
34
|
+
sections: Map<Constructor<Config>, SectionMetadata>;
|
|
35
|
+
properties: Map<string, PropertyMetadata>;
|
|
36
|
+
}> {
|
|
37
|
+
return {
|
|
38
|
+
properties: this.getPropertiesMap(),
|
|
39
|
+
sections: this.getSectionsMap(),
|
|
40
|
+
sources: this.getSourcesMap(),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getPropertiesMap(): Map<string, PropertyMetadata> {
|
|
45
|
+
return new Map(
|
|
46
|
+
this.getPropertiesMetadata().map(
|
|
47
|
+
(resource) => [resource.value.alias, resource.value.metadata] as const,
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getSectionsMap(): Map<Constructor<Config>, SectionMetadata> {
|
|
53
|
+
return new Map(
|
|
54
|
+
this.getSectionsMetadata().map(
|
|
55
|
+
(resource) => [resource.value.target, resource.value.metadata] as const,
|
|
56
|
+
),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getSourcesMap(): Map<Constructor<ConfigSource>, SourceMetadata> {
|
|
61
|
+
return new Map(
|
|
62
|
+
this.getSourcesMetadata().map(
|
|
63
|
+
(resource) => [resource.value.target, resource.value.metadata] as const,
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getSectionsMetadata(): Resource<SectionRsdkMetadata>[] {
|
|
69
|
+
return this.rsdkMetadataProvider.get<SectionRsdkMetadata>(
|
|
70
|
+
CONFIG_SECTION_RSDK_METADATA_SCOPE,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private getSourcesMetadata(): Resource<SourcesRsdkMetadata>[] {
|
|
75
|
+
return this.rsdkMetadataProvider.get<SourcesRsdkMetadata>(
|
|
76
|
+
CONFIG_SOURCE_RSDK_METADATA_SCOPE,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Constructor } from '@rsdk/common';
|
|
2
|
+
import { RsdkMetadata } from '@rsdk/metadata';
|
|
2
3
|
|
|
3
|
-
import { IndicatorsRegistry } from '../../health/metadata';
|
|
4
|
+
import { IndicatorsRegistry } from '../../health/metadata/indicators.registry';
|
|
4
5
|
import type { Config } from '../config.abstract';
|
|
5
6
|
import { ConfigReloadIndicator } from '../config-reload.indicator';
|
|
6
7
|
import type { ConfigSource } from '../sources';
|
|
@@ -11,66 +12,60 @@ import type {
|
|
|
11
12
|
} from '../types';
|
|
12
13
|
|
|
13
14
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from './
|
|
15
|
+
CONFIG_PROPERTIES_RSDK_METADATA_SCOPE,
|
|
16
|
+
CONFIG_SECTION_RSDK_METADATA_SCOPE,
|
|
17
|
+
CONFIG_SOURCE_RSDK_METADATA_SCOPE,
|
|
18
|
+
} from './constants';
|
|
19
|
+
import type {
|
|
20
|
+
PropertyRsdkMetadata,
|
|
21
|
+
SectionRsdkMetadata,
|
|
22
|
+
SourcesRsdkMetadata,
|
|
23
|
+
} from './types';
|
|
18
24
|
|
|
19
25
|
export class ConfigMetadataRegistry {
|
|
20
|
-
private static properties = new Map<string, PropertyMetadata>();
|
|
21
|
-
private static sources = new Map<Constructor<ConfigSource>, SourceMetadata>();
|
|
22
|
-
private static sections = new Map<Constructor<Config>, SectionMetadata>();
|
|
23
|
-
|
|
24
26
|
static registerSource(
|
|
25
27
|
target: Constructor<ConfigSource>,
|
|
26
28
|
metadata: SourceMetadata,
|
|
27
29
|
): void {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
RsdkMetadata.setWithScope<SourcesRsdkMetadata>(
|
|
31
|
+
target,
|
|
32
|
+
CONFIG_SOURCE_RSDK_METADATA_SCOPE,
|
|
33
|
+
target,
|
|
34
|
+
{ target, metadata },
|
|
35
|
+
);
|
|
31
36
|
|
|
32
|
-
if (
|
|
33
|
-
metadata.type === 'reloadable' &&
|
|
34
|
-
!IndicatorsRegistry.isRegistered(ConfigReloadIndicator)
|
|
35
|
-
) {
|
|
37
|
+
if (metadata.type === 'reloadable') {
|
|
36
38
|
IndicatorsRegistry.register(ConfigReloadIndicator, {
|
|
37
39
|
description: 'Will be "down" if there are problems with config reload',
|
|
38
40
|
key: 'config-reload',
|
|
39
41
|
scope: 'common',
|
|
40
42
|
});
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
this.sources.set(target, metadata);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
static registerSection(
|
|
47
47
|
target: Constructor<Config>,
|
|
48
48
|
metadata: SectionMetadata,
|
|
49
49
|
): void {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
RsdkMetadata.setWithScope<SectionRsdkMetadata>(
|
|
51
|
+
target,
|
|
52
|
+
CONFIG_SECTION_RSDK_METADATA_SCOPE,
|
|
53
|
+
target,
|
|
54
|
+
{ target, metadata },
|
|
55
|
+
);
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
static registerProperty(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}> {
|
|
70
|
-
return {
|
|
71
|
-
properties: this.properties,
|
|
72
|
-
sections: this.sections,
|
|
73
|
-
sources: this.sources,
|
|
74
|
-
};
|
|
58
|
+
static registerProperty(
|
|
59
|
+
target: object,
|
|
60
|
+
alias: string,
|
|
61
|
+
metadata: PropertyMetadata,
|
|
62
|
+
): void {
|
|
63
|
+
RsdkMetadata.setWithScope(
|
|
64
|
+
target,
|
|
65
|
+
CONFIG_PROPERTIES_RSDK_METADATA_SCOPE,
|
|
66
|
+
alias,
|
|
67
|
+
<PropertyRsdkMetadata>{ metadata, alias },
|
|
68
|
+
true,
|
|
69
|
+
);
|
|
75
70
|
}
|
|
76
71
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const CONFIG_SOURCE_RSDK_METADATA_SCOPE =
|
|
2
|
+
'CONFIG_SOURCE_RSDK_METADATA_SCOPE';
|
|
3
|
+
export const CONFIG_SECTION_RSDK_METADATA_SCOPE =
|
|
4
|
+
'CONFIG_SECTION_RSDK_METADATA_SCOPE';
|
|
5
|
+
export const CONFIG_PROPERTIES_RSDK_METADATA_SCOPE =
|
|
6
|
+
'CONFIG_PROPERTIES_RSDK_METADATA_SCOPE';
|
|
@@ -26,8 +26,8 @@ export const DeclareProperty = <T extends ConfigValue>(
|
|
|
26
26
|
parser: PropertyParser<T>,
|
|
27
27
|
options: PropertyOptions<T>,
|
|
28
28
|
): ClassDecorator => {
|
|
29
|
-
return function (): void {
|
|
30
|
-
ConfigMetadataRegistry.registerProperty(alias, {
|
|
29
|
+
return function (target): void {
|
|
30
|
+
ConfigMetadataRegistry.registerProperty(target, alias, {
|
|
31
31
|
expectedInEnv: true,
|
|
32
32
|
...options,
|
|
33
33
|
key: alias,
|
|
@@ -19,7 +19,7 @@ export const trimPrefix = (token: PropertyToken): string =>
|
|
|
19
19
|
* 1. To inject properties into ConfigSource constructors. In this case
|
|
20
20
|
* one should add @DeclareProperty() to ConfigSource constructor first.
|
|
21
21
|
*
|
|
22
|
-
* 2. To create and inject dynamic properties (ex: @rsdk/grpc
|
|
22
|
+
* 2. To create and inject dynamic properties (ex: @rsdk/grpc.clients).
|
|
23
23
|
* In this case they should be registered manually using
|
|
24
24
|
* ConfigMetadataRegistry.registerProperty() method.
|
|
25
25
|
*
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Constructor } from '@rsdk/common';
|
|
2
|
+
|
|
3
|
+
import type { Config } from '../config.abstract';
|
|
4
|
+
import type { ConfigSource } from '../sources';
|
|
5
|
+
import type {
|
|
6
|
+
PropertyMetadata,
|
|
7
|
+
SectionMetadata,
|
|
8
|
+
SourceMetadata,
|
|
9
|
+
} from '../types';
|
|
10
|
+
|
|
11
|
+
export type PropertyRsdkMetadata = {
|
|
12
|
+
metadata: PropertyMetadata;
|
|
13
|
+
alias: string;
|
|
14
|
+
};
|
|
15
|
+
export type SectionRsdkMetadata = {
|
|
16
|
+
target: Constructor<Config>;
|
|
17
|
+
metadata: SectionMetadata;
|
|
18
|
+
};
|
|
19
|
+
export type SourcesRsdkMetadata = {
|
|
20
|
+
target: Constructor<ConfigSource>;
|
|
21
|
+
metadata: SourceMetadata;
|
|
22
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable prettier/prettier */
|
|
2
1
|
import EventEmitter from 'events';
|
|
3
2
|
|
|
4
3
|
import type { Config } from '../config.abstract';
|
|
@@ -6,17 +5,7 @@ import type { PropertyException } from '../exceptions';
|
|
|
6
5
|
import type { ConfigSource, ConfigSourceException } from '../sources';
|
|
7
6
|
import type { Changes, RawValues } from '../types';
|
|
8
7
|
|
|
9
|
-
export class ReloadEvents extends EventEmitter {
|
|
10
|
-
private static instance: ReloadEvents;
|
|
11
|
-
|
|
12
|
-
static getInstance(): ReloadEvents {
|
|
13
|
-
if (!this.instance) {
|
|
14
|
-
this.instance = new ReloadEvents();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return this.instance;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
8
|
+
export class ReloadEvents extends EventEmitter {}
|
|
20
9
|
|
|
21
10
|
export declare interface ReloadEvents {
|
|
22
11
|
on(e: 'reload', fn: (source: ConfigSource, values: RawValues) => void): this;
|
|
@@ -30,7 +19,6 @@ export declare interface ReloadEvents {
|
|
|
30
19
|
e: 'update_failure',
|
|
31
20
|
fn: (section: Config, err: PropertyException) => void,
|
|
32
21
|
): this;
|
|
33
|
-
|
|
34
22
|
emit(e: 'reload', source: ConfigSource, values: RawValues): boolean;
|
|
35
23
|
emit(
|
|
36
24
|
e: 'reload_failure',
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { ILogger } from '@rsdk/logging';
|
|
2
2
|
|
|
3
|
-
import { ReloadEvents } from '../../reload';
|
|
3
|
+
import type { ReloadEvents } from '../../reload';
|
|
4
4
|
import type { SourceType } from '../../types';
|
|
5
5
|
|
|
6
6
|
import { ConfigSource } from './config-source.abstract';
|
|
7
7
|
|
|
8
8
|
export abstract class ReloadableConfigSource extends ConfigSource {
|
|
9
9
|
protected readonly logger: ILogger;
|
|
10
|
-
private readonly events = ReloadEvents.getInstance();
|
|
11
10
|
|
|
12
|
-
constructor(logger: ILogger) {
|
|
11
|
+
constructor(logger: ILogger, private readonly events: ReloadEvents) {
|
|
13
12
|
super();
|
|
14
13
|
this.logger = logger;
|
|
15
14
|
}
|
|
@@ -5,6 +5,7 @@ import { LoggerFactory } from '@rsdk/logging';
|
|
|
5
5
|
|
|
6
6
|
import { DeclareProperty, InjectProperty } from '../../metadata';
|
|
7
7
|
import { FsPathParser } from '../../parsers';
|
|
8
|
+
import { ReloadEvents } from '../../reload';
|
|
8
9
|
import { ReloadableConfigSource } from '../base';
|
|
9
10
|
import { Source } from '../config-source.decorator';
|
|
10
11
|
|
|
@@ -13,8 +14,11 @@ import { Source } from '../config-source.decorator';
|
|
|
13
14
|
description: 'Path to some configuration file',
|
|
14
15
|
})
|
|
15
16
|
export class ReloadableFileSource extends ReloadableConfigSource {
|
|
16
|
-
constructor(
|
|
17
|
-
|
|
17
|
+
constructor(
|
|
18
|
+
@InjectProperty('CONFIG_PATH') private readonly path: string,
|
|
19
|
+
private reloadEvents: ReloadEvents,
|
|
20
|
+
) {
|
|
21
|
+
super(LoggerFactory.create(ReloadableFileSource), reloadEvents);
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
override name(): string {
|
package/src/config/vars.class.ts
CHANGED
|
@@ -69,8 +69,10 @@ export class Vars {
|
|
|
69
69
|
return { createdKeys, updatedKeys };
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
extract<T extends ConfigValue>(
|
|
73
|
-
|
|
72
|
+
extract<T extends ConfigValue>(
|
|
73
|
+
propertyMetadata: PropertyMetadata<T>,
|
|
74
|
+
): T | undefined {
|
|
75
|
+
const { key, parser } = propertyMetadata;
|
|
74
76
|
const preparedKey = this.toUpperSnakeCase(key);
|
|
75
77
|
|
|
76
78
|
const withPrefix = this.prefix
|
|
@@ -80,20 +82,20 @@ export class Vars {
|
|
|
80
82
|
const raw = this.values.get(withPrefix) ?? this.values.get(preparedKey);
|
|
81
83
|
|
|
82
84
|
if (raw === undefined) {
|
|
83
|
-
if ('defaultValue' in
|
|
84
|
-
return
|
|
85
|
+
if ('defaultValue' in propertyMetadata) {
|
|
86
|
+
return propertyMetadata.defaultValue;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
throw new PropertyException(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
`No value by key ${propertyMetadata.key} was provided!`,
|
|
91
|
+
{ propertyMetadata, preparedKey },
|
|
90
92
|
);
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
try {
|
|
94
96
|
return parser.parse(raw);
|
|
95
97
|
} catch (err) {
|
|
96
|
-
throw PropertyException.fromError(err, preparedKey);
|
|
98
|
+
throw PropertyException.fromError(err, { preparedKey, propertyMetadata });
|
|
97
99
|
}
|
|
98
100
|
}
|
|
99
101
|
|