@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.
Files changed (248) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/dist/app/platform.app.d.ts +1 -1
  3. package/dist/app/platform.app.js +3 -25
  4. package/dist/app/platform.app.js.map +1 -1
  5. package/dist/app-metadata/app-metadata.module.js.map +1 -1
  6. package/dist/app-metadata/exceptions/app-name-validation.exception.js.map +1 -1
  7. package/dist/config/additional-source/additional-source.initializer.d.ts +6 -2
  8. package/dist/config/additional-source/additional-source.initializer.js +24 -18
  9. package/dist/config/additional-source/additional-source.initializer.js.map +1 -1
  10. package/dist/config/additional-source/additional-source.module.d.ts +1 -1
  11. package/dist/config/additional-source/additional-source.module.js +3 -1
  12. package/dist/config/additional-source/additional-source.module.js.map +1 -1
  13. package/dist/config/config-reload.indicator.d.ts +3 -2
  14. package/dist/config/config-reload.indicator.js +4 -3
  15. package/dist/config/config-reload.indicator.js.map +1 -1
  16. package/dist/config/config.abstract.d.ts +3 -2
  17. package/dist/config/config.abstract.js +3 -3
  18. package/dist/config/config.abstract.js.map +1 -1
  19. package/dist/config/config.module.d.ts +0 -81
  20. package/dist/config/config.module.js +26 -203
  21. package/dist/config/config.module.js.map +1 -1
  22. package/dist/config/context/config.context.d.ts +75 -0
  23. package/dist/config/context/config.context.js +159 -0
  24. package/dist/config/context/config.context.js.map +1 -0
  25. package/dist/config/context/module.d.ts +5 -0
  26. package/dist/config/context/module.js +26 -0
  27. package/dist/config/context/module.js.map +1 -0
  28. package/dist/config/exceptions/config-not-bootstrapped.exception.js.map +1 -1
  29. package/dist/config/exceptions/property.exception.d.ts +9 -2
  30. package/dist/config/exceptions/property.exception.js +4 -6
  31. package/dist/config/exceptions/property.exception.js.map +1 -1
  32. package/dist/config/index.d.ts +1 -0
  33. package/dist/config/index.js +3 -1
  34. package/dist/config/index.js.map +1 -1
  35. package/dist/config/metadata/config-metadata.provider.d.ts +21 -0
  36. package/dist/config/metadata/config-metadata.provider.js +37 -0
  37. package/dist/config/metadata/config-metadata.provider.js.map +1 -0
  38. package/dist/config/metadata/config-metadata.registry.d.ts +1 -9
  39. package/dist/config/metadata/config-metadata.registry.js +9 -28
  40. package/dist/config/metadata/config-metadata.registry.js.map +1 -1
  41. package/dist/config/metadata/constants.d.ts +3 -0
  42. package/dist/config/metadata/constants.js +7 -0
  43. package/dist/config/metadata/constants.js.map +1 -0
  44. package/dist/config/metadata/decorators/declare-property.decorator.js +2 -2
  45. package/dist/config/metadata/decorators/declare-property.decorator.js.map +1 -1
  46. package/dist/config/metadata/decorators/inject-property.decorator.d.ts +1 -1
  47. package/dist/config/metadata/decorators/inject-property.decorator.js +1 -1
  48. package/dist/config/metadata/exceptions/duplicate-property.exception.js.map +1 -1
  49. package/dist/config/metadata/exceptions/duplicate-section.exception.js.map +1 -1
  50. package/dist/config/metadata/exceptions/duplicate-source.exception.js.map +1 -1
  51. package/dist/config/metadata/types.d.ts +16 -0
  52. package/dist/config/metadata/types.js +3 -0
  53. package/dist/config/metadata/types.js.map +1 -0
  54. package/dist/config/reload/config-reload.events.d.ts +0 -2
  55. package/dist/config/reload/config-reload.events.js +0 -8
  56. package/dist/config/reload/config-reload.events.js.map +1 -1
  57. package/dist/config/sources/base/reloadable-config-source.abstract.d.ts +3 -2
  58. package/dist/config/sources/base/reloadable-config-source.abstract.js +3 -3
  59. package/dist/config/sources/base/reloadable-config-source.abstract.js.map +1 -1
  60. package/dist/config/sources/exceptions/config-source-di.exception.js.map +1 -1
  61. package/dist/config/sources/implementations/json-file.source.js.map +1 -1
  62. package/dist/config/sources/implementations/relodable-json-file.source.d.ts +3 -1
  63. package/dist/config/sources/implementations/relodable-json-file.source.js +6 -3
  64. package/dist/config/sources/implementations/relodable-json-file.source.js.map +1 -1
  65. package/dist/config/vars.class.d.ts +1 -1
  66. package/dist/config/vars.class.js +6 -6
  67. package/dist/config/vars.class.js.map +1 -1
  68. package/dist/context.aggregator.d.ts +21 -0
  69. package/dist/context.aggregator.js +53 -0
  70. package/dist/context.aggregator.js.map +1 -0
  71. package/dist/exceptions/base/platform-exception.absract.d.ts +2 -2
  72. package/dist/exceptions/base/platform-exception.absract.js +4 -1
  73. package/dist/exceptions/base/platform-exception.absract.js.map +1 -1
  74. package/dist/exceptions/implementations/bootstrap/double-init.exception.js.map +1 -1
  75. package/dist/exceptions/implementations/bootstrap/duplicate-protocol.exception.js.map +1 -1
  76. package/dist/exceptions/implementations/bootstrap/no-http.exception.js.map +1 -1
  77. package/dist/exceptions/implementations/bootstrap/no-init.exception.js.map +1 -1
  78. package/dist/exceptions/implementations/bootstrap/no-matching-transport.exception.js.map +1 -1
  79. package/dist/exceptions/implementations/bootstrap/sequence.exception.js.map +1 -1
  80. package/dist/exceptions/implementations/bootstrap/symbol-key-decoration.exception.js.map +1 -1
  81. package/dist/exceptions/implementations/bootstrap/unknown-bootstrap.exception.js.map +1 -1
  82. package/dist/exceptions/implementations/pipeline/authentication.exception.js.map +1 -1
  83. package/dist/exceptions/implementations/pipeline/conflict.exception.js.map +1 -1
  84. package/dist/exceptions/implementations/pipeline/duplicate-entity.exception.js.map +1 -1
  85. package/dist/exceptions/implementations/pipeline/input.exception.js.map +1 -1
  86. package/dist/exceptions/implementations/pipeline/internal.exception.js.map +1 -1
  87. package/dist/exceptions/implementations/pipeline/not-allowed.exception.js.map +1 -1
  88. package/dist/exceptions/implementations/pipeline/not-found.exception.js.map +1 -1
  89. package/dist/exceptions/implementations/pipeline/timeout.exception.js.map +1 -1
  90. package/dist/exceptions.handling/global-exceptions.config.js.map +1 -1
  91. package/dist/exceptions.handling/global-exceptions.filter.js.map +1 -1
  92. package/dist/exceptions.handling/global-exceptions.module.js.map +1 -1
  93. package/dist/health/autodoc/heath.autodoc-resolver.d.ts +5 -15
  94. package/dist/health/autodoc/heath.autodoc-resolver.js +11 -13
  95. package/dist/health/autodoc/heath.autodoc-resolver.js.map +1 -1
  96. package/dist/health/exceptions/health-check.exception.js.map +1 -1
  97. package/dist/health/health.const.d.ts +1 -0
  98. package/dist/health/health.const.js +2 -1
  99. package/dist/health/health.const.js.map +1 -1
  100. package/dist/health/health.module.js.map +1 -1
  101. package/dist/health/health.service.d.ts +6 -2
  102. package/dist/health/health.service.js +19 -6
  103. package/dist/health/health.service.js.map +1 -1
  104. package/dist/health/metadata/constants.d.ts +1 -0
  105. package/dist/health/metadata/constants.js +5 -0
  106. package/dist/health/metadata/constants.js.map +1 -0
  107. package/dist/health/metadata/indicator.decorator.js +2 -12
  108. package/dist/health/metadata/indicator.decorator.js.map +1 -1
  109. package/dist/health/metadata/indicators.registry.d.ts +0 -7
  110. package/dist/health/metadata/indicators.registry.js +6 -14
  111. package/dist/health/metadata/indicators.registry.js.map +1 -1
  112. package/dist/health/metadata/types.d.ts +7 -0
  113. package/dist/health/metadata/types.js +3 -0
  114. package/dist/health/metadata/types.js.map +1 -0
  115. package/dist/index.d.ts +8 -1
  116. package/dist/index.js +13 -7
  117. package/dist/index.js.map +1 -1
  118. package/dist/logging/decorators/inject-logger.decorator.js +5 -3
  119. package/dist/logging/decorators/inject-logger.decorator.js.map +1 -1
  120. package/dist/logging/global-logger-provider.generator.d.ts +7 -0
  121. package/dist/logging/global-logger-provider.generator.js +22 -0
  122. package/dist/logging/global-logger-provider.generator.js.map +1 -0
  123. package/dist/logging/index.d.ts +2 -0
  124. package/dist/logging/index.js +3 -0
  125. package/dist/logging/index.js.map +1 -1
  126. package/dist/logging/logging.config.js +1 -1
  127. package/dist/logging/logging.config.js.map +1 -1
  128. package/dist/logging/logging.module.d.ts +5 -3
  129. package/dist/logging/logging.module.js +25 -13
  130. package/dist/logging/logging.module.js.map +1 -1
  131. package/dist/logging/metadata/constants.d.ts +1 -0
  132. package/dist/logging/metadata/constants.js +5 -0
  133. package/dist/logging/metadata/constants.js.map +1 -0
  134. package/dist/logging/types.d.ts +6 -2
  135. package/dist/metrics/index.d.ts +1 -1
  136. package/dist/metrics/index.js +3 -3
  137. package/dist/metrics/index.js.map +1 -1
  138. package/dist/metrics/metadata/autodoc/metrics.autodoc-resolver.d.ts +6 -7
  139. package/dist/metrics/metadata/autodoc/metrics.autodoc-resolver.js +8 -11
  140. package/dist/metrics/metadata/autodoc/metrics.autodoc-resolver.js.map +1 -1
  141. package/dist/metrics/metadata/constants.d.ts +1 -0
  142. package/dist/metrics/metadata/constants.js +5 -0
  143. package/dist/metrics/metadata/constants.js.map +1 -0
  144. package/dist/metrics/metadata/index.d.ts +0 -1
  145. package/dist/metrics/metadata/index.js +0 -3
  146. package/dist/metrics/metadata/index.js.map +1 -1
  147. package/dist/metrics/metadata/metrics.registry.d.ts +0 -3
  148. package/dist/metrics/metadata/metrics.registry.js +9 -16
  149. package/dist/metrics/metadata/metrics.registry.js.map +1 -1
  150. package/dist/metrics/metadata/types.d.ts +2 -4
  151. package/dist/metrics/metric.storage.d.ts +8 -0
  152. package/dist/metrics/metric.storage.js +11 -0
  153. package/dist/metrics/metric.storage.js.map +1 -0
  154. package/dist/metrics/metrics.config.js.map +1 -1
  155. package/dist/metrics/metrics.module.d.ts +1 -1
  156. package/dist/metrics/metrics.module.js +27 -21
  157. package/dist/metrics/metrics.module.js.map +1 -1
  158. package/dist/platform.context.d.ts +5 -3
  159. package/dist/platform.context.js +20 -19
  160. package/dist/platform.context.js.map +1 -1
  161. package/dist/platform.module.d.ts +5 -4
  162. package/dist/platform.module.js +24 -13
  163. package/dist/platform.module.js.map +1 -1
  164. package/dist/rsdk-metadata/constants.d.ts +3 -0
  165. package/dist/rsdk-metadata/constants.js +5 -0
  166. package/dist/rsdk-metadata/constants.js.map +1 -0
  167. package/dist/rsdk-metadata/rsdk-metadata.global-module.d.ts +6 -0
  168. package/dist/rsdk-metadata/rsdk-metadata.global-module.js +31 -0
  169. package/dist/rsdk-metadata/rsdk-metadata.global-module.js.map +1 -0
  170. package/dist/tracing/services/instrumentation.service.js.map +1 -1
  171. package/dist/tracing/services/metadata.scanner.js.map +1 -1
  172. package/dist/tracing/tracing.config.js.map +1 -1
  173. package/dist/tracing/tracing.module.js.map +1 -1
  174. package/dist/transport/transport.module.d.ts +1 -0
  175. package/dist/transport/transport.module.js +8 -2
  176. package/dist/transport/transport.module.js.map +1 -1
  177. package/dist/types/context-aggregated.d.ts +8 -0
  178. package/dist/types/context-aggregated.js +3 -0
  179. package/dist/types/context-aggregated.js.map +1 -0
  180. package/dist/types/options.d.ts +6 -6
  181. package/dist/types/transports.d.ts +10 -3
  182. package/dist/types/transports.js.map +1 -1
  183. package/dist/unhandled-rejection.handler.d.ts +1 -0
  184. package/dist/unhandled-rejection.handler.js +24 -0
  185. package/dist/unhandled-rejection.handler.js.map +1 -0
  186. package/package.json +8 -7
  187. package/src/app/platform.app.ts +6 -32
  188. package/src/config/additional-source/additional-source.initializer.ts +34 -25
  189. package/src/config/additional-source/additional-source.module.ts +5 -2
  190. package/src/config/config-reload.indicator.ts +3 -3
  191. package/src/config/config.abstract.ts +2 -3
  192. package/src/config/config.module.ts +23 -225
  193. package/src/config/context/config.context.ts +209 -0
  194. package/src/config/context/module.ts +25 -0
  195. package/src/config/exceptions/property.exception.ts +11 -6
  196. package/src/config/index.ts +1 -0
  197. package/src/config/metadata/config-metadata.provider.ts +79 -0
  198. package/src/config/metadata/config-metadata.registry.ts +36 -41
  199. package/src/config/metadata/constants.ts +6 -0
  200. package/src/config/metadata/decorators/declare-property.decorator.ts +2 -2
  201. package/src/config/metadata/decorators/inject-property.decorator.ts +1 -1
  202. package/src/config/metadata/types.ts +22 -0
  203. package/src/config/reload/config-reload.events.ts +1 -13
  204. package/src/config/sources/base/reloadable-config-source.abstract.ts +2 -3
  205. package/src/config/sources/implementations/relodable-json-file.source.ts +6 -2
  206. package/src/config/vars.class.ts +9 -7
  207. package/src/context.aggregator.ts +62 -0
  208. package/src/exceptions/base/platform-exception.absract.ts +8 -3
  209. package/src/health/autodoc/heath.autodoc-resolver.ts +15 -18
  210. package/src/health/health.const.ts +2 -0
  211. package/src/health/health.service.ts +23 -4
  212. package/src/health/metadata/constants.ts +1 -0
  213. package/src/health/metadata/indicator.decorator.ts +2 -18
  214. package/src/health/metadata/indicators.registry.ts +16 -23
  215. package/src/health/metadata/types.ts +9 -0
  216. package/src/index.ts +29 -12
  217. package/src/logging/decorators/inject-logger.decorator.ts +5 -4
  218. package/src/logging/global-logger-provider.generator.ts +28 -0
  219. package/src/logging/index.ts +2 -0
  220. package/src/logging/logging.config.ts +2 -1
  221. package/src/logging/logging.module.ts +42 -16
  222. package/src/logging/metadata/constants.ts +1 -0
  223. package/src/logging/types.ts +6 -2
  224. package/src/metrics/index.ts +1 -1
  225. package/src/metrics/metadata/autodoc/metrics.autodoc-resolver.ts +13 -9
  226. package/src/metrics/metadata/constants.ts +1 -0
  227. package/src/metrics/metadata/index.ts +0 -1
  228. package/src/metrics/metadata/metrics.registry.ts +19 -23
  229. package/src/metrics/metadata/types.ts +2 -5
  230. package/src/metrics/metric.storage.ts +10 -0
  231. package/src/metrics/metrics.module.ts +32 -31
  232. package/src/platform.context.ts +32 -20
  233. package/src/platform.module.ts +18 -20
  234. package/src/rsdk-metadata/constants.ts +5 -0
  235. package/src/rsdk-metadata/rsdk-metadata.global-module.ts +34 -0
  236. package/src/transport/transport.module.ts +13 -1
  237. package/src/types/context-aggregated.ts +10 -0
  238. package/src/types/options.ts +6 -5
  239. package/src/types/transports.ts +15 -3
  240. package/src/unhandled-rejection.handler.ts +29 -0
  241. package/dist/health/index.d.ts +0 -7
  242. package/dist/health/index.js +0 -26
  243. package/dist/health/index.js.map +0 -1
  244. package/dist/health/metadata/index.d.ts +0 -2
  245. package/dist/health/metadata/index.js +0 -19
  246. package/dist/health/metadata/index.js.map +0 -1
  247. package/src/health/index.ts +0 -7
  248. 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(property: string, msg: string) {
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(err: any, key: string): PropertyException {
13
- return new PropertyException(key, err.message || 'UNKNOWN ERROR');
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
  }
@@ -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
- DuplicatePropertyException,
15
- DuplicateSectionException,
16
- DuplicateSourceException,
17
- } from './exceptions';
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
- if (this.sources.has(target)) {
29
- throw new DuplicateSourceException(target);
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
- if (this.sections.has(target)) {
51
- throw new DuplicateSectionException(target);
52
- }
53
-
54
- this.sections.set(target, metadata);
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(alias: string, metadata: PropertyMetadata): void {
58
- if (this.properties.has(alias)) {
59
- throw new DuplicatePropertyException(alias);
60
- }
61
-
62
- this.properties.set(alias, metadata);
63
- }
64
-
65
- static getMetadata(): Readonly<{
66
- sources: Map<Constructor<ConfigSource>, SourceMetadata>;
67
- sections: Map<Constructor<Config>, SectionMetadata>;
68
- properties: Map<string, PropertyMetadata>;
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-clients).
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(@InjectProperty('CONFIG_PATH') private readonly path: string) {
17
- super(LoggerFactory.create(ReloadableFileSource));
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 {
@@ -69,8 +69,10 @@ export class Vars {
69
69
  return { createdKeys, updatedKeys };
70
70
  }
71
71
 
72
- extract<T extends ConfigValue>(propMeta: PropertyMetadata<T>): T | undefined {
73
- const { key, parser } = propMeta;
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 propMeta) {
84
- return propMeta.defaultValue;
85
+ if ('defaultValue' in propertyMetadata) {
86
+ return propertyMetadata.defaultValue;
85
87
  }
86
88
 
87
89
  throw new PropertyException(
88
- preparedKey,
89
- 'No value by key ' + propMeta.key + ' was provided!',
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