@rawnodes/config-loader 1.3.0 → 1.5.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/README.md +205 -1
- package/dist/index.d.mts +81 -2
- package/dist/index.d.ts +81 -2
- package/dist/index.js +299 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +293 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ Flexible YAML configuration loader for Node.js applications with environment ove
|
|
|
6
6
|
|
|
7
7
|
- **YAML Configuration** - Load config from YAML files with environment-specific overrides
|
|
8
8
|
- **Environment Variables** - Replace `${VAR}` placeholders with env values
|
|
9
|
+
- **HashiCorp Vault** - Read secrets from Vault using `${vault:path:field}` syntax
|
|
10
|
+
- **AWS Secrets Manager** - Read secrets from AWS using `${aws:secret-name:field}` syntax
|
|
9
11
|
- **Zod Validation** - Optional schema validation with detailed error messages
|
|
10
12
|
- **Docker/K8s Ready** - Mount additional config files via `overrideDir`
|
|
11
13
|
- **Secret Masking** - Automatic masking of sensitive values in logs
|
|
@@ -99,6 +101,25 @@ interface ConfigLoaderOptions<T> {
|
|
|
99
101
|
// Directory with additional YAML files to merge (default: '/etc/app/config')
|
|
100
102
|
// Set to false to disable
|
|
101
103
|
overrideDir?: string | false;
|
|
104
|
+
|
|
105
|
+
// Remove empty strings and empty objects from config (default: false)
|
|
106
|
+
// Useful for optional fields with ${VAR:} placeholders
|
|
107
|
+
stripEmpty?: boolean;
|
|
108
|
+
|
|
109
|
+
// HashiCorp Vault options (requires loadConfigAsync)
|
|
110
|
+
vault?: {
|
|
111
|
+
endpoint: string; // Vault server URL
|
|
112
|
+
roleId: string; // AppRole role_id
|
|
113
|
+
secretId: string; // AppRole secret_id
|
|
114
|
+
namespace?: string; // Optional Vault Enterprise namespace
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// AWS Secrets Manager options (requires loadConfigAsync)
|
|
118
|
+
aws?: {
|
|
119
|
+
region: string; // AWS region
|
|
120
|
+
accessKeyId: string; // AWS access key ID
|
|
121
|
+
secretAccessKey: string; // AWS secret access key
|
|
122
|
+
};
|
|
102
123
|
}
|
|
103
124
|
```
|
|
104
125
|
|
|
@@ -113,6 +134,160 @@ database:
|
|
|
113
134
|
password: ${DB_PASSWORD} # Required - throws if not set
|
|
114
135
|
```
|
|
115
136
|
|
|
137
|
+
## Optional Fields
|
|
138
|
+
|
|
139
|
+
Use `${VAR:}` (empty default) with `stripEmpty: true` to support optional fields:
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
# config/base.yml
|
|
143
|
+
server:
|
|
144
|
+
port: 3000
|
|
145
|
+
|
|
146
|
+
monitoring:
|
|
147
|
+
serviceId: ${MONITORING_SERVICE_ID:}
|
|
148
|
+
apiKey: ${MONITORING_API_KEY:}
|
|
149
|
+
healthcheckUrls:
|
|
150
|
+
cleanup: ${MONITORING_CLEANUP_URL:}
|
|
151
|
+
sync: ${MONITORING_SYNC_URL:}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const schema = z.object({
|
|
156
|
+
server: z.object({ port: z.number() }),
|
|
157
|
+
monitoring: z.object({
|
|
158
|
+
serviceId: z.string(),
|
|
159
|
+
apiKey: z.string(),
|
|
160
|
+
healthcheckUrls: z.object({
|
|
161
|
+
cleanup: z.string().url().optional(),
|
|
162
|
+
sync: z.string().url().optional(),
|
|
163
|
+
}).optional(),
|
|
164
|
+
}).optional(),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const { config } = loadConfig({
|
|
168
|
+
schema,
|
|
169
|
+
stripEmpty: true, // Empty strings → undefined, empty objects removed
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// If no MONITORING_* env vars are set, config.monitoring will be undefined
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**How `stripEmpty` works:**
|
|
176
|
+
- `""` (empty string) → `undefined`
|
|
177
|
+
- Objects with all `undefined` values → removed
|
|
178
|
+
- Arrays: empty strings filtered out
|
|
179
|
+
- Other falsy values (`0`, `false`, `null`) are preserved
|
|
180
|
+
|
|
181
|
+
## HashiCorp Vault Integration
|
|
182
|
+
|
|
183
|
+
Read secrets directly from HashiCorp Vault using AppRole authentication.
|
|
184
|
+
|
|
185
|
+
### Setup
|
|
186
|
+
|
|
187
|
+
```yaml
|
|
188
|
+
# config/base.yml
|
|
189
|
+
database:
|
|
190
|
+
host: localhost
|
|
191
|
+
password: ${vault:secret/data/api:DB_PASSWORD}
|
|
192
|
+
port: ${vault:secret/data/api:DB_PORT:5432} # with default value
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { loadConfigAsync } from '@rawnodes/config-loader';
|
|
197
|
+
|
|
198
|
+
const { config } = await loadConfigAsync({
|
|
199
|
+
configDir: './config',
|
|
200
|
+
vault: {
|
|
201
|
+
endpoint: 'https://vault.example.com',
|
|
202
|
+
roleId: process.env.VAULT_ROLE_ID!,
|
|
203
|
+
secretId: process.env.VAULT_SECRET_ID!,
|
|
204
|
+
namespace: 'optional-namespace', // for Vault Enterprise
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Syntax
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
${vault:PATH:FIELD} - Required secret
|
|
213
|
+
${vault:PATH:FIELD:DEFAULT} - With default value (used if secret not found)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Examples:**
|
|
217
|
+
```yaml
|
|
218
|
+
database:
|
|
219
|
+
# Read DB_PASSWORD from secret/data/api
|
|
220
|
+
password: ${vault:secret/data/api:DB_PASSWORD}
|
|
221
|
+
|
|
222
|
+
# With default value (supports colons in default)
|
|
223
|
+
url: ${vault:secret/data/db:URL:postgres://localhost:5432/app}
|
|
224
|
+
|
|
225
|
+
# Mix with env variables
|
|
226
|
+
host: ${DB_HOST:localhost}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Notes
|
|
230
|
+
|
|
231
|
+
- Use `loadConfigAsync()` instead of `loadConfig()` when using Vault
|
|
232
|
+
- Secrets are cached per path during config load (multiple fields from same path = 1 API call)
|
|
233
|
+
- Supports Vault KV v1 and v2 secret engines
|
|
234
|
+
|
|
235
|
+
## AWS Secrets Manager Integration
|
|
236
|
+
|
|
237
|
+
Read secrets from AWS Secrets Manager.
|
|
238
|
+
|
|
239
|
+
### Setup
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
# config/base.yml
|
|
243
|
+
database:
|
|
244
|
+
password: ${aws:my-app/database:DB_PASSWORD}
|
|
245
|
+
host: ${aws:my-app/database:DB_HOST:localhost}
|
|
246
|
+
api:
|
|
247
|
+
key: ${aws:my-app/api-key} # plain string secret (no field)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { loadConfigAsync } from '@rawnodes/config-loader';
|
|
252
|
+
|
|
253
|
+
const { config } = await loadConfigAsync({
|
|
254
|
+
configDir: './config',
|
|
255
|
+
aws: {
|
|
256
|
+
region: 'us-east-1',
|
|
257
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
258
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Syntax
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
${aws:SECRET_NAME} - Plain string secret (entire value)
|
|
267
|
+
${aws:SECRET_NAME:FIELD} - JSON secret, extract field
|
|
268
|
+
${aws:SECRET_NAME:FIELD:DEFAULT} - With default value
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Examples:**
|
|
272
|
+
```yaml
|
|
273
|
+
database:
|
|
274
|
+
# JSON secret: {"DB_PASSWORD": "secret", "DB_USER": "admin"}
|
|
275
|
+
password: ${aws:my-app/database:DB_PASSWORD}
|
|
276
|
+
user: ${aws:my-app/database:DB_USER}
|
|
277
|
+
|
|
278
|
+
# Plain string secret (no field)
|
|
279
|
+
api_key: ${aws:my-app/api-key}
|
|
280
|
+
|
|
281
|
+
# With default value
|
|
282
|
+
host: ${aws:my-app/database:DB_HOST:localhost}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Notes
|
|
286
|
+
|
|
287
|
+
- Use `loadConfigAsync()` instead of `loadConfig()` when using AWS
|
|
288
|
+
- Secrets are cached per secret name during config load
|
|
289
|
+
- Supports both JSON and plain string secrets
|
|
290
|
+
|
|
116
291
|
## Zod Validation
|
|
117
292
|
|
|
118
293
|
```typescript
|
|
@@ -186,7 +361,7 @@ export class ConfigModule {}
|
|
|
186
361
|
|
|
187
362
|
### `loadConfig<T>(options?): ConfigLoaderResult<T>`
|
|
188
363
|
|
|
189
|
-
Loads and merges configuration files.
|
|
364
|
+
Loads and merges configuration files synchronously.
|
|
190
365
|
|
|
191
366
|
**Returns:**
|
|
192
367
|
```typescript
|
|
@@ -197,6 +372,21 @@ interface ConfigLoaderResult<T> {
|
|
|
197
372
|
}
|
|
198
373
|
```
|
|
199
374
|
|
|
375
|
+
### `loadConfigAsync<T>(options?): Promise<ConfigLoaderResult<T>>`
|
|
376
|
+
|
|
377
|
+
Async version with Vault support. Required when using `vault` option.
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
const { config } = await loadConfigAsync({
|
|
381
|
+
configDir: './config',
|
|
382
|
+
vault: {
|
|
383
|
+
endpoint: 'https://vault.example.com',
|
|
384
|
+
roleId: 'role-id',
|
|
385
|
+
secretId: 'secret-id',
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
```
|
|
389
|
+
|
|
200
390
|
### `maskSecrets(obj): unknown`
|
|
201
391
|
|
|
202
392
|
Masks sensitive values in an object. Useful for logging.
|
|
@@ -220,6 +410,20 @@ Deep merges two objects.
|
|
|
220
410
|
|
|
221
411
|
Replaces `${VAR}` placeholders with environment variable values.
|
|
222
412
|
|
|
413
|
+
### `stripEmpty(obj): unknown`
|
|
414
|
+
|
|
415
|
+
Removes empty strings and empty objects recursively. Useful for cleaning up config before validation.
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
import { stripEmpty } from '@rawnodes/config-loader';
|
|
419
|
+
|
|
420
|
+
const cleaned = stripEmpty({
|
|
421
|
+
server: { port: 3000 },
|
|
422
|
+
optional: { url: '', name: '' },
|
|
423
|
+
});
|
|
424
|
+
// { server: { port: 3000 } }
|
|
425
|
+
```
|
|
426
|
+
|
|
223
427
|
## License
|
|
224
428
|
|
|
225
429
|
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
interface VaultOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Vault server endpoint URL
|
|
6
|
+
* @example 'https://vault.example.com'
|
|
7
|
+
*/
|
|
8
|
+
endpoint: string;
|
|
9
|
+
/**
|
|
10
|
+
* AppRole role_id for authentication
|
|
11
|
+
*/
|
|
12
|
+
roleId: string;
|
|
13
|
+
/**
|
|
14
|
+
* AppRole secret_id for authentication
|
|
15
|
+
*/
|
|
16
|
+
secretId: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional namespace for Vault Enterprise
|
|
19
|
+
*/
|
|
20
|
+
namespace?: string;
|
|
21
|
+
}
|
|
22
|
+
interface AwsSecretsOptions {
|
|
23
|
+
/**
|
|
24
|
+
* AWS region
|
|
25
|
+
* @example 'us-east-1'
|
|
26
|
+
*/
|
|
27
|
+
region: string;
|
|
28
|
+
/**
|
|
29
|
+
* AWS access key ID
|
|
30
|
+
*/
|
|
31
|
+
accessKeyId: string;
|
|
32
|
+
/**
|
|
33
|
+
* AWS secret access key
|
|
34
|
+
*/
|
|
35
|
+
secretAccessKey: string;
|
|
36
|
+
}
|
|
3
37
|
interface DotenvOptions {
|
|
4
38
|
/**
|
|
5
39
|
* Path to .env file
|
|
@@ -55,6 +89,26 @@ interface ConfigLoaderOptions<T = unknown> {
|
|
|
55
89
|
* @default '/etc/app/config'
|
|
56
90
|
*/
|
|
57
91
|
overrideDir?: string | false;
|
|
92
|
+
/**
|
|
93
|
+
* Remove empty strings and empty objects from config
|
|
94
|
+
* Useful for optional fields with ${VAR:} placeholders
|
|
95
|
+
* - Empty strings "" become undefined
|
|
96
|
+
* - Objects with all undefined values are removed
|
|
97
|
+
* @default false
|
|
98
|
+
*/
|
|
99
|
+
stripEmpty?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* HashiCorp Vault options for secret retrieval
|
|
102
|
+
* If provided, ${vault:path:field} placeholders will be resolved
|
|
103
|
+
* Requires using loadConfigAsync() instead of loadConfig()
|
|
104
|
+
*/
|
|
105
|
+
vault?: VaultOptions;
|
|
106
|
+
/**
|
|
107
|
+
* AWS Secrets Manager options for secret retrieval
|
|
108
|
+
* If provided, ${aws:secret-name:field} placeholders will be resolved
|
|
109
|
+
* Requires using loadConfigAsync() instead of loadConfig()
|
|
110
|
+
*/
|
|
111
|
+
aws?: AwsSecretsOptions;
|
|
58
112
|
}
|
|
59
113
|
interface ConfigLoaderResult<T> {
|
|
60
114
|
config: T;
|
|
@@ -63,12 +117,37 @@ interface ConfigLoaderResult<T> {
|
|
|
63
117
|
}
|
|
64
118
|
|
|
65
119
|
declare function loadConfig<T>(options?: ConfigLoaderOptions<T>): ConfigLoaderResult<T>;
|
|
120
|
+
declare function loadConfigAsync<T>(options?: ConfigLoaderOptions<T>): Promise<ConfigLoaderResult<T>>;
|
|
66
121
|
|
|
67
122
|
type DeepObject = Record<string, unknown>;
|
|
68
123
|
declare function deepMerge(base: DeepObject, override: DeepObject): DeepObject;
|
|
69
124
|
|
|
70
|
-
|
|
125
|
+
interface VaultSecretCache {
|
|
126
|
+
[path: string]: Record<string, unknown>;
|
|
127
|
+
}
|
|
128
|
+
interface VaultClient {
|
|
129
|
+
fetchSecrets(obj: unknown): Promise<VaultSecretCache>;
|
|
130
|
+
getSecret(path: string, field: string): unknown;
|
|
131
|
+
}
|
|
132
|
+
declare function createVaultClient(options: VaultOptions): Promise<VaultClient>;
|
|
133
|
+
|
|
134
|
+
interface AwsSecretsCache {
|
|
135
|
+
[secretName: string]: string | Record<string, unknown>;
|
|
136
|
+
}
|
|
137
|
+
interface AwsSecretsClient {
|
|
138
|
+
fetchSecrets(obj: unknown): Promise<AwsSecretsCache>;
|
|
139
|
+
getSecret(secretName: string, field?: string): unknown;
|
|
140
|
+
}
|
|
141
|
+
declare function createAwsSecretsClient(options: AwsSecretsOptions): Promise<AwsSecretsClient>;
|
|
142
|
+
|
|
143
|
+
interface ReplacePlaceholdersOptions {
|
|
144
|
+
vaultClient?: VaultClient;
|
|
145
|
+
awsClient?: AwsSecretsClient;
|
|
146
|
+
}
|
|
147
|
+
declare function replacePlaceholders(obj: unknown, options?: ReplacePlaceholdersOptions): unknown;
|
|
71
148
|
|
|
72
149
|
declare function maskSecrets(obj: unknown): unknown;
|
|
73
150
|
|
|
74
|
-
|
|
151
|
+
declare function stripEmpty(obj: unknown): unknown;
|
|
152
|
+
|
|
153
|
+
export { type AwsSecretsCache, type AwsSecretsClient, type AwsSecretsOptions, type ConfigLoaderOptions, type ConfigLoaderResult, type DotenvOptions, type VaultClient, type VaultOptions, type VaultSecretCache, createAwsSecretsClient, createVaultClient, deepMerge, loadConfig, loadConfigAsync, maskSecrets, replacePlaceholders, stripEmpty };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
interface VaultOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Vault server endpoint URL
|
|
6
|
+
* @example 'https://vault.example.com'
|
|
7
|
+
*/
|
|
8
|
+
endpoint: string;
|
|
9
|
+
/**
|
|
10
|
+
* AppRole role_id for authentication
|
|
11
|
+
*/
|
|
12
|
+
roleId: string;
|
|
13
|
+
/**
|
|
14
|
+
* AppRole secret_id for authentication
|
|
15
|
+
*/
|
|
16
|
+
secretId: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional namespace for Vault Enterprise
|
|
19
|
+
*/
|
|
20
|
+
namespace?: string;
|
|
21
|
+
}
|
|
22
|
+
interface AwsSecretsOptions {
|
|
23
|
+
/**
|
|
24
|
+
* AWS region
|
|
25
|
+
* @example 'us-east-1'
|
|
26
|
+
*/
|
|
27
|
+
region: string;
|
|
28
|
+
/**
|
|
29
|
+
* AWS access key ID
|
|
30
|
+
*/
|
|
31
|
+
accessKeyId: string;
|
|
32
|
+
/**
|
|
33
|
+
* AWS secret access key
|
|
34
|
+
*/
|
|
35
|
+
secretAccessKey: string;
|
|
36
|
+
}
|
|
3
37
|
interface DotenvOptions {
|
|
4
38
|
/**
|
|
5
39
|
* Path to .env file
|
|
@@ -55,6 +89,26 @@ interface ConfigLoaderOptions<T = unknown> {
|
|
|
55
89
|
* @default '/etc/app/config'
|
|
56
90
|
*/
|
|
57
91
|
overrideDir?: string | false;
|
|
92
|
+
/**
|
|
93
|
+
* Remove empty strings and empty objects from config
|
|
94
|
+
* Useful for optional fields with ${VAR:} placeholders
|
|
95
|
+
* - Empty strings "" become undefined
|
|
96
|
+
* - Objects with all undefined values are removed
|
|
97
|
+
* @default false
|
|
98
|
+
*/
|
|
99
|
+
stripEmpty?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* HashiCorp Vault options for secret retrieval
|
|
102
|
+
* If provided, ${vault:path:field} placeholders will be resolved
|
|
103
|
+
* Requires using loadConfigAsync() instead of loadConfig()
|
|
104
|
+
*/
|
|
105
|
+
vault?: VaultOptions;
|
|
106
|
+
/**
|
|
107
|
+
* AWS Secrets Manager options for secret retrieval
|
|
108
|
+
* If provided, ${aws:secret-name:field} placeholders will be resolved
|
|
109
|
+
* Requires using loadConfigAsync() instead of loadConfig()
|
|
110
|
+
*/
|
|
111
|
+
aws?: AwsSecretsOptions;
|
|
58
112
|
}
|
|
59
113
|
interface ConfigLoaderResult<T> {
|
|
60
114
|
config: T;
|
|
@@ -63,12 +117,37 @@ interface ConfigLoaderResult<T> {
|
|
|
63
117
|
}
|
|
64
118
|
|
|
65
119
|
declare function loadConfig<T>(options?: ConfigLoaderOptions<T>): ConfigLoaderResult<T>;
|
|
120
|
+
declare function loadConfigAsync<T>(options?: ConfigLoaderOptions<T>): Promise<ConfigLoaderResult<T>>;
|
|
66
121
|
|
|
67
122
|
type DeepObject = Record<string, unknown>;
|
|
68
123
|
declare function deepMerge(base: DeepObject, override: DeepObject): DeepObject;
|
|
69
124
|
|
|
70
|
-
|
|
125
|
+
interface VaultSecretCache {
|
|
126
|
+
[path: string]: Record<string, unknown>;
|
|
127
|
+
}
|
|
128
|
+
interface VaultClient {
|
|
129
|
+
fetchSecrets(obj: unknown): Promise<VaultSecretCache>;
|
|
130
|
+
getSecret(path: string, field: string): unknown;
|
|
131
|
+
}
|
|
132
|
+
declare function createVaultClient(options: VaultOptions): Promise<VaultClient>;
|
|
133
|
+
|
|
134
|
+
interface AwsSecretsCache {
|
|
135
|
+
[secretName: string]: string | Record<string, unknown>;
|
|
136
|
+
}
|
|
137
|
+
interface AwsSecretsClient {
|
|
138
|
+
fetchSecrets(obj: unknown): Promise<AwsSecretsCache>;
|
|
139
|
+
getSecret(secretName: string, field?: string): unknown;
|
|
140
|
+
}
|
|
141
|
+
declare function createAwsSecretsClient(options: AwsSecretsOptions): Promise<AwsSecretsClient>;
|
|
142
|
+
|
|
143
|
+
interface ReplacePlaceholdersOptions {
|
|
144
|
+
vaultClient?: VaultClient;
|
|
145
|
+
awsClient?: AwsSecretsClient;
|
|
146
|
+
}
|
|
147
|
+
declare function replacePlaceholders(obj: unknown, options?: ReplacePlaceholdersOptions): unknown;
|
|
71
148
|
|
|
72
149
|
declare function maskSecrets(obj: unknown): unknown;
|
|
73
150
|
|
|
74
|
-
|
|
151
|
+
declare function stripEmpty(obj: unknown): unknown;
|
|
152
|
+
|
|
153
|
+
export { type AwsSecretsCache, type AwsSecretsClient, type AwsSecretsOptions, type ConfigLoaderOptions, type ConfigLoaderResult, type DotenvOptions, type VaultClient, type VaultOptions, type VaultSecretCache, createAwsSecretsClient, createVaultClient, deepMerge, loadConfig, loadConfigAsync, maskSecrets, replacePlaceholders, stripEmpty };
|