@abdokouta/react-config 1.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/.examples/01-basic-usage.ts +289 -0
- package/.examples/02-env-helper.ts +282 -0
- package/.examples/README.md +285 -0
- package/.prettierrc.js +1 -0
- package/README.md +261 -0
- package/__tests__/config.module.test.ts +244 -0
- package/__tests__/drivers/env.driver.test.ts +259 -0
- package/__tests__/services/config.service.test.ts +328 -0
- package/__tests__/setup.d.ts +11 -0
- package/__tests__/vitest.setup.ts +30 -0
- package/config/config.config.ts +62 -0
- package/dist/index.d.mts +474 -0
- package/dist/index.d.ts +474 -0
- package/dist/index.js +516 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +501 -0
- package/dist/index.mjs.map +1 -0
- package/eslint.config.js +13 -0
- package/package.json +77 -0
- package/src/config.module.ts +154 -0
- package/src/constants/index.ts +5 -0
- package/src/constants/tokens.constant.ts +38 -0
- package/src/drivers/env.driver.ts +194 -0
- package/src/drivers/file.driver.ts +81 -0
- package/src/drivers/index.ts +6 -0
- package/src/index.ts +92 -0
- package/src/interfaces/config-driver.interface.ts +30 -0
- package/src/interfaces/config-module-options.interface.ts +84 -0
- package/src/interfaces/config-service.interface.ts +71 -0
- package/src/interfaces/index.ts +8 -0
- package/src/interfaces/vite-config-plugin-options.interface.ts +56 -0
- package/src/plugins/index.ts +5 -0
- package/src/plugins/vite.plugin.ts +115 -0
- package/src/services/config.service.ts +172 -0
- package/src/services/index.ts +5 -0
- package/src/utils/get-nested-value.util.ts +56 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/load-config-file.util.ts +37 -0
- package/src/utils/scan-config-files.util.ts +40 -0
- package/tsconfig.json +28 -0
- package/tsup.config.ts +105 -0
- package/vitest.config.ts +66 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { DynamicModule } from '@abdokouta/react-di';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration Module Options
|
|
5
|
+
*/
|
|
6
|
+
interface ConfigModuleOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Configuration driver to use
|
|
9
|
+
* @default 'env'
|
|
10
|
+
*/
|
|
11
|
+
driver?: 'env' | 'file' | 'firebase' | string;
|
|
12
|
+
/**
|
|
13
|
+
* Path to .env file (for env driver)
|
|
14
|
+
* @default '.env'
|
|
15
|
+
*/
|
|
16
|
+
envFilePath?: string | string[];
|
|
17
|
+
/**
|
|
18
|
+
* Path pattern to scan for config files (for file driver)
|
|
19
|
+
* @example 'config/**\/*.config.ts'
|
|
20
|
+
*/
|
|
21
|
+
filePattern?: string | string[];
|
|
22
|
+
/**
|
|
23
|
+
* Whether to ignore .env file
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
ignoreEnvFile?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Whether to expand environment variables
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
expandVariables?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Custom configuration object to merge
|
|
34
|
+
*/
|
|
35
|
+
load?: Record<string, any> | (() => Record<string, any> | Promise<Record<string, any>>);
|
|
36
|
+
/**
|
|
37
|
+
* Whether configuration is global
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
40
|
+
isGlobal?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Cache configuration values
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
cache?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Validate configuration on load
|
|
48
|
+
*/
|
|
49
|
+
validate?: (config: Record<string, any>) => void | Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Firebase configuration (for firebase driver)
|
|
52
|
+
*/
|
|
53
|
+
firebase?: {
|
|
54
|
+
projectId: string;
|
|
55
|
+
configPath?: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Environment variable prefix to strip
|
|
59
|
+
* Set to 'auto' to auto-detect (VITE_ for Vite, NEXT_PUBLIC_ for Next.js)
|
|
60
|
+
* Set to 'VITE_' or 'NEXT_PUBLIC_' for specific framework
|
|
61
|
+
* Set to a custom string to strip that prefix
|
|
62
|
+
* Set to false to disable prefix stripping
|
|
63
|
+
* @default 'auto'
|
|
64
|
+
* @example 'VITE_' - strips VITE_ prefix, so VITE_APP_NAME becomes APP_NAME
|
|
65
|
+
* @example 'NEXT_PUBLIC_' - strips NEXT_PUBLIC_ prefix, so NEXT_PUBLIC_API_URL becomes API_URL
|
|
66
|
+
* @example 'auto' - auto-detects framework and strips appropriate prefix
|
|
67
|
+
*/
|
|
68
|
+
envPrefix?: 'auto' | 'VITE_' | 'NEXT_PUBLIC_' | string | false;
|
|
69
|
+
/**
|
|
70
|
+
* Global variable name to read config from in browser
|
|
71
|
+
* @default '__APP_CONFIG__'
|
|
72
|
+
* @example '__APP_CONFIG__' - reads from window.__APP_CONFIG__
|
|
73
|
+
*/
|
|
74
|
+
globalName?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Configuration Module
|
|
79
|
+
*
|
|
80
|
+
* Provides configuration management with multiple drivers.
|
|
81
|
+
* Similar to NestJS ConfigModule.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* // Using environment variables (default)
|
|
86
|
+
* @Module({
|
|
87
|
+
* imports: [
|
|
88
|
+
* ConfigModule.forRoot({
|
|
89
|
+
* envFilePath: '.env',
|
|
90
|
+
* isGlobal: true,
|
|
91
|
+
* }),
|
|
92
|
+
* ],
|
|
93
|
+
* })
|
|
94
|
+
* export class AppModule {}
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* // Using file-based configuration
|
|
100
|
+
* @Module({
|
|
101
|
+
* imports: [
|
|
102
|
+
* ConfigModule.forRoot({
|
|
103
|
+
* driver: 'file',
|
|
104
|
+
* filePattern: 'config/**\/*.config.ts',
|
|
105
|
+
* isGlobal: true,
|
|
106
|
+
* }),
|
|
107
|
+
* ],
|
|
108
|
+
* })
|
|
109
|
+
* export class AppModule {}
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
declare class ConfigModule {
|
|
113
|
+
/**
|
|
114
|
+
* Register configuration module with options
|
|
115
|
+
*
|
|
116
|
+
* @param options - Configuration options
|
|
117
|
+
* @returns Dynamic module
|
|
118
|
+
*/
|
|
119
|
+
static forRoot(options?: ConfigModuleOptions): DynamicModule;
|
|
120
|
+
/**
|
|
121
|
+
* Register configuration module asynchronously
|
|
122
|
+
*
|
|
123
|
+
* @param options - Async configuration options
|
|
124
|
+
* @returns Dynamic module
|
|
125
|
+
*/
|
|
126
|
+
static forRootAsync(options: ConfigModuleOptions & {
|
|
127
|
+
useFactory?: () => Promise<ConfigModuleOptions> | ConfigModuleOptions;
|
|
128
|
+
}): Promise<DynamicModule>;
|
|
129
|
+
/**
|
|
130
|
+
* Create configuration driver based on options
|
|
131
|
+
*/
|
|
132
|
+
private static createDriver;
|
|
133
|
+
/**
|
|
134
|
+
* Merge custom configuration into driver
|
|
135
|
+
*/
|
|
136
|
+
private static mergeCustomConfig;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Configuration Driver Interface
|
|
141
|
+
*
|
|
142
|
+
* Defines the contract for configuration drivers (env, file, firebase, etc.)
|
|
143
|
+
*/
|
|
144
|
+
interface ConfigDriver {
|
|
145
|
+
/**
|
|
146
|
+
* Load configuration from the driver source
|
|
147
|
+
* @returns Configuration object
|
|
148
|
+
*/
|
|
149
|
+
load(): Promise<Record<string, any>> | Record<string, any>;
|
|
150
|
+
/**
|
|
151
|
+
* Get a configuration value by key
|
|
152
|
+
* @param key - Configuration key (supports dot notation)
|
|
153
|
+
* @param defaultValue - Default value if key not found
|
|
154
|
+
*/
|
|
155
|
+
get<T = any>(key: string, defaultValue?: T): T | undefined;
|
|
156
|
+
/**
|
|
157
|
+
* Check if a configuration key exists
|
|
158
|
+
* @param key - Configuration key
|
|
159
|
+
*/
|
|
160
|
+
has(key: string): boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Get all configuration values
|
|
163
|
+
*/
|
|
164
|
+
all(): Record<string, any>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Configuration Service Interface
|
|
169
|
+
*
|
|
170
|
+
* Defines the contract for configuration service implementations.
|
|
171
|
+
*/
|
|
172
|
+
interface ConfigServiceInterface {
|
|
173
|
+
/**
|
|
174
|
+
* Get configuration value
|
|
175
|
+
*/
|
|
176
|
+
get<T = any>(key: string, defaultValue?: T): T | undefined;
|
|
177
|
+
/**
|
|
178
|
+
* Get configuration value or throw if not found
|
|
179
|
+
*/
|
|
180
|
+
getOrThrow<T = any>(key: string): T;
|
|
181
|
+
/**
|
|
182
|
+
* Get string value
|
|
183
|
+
*/
|
|
184
|
+
getString(key: string, defaultValue?: string): string | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* Get string value or throw
|
|
187
|
+
*/
|
|
188
|
+
getStringOrThrow(key: string): string;
|
|
189
|
+
/**
|
|
190
|
+
* Get number value
|
|
191
|
+
*/
|
|
192
|
+
getNumber(key: string, defaultValue?: number): number | undefined;
|
|
193
|
+
/**
|
|
194
|
+
* Get number value or throw
|
|
195
|
+
*/
|
|
196
|
+
getNumberOrThrow(key: string): number;
|
|
197
|
+
/**
|
|
198
|
+
* Get boolean value
|
|
199
|
+
*/
|
|
200
|
+
getBool(key: string, defaultValue?: boolean): boolean | undefined;
|
|
201
|
+
/**
|
|
202
|
+
* Get boolean value or throw
|
|
203
|
+
*/
|
|
204
|
+
getBoolOrThrow(key: string): boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Get array value
|
|
207
|
+
*/
|
|
208
|
+
getArray(key: string, defaultValue?: string[]): string[] | undefined;
|
|
209
|
+
/**
|
|
210
|
+
* Get JSON value
|
|
211
|
+
*/
|
|
212
|
+
getJson<T = any>(key: string, defaultValue?: T): T | undefined;
|
|
213
|
+
/**
|
|
214
|
+
* Check if configuration key exists
|
|
215
|
+
*/
|
|
216
|
+
has(key: string): boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Get all configuration values
|
|
219
|
+
*/
|
|
220
|
+
all(): Record<string, any>;
|
|
221
|
+
/**
|
|
222
|
+
* Clear cache
|
|
223
|
+
*/
|
|
224
|
+
clearCache(): void;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Configuration Service
|
|
229
|
+
*
|
|
230
|
+
* Provides type-safe access to configuration values with various getter methods.
|
|
231
|
+
* Similar to NestJS ConfigService.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```typescript
|
|
235
|
+
* class MyService {
|
|
236
|
+
* constructor(private config: ConfigService) {}
|
|
237
|
+
*
|
|
238
|
+
* getDbConfig() {
|
|
239
|
+
* return {
|
|
240
|
+
* host: this.config.getString('DB_HOST', 'localhost'),
|
|
241
|
+
* port: this.config.getNumber('DB_PORT', 5432),
|
|
242
|
+
* ssl: this.config.getBool('DB_SSL', false),
|
|
243
|
+
* };
|
|
244
|
+
* }
|
|
245
|
+
* }
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
declare class ConfigService implements ConfigServiceInterface {
|
|
249
|
+
private driver;
|
|
250
|
+
constructor(driver: ConfigDriver);
|
|
251
|
+
/**
|
|
252
|
+
* Get configuration value
|
|
253
|
+
*/
|
|
254
|
+
get<T = any>(key: string, defaultValue?: T): T | undefined;
|
|
255
|
+
/**
|
|
256
|
+
* Get configuration value or throw if not found
|
|
257
|
+
*/
|
|
258
|
+
getOrThrow<T = any>(key: string): T;
|
|
259
|
+
/**
|
|
260
|
+
* Get string value
|
|
261
|
+
*/
|
|
262
|
+
getString(key: string, defaultValue?: string): string | undefined;
|
|
263
|
+
/**
|
|
264
|
+
* Get string value or throw
|
|
265
|
+
*/
|
|
266
|
+
getStringOrThrow(key: string): string;
|
|
267
|
+
/**
|
|
268
|
+
* Get number value
|
|
269
|
+
*/
|
|
270
|
+
getNumber(key: string, defaultValue?: number): number | undefined;
|
|
271
|
+
/**
|
|
272
|
+
* Get number value or throw
|
|
273
|
+
*/
|
|
274
|
+
getNumberOrThrow(key: string): number;
|
|
275
|
+
/**
|
|
276
|
+
* Get boolean value
|
|
277
|
+
* Treats 'true', '1', 'yes', 'on' as true
|
|
278
|
+
*/
|
|
279
|
+
getBool(key: string, defaultValue?: boolean): boolean | undefined;
|
|
280
|
+
/**
|
|
281
|
+
* Get boolean value or throw
|
|
282
|
+
*/
|
|
283
|
+
getBoolOrThrow(key: string): boolean;
|
|
284
|
+
/**
|
|
285
|
+
* Get array value (comma-separated string or actual array)
|
|
286
|
+
*/
|
|
287
|
+
getArray(key: string, defaultValue?: string[]): string[] | undefined;
|
|
288
|
+
/**
|
|
289
|
+
* Get JSON value
|
|
290
|
+
*/
|
|
291
|
+
getJson<T = any>(key: string, defaultValue?: T): T | undefined;
|
|
292
|
+
/**
|
|
293
|
+
* Check if configuration key exists
|
|
294
|
+
*/
|
|
295
|
+
has(key: string): boolean;
|
|
296
|
+
/**
|
|
297
|
+
* Get all configuration values
|
|
298
|
+
*/
|
|
299
|
+
all(): Record<string, any>;
|
|
300
|
+
/**
|
|
301
|
+
* Clear cache (no-op since we don't cache in ConfigService)
|
|
302
|
+
*/
|
|
303
|
+
clearCache(): void;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Environment Variable Configuration Driver
|
|
308
|
+
*
|
|
309
|
+
* Loads configuration from environment variables (process.env).
|
|
310
|
+
* Supports .env files via dotenv.
|
|
311
|
+
*/
|
|
312
|
+
declare class EnvDriver implements ConfigDriver {
|
|
313
|
+
private options;
|
|
314
|
+
private config;
|
|
315
|
+
private loaded;
|
|
316
|
+
constructor(options?: {
|
|
317
|
+
envFilePath?: string | string[];
|
|
318
|
+
ignoreEnvFile?: boolean;
|
|
319
|
+
expandVariables?: boolean;
|
|
320
|
+
envPrefix?: string | false;
|
|
321
|
+
globalName?: string;
|
|
322
|
+
});
|
|
323
|
+
/**
|
|
324
|
+
* Load environment variables
|
|
325
|
+
*/
|
|
326
|
+
load(): Record<string, any>;
|
|
327
|
+
/**
|
|
328
|
+
* Get configuration value
|
|
329
|
+
*/
|
|
330
|
+
get<T = any>(key: string, defaultValue?: T): T | undefined;
|
|
331
|
+
/**
|
|
332
|
+
* Check if key exists
|
|
333
|
+
*/
|
|
334
|
+
has(key: string): boolean;
|
|
335
|
+
/**
|
|
336
|
+
* Get all configuration
|
|
337
|
+
*/
|
|
338
|
+
all(): Record<string, any>;
|
|
339
|
+
/**
|
|
340
|
+
* Load .env file using dotenv
|
|
341
|
+
*/
|
|
342
|
+
private loadDotEnv;
|
|
343
|
+
/**
|
|
344
|
+
* Expand environment variables (e.g., ${VAR_NAME})
|
|
345
|
+
*/
|
|
346
|
+
private expandEnvVariables;
|
|
347
|
+
/**
|
|
348
|
+
* Strip environment variable prefix
|
|
349
|
+
* Auto-detects framework (Vite, Next.js) or uses custom prefix
|
|
350
|
+
*/
|
|
351
|
+
private stripPrefix;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* File-based Configuration Driver
|
|
356
|
+
*
|
|
357
|
+
* Loads configuration from TypeScript/JavaScript files.
|
|
358
|
+
* This is a server-side only driver. For client-side, use the Vite plugin.
|
|
359
|
+
*
|
|
360
|
+
* @see packages/pixielity/config/src/plugins/vite-config.plugin.ts
|
|
361
|
+
*/
|
|
362
|
+
declare class FileDriver implements ConfigDriver {
|
|
363
|
+
private config;
|
|
364
|
+
private loaded;
|
|
365
|
+
constructor(options?: {
|
|
366
|
+
config?: Record<string, any>;
|
|
367
|
+
});
|
|
368
|
+
/**
|
|
369
|
+
* Load configuration
|
|
370
|
+
* Config should be pre-loaded via Vite plugin or passed in constructor
|
|
371
|
+
*/
|
|
372
|
+
load(): Promise<Record<string, any>>;
|
|
373
|
+
/**
|
|
374
|
+
* Get configuration value
|
|
375
|
+
*/
|
|
376
|
+
get<T = any>(key: string, defaultValue?: T): T | undefined;
|
|
377
|
+
/**
|
|
378
|
+
* Check if key exists
|
|
379
|
+
*/
|
|
380
|
+
has(key: string): boolean;
|
|
381
|
+
/**
|
|
382
|
+
* Get all configuration
|
|
383
|
+
*/
|
|
384
|
+
all(): Record<string, any>;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Vite Config Plugin Options Interface
|
|
389
|
+
*
|
|
390
|
+
* Configuration options for the Vite config plugin that injects
|
|
391
|
+
* environment variables into the browser.
|
|
392
|
+
*/
|
|
393
|
+
interface ViteConfigPluginOptions {
|
|
394
|
+
/**
|
|
395
|
+
* Environment variables loaded by Vite's loadEnv
|
|
396
|
+
* Pass the result of loadEnv(mode, envDir, '') here
|
|
397
|
+
*/
|
|
398
|
+
env?: Record<string, string>;
|
|
399
|
+
/**
|
|
400
|
+
* Scan and collect .config.ts files
|
|
401
|
+
* @default false (disabled by default to avoid Node.js module issues)
|
|
402
|
+
*/
|
|
403
|
+
scanConfigFiles?: boolean;
|
|
404
|
+
/**
|
|
405
|
+
* Pattern to match config files
|
|
406
|
+
* @default 'src/**\/*.config.ts'
|
|
407
|
+
*/
|
|
408
|
+
configFilePattern?: string | string[];
|
|
409
|
+
/**
|
|
410
|
+
* Directories to exclude from config file scanning
|
|
411
|
+
* @default ['node_modules', 'dist', 'build', '.git']
|
|
412
|
+
*/
|
|
413
|
+
excludeDirs?: string[];
|
|
414
|
+
/**
|
|
415
|
+
* Root directory for scanning config files
|
|
416
|
+
* @default process.cwd()
|
|
417
|
+
*/
|
|
418
|
+
root?: string;
|
|
419
|
+
/**
|
|
420
|
+
* Include all environment variables
|
|
421
|
+
* @default true
|
|
422
|
+
*/
|
|
423
|
+
includeAll?: boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Specific environment variables to include
|
|
426
|
+
* Only used if includeAll is false
|
|
427
|
+
*/
|
|
428
|
+
include?: string[];
|
|
429
|
+
/**
|
|
430
|
+
* Global variable name to inject config into
|
|
431
|
+
* @default '__APP_CONFIG__'
|
|
432
|
+
*/
|
|
433
|
+
globalName?: string;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Get nested value from object using dot notation
|
|
438
|
+
*
|
|
439
|
+
* @param obj - Source object
|
|
440
|
+
* @param path - Dot-notated path (e.g., 'database.host')
|
|
441
|
+
* @param defaultValue - Default value if path not found
|
|
442
|
+
* @returns Value at path or default value
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```typescript
|
|
446
|
+
* const config = { database: { host: 'localhost' } };
|
|
447
|
+
* getNestedValue(config, 'database.host'); // 'localhost'
|
|
448
|
+
* getNestedValue(config, 'database.port', 5432); // 5432
|
|
449
|
+
* ```
|
|
450
|
+
*/
|
|
451
|
+
declare function getNestedValue<T = any>(obj: Record<string, any>, path: string, defaultValue?: T): T | undefined;
|
|
452
|
+
/**
|
|
453
|
+
* Check if nested path exists in object
|
|
454
|
+
*
|
|
455
|
+
* @param obj - Source object
|
|
456
|
+
* @param path - Dot-notated path
|
|
457
|
+
* @returns True if path exists
|
|
458
|
+
*/
|
|
459
|
+
declare function hasNestedValue(obj: Record<string, any>, path: string): boolean;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Load Config File Utility
|
|
463
|
+
*
|
|
464
|
+
* Dynamically loads and parses a config file.
|
|
465
|
+
*/
|
|
466
|
+
/**
|
|
467
|
+
* Load and parse config file
|
|
468
|
+
*
|
|
469
|
+
* @param filePath - Absolute path to the config file
|
|
470
|
+
* @returns Parsed config object
|
|
471
|
+
*/
|
|
472
|
+
declare function loadConfigFile(filePath: string): Promise<Record<string, any>>;
|
|
473
|
+
|
|
474
|
+
export { type ConfigDriver, ConfigModule, type ConfigModuleOptions, ConfigService, type ConfigServiceInterface, EnvDriver, FileDriver, type ViteConfigPluginOptions, getNestedValue, hasNestedValue, loadConfigFile };
|