created new config lib
This commit is contained in:
parent
bc14acaeba
commit
68a4c2d550
36 changed files with 2681 additions and 134 deletions
127
libs/config-new/src/loaders/env.loader.ts
Normal file
127
libs/config-new/src/loaders/env.loader.ts
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import { ConfigLoader } from '../types';
|
||||
import { ConfigLoaderError } from '../errors';
|
||||
|
||||
export interface EnvLoaderOptions {
|
||||
convertCase?: boolean;
|
||||
parseJson?: boolean;
|
||||
parseValues?: boolean;
|
||||
nestedDelimiter?: string;
|
||||
}
|
||||
|
||||
export class EnvLoader implements ConfigLoader {
|
||||
readonly priority = 100; // Highest priority
|
||||
|
||||
constructor(
|
||||
private prefix = '',
|
||||
private options: EnvLoaderOptions = {}
|
||||
) {
|
||||
this.options = {
|
||||
convertCase: false,
|
||||
parseJson: true,
|
||||
parseValues: true,
|
||||
nestedDelimiter: '_',
|
||||
...options
|
||||
};
|
||||
}
|
||||
|
||||
async load(): Promise<Record<string, unknown>> {
|
||||
try {
|
||||
const config: Record<string, unknown> = {};
|
||||
const envVars = process.env;
|
||||
|
||||
for (const [key, value] of Object.entries(envVars)) {
|
||||
if (this.prefix && !key.startsWith(this.prefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const configKey = this.prefix
|
||||
? key.slice(this.prefix.length)
|
||||
: key;
|
||||
|
||||
if (!this.options.convertCase && !this.options.nestedDelimiter) {
|
||||
// Simple case - just keep the key as is
|
||||
config[configKey] = this.parseValue(value || '');
|
||||
} else {
|
||||
// Handle nested structure or case conversion
|
||||
this.setConfigValue(config, configKey, value || '');
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
} catch (error) {
|
||||
throw new ConfigLoaderError(
|
||||
`Failed to load environment variables: ${error}`,
|
||||
'EnvLoader'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private setConfigValue(config: Record<string, any>, key: string, value: string): void {
|
||||
const parsedValue = this.parseValue(value);
|
||||
|
||||
if (this.options.nestedDelimiter && key.includes(this.options.nestedDelimiter)) {
|
||||
// Handle nested delimiter (e.g., APP__NAME -> { APP: { NAME: value } })
|
||||
const parts = key.split(this.options.nestedDelimiter);
|
||||
this.setNestedValue(config, parts, parsedValue);
|
||||
} else if (this.options.convertCase) {
|
||||
// Convert to camelCase
|
||||
const camelKey = this.toCamelCase(key);
|
||||
config[camelKey] = parsedValue;
|
||||
} else {
|
||||
// Convert to nested structure based on underscores
|
||||
const path = key.toLowerCase().split('_');
|
||||
this.setNestedValue(config, path, parsedValue);
|
||||
}
|
||||
}
|
||||
|
||||
private setNestedValue(obj: Record<string, any>, path: string[], value: unknown): void {
|
||||
const lastKey = path.pop()!;
|
||||
const target = path.reduce((acc, key) => {
|
||||
if (!acc[key]) {
|
||||
acc[key] = {};
|
||||
}
|
||||
return acc[key];
|
||||
}, obj);
|
||||
target[lastKey] = value;
|
||||
}
|
||||
|
||||
private toCamelCase(str: string): string {
|
||||
return str
|
||||
.toLowerCase()
|
||||
.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
|
||||
}
|
||||
|
||||
private parseValue(value: string): unknown {
|
||||
if (!this.options.parseValues && !this.options.parseJson) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Try to parse as JSON first if enabled
|
||||
if (this.options.parseJson) {
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch {
|
||||
// Not JSON, continue with other parsing
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.options.parseValues) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Handle booleans
|
||||
if (value.toLowerCase() === 'true') return true;
|
||||
if (value.toLowerCase() === 'false') return false;
|
||||
|
||||
// Handle numbers
|
||||
const num = Number(value);
|
||||
if (!isNaN(num) && value !== '') return num;
|
||||
|
||||
// Handle null/undefined
|
||||
if (value.toLowerCase() === 'null') return null;
|
||||
if (value.toLowerCase() === 'undefined') return undefined;
|
||||
|
||||
// Return as string
|
||||
return value;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue