@rawnodes/config-loader 1.5.0 → 1.7.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 +33 -0
- package/dist/index.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +73 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -331,6 +331,39 @@ server:
|
|
|
331
331
|
|
|
332
332
|
Files are merged in alphabetical order.
|
|
333
333
|
|
|
334
|
+
## Environment Helpers
|
|
335
|
+
|
|
336
|
+
### `env`
|
|
337
|
+
|
|
338
|
+
Environment detection helpers:
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
import { env } from '@rawnodes/config-loader';
|
|
342
|
+
|
|
343
|
+
env.nodeEnv // process.env.NODE_ENV || 'local'
|
|
344
|
+
env.isProduction // true if NODE_ENV === 'production'
|
|
345
|
+
env.isDevelopment // true if NODE_ENV === 'development'
|
|
346
|
+
env.isTest // true if NODE_ENV === 'test'
|
|
347
|
+
env.isLocal // true if NODE_ENV is 'local' or not set
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Usage with Vault/AWS
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
import { loadConfigAsync, env } from '@rawnodes/config-loader';
|
|
354
|
+
|
|
355
|
+
const { config } = await loadConfigAsync({
|
|
356
|
+
configDir: './config',
|
|
357
|
+
vault: !env.isLocal && {
|
|
358
|
+
endpoint: process.env.VAULT_ENDPOINT,
|
|
359
|
+
roleId: process.env.VAULT_ROLE_ID,
|
|
360
|
+
secretId: process.env.VAULT_SECRET_ID,
|
|
361
|
+
},
|
|
362
|
+
});
|
|
363
|
+
// If any value is missing, you'll get a clear error:
|
|
364
|
+
// "Vault endpoint is not set" or "Vault roleId is not set"
|
|
365
|
+
```
|
|
366
|
+
|
|
334
367
|
## NestJS Integration
|
|
335
368
|
|
|
336
369
|
```typescript
|
package/dist/index.d.mts
CHANGED
|
@@ -150,4 +150,15 @@ declare function maskSecrets(obj: unknown): unknown;
|
|
|
150
150
|
|
|
151
151
|
declare function stripEmpty(obj: unknown): unknown;
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Environment helpers
|
|
155
|
+
*/
|
|
156
|
+
declare const env: {
|
|
157
|
+
readonly nodeEnv: string;
|
|
158
|
+
readonly isProduction: boolean;
|
|
159
|
+
readonly isDevelopment: boolean;
|
|
160
|
+
readonly isTest: boolean;
|
|
161
|
+
readonly isLocal: boolean;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export { type AwsSecretsCache, type AwsSecretsClient, type AwsSecretsOptions, type ConfigLoaderOptions, type ConfigLoaderResult, type DotenvOptions, type VaultClient, type VaultOptions, type VaultSecretCache, createAwsSecretsClient, createVaultClient, deepMerge, env, loadConfig, loadConfigAsync, maskSecrets, replacePlaceholders, stripEmpty };
|
package/dist/index.d.ts
CHANGED
|
@@ -150,4 +150,15 @@ declare function maskSecrets(obj: unknown): unknown;
|
|
|
150
150
|
|
|
151
151
|
declare function stripEmpty(obj: unknown): unknown;
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Environment helpers
|
|
155
|
+
*/
|
|
156
|
+
declare const env: {
|
|
157
|
+
readonly nodeEnv: string;
|
|
158
|
+
readonly isProduction: boolean;
|
|
159
|
+
readonly isDevelopment: boolean;
|
|
160
|
+
readonly isTest: boolean;
|
|
161
|
+
readonly isLocal: boolean;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export { type AwsSecretsCache, type AwsSecretsClient, type AwsSecretsOptions, type ConfigLoaderOptions, type ConfigLoaderResult, type DotenvOptions, type VaultClient, type VaultOptions, type VaultSecretCache, createAwsSecretsClient, createVaultClient, deepMerge, env, loadConfig, loadConfigAsync, maskSecrets, replacePlaceholders, stripEmpty };
|
package/dist/index.js
CHANGED
|
@@ -230,7 +230,30 @@ function isPlainObject4(value) {
|
|
|
230
230
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
231
231
|
}
|
|
232
232
|
var VAULT_PLACEHOLDER_REGEX = /\${vault:([^:}]+):([^:}]+)(?::([^}]*))?}/g;
|
|
233
|
+
var URL_REGEX = /^https?:\/\/.+/;
|
|
234
|
+
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
235
|
+
function validateVaultOptions(options) {
|
|
236
|
+
if (!options.endpoint) {
|
|
237
|
+
throw new Error("Vault endpoint is not set");
|
|
238
|
+
}
|
|
239
|
+
if (!URL_REGEX.test(options.endpoint)) {
|
|
240
|
+
throw new Error(`Invalid Vault endpoint: "${options.endpoint}". Must be a valid URL (http:// or https://)`);
|
|
241
|
+
}
|
|
242
|
+
if (!options.roleId) {
|
|
243
|
+
throw new Error("Vault roleId is not set");
|
|
244
|
+
}
|
|
245
|
+
if (!UUID_REGEX.test(options.roleId)) {
|
|
246
|
+
throw new Error(`Invalid Vault roleId: "${options.roleId}". Must be a valid UUID`);
|
|
247
|
+
}
|
|
248
|
+
if (!options.secretId) {
|
|
249
|
+
throw new Error("Vault secretId is not set");
|
|
250
|
+
}
|
|
251
|
+
if (!UUID_REGEX.test(options.secretId)) {
|
|
252
|
+
throw new Error(`Invalid Vault secretId: "${options.secretId}". Must be a valid UUID`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
233
255
|
async function createVaultClient(options) {
|
|
256
|
+
validateVaultOptions(options);
|
|
234
257
|
const vault = NodeVault__default.default({
|
|
235
258
|
endpoint: options.endpoint,
|
|
236
259
|
apiVersion: "v1",
|
|
@@ -260,7 +283,14 @@ async function createVaultClient(options) {
|
|
|
260
283
|
return cache;
|
|
261
284
|
},
|
|
262
285
|
getSecret(path, field) {
|
|
263
|
-
|
|
286
|
+
const data = cache[path];
|
|
287
|
+
if (!data) return void 0;
|
|
288
|
+
return field.split(".").reduce((obj, key) => {
|
|
289
|
+
if (obj && typeof obj === "object" && key in obj) {
|
|
290
|
+
return obj[key];
|
|
291
|
+
}
|
|
292
|
+
return void 0;
|
|
293
|
+
}, data);
|
|
264
294
|
}
|
|
265
295
|
};
|
|
266
296
|
}
|
|
@@ -283,7 +313,29 @@ function extractVaultPaths(obj) {
|
|
|
283
313
|
return Array.from(paths);
|
|
284
314
|
}
|
|
285
315
|
var AWS_PLACEHOLDER_REGEX = /\${aws:([^:}]+)(?::([^:}]+))?(?::([^}]*))?}/g;
|
|
316
|
+
var AWS_REGION_REGEX = /^[a-z]{2}-[a-z]+-\d+$/;
|
|
317
|
+
function validateAwsOptions(options) {
|
|
318
|
+
if (!options.region) {
|
|
319
|
+
throw new Error("AWS region is not set");
|
|
320
|
+
}
|
|
321
|
+
if (!AWS_REGION_REGEX.test(options.region)) {
|
|
322
|
+
throw new Error(`Invalid AWS region: "${options.region}". Expected format: us-east-1, eu-west-2, etc.`);
|
|
323
|
+
}
|
|
324
|
+
if (!options.accessKeyId) {
|
|
325
|
+
throw new Error("AWS accessKeyId is not set");
|
|
326
|
+
}
|
|
327
|
+
if (options.accessKeyId.length < 16) {
|
|
328
|
+
throw new Error(`Invalid AWS accessKeyId: "${options.accessKeyId}". Must be at least 16 characters`);
|
|
329
|
+
}
|
|
330
|
+
if (!options.secretAccessKey) {
|
|
331
|
+
throw new Error("AWS secretAccessKey is not set");
|
|
332
|
+
}
|
|
333
|
+
if (options.secretAccessKey.length < 16) {
|
|
334
|
+
throw new Error("Invalid AWS secretAccessKey. Must be at least 16 characters");
|
|
335
|
+
}
|
|
336
|
+
}
|
|
286
337
|
async function createAwsSecretsClient(options) {
|
|
338
|
+
validateAwsOptions(options);
|
|
287
339
|
const client = new clientSecretsManager.SecretsManagerClient({
|
|
288
340
|
region: options.region,
|
|
289
341
|
credentials: {
|
|
@@ -353,6 +405,25 @@ function extractAwsSecretNames(obj) {
|
|
|
353
405
|
return Array.from(names);
|
|
354
406
|
}
|
|
355
407
|
|
|
408
|
+
// src/utils/env.ts
|
|
409
|
+
var env = {
|
|
410
|
+
get nodeEnv() {
|
|
411
|
+
return process.env.NODE_ENV || "local";
|
|
412
|
+
},
|
|
413
|
+
get isProduction() {
|
|
414
|
+
return process.env.NODE_ENV === "production";
|
|
415
|
+
},
|
|
416
|
+
get isDevelopment() {
|
|
417
|
+
return process.env.NODE_ENV === "development";
|
|
418
|
+
},
|
|
419
|
+
get isTest() {
|
|
420
|
+
return process.env.NODE_ENV === "test";
|
|
421
|
+
},
|
|
422
|
+
get isLocal() {
|
|
423
|
+
return !process.env.NODE_ENV || process.env.NODE_ENV === "local";
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
|
|
356
427
|
// src/loader.ts
|
|
357
428
|
var DEFAULT_OPTIONS = {
|
|
358
429
|
configDir: process.cwd(),
|
|
@@ -507,6 +578,7 @@ function loadOverrideDir(dir) {
|
|
|
507
578
|
exports.createAwsSecretsClient = createAwsSecretsClient;
|
|
508
579
|
exports.createVaultClient = createVaultClient;
|
|
509
580
|
exports.deepMerge = deepMerge;
|
|
581
|
+
exports.env = env;
|
|
510
582
|
exports.loadConfig = loadConfig;
|
|
511
583
|
exports.loadConfigAsync = loadConfigAsync;
|
|
512
584
|
exports.maskSecrets = maskSecrets;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/deep-merge.ts","../src/utils/env-replacer.ts","../src/utils/mask-secrets.ts","../src/utils/strip-empty.ts","../src/utils/vault-client.ts","../src/utils/aws-secrets-client.ts","../src/loader.ts"],"names":["isPlainObject","NodeVault","SecretsManagerClient","GetSecretValueCommand","config","dotenv","join","path","existsSync","readFileSync","yaml","readdirSync"],"mappings":"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","file":"index.js","sourcesContent":["type DeepObject = Record<string, unknown>;\n\nexport function deepMerge(base: DeepObject, override: DeepObject): DeepObject {\n const merged = { ...base };\n\n for (const key in override) {\n const overrideValue = override[key];\n const baseValue = base[key];\n\n if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {\n merged[key] = deepMerge(baseValue as DeepObject, overrideValue as DeepObject);\n } else {\n merged[key] = overrideValue;\n }\n }\n\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is DeepObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import type { VaultClient } from './vault-client.js';\nimport type { AwsSecretsClient } from './aws-secrets-client.js';\n\nconst ENV_PLACEHOLDER_REGEX = /\\${(.*?)}/g;\nconst VAULT_PREFIX = 'vault:';\nconst AWS_PREFIX = 'aws:';\n\nexport interface ReplacePlaceholdersOptions {\n vaultClient?: VaultClient;\n awsClient?: AwsSecretsClient;\n}\n\nexport function replacePlaceholders(obj: unknown, options: ReplacePlaceholdersOptions = {}): unknown {\n if (typeof obj === 'string') {\n return replaceStringPlaceholders(obj, options);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => replacePlaceholders(item, options));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = replacePlaceholders(obj[key], options);\n }\n return result;\n }\n\n return obj;\n}\n\nfunction replaceStringPlaceholders(str: string, options: ReplacePlaceholdersOptions): string {\n return str.replace(ENV_PLACEHOLDER_REGEX, (match, key) => {\n // Handle Vault placeholders: ${vault:path:field} or ${vault:path:field:default}\n if (key.startsWith(VAULT_PREFIX)) {\n return resolveVaultPlaceholder(key, match, options);\n }\n\n // Handle AWS placeholders: ${aws:secret:field} or ${aws:secret:field:default} or ${aws:secret}\n if (key.startsWith(AWS_PREFIX)) {\n return resolveAwsPlaceholder(key, match, options);\n }\n\n // Handle environment variable placeholders: ${VAR} or ${VAR:default}\n return resolveEnvPlaceholder(key, match, options);\n });\n}\n\nfunction resolveVaultPlaceholder(\n key: string,\n originalMatch: string,\n options: ReplacePlaceholdersOptions,\n): string {\n // Parse: vault:secret/data/api:DB_PASSWORD:default_value\n const parts = key.substring(VAULT_PREFIX.length).split(':');\n\n if (parts.length < 2) {\n throw new Error(\n `Invalid Vault placeholder format \"${originalMatch}\". ` +\n `Expected \\${vault:path:field} or \\${vault:path:field:default}`,\n );\n }\n\n const [path, field, ...defaultParts] = parts;\n const defaultValue = defaultParts.length > 0 ? defaultParts.join(':') : undefined;\n\n if (!options.vaultClient) {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`Vault placeholder \"${originalMatch}\" found but no Vault options provided`);\n }\n\n const secretValue = options.vaultClient.getSecret(path, field);\n\n if (secretValue !== undefined) {\n return String(secretValue);\n }\n\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n throw new Error(`Vault secret \"${field}\" not found at path \"${path}\" and no default value provided`);\n}\n\nfunction resolveAwsPlaceholder(\n key: string,\n originalMatch: string,\n options: ReplacePlaceholdersOptions,\n): string {\n // Parse: aws:secret-name:field:default or aws:secret-name:field or aws:secret-name\n const parts = key.substring(AWS_PREFIX.length).split(':');\n\n if (parts.length < 1 || !parts[0]) {\n throw new Error(\n `Invalid AWS placeholder format \"${originalMatch}\". ` +\n `Expected \\${aws:secret-name} or \\${aws:secret-name:field} or \\${aws:secret-name:field:default}`,\n );\n }\n\n const [secretName, field, ...defaultParts] = parts;\n const defaultValue = defaultParts.length > 0 ? defaultParts.join(':') : undefined;\n\n if (!options.awsClient) {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`AWS placeholder \"${originalMatch}\" found but no AWS options provided`);\n }\n\n const secretValue = options.awsClient.getSecret(secretName, field || undefined);\n\n if (secretValue !== undefined) {\n return String(secretValue);\n }\n\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n if (field) {\n throw new Error(`AWS secret field \"${field}\" not found in \"${secretName}\" and no default value provided`);\n } else {\n throw new Error(`AWS secret \"${secretName}\" not found and no default value provided`);\n }\n}\n\nfunction resolveEnvPlaceholder(key: string, _match: string, options: ReplacePlaceholdersOptions): string {\n const [envKey, ...rest] = key.split(':');\n const defaultValue = rest.length > 0 ? rest.join(':') : undefined;\n const envValue = process.env[envKey];\n\n let value: string;\n if (envValue !== undefined) {\n value = envValue;\n } else if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throw new Error(`Environment variable \"${envKey}\" is not defined and no default value provided`);\n }\n\n // Handle nested placeholders\n if (value.includes('${')) {\n return replacePlaceholders(value, options) as string;\n }\n\n return value;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const SECRET_PATTERNS = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'credential'];\n\nconst URL_WITH_CREDENTIALS_REGEX = /^([a-z]+:\\/\\/)([^:]+):([^@]+)@(.+)$/i;\n\nexport function maskSecrets(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return maskUrlCredentials(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => maskSecrets(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (isSecretKey(key)) {\n result[key] = maskValue(value);\n } else {\n result[key] = maskSecrets(value);\n }\n }\n return result;\n }\n\n return obj;\n}\n\nfunction isSecretKey(key: string): boolean {\n const lowerKey = key.toLowerCase();\n return SECRET_PATTERNS.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction maskValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '***';\n }\n if (value.length <= 4) {\n return '***';\n }\n return value.slice(0, 2) + '***' + value.slice(-2);\n}\n\nfunction maskUrlCredentials(url: string): string {\n const match = url.match(URL_WITH_CREDENTIALS_REGEX);\n if (match) {\n const [, protocol, user, , host] = match;\n return `${protocol}${user}:***@${host}`;\n }\n return url;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","export function stripEmpty(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return obj === '' ? undefined : obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => stripEmpty(item)).filter((item) => item !== undefined);\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n let hasValues = false;\n\n for (const key of Object.keys(obj)) {\n const value = stripEmpty(obj[key]);\n if (value !== undefined) {\n result[key] = value;\n hasValues = true;\n }\n }\n\n return hasValues ? result : undefined;\n }\n\n return obj;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import NodeVault from 'node-vault';\nimport type { VaultOptions } from '../types.js';\n\nconst VAULT_PLACEHOLDER_REGEX = /\\${vault:([^:}]+):([^:}]+)(?::([^}]*))?}/g;\n\nexport interface VaultSecretCache {\n [path: string]: Record<string, unknown>;\n}\n\nexport interface VaultClient {\n fetchSecrets(obj: unknown): Promise<VaultSecretCache>;\n getSecret(path: string, field: string): unknown;\n}\n\nexport async function createVaultClient(options: VaultOptions): Promise<VaultClient> {\n const vault = NodeVault({\n endpoint: options.endpoint,\n apiVersion: 'v1',\n namespace: options.namespace,\n });\n\n // Authenticate with AppRole\n const loginResult = await vault.approleLogin({\n role_id: options.roleId,\n secret_id: options.secretId,\n });\n\n vault.token = loginResult.auth.client_token;\n\n const cache: VaultSecretCache = {};\n\n return {\n async fetchSecrets(obj: unknown): Promise<VaultSecretCache> {\n const paths = extractVaultPaths(obj);\n\n // Fetch all unique paths in parallel\n await Promise.all(\n paths.map(async (path) => {\n if (!cache[path]) {\n try {\n const result = await vault.read(path);\n // Vault KV v2 stores data under result.data.data\n // KV v1 stores under result.data\n cache[path] = result.data?.data ?? result.data ?? {};\n } catch {\n // Store empty object for failed paths - will use defaults or throw later\n cache[path] = {};\n }\n }\n }),\n );\n\n return cache;\n },\n\n getSecret(path: string, field: string): unknown {\n return cache[path]?.[field];\n },\n };\n}\n\n/**\n * Extract all unique Vault paths from config object\n */\nfunction extractVaultPaths(obj: unknown): string[] {\n const paths = new Set<string>();\n\n function traverse(value: unknown): void {\n if (typeof value === 'string') {\n let match;\n while ((match = VAULT_PLACEHOLDER_REGEX.exec(value)) !== null) {\n paths.add(match[1]); // path is first capture group\n }\n VAULT_PLACEHOLDER_REGEX.lastIndex = 0; // Reset regex state\n } else if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(traverse);\n }\n }\n\n traverse(obj);\n return Array.from(paths);\n}\n","import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';\nimport type { AwsSecretsOptions } from '../types.js';\n\nconst AWS_PLACEHOLDER_REGEX = /\\${aws:([^:}]+)(?::([^:}]+))?(?::([^}]*))?}/g;\n\nexport interface AwsSecretsCache {\n [secretName: string]: string | Record<string, unknown>;\n}\n\nexport interface AwsSecretsClient {\n fetchSecrets(obj: unknown): Promise<AwsSecretsCache>;\n getSecret(secretName: string, field?: string): unknown;\n}\n\nexport async function createAwsSecretsClient(options: AwsSecretsOptions): Promise<AwsSecretsClient> {\n const client = new SecretsManagerClient({\n region: options.region,\n credentials: {\n accessKeyId: options.accessKeyId,\n secretAccessKey: options.secretAccessKey,\n },\n });\n\n const cache: AwsSecretsCache = {};\n\n return {\n async fetchSecrets(obj: unknown): Promise<AwsSecretsCache> {\n const secretNames = extractAwsSecretNames(obj);\n\n // Fetch all unique secrets in parallel\n await Promise.all(\n secretNames.map(async (secretName) => {\n if (cache[secretName] === undefined) {\n try {\n const command = new GetSecretValueCommand({ SecretId: secretName });\n const response = await client.send(command);\n\n const secretString = response.SecretString;\n if (secretString) {\n // Try to parse as JSON, fallback to plain string\n try {\n cache[secretName] = JSON.parse(secretString);\n } catch {\n cache[secretName] = secretString;\n }\n } else {\n cache[secretName] = {};\n }\n } catch {\n // Store empty object for failed secrets - will use defaults or throw later\n cache[secretName] = {};\n }\n }\n }),\n );\n\n return cache;\n },\n\n getSecret(secretName: string, field?: string): unknown {\n const secret = cache[secretName];\n\n if (secret === undefined) {\n return undefined;\n }\n\n // If no field specified, return the whole secret (plain string or parsed JSON)\n if (!field) {\n return typeof secret === 'string' ? secret : undefined;\n }\n\n // If field specified, secret must be an object\n if (typeof secret === 'object' && secret !== null) {\n return (secret as Record<string, unknown>)[field];\n }\n\n return undefined;\n },\n };\n}\n\n/**\n * Extract all unique AWS secret names from config object\n */\nfunction extractAwsSecretNames(obj: unknown): string[] {\n const names = new Set<string>();\n\n function traverse(value: unknown): void {\n if (typeof value === 'string') {\n let match;\n while ((match = AWS_PLACEHOLDER_REGEX.exec(value)) !== null) {\n names.add(match[1]); // secret name is first capture group\n }\n AWS_PLACEHOLDER_REGEX.lastIndex = 0; // Reset regex state\n } else if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(traverse);\n }\n }\n\n traverse(obj);\n return Array.from(names);\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as yaml from 'js-yaml';\nimport * as dotenv from 'dotenv';\nimport { join } from 'path';\nimport type { ConfigLoaderOptions, ConfigLoaderResult } from './types.js';\nimport {\n deepMerge,\n replacePlaceholders,\n maskSecrets,\n stripEmpty,\n createVaultClient,\n createAwsSecretsClient,\n type VaultClient,\n type AwsSecretsClient,\n} from './utils/index.js';\n\nconst DEFAULT_OPTIONS = {\n configDir: process.cwd(),\n baseFileName: 'base',\n environment: process.env.NODE_ENV || 'local',\n extension: 'yml' as const,\n overrideDir: '/etc/app/config',\n};\n\nexport function loadConfig<T>(options: ConfigLoaderOptions<T> = {}): ConfigLoaderResult<T> {\n if (options.vault || options.aws) {\n throw new Error('Vault/AWS options require async loading. Use loadConfigAsync() instead of loadConfig()');\n }\n\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n let config = replacePlaceholders(mergedConfig) as T;\n\n // Strip empty strings and objects\n if (options.stripEmpty) {\n config = stripEmpty(config) as T;\n }\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nexport async function loadConfigAsync<T>(\n options: ConfigLoaderOptions<T> = {},\n): Promise<ConfigLoaderResult<T>> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n // Create Vault client and pre-fetch secrets if Vault options provided\n let vaultClient: VaultClient | undefined;\n if (options.vault) {\n vaultClient = await createVaultClient(options.vault);\n await vaultClient.fetchSecrets(mergedConfig);\n }\n\n // Create AWS Secrets Manager client and pre-fetch secrets if AWS options provided\n let awsClient: AwsSecretsClient | undefined;\n if (options.aws) {\n awsClient = await createAwsSecretsClient(options.aws);\n await awsClient.fetchSecrets(mergedConfig);\n }\n\n // Replace placeholders (with Vault and AWS support)\n let config = replacePlaceholders(mergedConfig, { vaultClient, awsClient }) as T;\n\n // Strip empty strings and objects\n if (options.stripEmpty) {\n config = stripEmpty(config) as T;\n }\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nfunction loadDotenv(\n dotenvOption: boolean | { path?: string },\n environment: string,\n): void {\n let envPath: string;\n\n if (typeof dotenvOption === 'object' && dotenvOption.path) {\n envPath = dotenvOption.path;\n } else {\n envPath = environment === 'production' ? '.env' : `.env.${environment}`;\n }\n\n dotenv.config({ path: envPath });\n}\n\nfunction resolveConfigDir(configDir: string): string {\n const possiblePaths = [\n join(configDir, 'src', 'config'),\n join(configDir, 'dist', 'config'),\n join(configDir, 'config'),\n configDir,\n ];\n\n for (const path of possiblePaths) {\n if (existsSync(join(path, 'base.yml')) || existsSync(join(path, 'base.yaml'))) {\n return path;\n }\n }\n\n throw new Error(\n `Config files not found. Searched in:\\n${possiblePaths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n}\n\nfunction loadYamlFile(dir: string, filename: string): Record<string, unknown> {\n const filePath = join(dir, filename);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf8');\n return (yaml.load(content) as Record<string, unknown>) || {};\n}\n\nfunction loadOverrideDir(dir: string): Record<string, unknown>[] {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = readdirSync(dir)\n .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))\n .sort();\n\n return files.map((file) => loadYamlFile(dir, file));\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/deep-merge.ts","../src/utils/env-replacer.ts","../src/utils/mask-secrets.ts","../src/utils/strip-empty.ts","../src/utils/vault-client.ts","../src/utils/aws-secrets-client.ts","../src/utils/env.ts","../src/loader.ts"],"names":["isPlainObject","NodeVault","SecretsManagerClient","GetSecretValueCommand","config","dotenv","join","path","existsSync","readFileSync","yaml","readdirSync"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEO,SAAS,SAAA,CAAU,MAAkB,QAAA,EAAkC;AAC5E,EAAA,MAAM,MAAA,GAAS,EAAE,GAAG,IAAA,EAAK;AAEzB,EAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,IAAA,MAAM,aAAA,GAAgB,SAAS,GAAG,CAAA;AAClC,IAAA,MAAM,SAAA,GAAY,KAAK,GAAG,CAAA;AAE1B,IAAA,IAAI,aAAA,CAAc,aAAa,CAAA,IAAK,aAAA,CAAc,SAAS,CAAA,EAAG;AAC5D,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,SAAA,CAAU,SAAA,EAAyB,aAA2B,CAAA;AAAA,IAC9E,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,aAAA;AAAA,IAChB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,cAAc,KAAA,EAAqC;AAC1D,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;;;AClBA,IAAM,qBAAA,GAAwB,YAAA;AAC9B,IAAM,YAAA,GAAe,QAAA;AACrB,IAAM,UAAA,GAAa,MAAA;AAOZ,SAAS,mBAAA,CAAoB,GAAA,EAAc,OAAA,GAAsC,EAAC,EAAY;AACnG,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,IAAA,OAAO,yBAAA,CAA0B,KAAK,OAAO,CAAA;AAAA,EAC/C;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACtB,IAAA,OAAO,IAAI,GAAA,CAAI,CAAC,SAAS,mBAAA,CAAoB,IAAA,EAAM,OAAO,CAAC,CAAA;AAAA,EAC7D;AAEA,EAAA,IAAIA,cAAAA,CAAc,GAAG,CAAA,EAAG;AACtB,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,EAAG;AAClC,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,mBAAA,CAAoB,GAAA,CAAI,GAAG,GAAG,OAAO,CAAA;AAAA,IACrD;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,yBAAA,CAA0B,KAAa,OAAA,EAA6C;AAC3F,EAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,qBAAA,EAAuB,CAAC,OAAO,GAAA,KAAQ;AAExD,IAAA,IAAI,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,EAAG;AAChC,MAAA,OAAO,uBAAA,CAAwB,GAAA,EAAK,KAAA,EAAO,OAAO,CAAA;AAAA,IACpD;AAGA,IAAA,IAAI,GAAA,CAAI,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,MAAA,OAAO,qBAAA,CAAsB,GAAA,EAAK,KAAA,EAAO,OAAO,CAAA;AAAA,IAClD;AAGA,IAAA,OAAO,qBAAA,CAAsB,GAAA,EAAK,KAAA,EAAO,OAAO,CAAA;AAAA,EAClD,CAAC,CAAA;AACH;AAEA,SAAS,uBAAA,CACP,GAAA,EACA,aAAA,EACA,OAAA,EACQ;AAER,EAAA,MAAM,QAAQ,GAAA,CAAI,SAAA,CAAU,aAAa,MAAM,CAAA,CAAE,MAAM,GAAG,CAAA;AAE1D,EAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,qCAAqC,aAAa,CAAA,gEAAA;AAAA,KAEpD;AAAA,EACF;AAEA,EAAA,MAAM,CAAC,IAAA,EAAM,KAAA,EAAO,GAAG,YAAY,CAAA,GAAI,KAAA;AACvC,EAAA,MAAM,eAAe,YAAA,CAAa,MAAA,GAAS,IAAI,YAAA,CAAa,IAAA,CAAK,GAAG,CAAA,GAAI,MAAA;AAExE,EAAA,IAAI,CAAC,QAAQ,WAAA,EAAa;AACxB,IAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,MAAA,OAAO,YAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,aAAa,CAAA,qCAAA,CAAuC,CAAA;AAAA,EAC5F;AAEA,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,WAAA,CAAY,SAAA,CAAU,MAAM,KAAK,CAAA;AAE7D,EAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,IAAA,OAAO,OAAO,WAAW,CAAA;AAAA,EAC3B;AAEA,EAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,IAAA,OAAO,YAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,KAAK,CAAA,qBAAA,EAAwB,IAAI,CAAA,+BAAA,CAAiC,CAAA;AACrG;AAEA,SAAS,qBAAA,CACP,GAAA,EACA,aAAA,EACA,OAAA,EACQ;AAER,EAAA,MAAM,QAAQ,GAAA,CAAI,SAAA,CAAU,WAAW,MAAM,CAAA,CAAE,MAAM,GAAG,CAAA;AAExD,EAAA,IAAI,MAAM,MAAA,GAAS,CAAA,IAAK,CAAC,KAAA,CAAM,CAAC,CAAA,EAAG;AACjC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,mCAAmC,aAAa,CAAA,iGAAA;AAAA,KAElD;AAAA,EACF;AAEA,EAAA,MAAM,CAAC,UAAA,EAAY,KAAA,EAAO,GAAG,YAAY,CAAA,GAAI,KAAA;AAC7C,EAAA,MAAM,eAAe,YAAA,CAAa,MAAA,GAAS,IAAI,YAAA,CAAa,IAAA,CAAK,GAAG,CAAA,GAAI,MAAA;AAExE,EAAA,IAAI,CAAC,QAAQ,SAAA,EAAW;AACtB,IAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,MAAA,OAAO,YAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,aAAa,CAAA,mCAAA,CAAqC,CAAA;AAAA,EACxF;AAEA,EAAA,MAAM,cAAc,OAAA,CAAQ,SAAA,CAAU,SAAA,CAAU,UAAA,EAAY,SAAS,MAAS,CAAA;AAE9E,EAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,IAAA,OAAO,OAAO,WAAW,CAAA;AAAA,EAC3B;AAEA,EAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,IAAA,OAAO,YAAA;AAAA,EACT;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,KAAK,CAAA,gBAAA,EAAmB,UAAU,CAAA,+BAAA,CAAiC,CAAA;AAAA,EAC1G,CAAA,MAAO;AACL,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,YAAA,EAAe,UAAU,CAAA,yCAAA,CAA2C,CAAA;AAAA,EACtF;AACF;AAEA,SAAS,qBAAA,CAAsB,GAAA,EAAa,MAAA,EAAgB,OAAA,EAA6C;AACvG,EAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,IAAI,CAAA,GAAI,GAAA,CAAI,MAAM,GAAG,CAAA;AACvC,EAAA,MAAM,eAAe,IAAA,CAAK,MAAA,GAAS,IAAI,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,GAAI,MAAA;AACxD,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA;AAEnC,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,KAAA,GAAQ,QAAA;AAAA,EACV,CAAA,MAAA,IAAW,iBAAiB,MAAA,EAAW;AACrC,IAAA,KAAA,GAAQ,YAAA;AAAA,EACV,CAAA,MAAO;AACL,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,MAAM,CAAA,8CAAA,CAAgD,CAAA;AAAA,EACjG;AAGA,EAAA,IAAI,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,EAAG;AACxB,IAAA,OAAO,mBAAA,CAAoB,OAAO,OAAO,CAAA;AAAA,EAC3C;AAEA,EAAA,OAAO,KAAA;AACT;AAEA,SAASA,eAAc,KAAA,EAAkD;AACvE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;;;ACzJA,IAAM,eAAA,GAAkB,CAAC,OAAA,EAAS,UAAA,EAAY,UAAU,KAAA,EAAO,QAAA,EAAU,WAAW,YAAY,CAAA;AAEhG,IAAM,0BAAA,GAA6B,sCAAA;AAE5B,SAAS,YAAY,GAAA,EAAuB;AACjD,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,IAAA,OAAO,mBAAmB,GAAG,CAAA;AAAA,EAC/B;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACtB,IAAA,OAAO,IAAI,GAAA,CAAI,CAAC,IAAA,KAAS,WAAA,CAAY,IAAI,CAAC,CAAA;AAAA,EAC5C;AAEA,EAAA,IAAIA,cAAAA,CAAc,GAAG,CAAA,EAAG;AACtB,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,EAAG;AAClC,MAAA,MAAM,KAAA,GAAQ,IAAI,GAAG,CAAA;AACrB,MAAA,IAAI,WAAA,CAAY,GAAG,CAAA,EAAG;AACpB,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,SAAA,CAAU,KAAK,CAAA;AAAA,MAC/B,CAAA,MAAO;AACL,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,WAAA,CAAY,KAAK,CAAA;AAAA,MACjC;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,YAAY,GAAA,EAAsB;AACzC,EAAA,MAAM,QAAA,GAAW,IAAI,WAAA,EAAY;AACjC,EAAA,OAAO,gBAAgB,IAAA,CAAK,CAAC,YAAY,QAAA,CAAS,QAAA,CAAS,OAAO,CAAC,CAAA;AACrE;AAEA,SAAS,UAAU,KAAA,EAAwB;AACzC,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,UAAU,CAAA,EAAG;AACrB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA,CAAM,MAAM,CAAA,EAAG,CAAC,IAAI,KAAA,GAAQ,KAAA,CAAM,MAAM,EAAE,CAAA;AACnD;AAEA,SAAS,mBAAmB,GAAA,EAAqB;AAC/C,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,0BAA0B,CAAA;AAClD,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,GAAG,QAAA,EAAU,IAAA,IAAQ,IAAI,CAAA,GAAI,KAAA;AACnC,IAAA,OAAO,CAAA,EAAG,QAAQ,CAAA,EAAG,IAAI,QAAQ,IAAI,CAAA,CAAA;AAAA,EACvC;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAASA,eAAc,KAAA,EAAkD;AACvE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;;;ACvDO,SAAS,WAAW,GAAA,EAAuB;AAChD,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,IAAA,OAAO,GAAA,KAAQ,KAAK,MAAA,GAAY,GAAA;AAAA,EAClC;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACtB,IAAA,OAAO,GAAA,CAAI,GAAA,CAAI,CAAC,IAAA,KAAS,UAAA,CAAW,IAAI,CAAC,CAAA,CAAE,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,KAAS,MAAS,CAAA;AAAA,EAChF;AAEA,EAAA,IAAIA,cAAAA,CAAc,GAAG,CAAA,EAAG;AACtB,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,EAAG;AAClC,MAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,GAAA,CAAI,GAAG,CAAC,CAAA;AACjC,MAAA,IAAI,UAAU,MAAA,EAAW;AACvB,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AACd,QAAA,SAAA,GAAY,IAAA;AAAA,MACd;AAAA,IACF;AAEA,IAAA,OAAO,YAAY,MAAA,GAAS,MAAA;AAAA,EAC9B;AAEA,EAAA,OAAO,GAAA;AACT;AAEA,SAASA,eAAc,KAAA,EAAkD;AACvE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AC1BA,IAAM,uBAAA,GAA0B,2CAAA;AAChC,IAAM,SAAA,GAAY,gBAAA;AAClB,IAAM,UAAA,GAAa,iEAAA;AAEnB,SAAS,qBAAqB,OAAA,EAA6B;AACzD,EAAA,IAAI,CAAC,QAAQ,QAAA,EAAU;AACrB,IAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,EAC7C;AACA,EAAA,IAAI,CAAC,SAAA,CAAU,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACrC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,OAAA,CAAQ,QAAQ,CAAA,4CAAA,CAA8C,CAAA;AAAA,EAC5G;AACA,EAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AACnB,IAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA,EAC3C;AACA,EAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,OAAA,CAAQ,MAAM,CAAA,uBAAA,CAAyB,CAAA;AAAA,EACnF;AACA,EAAA,IAAI,CAAC,QAAQ,QAAA,EAAU;AACrB,IAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,EAC7C;AACA,EAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACtC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,OAAA,CAAQ,QAAQ,CAAA,uBAAA,CAAyB,CAAA;AAAA,EACvF;AACF;AAWA,eAAsB,kBAAkB,OAAA,EAA6C;AACnF,EAAA,oBAAA,CAAqB,OAAO,CAAA;AAE5B,EAAA,MAAM,QAAQC,0BAAA,CAAU;AAAA,IACtB,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,UAAA,EAAY,IAAA;AAAA,IACZ,WAAW,OAAA,CAAQ;AAAA,GACpB,CAAA;AAGD,EAAA,MAAM,WAAA,GAAc,MAAM,KAAA,CAAM,YAAA,CAAa;AAAA,IAC3C,SAAS,OAAA,CAAQ,MAAA;AAAA,IACjB,WAAW,OAAA,CAAQ;AAAA,GACpB,CAAA;AAED,EAAA,KAAA,CAAM,KAAA,GAAQ,YAAY,IAAA,CAAK,YAAA;AAE/B,EAAA,MAAM,QAA0B,EAAC;AAEjC,EAAA,OAAO;AAAA,IACL,MAAM,aAAa,GAAA,EAAyC;AAC1D,MAAA,MAAM,KAAA,GAAQ,kBAAkB,GAAG,CAAA;AAGnC,MAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,QACZ,KAAA,CAAM,GAAA,CAAI,OAAO,IAAA,KAAS;AACxB,UAAA,IAAI,CAAC,KAAA,CAAM,IAAI,CAAA,EAAG;AAChB,YAAA,IAAI;AACF,cAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAGpC,cAAA,KAAA,CAAM,IAAI,CAAA,GAAI,MAAA,CAAO,MAAM,IAAA,IAAQ,MAAA,CAAO,QAAQ,EAAC;AAAA,YACrD,CAAA,CAAA,MAAQ;AAEN,cAAA,KAAA,CAAM,IAAI,IAAI,EAAC;AAAA,YACjB;AAAA,UACF;AAAA,QACF,CAAC;AAAA,OACH;AAEA,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IAEA,SAAA,CAAU,MAAc,KAAA,EAAwB;AAC9C,MAAA,MAAM,IAAA,GAAO,MAAM,IAAI,CAAA;AACvB,MAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAGlB,MAAA,OAAO,MAAM,KAAA,CAAM,GAAG,EAAE,MAAA,CAAgB,CAAC,KAAK,GAAA,KAAQ;AACpD,QAAA,IAAI,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,OAAO,GAAA,EAAK;AAChD,UAAA,OAAQ,IAAgC,GAAG,CAAA;AAAA,QAC7C;AACA,QAAA,OAAO,MAAA;AAAA,MACT,GAAG,IAAI,CAAA;AAAA,IACT;AAAA,GACF;AACF;AAKA,SAAS,kBAAkB,GAAA,EAAwB;AACjD,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAE9B,EAAA,SAAS,SAAS,KAAA,EAAsB;AACtC,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,IAAI,KAAA;AACJ,MAAA,OAAA,CAAQ,KAAA,GAAQ,uBAAA,CAAwB,IAAA,CAAK,KAAK,OAAO,IAAA,EAAM;AAC7D,QAAA,KAAA,CAAM,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,MACpB;AACA,MAAA,uBAAA,CAAwB,SAAA,GAAY,CAAA;AAAA,IACtC,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC/B,MAAA,KAAA,CAAM,QAAQ,QAAQ,CAAA;AAAA,IACxB,CAAA,MAAA,IAAW,KAAA,KAAU,IAAA,IAAQ,OAAO,UAAU,QAAA,EAAU;AACtD,MAAA,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,IACvC;AAAA,EACF;AAEA,EAAA,QAAA,CAAS,GAAG,CAAA;AACZ,EAAA,OAAO,KAAA,CAAM,KAAK,KAAK,CAAA;AACzB;AClHA,IAAM,qBAAA,GAAwB,8CAAA;AAC9B,IAAM,gBAAA,GAAmB,uBAAA;AAEzB,SAAS,mBAAmB,OAAA,EAAkC;AAC5D,EAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AACnB,IAAA,MAAM,IAAI,MAAM,uBAAuB,CAAA;AAAA,EACzC;AACA,EAAA,IAAI,CAAC,gBAAA,CAAiB,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA,EAAG;AAC1C,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,OAAA,CAAQ,MAAM,CAAA,8CAAA,CAAgD,CAAA;AAAA,EACxG;AACA,EAAA,IAAI,CAAC,QAAQ,WAAA,EAAa;AACxB,IAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,EAC9C;AACA,EAAA,IAAI,OAAA,CAAQ,WAAA,CAAY,MAAA,GAAS,EAAA,EAAI;AACnC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,OAAA,CAAQ,WAAW,CAAA,iCAAA,CAAmC,CAAA;AAAA,EACrG;AACA,EAAA,IAAI,CAAC,QAAQ,eAAA,EAAiB;AAC5B,IAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,EAClD;AACA,EAAA,IAAI,OAAA,CAAQ,eAAA,CAAgB,MAAA,GAAS,EAAA,EAAI;AACvC,IAAA,MAAM,IAAI,MAAM,6DAA6D,CAAA;AAAA,EAC/E;AACF;AAWA,eAAsB,uBAAuB,OAAA,EAAuD;AAClG,EAAA,kBAAA,CAAmB,OAAO,CAAA;AAE1B,EAAA,MAAM,MAAA,GAAS,IAAIC,yCAAA,CAAqB;AAAA,IACtC,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,WAAA,EAAa;AAAA,MACX,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,iBAAiB,OAAA,CAAQ;AAAA;AAC3B,GACD,CAAA;AAED,EAAA,MAAM,QAAyB,EAAC;AAEhC,EAAA,OAAO;AAAA,IACL,MAAM,aAAa,GAAA,EAAwC;AACzD,MAAA,MAAM,WAAA,GAAc,sBAAsB,GAAG,CAAA;AAG7C,MAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,QACZ,WAAA,CAAY,GAAA,CAAI,OAAO,UAAA,KAAe;AACpC,UAAA,IAAI,KAAA,CAAM,UAAU,CAAA,KAAM,MAAA,EAAW;AACnC,YAAA,IAAI;AACF,cAAA,MAAM,UAAU,IAAIC,0CAAA,CAAsB,EAAE,QAAA,EAAU,YAAY,CAAA;AAClE,cAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAE1C,cAAA,MAAM,eAAe,QAAA,CAAS,YAAA;AAC9B,cAAA,IAAI,YAAA,EAAc;AAEhB,gBAAA,IAAI;AACF,kBAAA,KAAA,CAAM,UAAU,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,YAAY,CAAA;AAAA,gBAC7C,CAAA,CAAA,MAAQ;AACN,kBAAA,KAAA,CAAM,UAAU,CAAA,GAAI,YAAA;AAAA,gBACtB;AAAA,cACF,CAAA,MAAO;AACL,gBAAA,KAAA,CAAM,UAAU,IAAI,EAAC;AAAA,cACvB;AAAA,YACF,CAAA,CAAA,MAAQ;AAEN,cAAA,KAAA,CAAM,UAAU,IAAI,EAAC;AAAA,YACvB;AAAA,UACF;AAAA,QACF,CAAC;AAAA,OACH;AAEA,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IAEA,SAAA,CAAU,YAAoB,KAAA,EAAyB;AACrD,MAAA,MAAM,MAAA,GAAS,MAAM,UAAU,CAAA;AAE/B,MAAA,IAAI,WAAW,MAAA,EAAW;AACxB,QAAA,OAAO,MAAA;AAAA,MACT;AAGA,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,OAAO,OAAO,MAAA,KAAW,QAAA,GAAW,MAAA,GAAS,MAAA;AAAA,MAC/C;AAGA,MAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,IAAA,EAAM;AACjD,QAAA,OAAQ,OAAmC,KAAK,CAAA;AAAA,MAClD;AAEA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,GACF;AACF;AAKA,SAAS,sBAAsB,GAAA,EAAwB;AACrD,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAE9B,EAAA,SAAS,SAAS,KAAA,EAAsB;AACtC,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,IAAI,KAAA;AACJ,MAAA,OAAA,CAAQ,KAAA,GAAQ,qBAAA,CAAsB,IAAA,CAAK,KAAK,OAAO,IAAA,EAAM;AAC3D,QAAA,KAAA,CAAM,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,MACpB;AACA,MAAA,qBAAA,CAAsB,SAAA,GAAY,CAAA;AAAA,IACpC,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC/B,MAAA,KAAA,CAAM,QAAQ,QAAQ,CAAA;AAAA,IACxB,CAAA,MAAA,IAAW,KAAA,KAAU,IAAA,IAAQ,OAAO,UAAU,QAAA,EAAU;AACtD,MAAA,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,IACvC;AAAA,EACF;AAEA,EAAA,QAAA,CAAS,GAAG,CAAA;AACZ,EAAA,OAAO,KAAA,CAAM,KAAK,KAAK,CAAA;AACzB;;;AC5HO,IAAM,GAAA,GAAM;AAAA,EACjB,IAAI,OAAA,GAAU;AACZ,IAAA,OAAO,OAAA,CAAQ,IAAI,QAAA,IAAY,OAAA;AAAA,EACjC,CAAA;AAAA,EACA,IAAI,YAAA,GAAe;AACjB,IAAA,OAAO,OAAA,CAAQ,IAAI,QAAA,KAAa,YAAA;AAAA,EAClC,CAAA;AAAA,EACA,IAAI,aAAA,GAAgB;AAClB,IAAA,OAAO,OAAA,CAAQ,IAAI,QAAA,KAAa,aAAA;AAAA,EAClC,CAAA;AAAA,EACA,IAAI,MAAA,GAAS;AACX,IAAA,OAAO,OAAA,CAAQ,IAAI,QAAA,KAAa,MAAA;AAAA,EAClC,CAAA;AAAA,EACA,IAAI,OAAA,GAAU;AACZ,IAAA,OAAO,CAAC,OAAA,CAAQ,GAAA,CAAI,QAAA,IAAY,OAAA,CAAQ,IAAI,QAAA,KAAa,OAAA;AAAA,EAC3D;AACF;;;ACHA,IAAM,eAAA,GAAkB;AAAA,EACtB,SAAA,EAAW,QAAQ,GAAA,EAAI;AAAA,EACvB,YAAA,EAAc,MAAA;AAAA,EACd,WAAA,EAAa,OAAA,CAAQ,GAAA,CAAI,QAAA,IAAY,OAAA;AAAA,EACrC,SAAA,EAAW,KAAA;AAAA,EACX,WAAA,EAAa;AACf,CAAA;AAEO,SAAS,UAAA,CAAc,OAAA,GAAkC,EAAC,EAA0B;AACzF,EAAA,IAAI,OAAA,CAAQ,KAAA,IAAS,OAAA,CAAQ,GAAA,EAAK;AAChC,IAAA,MAAM,IAAI,MAAM,wFAAwF,CAAA;AAAA,EAC1G;AAEA,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,eAAA,EAAiB,GAAG,OAAA,EAAQ;AAC9C,EAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAc,WAAA,EAAa,WAAU,GAAI,IAAA;AAG5D,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,UAAA,CAAW,OAAA,CAAQ,QAAQ,WAAW,CAAA;AAAA,EACxC;AAEA,EAAA,MAAM,iBAAA,GAAoB,iBAAiB,SAAS,CAAA;AAEpD,EAAA,MAAM,aAAa,YAAA,CAAa,iBAAA,EAAmB,GAAG,YAAY,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAA;AACjF,EAAA,MAAM,YAAY,YAAA,CAAa,iBAAA,EAAmB,GAAG,WAAW,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAA;AAE/E,EAAA,IAAI,YAAA,GAAe,SAAA,CAAU,UAAA,EAAY,SAAS,CAAA;AAGlD,EAAA,MAAM,cAAc,OAAA,CAAQ,WAAA,KAAgB,QAAS,OAAA,CAAQ,WAAA,IAAe,gBAAgB,WAAA,GAAe,IAAA;AAC3G,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAM,eAAA,GAAkB,gBAAgB,WAAW,CAAA;AACnD,IAAA,KAAA,MAAW,YAAY,eAAA,EAAiB;AACtC,MAAA,YAAA,GAAe,SAAA,CAAU,cAAc,QAAQ,CAAA;AAAA,IACjD;AAAA,EACF;AAEA,EAAA,IAAIC,OAAAA,GAAS,oBAAoB,YAAY,CAAA;AAG7C,EAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,IAAAA,OAAAA,GAAS,WAAWA,OAAM,CAAA;AAAA,EAC5B;AAGA,EAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,IAAAA,OAAAA,GAAS,OAAA,CAAQ,WAAA,CAAYA,OAAM,CAAA;AAAA,EACrC;AAGA,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,SAAA,CAAUA,OAAM,CAAA;AAC9C,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,MAAM,SAAS,MAAA,CAAO,KAAA,CAAM,OACzB,GAAA,CAAI,CAAC,MAAM,CAAA,IAAA,EAAO,CAAA,CAAE,KAAK,IAAA,CAAK,GAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA,CAClD,KAAK,IAAI,CAAA;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA;AAAA,EAA8B,MAAM,CAAA,CAAE,CAAA;AAAA,IACxD;AACA,IAAAA,UAAS,MAAA,CAAO,IAAA;AAAA,EAClB;AAGA,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,MAAM,YAAA,GAAe,YAAYA,OAAM,CAAA;AACvC,IAAA,OAAA,CAAQ,MAAA,CAAO,kBAAkB,WAAW,CAAA;AAAA,EAAO,KAAK,SAAA,CAAU,YAAA,EAAc,IAAA,EAAM,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,EAC5F;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAAA,OAAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACb;AACF;AAEA,eAAsB,eAAA,CACpB,OAAA,GAAkC,EAAC,EACH;AAChC,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,eAAA,EAAiB,GAAG,OAAA,EAAQ;AAC9C,EAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAc,WAAA,EAAa,WAAU,GAAI,IAAA;AAG5D,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,UAAA,CAAW,OAAA,CAAQ,QAAQ,WAAW,CAAA;AAAA,EACxC;AAEA,EAAA,MAAM,iBAAA,GAAoB,iBAAiB,SAAS,CAAA;AAEpD,EAAA,MAAM,aAAa,YAAA,CAAa,iBAAA,EAAmB,GAAG,YAAY,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAA;AACjF,EAAA,MAAM,YAAY,YAAA,CAAa,iBAAA,EAAmB,GAAG,WAAW,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAA;AAE/E,EAAA,IAAI,YAAA,GAAe,SAAA,CAAU,UAAA,EAAY,SAAS,CAAA;AAGlD,EAAA,MAAM,cAAc,OAAA,CAAQ,WAAA,KAAgB,QAAS,OAAA,CAAQ,WAAA,IAAe,gBAAgB,WAAA,GAAe,IAAA;AAC3G,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAM,eAAA,GAAkB,gBAAgB,WAAW,CAAA;AACnD,IAAA,KAAA,MAAW,YAAY,eAAA,EAAiB;AACtC,MAAA,YAAA,GAAe,SAAA,CAAU,cAAc,QAAQ,CAAA;AAAA,IACjD;AAAA,EACF;AAGA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,IAAA,WAAA,GAAc,MAAM,iBAAA,CAAkB,OAAA,CAAQ,KAAK,CAAA;AACnD,IAAA,MAAM,WAAA,CAAY,aAAa,YAAY,CAAA;AAAA,EAC7C;AAGA,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,QAAQ,GAAA,EAAK;AACf,IAAA,SAAA,GAAY,MAAM,sBAAA,CAAuB,OAAA,CAAQ,GAAG,CAAA;AACpD,IAAA,MAAM,SAAA,CAAU,aAAa,YAAY,CAAA;AAAA,EAC3C;AAGA,EAAA,IAAIA,UAAS,mBAAA,CAAoB,YAAA,EAAc,EAAE,WAAA,EAAa,WAAW,CAAA;AAGzE,EAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,IAAAA,OAAAA,GAAS,WAAWA,OAAM,CAAA;AAAA,EAC5B;AAGA,EAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,IAAAA,OAAAA,GAAS,OAAA,CAAQ,WAAA,CAAYA,OAAM,CAAA;AAAA,EACrC;AAGA,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,SAAA,CAAUA,OAAM,CAAA;AAC9C,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,MAAM,SAAS,MAAA,CAAO,KAAA,CAAM,OACzB,GAAA,CAAI,CAAC,MAAM,CAAA,IAAA,EAAO,CAAA,CAAE,KAAK,IAAA,CAAK,GAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA,CAClD,KAAK,IAAI,CAAA;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA;AAAA,EAA8B,MAAM,CAAA,CAAE,CAAA;AAAA,IACxD;AACA,IAAAA,UAAS,MAAA,CAAO,IAAA;AAAA,EAClB;AAGA,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,MAAM,YAAA,GAAe,YAAYA,OAAM,CAAA;AACvC,IAAA,OAAA,CAAQ,MAAA,CAAO,kBAAkB,WAAW,CAAA;AAAA,EAAO,KAAK,SAAA,CAAU,YAAA,EAAc,IAAA,EAAM,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,EAC5F;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAAA,OAAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACb;AACF;AAEA,SAAS,UAAA,CACP,cACA,WAAA,EACM;AACN,EAAA,IAAI,OAAA;AAEJ,EAAA,IAAI,OAAO,YAAA,KAAiB,QAAA,IAAY,YAAA,CAAa,IAAA,EAAM;AACzD,IAAA,OAAA,GAAU,YAAA,CAAa,IAAA;AAAA,EACzB,CAAA,MAAO;AACL,IAAA,OAAA,GAAU,WAAA,KAAgB,YAAA,GAAe,MAAA,GAAS,CAAA,KAAA,EAAQ,WAAW,CAAA,CAAA;AAAA,EACvE;AAEA,EAAOC,iBAAA,CAAA,MAAA,CAAO,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AACjC;AAEA,SAAS,iBAAiB,SAAA,EAA2B;AACnD,EAAA,MAAM,aAAA,GAAgB;AAAA,IACpBC,SAAA,CAAK,SAAA,EAAW,KAAA,EAAO,QAAQ,CAAA;AAAA,IAC/BA,SAAA,CAAK,SAAA,EAAW,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAChCA,SAAA,CAAK,WAAW,QAAQ,CAAA;AAAA,IACxB;AAAA,GACF;AAEA,EAAA,KAAA,MAAWC,UAAQ,aAAA,EAAe;AAChC,IAAA,IAAIC,aAAA,CAAWF,SAAA,CAAKC,MAAA,EAAM,UAAU,CAAC,CAAA,IAAKC,aAAA,CAAWF,SAAA,CAAKC,MAAA,EAAM,WAAW,CAAC,CAAA,EAAG;AAC7E,MAAA,OAAOA,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA;AAAA,EAAyC,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,IAAA,EAAO,CAAC,CAAA,CAAE,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,GAC1F;AACF;AAEA,SAAS,YAAA,CAAa,KAAa,QAAA,EAA2C;AAC5E,EAAA,MAAM,QAAA,GAAWD,SAAA,CAAK,GAAA,EAAK,QAAQ,CAAA;AAEnC,EAAA,IAAI,CAACE,aAAA,CAAW,QAAQ,CAAA,EAAG;AACzB,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,OAAA,GAAUC,eAAA,CAAa,QAAA,EAAU,MAAM,CAAA;AAC7C,EAAA,OAAaC,eAAA,CAAA,IAAA,CAAK,OAAO,CAAA,IAAiC,EAAC;AAC7D;AAEA,SAAS,gBAAgB,GAAA,EAAwC;AAC/D,EAAA,IAAI,CAACF,aAAA,CAAW,GAAG,CAAA,EAAG;AACpB,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,QAAQG,cAAA,CAAY,GAAG,CAAA,CAC1B,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,CAAS,MAAM,KAAK,CAAA,CAAE,QAAA,CAAS,OAAO,CAAC,EACvD,IAAA,EAAK;AAER,EAAA,OAAO,MAAM,GAAA,CAAI,CAAC,SAAS,YAAA,CAAa,GAAA,EAAK,IAAI,CAAC,CAAA;AACpD","file":"index.js","sourcesContent":["type DeepObject = Record<string, unknown>;\n\nexport function deepMerge(base: DeepObject, override: DeepObject): DeepObject {\n const merged = { ...base };\n\n for (const key in override) {\n const overrideValue = override[key];\n const baseValue = base[key];\n\n if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {\n merged[key] = deepMerge(baseValue as DeepObject, overrideValue as DeepObject);\n } else {\n merged[key] = overrideValue;\n }\n }\n\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is DeepObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import type { VaultClient } from './vault-client.js';\nimport type { AwsSecretsClient } from './aws-secrets-client.js';\n\nconst ENV_PLACEHOLDER_REGEX = /\\${(.*?)}/g;\nconst VAULT_PREFIX = 'vault:';\nconst AWS_PREFIX = 'aws:';\n\nexport interface ReplacePlaceholdersOptions {\n vaultClient?: VaultClient;\n awsClient?: AwsSecretsClient;\n}\n\nexport function replacePlaceholders(obj: unknown, options: ReplacePlaceholdersOptions = {}): unknown {\n if (typeof obj === 'string') {\n return replaceStringPlaceholders(obj, options);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => replacePlaceholders(item, options));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = replacePlaceholders(obj[key], options);\n }\n return result;\n }\n\n return obj;\n}\n\nfunction replaceStringPlaceholders(str: string, options: ReplacePlaceholdersOptions): string {\n return str.replace(ENV_PLACEHOLDER_REGEX, (match, key) => {\n // Handle Vault placeholders: ${vault:path:field} or ${vault:path:field:default}\n if (key.startsWith(VAULT_PREFIX)) {\n return resolveVaultPlaceholder(key, match, options);\n }\n\n // Handle AWS placeholders: ${aws:secret:field} or ${aws:secret:field:default} or ${aws:secret}\n if (key.startsWith(AWS_PREFIX)) {\n return resolveAwsPlaceholder(key, match, options);\n }\n\n // Handle environment variable placeholders: ${VAR} or ${VAR:default}\n return resolveEnvPlaceholder(key, match, options);\n });\n}\n\nfunction resolveVaultPlaceholder(\n key: string,\n originalMatch: string,\n options: ReplacePlaceholdersOptions,\n): string {\n // Parse: vault:secret/data/api:DB_PASSWORD:default_value\n const parts = key.substring(VAULT_PREFIX.length).split(':');\n\n if (parts.length < 2) {\n throw new Error(\n `Invalid Vault placeholder format \"${originalMatch}\". ` +\n `Expected \\${vault:path:field} or \\${vault:path:field:default}`,\n );\n }\n\n const [path, field, ...defaultParts] = parts;\n const defaultValue = defaultParts.length > 0 ? defaultParts.join(':') : undefined;\n\n if (!options.vaultClient) {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`Vault placeholder \"${originalMatch}\" found but no Vault options provided`);\n }\n\n const secretValue = options.vaultClient.getSecret(path, field);\n\n if (secretValue !== undefined) {\n return String(secretValue);\n }\n\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n throw new Error(`Vault secret \"${field}\" not found at path \"${path}\" and no default value provided`);\n}\n\nfunction resolveAwsPlaceholder(\n key: string,\n originalMatch: string,\n options: ReplacePlaceholdersOptions,\n): string {\n // Parse: aws:secret-name:field:default or aws:secret-name:field or aws:secret-name\n const parts = key.substring(AWS_PREFIX.length).split(':');\n\n if (parts.length < 1 || !parts[0]) {\n throw new Error(\n `Invalid AWS placeholder format \"${originalMatch}\". ` +\n `Expected \\${aws:secret-name} or \\${aws:secret-name:field} or \\${aws:secret-name:field:default}`,\n );\n }\n\n const [secretName, field, ...defaultParts] = parts;\n const defaultValue = defaultParts.length > 0 ? defaultParts.join(':') : undefined;\n\n if (!options.awsClient) {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`AWS placeholder \"${originalMatch}\" found but no AWS options provided`);\n }\n\n const secretValue = options.awsClient.getSecret(secretName, field || undefined);\n\n if (secretValue !== undefined) {\n return String(secretValue);\n }\n\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n if (field) {\n throw new Error(`AWS secret field \"${field}\" not found in \"${secretName}\" and no default value provided`);\n } else {\n throw new Error(`AWS secret \"${secretName}\" not found and no default value provided`);\n }\n}\n\nfunction resolveEnvPlaceholder(key: string, _match: string, options: ReplacePlaceholdersOptions): string {\n const [envKey, ...rest] = key.split(':');\n const defaultValue = rest.length > 0 ? rest.join(':') : undefined;\n const envValue = process.env[envKey];\n\n let value: string;\n if (envValue !== undefined) {\n value = envValue;\n } else if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throw new Error(`Environment variable \"${envKey}\" is not defined and no default value provided`);\n }\n\n // Handle nested placeholders\n if (value.includes('${')) {\n return replacePlaceholders(value, options) as string;\n }\n\n return value;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const SECRET_PATTERNS = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'credential'];\n\nconst URL_WITH_CREDENTIALS_REGEX = /^([a-z]+:\\/\\/)([^:]+):([^@]+)@(.+)$/i;\n\nexport function maskSecrets(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return maskUrlCredentials(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => maskSecrets(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (isSecretKey(key)) {\n result[key] = maskValue(value);\n } else {\n result[key] = maskSecrets(value);\n }\n }\n return result;\n }\n\n return obj;\n}\n\nfunction isSecretKey(key: string): boolean {\n const lowerKey = key.toLowerCase();\n return SECRET_PATTERNS.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction maskValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '***';\n }\n if (value.length <= 4) {\n return '***';\n }\n return value.slice(0, 2) + '***' + value.slice(-2);\n}\n\nfunction maskUrlCredentials(url: string): string {\n const match = url.match(URL_WITH_CREDENTIALS_REGEX);\n if (match) {\n const [, protocol, user, , host] = match;\n return `${protocol}${user}:***@${host}`;\n }\n return url;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","export function stripEmpty(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return obj === '' ? undefined : obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => stripEmpty(item)).filter((item) => item !== undefined);\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n let hasValues = false;\n\n for (const key of Object.keys(obj)) {\n const value = stripEmpty(obj[key]);\n if (value !== undefined) {\n result[key] = value;\n hasValues = true;\n }\n }\n\n return hasValues ? result : undefined;\n }\n\n return obj;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import NodeVault from 'node-vault';\nimport type { VaultOptions } from '../types.js';\n\nconst VAULT_PLACEHOLDER_REGEX = /\\${vault:([^:}]+):([^:}]+)(?::([^}]*))?}/g;\nconst URL_REGEX = /^https?:\\/\\/.+/;\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction validateVaultOptions(options: VaultOptions): void {\n if (!options.endpoint) {\n throw new Error('Vault endpoint is not set');\n }\n if (!URL_REGEX.test(options.endpoint)) {\n throw new Error(`Invalid Vault endpoint: \"${options.endpoint}\". Must be a valid URL (http:// or https://)`);\n }\n if (!options.roleId) {\n throw new Error('Vault roleId is not set');\n }\n if (!UUID_REGEX.test(options.roleId)) {\n throw new Error(`Invalid Vault roleId: \"${options.roleId}\". Must be a valid UUID`);\n }\n if (!options.secretId) {\n throw new Error('Vault secretId is not set');\n }\n if (!UUID_REGEX.test(options.secretId)) {\n throw new Error(`Invalid Vault secretId: \"${options.secretId}\". Must be a valid UUID`);\n }\n}\n\nexport interface VaultSecretCache {\n [path: string]: Record<string, unknown>;\n}\n\nexport interface VaultClient {\n fetchSecrets(obj: unknown): Promise<VaultSecretCache>;\n getSecret(path: string, field: string): unknown;\n}\n\nexport async function createVaultClient(options: VaultOptions): Promise<VaultClient> {\n validateVaultOptions(options);\n\n const vault = NodeVault({\n endpoint: options.endpoint,\n apiVersion: 'v1',\n namespace: options.namespace,\n });\n\n // Authenticate with AppRole\n const loginResult = await vault.approleLogin({\n role_id: options.roleId,\n secret_id: options.secretId,\n });\n\n vault.token = loginResult.auth.client_token;\n\n const cache: VaultSecretCache = {};\n\n return {\n async fetchSecrets(obj: unknown): Promise<VaultSecretCache> {\n const paths = extractVaultPaths(obj);\n\n // Fetch all unique paths in parallel\n await Promise.all(\n paths.map(async (path) => {\n if (!cache[path]) {\n try {\n const result = await vault.read(path);\n // Vault KV v2 stores data under result.data.data\n // KV v1 stores under result.data\n cache[path] = result.data?.data ?? result.data ?? {};\n } catch {\n // Store empty object for failed paths - will use defaults or throw later\n cache[path] = {};\n }\n }\n }),\n );\n\n return cache;\n },\n\n getSecret(path: string, field: string): unknown {\n const data = cache[path];\n if (!data) return undefined;\n\n // Support nested paths like \"postgres.password\"\n return field.split('.').reduce<unknown>((obj, key) => {\n if (obj && typeof obj === 'object' && key in obj) {\n return (obj as Record<string, unknown>)[key];\n }\n return undefined;\n }, data);\n }\n };\n}\n\n/**\n * Extract all unique Vault paths from config object\n */\nfunction extractVaultPaths(obj: unknown): string[] {\n const paths = new Set<string>();\n\n function traverse(value: unknown): void {\n if (typeof value === 'string') {\n let match;\n while ((match = VAULT_PLACEHOLDER_REGEX.exec(value)) !== null) {\n paths.add(match[1]); // path is first capture group\n }\n VAULT_PLACEHOLDER_REGEX.lastIndex = 0; // Reset regex state\n } else if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(traverse);\n }\n }\n\n traverse(obj);\n return Array.from(paths);\n}\n","import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';\nimport type { AwsSecretsOptions } from '../types.js';\n\nconst AWS_PLACEHOLDER_REGEX = /\\${aws:([^:}]+)(?::([^:}]+))?(?::([^}]*))?}/g;\nconst AWS_REGION_REGEX = /^[a-z]{2}-[a-z]+-\\d+$/;\n\nfunction validateAwsOptions(options: AwsSecretsOptions): void {\n if (!options.region) {\n throw new Error('AWS region is not set');\n }\n if (!AWS_REGION_REGEX.test(options.region)) {\n throw new Error(`Invalid AWS region: \"${options.region}\". Expected format: us-east-1, eu-west-2, etc.`);\n }\n if (!options.accessKeyId) {\n throw new Error('AWS accessKeyId is not set');\n }\n if (options.accessKeyId.length < 16) {\n throw new Error(`Invalid AWS accessKeyId: \"${options.accessKeyId}\". Must be at least 16 characters`);\n }\n if (!options.secretAccessKey) {\n throw new Error('AWS secretAccessKey is not set');\n }\n if (options.secretAccessKey.length < 16) {\n throw new Error('Invalid AWS secretAccessKey. Must be at least 16 characters');\n }\n}\n\nexport interface AwsSecretsCache {\n [secretName: string]: string | Record<string, unknown>;\n}\n\nexport interface AwsSecretsClient {\n fetchSecrets(obj: unknown): Promise<AwsSecretsCache>;\n getSecret(secretName: string, field?: string): unknown;\n}\n\nexport async function createAwsSecretsClient(options: AwsSecretsOptions): Promise<AwsSecretsClient> {\n validateAwsOptions(options);\n\n const client = new SecretsManagerClient({\n region: options.region,\n credentials: {\n accessKeyId: options.accessKeyId,\n secretAccessKey: options.secretAccessKey,\n },\n });\n\n const cache: AwsSecretsCache = {};\n\n return {\n async fetchSecrets(obj: unknown): Promise<AwsSecretsCache> {\n const secretNames = extractAwsSecretNames(obj);\n\n // Fetch all unique secrets in parallel\n await Promise.all(\n secretNames.map(async (secretName) => {\n if (cache[secretName] === undefined) {\n try {\n const command = new GetSecretValueCommand({ SecretId: secretName });\n const response = await client.send(command);\n\n const secretString = response.SecretString;\n if (secretString) {\n // Try to parse as JSON, fallback to plain string\n try {\n cache[secretName] = JSON.parse(secretString);\n } catch {\n cache[secretName] = secretString;\n }\n } else {\n cache[secretName] = {};\n }\n } catch {\n // Store empty object for failed secrets - will use defaults or throw later\n cache[secretName] = {};\n }\n }\n }),\n );\n\n return cache;\n },\n\n getSecret(secretName: string, field?: string): unknown {\n const secret = cache[secretName];\n\n if (secret === undefined) {\n return undefined;\n }\n\n // If no field specified, return the whole secret (plain string or parsed JSON)\n if (!field) {\n return typeof secret === 'string' ? secret : undefined;\n }\n\n // If field specified, secret must be an object\n if (typeof secret === 'object' && secret !== null) {\n return (secret as Record<string, unknown>)[field];\n }\n\n return undefined;\n },\n };\n}\n\n/**\n * Extract all unique AWS secret names from config object\n */\nfunction extractAwsSecretNames(obj: unknown): string[] {\n const names = new Set<string>();\n\n function traverse(value: unknown): void {\n if (typeof value === 'string') {\n let match;\n while ((match = AWS_PLACEHOLDER_REGEX.exec(value)) !== null) {\n names.add(match[1]); // secret name is first capture group\n }\n AWS_PLACEHOLDER_REGEX.lastIndex = 0; // Reset regex state\n } else if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(traverse);\n }\n }\n\n traverse(obj);\n return Array.from(names);\n}\n","/**\n * Environment helpers\n */\nexport const env = {\n get nodeEnv() {\n return process.env.NODE_ENV || 'local';\n },\n get isProduction() {\n return process.env.NODE_ENV === 'production';\n },\n get isDevelopment() {\n return process.env.NODE_ENV === 'development';\n },\n get isTest() {\n return process.env.NODE_ENV === 'test';\n },\n get isLocal() {\n return !process.env.NODE_ENV || process.env.NODE_ENV === 'local';\n },\n};\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as yaml from 'js-yaml';\nimport * as dotenv from 'dotenv';\nimport { join } from 'path';\nimport type { ConfigLoaderOptions, ConfigLoaderResult } from './types.js';\nimport {\n deepMerge,\n replacePlaceholders,\n maskSecrets,\n stripEmpty,\n createVaultClient,\n createAwsSecretsClient,\n type VaultClient,\n type AwsSecretsClient,\n} from './utils/index.js';\n\nconst DEFAULT_OPTIONS = {\n configDir: process.cwd(),\n baseFileName: 'base',\n environment: process.env.NODE_ENV || 'local',\n extension: 'yml' as const,\n overrideDir: '/etc/app/config',\n};\n\nexport function loadConfig<T>(options: ConfigLoaderOptions<T> = {}): ConfigLoaderResult<T> {\n if (options.vault || options.aws) {\n throw new Error('Vault/AWS options require async loading. Use loadConfigAsync() instead of loadConfig()');\n }\n\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n let config = replacePlaceholders(mergedConfig) as T;\n\n // Strip empty strings and objects\n if (options.stripEmpty) {\n config = stripEmpty(config) as T;\n }\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nexport async function loadConfigAsync<T>(\n options: ConfigLoaderOptions<T> = {},\n): Promise<ConfigLoaderResult<T>> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n // Create Vault client and pre-fetch secrets if Vault options provided\n let vaultClient: VaultClient | undefined;\n if (options.vault) {\n vaultClient = await createVaultClient(options.vault);\n await vaultClient.fetchSecrets(mergedConfig);\n }\n\n // Create AWS Secrets Manager client and pre-fetch secrets if AWS options provided\n let awsClient: AwsSecretsClient | undefined;\n if (options.aws) {\n awsClient = await createAwsSecretsClient(options.aws);\n await awsClient.fetchSecrets(mergedConfig);\n }\n\n // Replace placeholders (with Vault and AWS support)\n let config = replacePlaceholders(mergedConfig, { vaultClient, awsClient }) as T;\n\n // Strip empty strings and objects\n if (options.stripEmpty) {\n config = stripEmpty(config) as T;\n }\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nfunction loadDotenv(\n dotenvOption: boolean | { path?: string },\n environment: string,\n): void {\n let envPath: string;\n\n if (typeof dotenvOption === 'object' && dotenvOption.path) {\n envPath = dotenvOption.path;\n } else {\n envPath = environment === 'production' ? '.env' : `.env.${environment}`;\n }\n\n dotenv.config({ path: envPath });\n}\n\nfunction resolveConfigDir(configDir: string): string {\n const possiblePaths = [\n join(configDir, 'src', 'config'),\n join(configDir, 'dist', 'config'),\n join(configDir, 'config'),\n configDir,\n ];\n\n for (const path of possiblePaths) {\n if (existsSync(join(path, 'base.yml')) || existsSync(join(path, 'base.yaml'))) {\n return path;\n }\n }\n\n throw new Error(\n `Config files not found. Searched in:\\n${possiblePaths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n}\n\nfunction loadYamlFile(dir: string, filename: string): Record<string, unknown> {\n const filePath = join(dir, filename);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf8');\n return (yaml.load(content) as Record<string, unknown>) || {};\n}\n\nfunction loadOverrideDir(dir: string): Record<string, unknown>[] {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = readdirSync(dir)\n .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))\n .sort();\n\n return files.map((file) => loadYamlFile(dir, file));\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -204,7 +204,30 @@ function isPlainObject4(value) {
|
|
|
204
204
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
205
205
|
}
|
|
206
206
|
var VAULT_PLACEHOLDER_REGEX = /\${vault:([^:}]+):([^:}]+)(?::([^}]*))?}/g;
|
|
207
|
+
var URL_REGEX = /^https?:\/\/.+/;
|
|
208
|
+
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
209
|
+
function validateVaultOptions(options) {
|
|
210
|
+
if (!options.endpoint) {
|
|
211
|
+
throw new Error("Vault endpoint is not set");
|
|
212
|
+
}
|
|
213
|
+
if (!URL_REGEX.test(options.endpoint)) {
|
|
214
|
+
throw new Error(`Invalid Vault endpoint: "${options.endpoint}". Must be a valid URL (http:// or https://)`);
|
|
215
|
+
}
|
|
216
|
+
if (!options.roleId) {
|
|
217
|
+
throw new Error("Vault roleId is not set");
|
|
218
|
+
}
|
|
219
|
+
if (!UUID_REGEX.test(options.roleId)) {
|
|
220
|
+
throw new Error(`Invalid Vault roleId: "${options.roleId}". Must be a valid UUID`);
|
|
221
|
+
}
|
|
222
|
+
if (!options.secretId) {
|
|
223
|
+
throw new Error("Vault secretId is not set");
|
|
224
|
+
}
|
|
225
|
+
if (!UUID_REGEX.test(options.secretId)) {
|
|
226
|
+
throw new Error(`Invalid Vault secretId: "${options.secretId}". Must be a valid UUID`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
207
229
|
async function createVaultClient(options) {
|
|
230
|
+
validateVaultOptions(options);
|
|
208
231
|
const vault = NodeVault({
|
|
209
232
|
endpoint: options.endpoint,
|
|
210
233
|
apiVersion: "v1",
|
|
@@ -234,7 +257,14 @@ async function createVaultClient(options) {
|
|
|
234
257
|
return cache;
|
|
235
258
|
},
|
|
236
259
|
getSecret(path, field) {
|
|
237
|
-
|
|
260
|
+
const data = cache[path];
|
|
261
|
+
if (!data) return void 0;
|
|
262
|
+
return field.split(".").reduce((obj, key) => {
|
|
263
|
+
if (obj && typeof obj === "object" && key in obj) {
|
|
264
|
+
return obj[key];
|
|
265
|
+
}
|
|
266
|
+
return void 0;
|
|
267
|
+
}, data);
|
|
238
268
|
}
|
|
239
269
|
};
|
|
240
270
|
}
|
|
@@ -257,7 +287,29 @@ function extractVaultPaths(obj) {
|
|
|
257
287
|
return Array.from(paths);
|
|
258
288
|
}
|
|
259
289
|
var AWS_PLACEHOLDER_REGEX = /\${aws:([^:}]+)(?::([^:}]+))?(?::([^}]*))?}/g;
|
|
290
|
+
var AWS_REGION_REGEX = /^[a-z]{2}-[a-z]+-\d+$/;
|
|
291
|
+
function validateAwsOptions(options) {
|
|
292
|
+
if (!options.region) {
|
|
293
|
+
throw new Error("AWS region is not set");
|
|
294
|
+
}
|
|
295
|
+
if (!AWS_REGION_REGEX.test(options.region)) {
|
|
296
|
+
throw new Error(`Invalid AWS region: "${options.region}". Expected format: us-east-1, eu-west-2, etc.`);
|
|
297
|
+
}
|
|
298
|
+
if (!options.accessKeyId) {
|
|
299
|
+
throw new Error("AWS accessKeyId is not set");
|
|
300
|
+
}
|
|
301
|
+
if (options.accessKeyId.length < 16) {
|
|
302
|
+
throw new Error(`Invalid AWS accessKeyId: "${options.accessKeyId}". Must be at least 16 characters`);
|
|
303
|
+
}
|
|
304
|
+
if (!options.secretAccessKey) {
|
|
305
|
+
throw new Error("AWS secretAccessKey is not set");
|
|
306
|
+
}
|
|
307
|
+
if (options.secretAccessKey.length < 16) {
|
|
308
|
+
throw new Error("Invalid AWS secretAccessKey. Must be at least 16 characters");
|
|
309
|
+
}
|
|
310
|
+
}
|
|
260
311
|
async function createAwsSecretsClient(options) {
|
|
312
|
+
validateAwsOptions(options);
|
|
261
313
|
const client = new SecretsManagerClient({
|
|
262
314
|
region: options.region,
|
|
263
315
|
credentials: {
|
|
@@ -327,6 +379,25 @@ function extractAwsSecretNames(obj) {
|
|
|
327
379
|
return Array.from(names);
|
|
328
380
|
}
|
|
329
381
|
|
|
382
|
+
// src/utils/env.ts
|
|
383
|
+
var env = {
|
|
384
|
+
get nodeEnv() {
|
|
385
|
+
return process.env.NODE_ENV || "local";
|
|
386
|
+
},
|
|
387
|
+
get isProduction() {
|
|
388
|
+
return process.env.NODE_ENV === "production";
|
|
389
|
+
},
|
|
390
|
+
get isDevelopment() {
|
|
391
|
+
return process.env.NODE_ENV === "development";
|
|
392
|
+
},
|
|
393
|
+
get isTest() {
|
|
394
|
+
return process.env.NODE_ENV === "test";
|
|
395
|
+
},
|
|
396
|
+
get isLocal() {
|
|
397
|
+
return !process.env.NODE_ENV || process.env.NODE_ENV === "local";
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
|
|
330
401
|
// src/loader.ts
|
|
331
402
|
var DEFAULT_OPTIONS = {
|
|
332
403
|
configDir: process.cwd(),
|
|
@@ -478,6 +549,6 @@ function loadOverrideDir(dir) {
|
|
|
478
549
|
return files.map((file) => loadYamlFile(dir, file));
|
|
479
550
|
}
|
|
480
551
|
|
|
481
|
-
export { createAwsSecretsClient, createVaultClient, deepMerge, loadConfig, loadConfigAsync, maskSecrets, replacePlaceholders, stripEmpty };
|
|
552
|
+
export { createAwsSecretsClient, createVaultClient, deepMerge, env, loadConfig, loadConfigAsync, maskSecrets, replacePlaceholders, stripEmpty };
|
|
482
553
|
//# sourceMappingURL=index.mjs.map
|
|
483
554
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/deep-merge.ts","../src/utils/env-replacer.ts","../src/utils/mask-secrets.ts","../src/utils/strip-empty.ts","../src/utils/vault-client.ts","../src/utils/aws-secrets-client.ts","../src/loader.ts"],"names":["isPlainObject","config"],"mappings":"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","file":"index.mjs","sourcesContent":["type DeepObject = Record<string, unknown>;\n\nexport function deepMerge(base: DeepObject, override: DeepObject): DeepObject {\n const merged = { ...base };\n\n for (const key in override) {\n const overrideValue = override[key];\n const baseValue = base[key];\n\n if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {\n merged[key] = deepMerge(baseValue as DeepObject, overrideValue as DeepObject);\n } else {\n merged[key] = overrideValue;\n }\n }\n\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is DeepObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import type { VaultClient } from './vault-client.js';\nimport type { AwsSecretsClient } from './aws-secrets-client.js';\n\nconst ENV_PLACEHOLDER_REGEX = /\\${(.*?)}/g;\nconst VAULT_PREFIX = 'vault:';\nconst AWS_PREFIX = 'aws:';\n\nexport interface ReplacePlaceholdersOptions {\n vaultClient?: VaultClient;\n awsClient?: AwsSecretsClient;\n}\n\nexport function replacePlaceholders(obj: unknown, options: ReplacePlaceholdersOptions = {}): unknown {\n if (typeof obj === 'string') {\n return replaceStringPlaceholders(obj, options);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => replacePlaceholders(item, options));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = replacePlaceholders(obj[key], options);\n }\n return result;\n }\n\n return obj;\n}\n\nfunction replaceStringPlaceholders(str: string, options: ReplacePlaceholdersOptions): string {\n return str.replace(ENV_PLACEHOLDER_REGEX, (match, key) => {\n // Handle Vault placeholders: ${vault:path:field} or ${vault:path:field:default}\n if (key.startsWith(VAULT_PREFIX)) {\n return resolveVaultPlaceholder(key, match, options);\n }\n\n // Handle AWS placeholders: ${aws:secret:field} or ${aws:secret:field:default} or ${aws:secret}\n if (key.startsWith(AWS_PREFIX)) {\n return resolveAwsPlaceholder(key, match, options);\n }\n\n // Handle environment variable placeholders: ${VAR} or ${VAR:default}\n return resolveEnvPlaceholder(key, match, options);\n });\n}\n\nfunction resolveVaultPlaceholder(\n key: string,\n originalMatch: string,\n options: ReplacePlaceholdersOptions,\n): string {\n // Parse: vault:secret/data/api:DB_PASSWORD:default_value\n const parts = key.substring(VAULT_PREFIX.length).split(':');\n\n if (parts.length < 2) {\n throw new Error(\n `Invalid Vault placeholder format \"${originalMatch}\". ` +\n `Expected \\${vault:path:field} or \\${vault:path:field:default}`,\n );\n }\n\n const [path, field, ...defaultParts] = parts;\n const defaultValue = defaultParts.length > 0 ? defaultParts.join(':') : undefined;\n\n if (!options.vaultClient) {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`Vault placeholder \"${originalMatch}\" found but no Vault options provided`);\n }\n\n const secretValue = options.vaultClient.getSecret(path, field);\n\n if (secretValue !== undefined) {\n return String(secretValue);\n }\n\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n throw new Error(`Vault secret \"${field}\" not found at path \"${path}\" and no default value provided`);\n}\n\nfunction resolveAwsPlaceholder(\n key: string,\n originalMatch: string,\n options: ReplacePlaceholdersOptions,\n): string {\n // Parse: aws:secret-name:field:default or aws:secret-name:field or aws:secret-name\n const parts = key.substring(AWS_PREFIX.length).split(':');\n\n if (parts.length < 1 || !parts[0]) {\n throw new Error(\n `Invalid AWS placeholder format \"${originalMatch}\". ` +\n `Expected \\${aws:secret-name} or \\${aws:secret-name:field} or \\${aws:secret-name:field:default}`,\n );\n }\n\n const [secretName, field, ...defaultParts] = parts;\n const defaultValue = defaultParts.length > 0 ? defaultParts.join(':') : undefined;\n\n if (!options.awsClient) {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`AWS placeholder \"${originalMatch}\" found but no AWS options provided`);\n }\n\n const secretValue = options.awsClient.getSecret(secretName, field || undefined);\n\n if (secretValue !== undefined) {\n return String(secretValue);\n }\n\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n if (field) {\n throw new Error(`AWS secret field \"${field}\" not found in \"${secretName}\" and no default value provided`);\n } else {\n throw new Error(`AWS secret \"${secretName}\" not found and no default value provided`);\n }\n}\n\nfunction resolveEnvPlaceholder(key: string, _match: string, options: ReplacePlaceholdersOptions): string {\n const [envKey, ...rest] = key.split(':');\n const defaultValue = rest.length > 0 ? rest.join(':') : undefined;\n const envValue = process.env[envKey];\n\n let value: string;\n if (envValue !== undefined) {\n value = envValue;\n } else if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throw new Error(`Environment variable \"${envKey}\" is not defined and no default value provided`);\n }\n\n // Handle nested placeholders\n if (value.includes('${')) {\n return replacePlaceholders(value, options) as string;\n }\n\n return value;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const SECRET_PATTERNS = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'credential'];\n\nconst URL_WITH_CREDENTIALS_REGEX = /^([a-z]+:\\/\\/)([^:]+):([^@]+)@(.+)$/i;\n\nexport function maskSecrets(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return maskUrlCredentials(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => maskSecrets(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (isSecretKey(key)) {\n result[key] = maskValue(value);\n } else {\n result[key] = maskSecrets(value);\n }\n }\n return result;\n }\n\n return obj;\n}\n\nfunction isSecretKey(key: string): boolean {\n const lowerKey = key.toLowerCase();\n return SECRET_PATTERNS.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction maskValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '***';\n }\n if (value.length <= 4) {\n return '***';\n }\n return value.slice(0, 2) + '***' + value.slice(-2);\n}\n\nfunction maskUrlCredentials(url: string): string {\n const match = url.match(URL_WITH_CREDENTIALS_REGEX);\n if (match) {\n const [, protocol, user, , host] = match;\n return `${protocol}${user}:***@${host}`;\n }\n return url;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","export function stripEmpty(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return obj === '' ? undefined : obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => stripEmpty(item)).filter((item) => item !== undefined);\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n let hasValues = false;\n\n for (const key of Object.keys(obj)) {\n const value = stripEmpty(obj[key]);\n if (value !== undefined) {\n result[key] = value;\n hasValues = true;\n }\n }\n\n return hasValues ? result : undefined;\n }\n\n return obj;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import NodeVault from 'node-vault';\nimport type { VaultOptions } from '../types.js';\n\nconst VAULT_PLACEHOLDER_REGEX = /\\${vault:([^:}]+):([^:}]+)(?::([^}]*))?}/g;\n\nexport interface VaultSecretCache {\n [path: string]: Record<string, unknown>;\n}\n\nexport interface VaultClient {\n fetchSecrets(obj: unknown): Promise<VaultSecretCache>;\n getSecret(path: string, field: string): unknown;\n}\n\nexport async function createVaultClient(options: VaultOptions): Promise<VaultClient> {\n const vault = NodeVault({\n endpoint: options.endpoint,\n apiVersion: 'v1',\n namespace: options.namespace,\n });\n\n // Authenticate with AppRole\n const loginResult = await vault.approleLogin({\n role_id: options.roleId,\n secret_id: options.secretId,\n });\n\n vault.token = loginResult.auth.client_token;\n\n const cache: VaultSecretCache = {};\n\n return {\n async fetchSecrets(obj: unknown): Promise<VaultSecretCache> {\n const paths = extractVaultPaths(obj);\n\n // Fetch all unique paths in parallel\n await Promise.all(\n paths.map(async (path) => {\n if (!cache[path]) {\n try {\n const result = await vault.read(path);\n // Vault KV v2 stores data under result.data.data\n // KV v1 stores under result.data\n cache[path] = result.data?.data ?? result.data ?? {};\n } catch {\n // Store empty object for failed paths - will use defaults or throw later\n cache[path] = {};\n }\n }\n }),\n );\n\n return cache;\n },\n\n getSecret(path: string, field: string): unknown {\n return cache[path]?.[field];\n },\n };\n}\n\n/**\n * Extract all unique Vault paths from config object\n */\nfunction extractVaultPaths(obj: unknown): string[] {\n const paths = new Set<string>();\n\n function traverse(value: unknown): void {\n if (typeof value === 'string') {\n let match;\n while ((match = VAULT_PLACEHOLDER_REGEX.exec(value)) !== null) {\n paths.add(match[1]); // path is first capture group\n }\n VAULT_PLACEHOLDER_REGEX.lastIndex = 0; // Reset regex state\n } else if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(traverse);\n }\n }\n\n traverse(obj);\n return Array.from(paths);\n}\n","import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';\nimport type { AwsSecretsOptions } from '../types.js';\n\nconst AWS_PLACEHOLDER_REGEX = /\\${aws:([^:}]+)(?::([^:}]+))?(?::([^}]*))?}/g;\n\nexport interface AwsSecretsCache {\n [secretName: string]: string | Record<string, unknown>;\n}\n\nexport interface AwsSecretsClient {\n fetchSecrets(obj: unknown): Promise<AwsSecretsCache>;\n getSecret(secretName: string, field?: string): unknown;\n}\n\nexport async function createAwsSecretsClient(options: AwsSecretsOptions): Promise<AwsSecretsClient> {\n const client = new SecretsManagerClient({\n region: options.region,\n credentials: {\n accessKeyId: options.accessKeyId,\n secretAccessKey: options.secretAccessKey,\n },\n });\n\n const cache: AwsSecretsCache = {};\n\n return {\n async fetchSecrets(obj: unknown): Promise<AwsSecretsCache> {\n const secretNames = extractAwsSecretNames(obj);\n\n // Fetch all unique secrets in parallel\n await Promise.all(\n secretNames.map(async (secretName) => {\n if (cache[secretName] === undefined) {\n try {\n const command = new GetSecretValueCommand({ SecretId: secretName });\n const response = await client.send(command);\n\n const secretString = response.SecretString;\n if (secretString) {\n // Try to parse as JSON, fallback to plain string\n try {\n cache[secretName] = JSON.parse(secretString);\n } catch {\n cache[secretName] = secretString;\n }\n } else {\n cache[secretName] = {};\n }\n } catch {\n // Store empty object for failed secrets - will use defaults or throw later\n cache[secretName] = {};\n }\n }\n }),\n );\n\n return cache;\n },\n\n getSecret(secretName: string, field?: string): unknown {\n const secret = cache[secretName];\n\n if (secret === undefined) {\n return undefined;\n }\n\n // If no field specified, return the whole secret (plain string or parsed JSON)\n if (!field) {\n return typeof secret === 'string' ? secret : undefined;\n }\n\n // If field specified, secret must be an object\n if (typeof secret === 'object' && secret !== null) {\n return (secret as Record<string, unknown>)[field];\n }\n\n return undefined;\n },\n };\n}\n\n/**\n * Extract all unique AWS secret names from config object\n */\nfunction extractAwsSecretNames(obj: unknown): string[] {\n const names = new Set<string>();\n\n function traverse(value: unknown): void {\n if (typeof value === 'string') {\n let match;\n while ((match = AWS_PLACEHOLDER_REGEX.exec(value)) !== null) {\n names.add(match[1]); // secret name is first capture group\n }\n AWS_PLACEHOLDER_REGEX.lastIndex = 0; // Reset regex state\n } else if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(traverse);\n }\n }\n\n traverse(obj);\n return Array.from(names);\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as yaml from 'js-yaml';\nimport * as dotenv from 'dotenv';\nimport { join } from 'path';\nimport type { ConfigLoaderOptions, ConfigLoaderResult } from './types.js';\nimport {\n deepMerge,\n replacePlaceholders,\n maskSecrets,\n stripEmpty,\n createVaultClient,\n createAwsSecretsClient,\n type VaultClient,\n type AwsSecretsClient,\n} from './utils/index.js';\n\nconst DEFAULT_OPTIONS = {\n configDir: process.cwd(),\n baseFileName: 'base',\n environment: process.env.NODE_ENV || 'local',\n extension: 'yml' as const,\n overrideDir: '/etc/app/config',\n};\n\nexport function loadConfig<T>(options: ConfigLoaderOptions<T> = {}): ConfigLoaderResult<T> {\n if (options.vault || options.aws) {\n throw new Error('Vault/AWS options require async loading. Use loadConfigAsync() instead of loadConfig()');\n }\n\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n let config = replacePlaceholders(mergedConfig) as T;\n\n // Strip empty strings and objects\n if (options.stripEmpty) {\n config = stripEmpty(config) as T;\n }\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nexport async function loadConfigAsync<T>(\n options: ConfigLoaderOptions<T> = {},\n): Promise<ConfigLoaderResult<T>> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n // Create Vault client and pre-fetch secrets if Vault options provided\n let vaultClient: VaultClient | undefined;\n if (options.vault) {\n vaultClient = await createVaultClient(options.vault);\n await vaultClient.fetchSecrets(mergedConfig);\n }\n\n // Create AWS Secrets Manager client and pre-fetch secrets if AWS options provided\n let awsClient: AwsSecretsClient | undefined;\n if (options.aws) {\n awsClient = await createAwsSecretsClient(options.aws);\n await awsClient.fetchSecrets(mergedConfig);\n }\n\n // Replace placeholders (with Vault and AWS support)\n let config = replacePlaceholders(mergedConfig, { vaultClient, awsClient }) as T;\n\n // Strip empty strings and objects\n if (options.stripEmpty) {\n config = stripEmpty(config) as T;\n }\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nfunction loadDotenv(\n dotenvOption: boolean | { path?: string },\n environment: string,\n): void {\n let envPath: string;\n\n if (typeof dotenvOption === 'object' && dotenvOption.path) {\n envPath = dotenvOption.path;\n } else {\n envPath = environment === 'production' ? '.env' : `.env.${environment}`;\n }\n\n dotenv.config({ path: envPath });\n}\n\nfunction resolveConfigDir(configDir: string): string {\n const possiblePaths = [\n join(configDir, 'src', 'config'),\n join(configDir, 'dist', 'config'),\n join(configDir, 'config'),\n configDir,\n ];\n\n for (const path of possiblePaths) {\n if (existsSync(join(path, 'base.yml')) || existsSync(join(path, 'base.yaml'))) {\n return path;\n }\n }\n\n throw new Error(\n `Config files not found. Searched in:\\n${possiblePaths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n}\n\nfunction loadYamlFile(dir: string, filename: string): Record<string, unknown> {\n const filePath = join(dir, filename);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf8');\n return (yaml.load(content) as Record<string, unknown>) || {};\n}\n\nfunction loadOverrideDir(dir: string): Record<string, unknown>[] {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = readdirSync(dir)\n .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))\n .sort();\n\n return files.map((file) => loadYamlFile(dir, file));\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/deep-merge.ts","../src/utils/env-replacer.ts","../src/utils/mask-secrets.ts","../src/utils/strip-empty.ts","../src/utils/vault-client.ts","../src/utils/aws-secrets-client.ts","../src/utils/env.ts","../src/loader.ts"],"names":["isPlainObject","config"],"mappings":"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","file":"index.mjs","sourcesContent":["type DeepObject = Record<string, unknown>;\n\nexport function deepMerge(base: DeepObject, override: DeepObject): DeepObject {\n const merged = { ...base };\n\n for (const key in override) {\n const overrideValue = override[key];\n const baseValue = base[key];\n\n if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {\n merged[key] = deepMerge(baseValue as DeepObject, overrideValue as DeepObject);\n } else {\n merged[key] = overrideValue;\n }\n }\n\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is DeepObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import type { VaultClient } from './vault-client.js';\nimport type { AwsSecretsClient } from './aws-secrets-client.js';\n\nconst ENV_PLACEHOLDER_REGEX = /\\${(.*?)}/g;\nconst VAULT_PREFIX = 'vault:';\nconst AWS_PREFIX = 'aws:';\n\nexport interface ReplacePlaceholdersOptions {\n vaultClient?: VaultClient;\n awsClient?: AwsSecretsClient;\n}\n\nexport function replacePlaceholders(obj: unknown, options: ReplacePlaceholdersOptions = {}): unknown {\n if (typeof obj === 'string') {\n return replaceStringPlaceholders(obj, options);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => replacePlaceholders(item, options));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = replacePlaceholders(obj[key], options);\n }\n return result;\n }\n\n return obj;\n}\n\nfunction replaceStringPlaceholders(str: string, options: ReplacePlaceholdersOptions): string {\n return str.replace(ENV_PLACEHOLDER_REGEX, (match, key) => {\n // Handle Vault placeholders: ${vault:path:field} or ${vault:path:field:default}\n if (key.startsWith(VAULT_PREFIX)) {\n return resolveVaultPlaceholder(key, match, options);\n }\n\n // Handle AWS placeholders: ${aws:secret:field} or ${aws:secret:field:default} or ${aws:secret}\n if (key.startsWith(AWS_PREFIX)) {\n return resolveAwsPlaceholder(key, match, options);\n }\n\n // Handle environment variable placeholders: ${VAR} or ${VAR:default}\n return resolveEnvPlaceholder(key, match, options);\n });\n}\n\nfunction resolveVaultPlaceholder(\n key: string,\n originalMatch: string,\n options: ReplacePlaceholdersOptions,\n): string {\n // Parse: vault:secret/data/api:DB_PASSWORD:default_value\n const parts = key.substring(VAULT_PREFIX.length).split(':');\n\n if (parts.length < 2) {\n throw new Error(\n `Invalid Vault placeholder format \"${originalMatch}\". ` +\n `Expected \\${vault:path:field} or \\${vault:path:field:default}`,\n );\n }\n\n const [path, field, ...defaultParts] = parts;\n const defaultValue = defaultParts.length > 0 ? defaultParts.join(':') : undefined;\n\n if (!options.vaultClient) {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`Vault placeholder \"${originalMatch}\" found but no Vault options provided`);\n }\n\n const secretValue = options.vaultClient.getSecret(path, field);\n\n if (secretValue !== undefined) {\n return String(secretValue);\n }\n\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n throw new Error(`Vault secret \"${field}\" not found at path \"${path}\" and no default value provided`);\n}\n\nfunction resolveAwsPlaceholder(\n key: string,\n originalMatch: string,\n options: ReplacePlaceholdersOptions,\n): string {\n // Parse: aws:secret-name:field:default or aws:secret-name:field or aws:secret-name\n const parts = key.substring(AWS_PREFIX.length).split(':');\n\n if (parts.length < 1 || !parts[0]) {\n throw new Error(\n `Invalid AWS placeholder format \"${originalMatch}\". ` +\n `Expected \\${aws:secret-name} or \\${aws:secret-name:field} or \\${aws:secret-name:field:default}`,\n );\n }\n\n const [secretName, field, ...defaultParts] = parts;\n const defaultValue = defaultParts.length > 0 ? defaultParts.join(':') : undefined;\n\n if (!options.awsClient) {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`AWS placeholder \"${originalMatch}\" found but no AWS options provided`);\n }\n\n const secretValue = options.awsClient.getSecret(secretName, field || undefined);\n\n if (secretValue !== undefined) {\n return String(secretValue);\n }\n\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n if (field) {\n throw new Error(`AWS secret field \"${field}\" not found in \"${secretName}\" and no default value provided`);\n } else {\n throw new Error(`AWS secret \"${secretName}\" not found and no default value provided`);\n }\n}\n\nfunction resolveEnvPlaceholder(key: string, _match: string, options: ReplacePlaceholdersOptions): string {\n const [envKey, ...rest] = key.split(':');\n const defaultValue = rest.length > 0 ? rest.join(':') : undefined;\n const envValue = process.env[envKey];\n\n let value: string;\n if (envValue !== undefined) {\n value = envValue;\n } else if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throw new Error(`Environment variable \"${envKey}\" is not defined and no default value provided`);\n }\n\n // Handle nested placeholders\n if (value.includes('${')) {\n return replacePlaceholders(value, options) as string;\n }\n\n return value;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const SECRET_PATTERNS = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'credential'];\n\nconst URL_WITH_CREDENTIALS_REGEX = /^([a-z]+:\\/\\/)([^:]+):([^@]+)@(.+)$/i;\n\nexport function maskSecrets(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return maskUrlCredentials(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => maskSecrets(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (isSecretKey(key)) {\n result[key] = maskValue(value);\n } else {\n result[key] = maskSecrets(value);\n }\n }\n return result;\n }\n\n return obj;\n}\n\nfunction isSecretKey(key: string): boolean {\n const lowerKey = key.toLowerCase();\n return SECRET_PATTERNS.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction maskValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '***';\n }\n if (value.length <= 4) {\n return '***';\n }\n return value.slice(0, 2) + '***' + value.slice(-2);\n}\n\nfunction maskUrlCredentials(url: string): string {\n const match = url.match(URL_WITH_CREDENTIALS_REGEX);\n if (match) {\n const [, protocol, user, , host] = match;\n return `${protocol}${user}:***@${host}`;\n }\n return url;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","export function stripEmpty(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return obj === '' ? undefined : obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => stripEmpty(item)).filter((item) => item !== undefined);\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n let hasValues = false;\n\n for (const key of Object.keys(obj)) {\n const value = stripEmpty(obj[key]);\n if (value !== undefined) {\n result[key] = value;\n hasValues = true;\n }\n }\n\n return hasValues ? result : undefined;\n }\n\n return obj;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import NodeVault from 'node-vault';\nimport type { VaultOptions } from '../types.js';\n\nconst VAULT_PLACEHOLDER_REGEX = /\\${vault:([^:}]+):([^:}]+)(?::([^}]*))?}/g;\nconst URL_REGEX = /^https?:\\/\\/.+/;\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction validateVaultOptions(options: VaultOptions): void {\n if (!options.endpoint) {\n throw new Error('Vault endpoint is not set');\n }\n if (!URL_REGEX.test(options.endpoint)) {\n throw new Error(`Invalid Vault endpoint: \"${options.endpoint}\". Must be a valid URL (http:// or https://)`);\n }\n if (!options.roleId) {\n throw new Error('Vault roleId is not set');\n }\n if (!UUID_REGEX.test(options.roleId)) {\n throw new Error(`Invalid Vault roleId: \"${options.roleId}\". Must be a valid UUID`);\n }\n if (!options.secretId) {\n throw new Error('Vault secretId is not set');\n }\n if (!UUID_REGEX.test(options.secretId)) {\n throw new Error(`Invalid Vault secretId: \"${options.secretId}\". Must be a valid UUID`);\n }\n}\n\nexport interface VaultSecretCache {\n [path: string]: Record<string, unknown>;\n}\n\nexport interface VaultClient {\n fetchSecrets(obj: unknown): Promise<VaultSecretCache>;\n getSecret(path: string, field: string): unknown;\n}\n\nexport async function createVaultClient(options: VaultOptions): Promise<VaultClient> {\n validateVaultOptions(options);\n\n const vault = NodeVault({\n endpoint: options.endpoint,\n apiVersion: 'v1',\n namespace: options.namespace,\n });\n\n // Authenticate with AppRole\n const loginResult = await vault.approleLogin({\n role_id: options.roleId,\n secret_id: options.secretId,\n });\n\n vault.token = loginResult.auth.client_token;\n\n const cache: VaultSecretCache = {};\n\n return {\n async fetchSecrets(obj: unknown): Promise<VaultSecretCache> {\n const paths = extractVaultPaths(obj);\n\n // Fetch all unique paths in parallel\n await Promise.all(\n paths.map(async (path) => {\n if (!cache[path]) {\n try {\n const result = await vault.read(path);\n // Vault KV v2 stores data under result.data.data\n // KV v1 stores under result.data\n cache[path] = result.data?.data ?? result.data ?? {};\n } catch {\n // Store empty object for failed paths - will use defaults or throw later\n cache[path] = {};\n }\n }\n }),\n );\n\n return cache;\n },\n\n getSecret(path: string, field: string): unknown {\n const data = cache[path];\n if (!data) return undefined;\n\n // Support nested paths like \"postgres.password\"\n return field.split('.').reduce<unknown>((obj, key) => {\n if (obj && typeof obj === 'object' && key in obj) {\n return (obj as Record<string, unknown>)[key];\n }\n return undefined;\n }, data);\n }\n };\n}\n\n/**\n * Extract all unique Vault paths from config object\n */\nfunction extractVaultPaths(obj: unknown): string[] {\n const paths = new Set<string>();\n\n function traverse(value: unknown): void {\n if (typeof value === 'string') {\n let match;\n while ((match = VAULT_PLACEHOLDER_REGEX.exec(value)) !== null) {\n paths.add(match[1]); // path is first capture group\n }\n VAULT_PLACEHOLDER_REGEX.lastIndex = 0; // Reset regex state\n } else if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(traverse);\n }\n }\n\n traverse(obj);\n return Array.from(paths);\n}\n","import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';\nimport type { AwsSecretsOptions } from '../types.js';\n\nconst AWS_PLACEHOLDER_REGEX = /\\${aws:([^:}]+)(?::([^:}]+))?(?::([^}]*))?}/g;\nconst AWS_REGION_REGEX = /^[a-z]{2}-[a-z]+-\\d+$/;\n\nfunction validateAwsOptions(options: AwsSecretsOptions): void {\n if (!options.region) {\n throw new Error('AWS region is not set');\n }\n if (!AWS_REGION_REGEX.test(options.region)) {\n throw new Error(`Invalid AWS region: \"${options.region}\". Expected format: us-east-1, eu-west-2, etc.`);\n }\n if (!options.accessKeyId) {\n throw new Error('AWS accessKeyId is not set');\n }\n if (options.accessKeyId.length < 16) {\n throw new Error(`Invalid AWS accessKeyId: \"${options.accessKeyId}\". Must be at least 16 characters`);\n }\n if (!options.secretAccessKey) {\n throw new Error('AWS secretAccessKey is not set');\n }\n if (options.secretAccessKey.length < 16) {\n throw new Error('Invalid AWS secretAccessKey. Must be at least 16 characters');\n }\n}\n\nexport interface AwsSecretsCache {\n [secretName: string]: string | Record<string, unknown>;\n}\n\nexport interface AwsSecretsClient {\n fetchSecrets(obj: unknown): Promise<AwsSecretsCache>;\n getSecret(secretName: string, field?: string): unknown;\n}\n\nexport async function createAwsSecretsClient(options: AwsSecretsOptions): Promise<AwsSecretsClient> {\n validateAwsOptions(options);\n\n const client = new SecretsManagerClient({\n region: options.region,\n credentials: {\n accessKeyId: options.accessKeyId,\n secretAccessKey: options.secretAccessKey,\n },\n });\n\n const cache: AwsSecretsCache = {};\n\n return {\n async fetchSecrets(obj: unknown): Promise<AwsSecretsCache> {\n const secretNames = extractAwsSecretNames(obj);\n\n // Fetch all unique secrets in parallel\n await Promise.all(\n secretNames.map(async (secretName) => {\n if (cache[secretName] === undefined) {\n try {\n const command = new GetSecretValueCommand({ SecretId: secretName });\n const response = await client.send(command);\n\n const secretString = response.SecretString;\n if (secretString) {\n // Try to parse as JSON, fallback to plain string\n try {\n cache[secretName] = JSON.parse(secretString);\n } catch {\n cache[secretName] = secretString;\n }\n } else {\n cache[secretName] = {};\n }\n } catch {\n // Store empty object for failed secrets - will use defaults or throw later\n cache[secretName] = {};\n }\n }\n }),\n );\n\n return cache;\n },\n\n getSecret(secretName: string, field?: string): unknown {\n const secret = cache[secretName];\n\n if (secret === undefined) {\n return undefined;\n }\n\n // If no field specified, return the whole secret (plain string or parsed JSON)\n if (!field) {\n return typeof secret === 'string' ? secret : undefined;\n }\n\n // If field specified, secret must be an object\n if (typeof secret === 'object' && secret !== null) {\n return (secret as Record<string, unknown>)[field];\n }\n\n return undefined;\n },\n };\n}\n\n/**\n * Extract all unique AWS secret names from config object\n */\nfunction extractAwsSecretNames(obj: unknown): string[] {\n const names = new Set<string>();\n\n function traverse(value: unknown): void {\n if (typeof value === 'string') {\n let match;\n while ((match = AWS_PLACEHOLDER_REGEX.exec(value)) !== null) {\n names.add(match[1]); // secret name is first capture group\n }\n AWS_PLACEHOLDER_REGEX.lastIndex = 0; // Reset regex state\n } else if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(traverse);\n }\n }\n\n traverse(obj);\n return Array.from(names);\n}\n","/**\n * Environment helpers\n */\nexport const env = {\n get nodeEnv() {\n return process.env.NODE_ENV || 'local';\n },\n get isProduction() {\n return process.env.NODE_ENV === 'production';\n },\n get isDevelopment() {\n return process.env.NODE_ENV === 'development';\n },\n get isTest() {\n return process.env.NODE_ENV === 'test';\n },\n get isLocal() {\n return !process.env.NODE_ENV || process.env.NODE_ENV === 'local';\n },\n};\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as yaml from 'js-yaml';\nimport * as dotenv from 'dotenv';\nimport { join } from 'path';\nimport type { ConfigLoaderOptions, ConfigLoaderResult } from './types.js';\nimport {\n deepMerge,\n replacePlaceholders,\n maskSecrets,\n stripEmpty,\n createVaultClient,\n createAwsSecretsClient,\n type VaultClient,\n type AwsSecretsClient,\n} from './utils/index.js';\n\nconst DEFAULT_OPTIONS = {\n configDir: process.cwd(),\n baseFileName: 'base',\n environment: process.env.NODE_ENV || 'local',\n extension: 'yml' as const,\n overrideDir: '/etc/app/config',\n};\n\nexport function loadConfig<T>(options: ConfigLoaderOptions<T> = {}): ConfigLoaderResult<T> {\n if (options.vault || options.aws) {\n throw new Error('Vault/AWS options require async loading. Use loadConfigAsync() instead of loadConfig()');\n }\n\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n let config = replacePlaceholders(mergedConfig) as T;\n\n // Strip empty strings and objects\n if (options.stripEmpty) {\n config = stripEmpty(config) as T;\n }\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nexport async function loadConfigAsync<T>(\n options: ConfigLoaderOptions<T> = {},\n): Promise<ConfigLoaderResult<T>> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n // Create Vault client and pre-fetch secrets if Vault options provided\n let vaultClient: VaultClient | undefined;\n if (options.vault) {\n vaultClient = await createVaultClient(options.vault);\n await vaultClient.fetchSecrets(mergedConfig);\n }\n\n // Create AWS Secrets Manager client and pre-fetch secrets if AWS options provided\n let awsClient: AwsSecretsClient | undefined;\n if (options.aws) {\n awsClient = await createAwsSecretsClient(options.aws);\n await awsClient.fetchSecrets(mergedConfig);\n }\n\n // Replace placeholders (with Vault and AWS support)\n let config = replacePlaceholders(mergedConfig, { vaultClient, awsClient }) as T;\n\n // Strip empty strings and objects\n if (options.stripEmpty) {\n config = stripEmpty(config) as T;\n }\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nfunction loadDotenv(\n dotenvOption: boolean | { path?: string },\n environment: string,\n): void {\n let envPath: string;\n\n if (typeof dotenvOption === 'object' && dotenvOption.path) {\n envPath = dotenvOption.path;\n } else {\n envPath = environment === 'production' ? '.env' : `.env.${environment}`;\n }\n\n dotenv.config({ path: envPath });\n}\n\nfunction resolveConfigDir(configDir: string): string {\n const possiblePaths = [\n join(configDir, 'src', 'config'),\n join(configDir, 'dist', 'config'),\n join(configDir, 'config'),\n configDir,\n ];\n\n for (const path of possiblePaths) {\n if (existsSync(join(path, 'base.yml')) || existsSync(join(path, 'base.yaml'))) {\n return path;\n }\n }\n\n throw new Error(\n `Config files not found. Searched in:\\n${possiblePaths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n}\n\nfunction loadYamlFile(dir: string, filename: string): Record<string, unknown> {\n const filePath = join(dir, filename);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf8');\n return (yaml.load(content) as Record<string, unknown>) || {};\n}\n\nfunction loadOverrideDir(dir: string): Record<string, unknown>[] {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = readdirSync(dir)\n .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))\n .sort();\n\n return files.map((file) => loadYamlFile(dir, file));\n}\n"]}
|
package/package.json
CHANGED