- package.json (ESM, bin entry) - bin/delta-backup.js — entrypoint - lib/args.js — CLI arg parsing via Node parseArgs - lib/config.js — config file merging + required path guards - lib/spawn.js — safe process spawning (no shell strings) - lib/state.js — sequence number + phase state management - lib/backends/zstd.js — zstd delta backend - lib/backends/index.js — backend registry - lib/commands/run.js — full run skeleton (phases 1-3 wired, 4-6 stubbed) - lib/commands/status.js — status command
29 lines
812 B
JavaScript
29 lines
812 B
JavaScript
/**
|
|
* Process spawning — always explicit argument arrays, never shell strings.
|
|
*/
|
|
import { spawn } from 'child_process';
|
|
|
|
/**
|
|
* Spawn a process and stream its output.
|
|
* @param {string} cmd
|
|
* @param {string[]} args
|
|
* @param {{ dryRun?: boolean, label?: string }} opts
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export async function run(cmd, args, { dryRun = false, label } = {}) {
|
|
const display = [cmd, ...args].join(' ');
|
|
if (label) console.log(`[${label}] ${display}`);
|
|
else console.log(`$ ${display}`);
|
|
|
|
if (dryRun) return;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const child = spawn(cmd, args, { stdio: 'inherit' });
|
|
child.on('error', reject);
|
|
child.on('close', code => {
|
|
if (code === 0) resolve();
|
|
else reject(new Error(`${cmd} exited with code ${code}`));
|
|
});
|
|
});
|
|
}
|