40 lines
1.1 KiB
JavaScript
40 lines
1.1 KiB
JavaScript
import { closeSync, ftruncateSync, openSync, readFileSync, writeSync } from "node:fs";
|
|
|
|
// Keep the merge base and output on the same file even if its pathname changes
|
|
// while audio generation runs. The CLI owns this handle until write or exit.
|
|
export function openAudioMeta(path) {
|
|
let fd;
|
|
try {
|
|
fd = openSync(path, "r+");
|
|
} catch (error) {
|
|
if (error.code !== "ENOENT") throw error;
|
|
}
|
|
let value = {};
|
|
if (fd !== undefined) {
|
|
try {
|
|
value = JSON.parse(readFileSync(fd, "utf8"));
|
|
} catch (error) {
|
|
closeSync(fd);
|
|
throw error;
|
|
}
|
|
}
|
|
return {
|
|
value,
|
|
write(meta) {
|
|
const bytes = Buffer.from(JSON.stringify(meta, null, 2));
|
|
// Defer new-file creation until generation succeeds. Never overwrite a
|
|
// file (or follow a link) that appeared since the missing merge base.
|
|
if (fd === undefined) fd = openSync(path, "wx");
|
|
try {
|
|
let offset = 0;
|
|
while (offset < bytes.length) {
|
|
offset += writeSync(fd, bytes, offset, bytes.length - offset, offset);
|
|
}
|
|
ftruncateSync(fd, bytes.length);
|
|
} finally {
|
|
closeSync(fd);
|
|
}
|
|
},
|
|
};
|
|
}
|