@itgorillaz/configify 3.0.0-alpha.0 → 3.0.0-alpha.2

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 (103) hide show
  1. package/index.d.ts +3 -1
  2. package/index.js +20 -6
  3. package/package.json +1 -1
  4. package/.prettierrc +0 -4
  5. package/LICENSE +0 -21
  6. package/README.md +0 -319
  7. package/dist/index.d.ts +0 -3
  8. package/dist/index.js +0 -20
  9. package/index.ts +0 -1
  10. package/nest-cli.json +0 -8
  11. package/src/configify.module.ts +0 -223
  12. package/src/configuration/configuration-options.interface.ts +0 -43
  13. package/src/configuration/configuration-parser.interface.ts +0 -15
  14. package/src/configuration/configuration-providers.interface.ts +0 -9
  15. package/src/configuration/configuration.registry.ts +0 -70
  16. package/src/configuration/index.ts +0 -6
  17. package/src/configuration/parsers/configuration-parser.factory.ts +0 -53
  18. package/src/configuration/parsers/dotenv-configuration.parser.ts +0 -18
  19. package/src/configuration/parsers/index.ts +0 -4
  20. package/src/configuration/parsers/json-configuration.parser.ts +0 -17
  21. package/src/configuration/parsers/yaml-configuration.parser.ts +0 -18
  22. package/src/configuration/resolvers/aws/aws-secrets-resolver.factory.ts +0 -32
  23. package/src/configuration/resolvers/aws/index.ts +0 -3
  24. package/src/configuration/resolvers/aws/parameter-store-configuration.resolver.ts +0 -115
  25. package/src/configuration/resolvers/aws/secrets-manager-configuration.resolver.ts +0 -117
  26. package/src/configuration/resolvers/configuration-resolver.interface.ts +0 -11
  27. package/src/configuration/resolvers/index.ts +0 -2
  28. package/src/configuration/resolvers/resolved-value.interface.ts +0 -10
  29. package/src/decorators/configuration.decorator.ts +0 -26
  30. package/src/decorators/index.ts +0 -2
  31. package/src/decorators/value.decorator.ts +0 -57
  32. package/src/index.ts +0 -3
  33. package/src/interpolation/variables.ts +0 -107
  34. package/tsconfig.build.json +0 -11
  35. package/tsconfig.build.tsbuildinfo +0 -1
  36. package/tsconfig.json +0 -23
  37. /package/{dist/configify.module.d.ts → configify.module.d.ts} +0 -0
  38. /package/{dist/configify.module.js → configify.module.js} +0 -0
  39. /package/{dist/configify.module.js.map → configify.module.js.map} +0 -0
  40. /package/{dist/configuration → configuration}/configuration-options.interface.d.ts +0 -0
  41. /package/{dist/configuration → configuration}/configuration-options.interface.js +0 -0
  42. /package/{dist/configuration → configuration}/configuration-options.interface.js.map +0 -0
  43. /package/{dist/configuration → configuration}/configuration-parser.interface.d.ts +0 -0
  44. /package/{dist/configuration → configuration}/configuration-parser.interface.js +0 -0
  45. /package/{dist/configuration → configuration}/configuration-parser.interface.js.map +0 -0
  46. /package/{dist/configuration → configuration}/configuration-providers.interface.d.ts +0 -0
  47. /package/{dist/configuration → configuration}/configuration-providers.interface.js +0 -0
  48. /package/{dist/configuration → configuration}/configuration-providers.interface.js.map +0 -0
  49. /package/{dist/configuration → configuration}/configuration.registry.d.ts +0 -0
  50. /package/{dist/configuration → configuration}/configuration.registry.js +0 -0
  51. /package/{dist/configuration → configuration}/configuration.registry.js.map +0 -0
  52. /package/{dist/configuration → configuration}/index.d.ts +0 -0
  53. /package/{dist/configuration → configuration}/index.js +0 -0
  54. /package/{dist/configuration → configuration}/index.js.map +0 -0
  55. /package/{dist/configuration → configuration}/parsers/configuration-parser.factory.d.ts +0 -0
  56. /package/{dist/configuration → configuration}/parsers/configuration-parser.factory.js +0 -0
  57. /package/{dist/configuration → configuration}/parsers/configuration-parser.factory.js.map +0 -0
  58. /package/{dist/configuration → configuration}/parsers/dotenv-configuration.parser.d.ts +0 -0
  59. /package/{dist/configuration → configuration}/parsers/dotenv-configuration.parser.js +0 -0
  60. /package/{dist/configuration → configuration}/parsers/dotenv-configuration.parser.js.map +0 -0
  61. /package/{dist/configuration → configuration}/parsers/index.d.ts +0 -0
  62. /package/{dist/configuration → configuration}/parsers/index.js +0 -0
  63. /package/{dist/configuration → configuration}/parsers/index.js.map +0 -0
  64. /package/{dist/configuration → configuration}/parsers/json-configuration.parser.d.ts +0 -0
  65. /package/{dist/configuration → configuration}/parsers/json-configuration.parser.js +0 -0
  66. /package/{dist/configuration → configuration}/parsers/json-configuration.parser.js.map +0 -0
  67. /package/{dist/configuration → configuration}/parsers/yaml-configuration.parser.d.ts +0 -0
  68. /package/{dist/configuration → configuration}/parsers/yaml-configuration.parser.js +0 -0
  69. /package/{dist/configuration → configuration}/parsers/yaml-configuration.parser.js.map +0 -0
  70. /package/{dist/configuration → configuration}/resolvers/aws/aws-secrets-resolver.factory.d.ts +0 -0
  71. /package/{dist/configuration → configuration}/resolvers/aws/aws-secrets-resolver.factory.js +0 -0
  72. /package/{dist/configuration → configuration}/resolvers/aws/aws-secrets-resolver.factory.js.map +0 -0
  73. /package/{dist/configuration → configuration}/resolvers/aws/index.d.ts +0 -0
  74. /package/{dist/configuration → configuration}/resolvers/aws/index.js +0 -0
  75. /package/{dist/configuration → configuration}/resolvers/aws/index.js.map +0 -0
  76. /package/{dist/configuration → configuration}/resolvers/aws/parameter-store-configuration.resolver.d.ts +0 -0
  77. /package/{dist/configuration → configuration}/resolvers/aws/parameter-store-configuration.resolver.js +0 -0
  78. /package/{dist/configuration → configuration}/resolvers/aws/parameter-store-configuration.resolver.js.map +0 -0
  79. /package/{dist/configuration → configuration}/resolvers/aws/secrets-manager-configuration.resolver.d.ts +0 -0
  80. /package/{dist/configuration → configuration}/resolvers/aws/secrets-manager-configuration.resolver.js +0 -0
  81. /package/{dist/configuration → configuration}/resolvers/aws/secrets-manager-configuration.resolver.js.map +0 -0
  82. /package/{dist/configuration → configuration}/resolvers/configuration-resolver.interface.d.ts +0 -0
  83. /package/{dist/configuration → configuration}/resolvers/configuration-resolver.interface.js +0 -0
  84. /package/{dist/configuration → configuration}/resolvers/configuration-resolver.interface.js.map +0 -0
  85. /package/{dist/configuration → configuration}/resolvers/index.d.ts +0 -0
  86. /package/{dist/configuration → configuration}/resolvers/index.js +0 -0
  87. /package/{dist/configuration → configuration}/resolvers/index.js.map +0 -0
  88. /package/{dist/configuration → configuration}/resolvers/resolved-value.interface.d.ts +0 -0
  89. /package/{dist/configuration → configuration}/resolvers/resolved-value.interface.js +0 -0
  90. /package/{dist/configuration → configuration}/resolvers/resolved-value.interface.js.map +0 -0
  91. /package/{dist/decorators → decorators}/configuration.decorator.d.ts +0 -0
  92. /package/{dist/decorators → decorators}/configuration.decorator.js +0 -0
  93. /package/{dist/decorators → decorators}/configuration.decorator.js.map +0 -0
  94. /package/{dist/decorators → decorators}/index.d.ts +0 -0
  95. /package/{dist/decorators → decorators}/index.js +0 -0
  96. /package/{dist/decorators → decorators}/index.js.map +0 -0
  97. /package/{dist/decorators → decorators}/value.decorator.d.ts +0 -0
  98. /package/{dist/decorators → decorators}/value.decorator.js +0 -0
  99. /package/{dist/decorators → decorators}/value.decorator.js.map +0 -0
  100. /package/{dist/index.js.map → index.js.map} +0 -0
  101. /package/{dist/interpolation → interpolation}/variables.d.ts +0 -0
  102. /package/{dist/interpolation → interpolation}/variables.js +0 -0
  103. /package/{dist/interpolation → interpolation}/variables.js.map +0 -0
package/index.d.ts CHANGED
@@ -1 +1,3 @@
1
- export * from './dist';
1
+ export * from './configify.module';
2
+ export * from './configuration';
3
+ export * from './decorators';
package/index.js CHANGED
@@ -1,6 +1,20 @@
1
- 'use strict';
2
- function __export(m) {
3
- for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4
- }
5
- exports.__esModule = true;
6
- __export(require("./dist"));
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./configify.module"), exports);
18
+ __exportStar(require("./configuration"), exports);
19
+ __exportStar(require("./decorators"), exports);
20
+ //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itgorillaz/configify",
3
- "version": "3.0.0-alpha.0",
3
+ "version": "3.0.0-alpha.2",
4
4
  "description": "NestJS Config on Steroids",
5
5
  "author": "tommelo",
6
6
  "private": false,
package/.prettierrc DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "singleQuote": true,
3
- "trailingComma": "all"
4
- }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 ITGorillaz
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,319 +0,0 @@
1
- <p align="center">
2
- <a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
3
- </p>
4
-
5
- <p align="center"><b>@itgorillaz/configify</b></p>
6
- <p align="center">NestJS config on steroids</p>
7
-
8
- <p align="center">
9
- <a href="https://buymeacoffee.com/tommelo" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>
10
- </p>
11
-
12
- ## Description
13
-
14
- **configify** is a NestJS configuration module that makes it easier to deal with configuration files and secrets.
15
-
16
- ## Installation
17
-
18
- ```bash
19
- $ npm install --save @itgorillaz/configify
20
- ```
21
-
22
- ## Usage
23
-
24
- To start using the <b>configify</b> module in your application import the module by calling the `forRootAsync` function:
25
-
26
- ```js
27
- @Module({
28
- imports: [ConfigifyModule.forRootAsync()],
29
- controllers: [AppController],
30
- providers: [AppService],
31
- })
32
- export class AppModule {}
33
- ```
34
-
35
- **Important Note**: When working with strict mode enabled `"strict": true`(tsconfig.json) it's necessary to set the option `strictPropertyInitialization` to `false` since the module will initialize the configuration class properties during runtime after resolving the values of the environment variables.
36
-
37
- By default, when bootstraping, the module will lookup for a `.env`, an `application.yml` and an `application.json` file at the root folder of the project:
38
-
39
- ```
40
- my-web-app
41
- | .env
42
- | application.yml
43
- | application.json
44
- ```
45
-
46
- You can also provide the location of the configuration files by overriding the configuration options.
47
-
48
- ### Mapping Configuration Classes
49
-
50
- This module will lookup for every class decorated with `@Configuration` and it will make its instance globally available for the application.
51
-
52
- Example of a `.env` file mapped to a class:
53
-
54
- ```
55
- APPLICATION_CLIENT_ID=ABC
56
- APPLICATION_CLIENT_TOKEN=TEST
57
- ```
58
-
59
- ```js
60
- @Configuration()
61
- export class ApplicationClientConfig {
62
- @Value('APPLICATION_CLIENT_ID')
63
- appClientId: string;
64
-
65
- @Value('APPLICATION_CLIENT_TOKEN')
66
- appClientToken: string
67
- }
68
- ```
69
-
70
- Example of a `.yml` file mapped to a class:
71
-
72
- ```
73
- database:
74
- host: localhost
75
- port: 3306
76
- username: test
77
- password: test
78
- metadata: |
79
- {
80
- "label": "staging"
81
- }
82
- ```
83
-
84
- ```js
85
- @Configuration()
86
- export class DatabaseConfiguration {
87
- @Value('database.host')
88
- host: string;
89
-
90
- @Value('database.port', {
91
- parse: parseInt
92
- })
93
- port: number;
94
-
95
- @Value('database.metadata', {
96
- parse: JSON.parse
97
- })
98
- metadata: MetadataType;
99
- }
100
- ```
101
-
102
- You can map your configuration file to multiple configuration classes:
103
-
104
- ```
105
- # database config
106
- DATABASE_HOST=localhost
107
- DATABASE_USER=test
108
- DATABASE_PASSWORD=test
109
-
110
- # okta config
111
- OKTA_API_TOKEN=test
112
- OKTA_CLIENT_ID=test
113
- ```
114
-
115
- ```js
116
- @Configuration()
117
- export class DatabaseConfiguration {
118
- // database configuration attributes
119
- }
120
- ```
121
-
122
- ```js
123
- @Configuration()
124
- export class OktaConfiguration {
125
- // okta configuration attributes
126
- }
127
- ```
128
-
129
- ### Dependency Injection
130
-
131
- This module makes all the configuration instances globally available to the application, to access it you just need to declare the configuration class as an argument in the class constructor:
132
-
133
- ```js
134
- export class AppService {
135
- private readonly LOGGER = new Logger(AppService.name);
136
-
137
- constructor(private readonly config: MyConfig) {
138
- this.LOGGER.log(JSON.stringify(config));
139
- }
140
-
141
- }
142
- ```
143
-
144
- ### Variables Expansion
145
-
146
- You can make use of variable expansion in your configuration files:
147
-
148
- ```
149
- MY_API_KEY=${MY_SECRET} // --> MY_API_KEY=TEST
150
- ANY_OTHER_CONFIG=TEST
151
- MY_SECRET=TEST
152
- APP_CLIENT_ID=${NON_EXISTING_ENV:-DEFAULT_ID} // --> APP_CLIENT_ID=DEFAULT_ID
153
- ```
154
-
155
- ### Defining Default Configuration Values
156
-
157
- Other than defining default values with variables expansion, you can also define a default value to an attribute using the `default` option provided by the `@Value()` decorator:
158
-
159
- ```js
160
- @Configuration()
161
- export class DatabaseConfiguration {
162
- @Value('DB_HOST', { default: 'localhost' })
163
- host: string;
164
-
165
- @Value('DB_PORT', {
166
- parse: parseInt,
167
- default: 3306
168
- })
169
- port: number;
170
- }
171
- ```
172
-
173
- ### Dealing with Secrets
174
-
175
- Out of the box, this module can resolve AWS Secrets Manager and Parameter Store secrets. For that, just need to choose which strategies you would like to use to resolve AWS secrets:
176
-
177
- ```js
178
- // use default aws client instances
179
- ConfigifyModule.forRootAsync({
180
- secretsResolverStrategies: [
181
- AwsSecretsResolverFactory.defaultParameterStoreResolver(),
182
- AwsSecretsResolverFactory.defaultSecretsManagerResolver(),
183
- ],
184
- });
185
-
186
- // or provide your own aws client instances
187
- ConfigifyModule.forRootAsync({
188
- secretsResolverStrategies: [
189
- new AwsParameterStoreConfigurationResolver(new SSMClient())
190
- new AwsSecretsManagerConfigurationResolver(
191
- new SecretsManagerClient(),
192
- ),
193
- ],
194
- });
195
- ```
196
-
197
- Every configuration attribute stating with `AWS_SECRETS_MANAGER`, `AWS_PARAMETER_STORE`, `aws-secrets-manager` and `aws-parameter-store` will be considered a special configuration attribute and the module will try to resolve it's remote value.
198
-
199
- E.g.: `.env`
200
-
201
- ```
202
- MY_DB_PASSWORD=${AWS_SECRETS_MANAGER_DB_PASSWORD}
203
- MY_API_TOKEN=${AWS_PARAMETER_STORE_API_TOKEN}
204
-
205
- AWS_SECRETS_MANAGER_DB_PASSWORD=<secret-id-here>
206
- AWS_PARAMETER_STORE_API_TOKEN=<parameter-name-here>
207
- ```
208
-
209
- `application.yml`
210
-
211
- ```yaml
212
- my-db-password: ${aws-secrets-manager.db.password}
213
- my-api-token: ${aws-parameter-store.api.token}
214
-
215
- aws-secrets-manager:
216
- db:
217
- password: <secret-id-here>
218
-
219
- aws-parameter-store:
220
- api:
221
- token: <parameter-name-here>
222
- ```
223
-
224
- ```js
225
- @Configuration()
226
- export class SecretConfiguration {
227
- @Value('my-db-password') // or @Value('aws-secrets-manager.db.password')
228
- myDbPassword: string;
229
-
230
- @Value('my-api-token') // or @Value('aws-parameter-store.api.token')
231
- myApiToken: string;
232
- }
233
- ```
234
-
235
- ### Parsing Configuration Values
236
-
237
- Parsing a configuration value can be easily done by using a parse callback function available as argument of the `@Value()` decorator:
238
-
239
- ```yaml
240
- db-json-config: |
241
- {
242
- "host": "localhost",
243
- "user": "test",
244
- "password": "test"
245
- }
246
- ```
247
-
248
- ```js
249
- export interface MyDBConfig {
250
- host: string;
251
- user: string;
252
- password: string;
253
- }
254
-
255
- @Configuration()
256
- export class SuperSecretConfiguration {
257
- @Value('db-json-config', {
258
- parse: JSON.parse
259
- })
260
- myDbConfig: MyDBConfig;
261
- }
262
- ```
263
-
264
- ### Validating Configuration Classes
265
-
266
- Depending on how critical a configuration is, you may want to validate it before starting the application, for that you can use [class-validator](https://github.com/typestack/class-validator) to make sure your configuration is loaded correctly:
267
-
268
- ```js
269
- @Configuration()
270
- export class MyConfiguration {
271
- @IsEmail()
272
- @Value('SENDER_EMAIL')
273
- senderEmail: string;
274
-
275
- @IsNotEmpty()
276
- @Value('my-api-token')
277
- myApiToken: string;
278
- }
279
- ```
280
-
281
- ### Overwrite Default Options
282
-
283
- You can overwrite default module options by providing an object as argument to the `forRootAsync()` method:
284
-
285
- ```js
286
- /**
287
- * Ignores any config file.
288
- * The default value is false;
289
- */
290
- ignoreConfigFile?: boolean;
291
-
292
- /**
293
- * Ignores environment variables
294
- * The default value is false;
295
- */
296
- ignoreEnvVars?: boolean;
297
-
298
- /**
299
- * The path of the configuration files
300
- */
301
- configFilePath?: string | string[];
302
-
303
- /**
304
- * Expands variables
305
- * The default value is true
306
- */
307
- expandConfig?: boolean;
308
-
309
- /**
310
- * The secrets resolvers strategies
311
- */
312
- secretsResolverStrategies?: ConfigurationResolver[];
313
- ```
314
-
315
- ## License
316
-
317
- This code is licensed under the [MIT License](./LICENSE.txt).
318
-
319
- All files located in the node_modules and external directories are externally maintained libraries used by this software which have their own licenses; we recommend you read them, as their terms may differ from the terms in the MIT License.
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './configify.module';
2
- export * from './configuration';
3
- export * from './decorators';
package/dist/index.js DELETED
@@ -1,20 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./configify.module"), exports);
18
- __exportStar(require("./configuration"), exports);
19
- __exportStar(require("./decorators"), exports);
20
- //# sourceMappingURL=index.js.map
package/index.ts DELETED
@@ -1 +0,0 @@
1
- export * from './dist';
package/nest-cli.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/nest-cli",
3
- "collection": "@nestjs/schematics",
4
- "sourceRoot": "src",
5
- "compilerOptions": {
6
- "deleteOutDir": true
7
- }
8
- }
@@ -1,223 +0,0 @@
1
- import { DynamicModule, Module, Provider } from '@nestjs/common';
2
- import { validateSync } from 'class-validator';
3
- import * as fs from 'fs';
4
- import { resolve } from 'path';
5
- import {
6
- ConfigifyModuleOptions,
7
- ConfigurationParserFactory,
8
- ConfigurationProviders,
9
- ConfigurationRegistry,
10
- DefaultConfigifyModuleOptions,
11
- } from './configuration';
12
- import { Variables } from './interpolation/variables';
13
-
14
- /**
15
- * The configify module.
16
- * A NestJS configuration module on steroids.
17
- *
18
- * This module provides out of the box configuration files parsing,
19
- * remote secrets fetching, variables expansion and configuration validation.
20
- *
21
- * The lifecycle of the module consists of:
22
- * - Reading configuration files
23
- * - Resolving remote secrets
24
- * - Expanding variables
25
- * - Creating object instances decorated with Configuration and assigning its values
26
- * - Validating the configuration instance
27
- *
28
- * All the configuration set to the configuration files will be assigned to the process.env object
29
- */
30
- @Module({})
31
- export class ConfigifyModule {
32
- /**
33
- * The default configuration files.
34
- * If no configuration files are provided this module will
35
- * lookup at a .env, application.yml and an application.json files
36
- * at the root path of the project.
37
- */
38
- private static readonly DEFAULT_CONFIG_FILES = [
39
- resolve(process.cwd(), '.env'),
40
- resolve(process.cwd(), 'application.yml'),
41
- resolve(process.cwd(), 'application.json'),
42
- ];
43
-
44
- /**
45
- * Creates the configfy dynamic module.
46
- *
47
- * The module will manage the instance of all classes decorated the Configuration decorator,
48
- * meaning, the module will create the instance and associate the value to attributes according to the
49
- * keys provided by the Value decorator.
50
- *
51
- * The configuration key pair values will also be available on process.env object.
52
- *
53
- * @param { ConfigifyModuleOptions } options The module config options
54
- * @returns { DynamicModule } module The configy module
55
- */
56
- static async forRootAsync(
57
- options: ConfigifyModuleOptions = {},
58
- ): Promise<DynamicModule> {
59
- const settings = { ...options, ...DefaultConfigifyModuleOptions };
60
- const files = this.resolveConfigurationFiles(settings.configFilePath);
61
-
62
- const envVars = settings.ignoreEnvVars ? {} : process.env;
63
- const fromFile = settings.ignoreConfigFile
64
- ? {}
65
- : this.parseConfigurationFiles(files);
66
-
67
- const container = { ...envVars, ...fromFile };
68
- const secrets = await this.runSecretsResolverPipeline(container, settings);
69
- const configuration = { ...container, ...secrets };
70
-
71
- if (settings.expandConfig) {
72
- const expanded = Variables.expand(configuration);
73
- Object.assign(configuration, expanded);
74
- }
75
-
76
- Object.assign(process.env, configuration);
77
-
78
- const { exports, providers } = this.buildConfigurationProviders();
79
-
80
- return {
81
- exports,
82
- providers,
83
- global: true,
84
- module: ConfigifyModule,
85
- };
86
- }
87
-
88
- /**
89
- * Runs the secrets resolver pipeline.
90
- *
91
- * @param {Record<string, any>} config the configuration object
92
- * @param {ConfigifyModuleOptions} options the module options
93
- * @returns {Promise<Record<string, any>>} the resolved secrets
94
- */
95
- private static async runSecretsResolverPipeline(
96
- config: Record<string, any>,
97
- options: ConfigifyModuleOptions,
98
- ): Promise<Record<string, any>> {
99
- const secrets = {};
100
- if (options.secretsResolverStrategies?.length) {
101
- for (const resolver of options.secretsResolverStrategies) {
102
- const result = await resolver.resolve(config);
103
- Object.assign(secrets, result);
104
- }
105
- }
106
- return secrets;
107
- }
108
-
109
- /**
110
- * Creates the configuration module providers.
111
- * It creates the configuration instances, assign its value
112
- * and perform the object validation.
113
- *
114
- * @returns {ConfigurationProviders} the module configuration providers
115
- */
116
- private static buildConfigurationProviders(): ConfigurationProviders {
117
- const exports: unknown[] = [];
118
- const providers: Provider[] = [];
119
-
120
- const registry = ConfigurationRegistry.getRegistry();
121
- for (const ConfigType of registry) {
122
- const instance = new ConfigType();
123
-
124
- const attributes =
125
- ConfigurationRegistry.getValueDecoratedAttributes(instance);
126
-
127
- for (const attribute of attributes) {
128
- const metadata = ConfigurationRegistry.getValueDecoratedKey(
129
- instance,
130
- attribute,
131
- );
132
-
133
- const parse = metadata.options?.parse;
134
-
135
- const defaultValue =
136
- process.env[metadata.key] || metadata.options?.default;
137
-
138
- const value = parse ? parse(defaultValue) : defaultValue;
139
-
140
- instance[attribute] = value;
141
- }
142
-
143
- const errors = validateSync(instance);
144
- if (errors && errors.length) {
145
- throw new Error(
146
- `validation constraints violated:\n${errors
147
- .map((e) =>
148
- JSON.stringify(
149
- { attribute: e.property, constraints: e.constraints },
150
- null,
151
- 2,
152
- ),
153
- )
154
- .join('\n')}`,
155
- );
156
- }
157
-
158
- exports.push(ConfigType);
159
- providers.push({ provide: ConfigType, useValue: instance });
160
- }
161
-
162
- return { exports, providers };
163
- }
164
-
165
- /**
166
- * Flattens a nested object into an one level key value pair object
167
- *
168
- * @param {object} source the source object
169
- * @param {string[]} path the key path
170
- * @param {Record<string, any>} target the target object
171
- */
172
- private static flattenObjectKeys(
173
- source: any,
174
- path: string[] = [],
175
- target: Record<string, any> = {},
176
- ) {
177
- if (typeof source === 'object') {
178
- for (const key in source) {
179
- this.flattenObjectKeys(source[key], [...path, key], target);
180
- }
181
- } else {
182
- target[path.join('.')] = source;
183
- }
184
- }
185
-
186
- /**
187
- * Parses configuration files and assign its contents to a configuration object.
188
- *
189
- * @param {string[]} files the configuration file paths
190
- * @returns {object} the object representation of the configuration files
191
- */
192
- private static parseConfigurationFiles(files: string[]): Record<string, any> {
193
- const kv = {};
194
- const config = {};
195
-
196
- for (const file of files) {
197
- const parser = ConfigurationParserFactory.getParser(file);
198
- const parsed = parser.parse(file);
199
- Object.assign(config, parsed);
200
- }
201
-
202
- this.flattenObjectKeys(config, [], kv);
203
-
204
- return kv;
205
- }
206
-
207
- /**
208
- * Resolve the path of the configuration files.
209
- * It ignores files that does not exist or is not
210
- * suppported by the configuration parsers.
211
- *
212
- * @param {string | string[]} path the configuration path
213
- * @returns {string[]} list of configuration files
214
- */
215
- private static resolveConfigurationFiles(path?: string | string[]): string[] {
216
- return ([] as string[])
217
- .concat(path || [], this.DEFAULT_CONFIG_FILES)
218
- .filter(
219
- (file) =>
220
- fs.existsSync(file) && ConfigurationParserFactory.supports(file),
221
- );
222
- }
223
- }
@@ -1,43 +0,0 @@
1
- import { ConfigurationResolver } from './resolvers';
2
-
3
- /**
4
- * The configuration options interface
5
- */
6
- export interface ConfigifyModuleOptions {
7
- /**
8
- * Ignores any config file.
9
- * The default value is false;
10
- */
11
- ignoreConfigFile?: boolean;
12
-
13
- /**
14
- * Ignores environment variables
15
- * The default value is false;
16
- */
17
- ignoreEnvVars?: boolean;
18
-
19
- /**
20
- * The path of the configuration files
21
- */
22
- configFilePath?: string | string[];
23
-
24
- /**
25
- * Expands variables
26
- * The default value is true
27
- */
28
- expandConfig?: boolean;
29
-
30
- /**
31
- * The secrets resolvers strategies
32
- */
33
- secretsResolverStrategies?: ConfigurationResolver[];
34
- }
35
-
36
- /**
37
- * The default module options
38
- */
39
- export const DefaultConfigifyModuleOptions: ConfigifyModuleOptions = {
40
- ignoreConfigFile: false,
41
- ignoreEnvVars: false,
42
- expandConfig: true,
43
- };