72 lines
No EOL
2 KiB
TypeScript
72 lines
No EOL
2 KiB
TypeScript
import { readFile } from 'fs/promises';
|
|
import { join } from 'path';
|
|
import { ConfigLoader } from '../types';
|
|
import { ConfigLoaderError } from '../errors';
|
|
|
|
export class FileLoader implements ConfigLoader {
|
|
readonly priority = 50; // Medium priority
|
|
|
|
constructor(
|
|
private configPath: string,
|
|
private environment: string
|
|
) {}
|
|
|
|
async load(): Promise<Record<string, unknown>> {
|
|
try {
|
|
const configs: Record<string, unknown>[] = [];
|
|
|
|
// Load default config
|
|
const defaultConfig = await this.loadFile('default.json');
|
|
if (defaultConfig) {
|
|
configs.push(defaultConfig);
|
|
}
|
|
|
|
// Load environment-specific config
|
|
const envConfig = await this.loadFile(`${this.environment}.json`);
|
|
if (envConfig) {
|
|
configs.push(envConfig);
|
|
}
|
|
|
|
// Merge configs (later configs override earlier ones)
|
|
return this.deepMerge(...configs);
|
|
} catch (error) {
|
|
throw new ConfigLoaderError(
|
|
`Failed to load configuration files: ${error}`,
|
|
'FileLoader'
|
|
);
|
|
}
|
|
}
|
|
|
|
private async loadFile(filename: string): Promise<Record<string, unknown> | null> {
|
|
const filepath = join(this.configPath, filename);
|
|
|
|
try {
|
|
const content = await readFile(filepath, 'utf-8');
|
|
return JSON.parse(content);
|
|
} catch (error: unknown) {
|
|
// File not found is not an error (configs are optional)
|
|
if (error.code === 'ENOENT') {
|
|
return null;
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
private deepMerge(...objects: Record<string, any>[]): Record<string, any> {
|
|
const result: Record<string, any> = {};
|
|
|
|
for (const obj of objects) {
|
|
for (const [key, value] of Object.entries(obj)) {
|
|
if (value === null || value === undefined) {
|
|
result[key] = value;
|
|
} else if (typeof value === 'object' && !Array.isArray(value)) {
|
|
result[key] = this.deepMerge(result[key] || {}, value);
|
|
} else {
|
|
result[key] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
} |