52 lines
1.5 KiB
JavaScript
52 lines
1.5 KiB
JavaScript
/**
|
|
* Config loading — merges JSON config file with CLI args.
|
|
* CLI args always win. Required paths are validated here.
|
|
*/
|
|
import { readFile } from 'fs/promises';
|
|
import { join } from 'path';
|
|
|
|
const REQUIRED_PATHS = ['source', 'prev', 'pend', 'deltas'];
|
|
const DEFAULTS = {
|
|
backend: 'zstd',
|
|
};
|
|
|
|
export async function loadConfig(args) {
|
|
let fileConfig = {};
|
|
|
|
if (args.config) {
|
|
try {
|
|
const raw = await readFile(args.config, 'utf8');
|
|
fileConfig = JSON.parse(raw);
|
|
} catch (err) {
|
|
console.error(`Error reading config file ${args.config}: ${err.message}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// CLI args override file config, file config overrides defaults
|
|
const config = { ...DEFAULTS, ...fileConfig, ...filterDefined(args) };
|
|
|
|
// Expand --base into --prev/--pend/--deltas, explicit flags take priority
|
|
if (config.base) {
|
|
config.prev ??= join(config.base, 'previous');
|
|
config.pend ??= join(config.base, 'pending');
|
|
config.deltas ??= join(config.base, 'deltas');
|
|
}
|
|
|
|
// Guard: refuse to run if any required path is missing
|
|
if (config.command === 'run') {
|
|
const missing = REQUIRED_PATHS.filter(k => !config[k]);
|
|
if (missing.length > 0) {
|
|
console.error(`Error: missing required options: ${missing.map(k => `--${k}`).join(', ')}`);
|
|
console.error('Provide them as CLI flags or in a --config JSON file.');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
function filterDefined(obj) {
|
|
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));
|
|
}
|