Files
MangaCircus/scraper/lib/json-file.js

31 lines
1.2 KiB
JavaScript

'use strict';
const fs = require('fs').promises;
const path = require('path');
const crypto = require('crypto');
async function writeJsonAtomic(file, value, io = fs) {
const folder = path.dirname(file), name = path.basename(file);
const temp = path.join(folder, `.${name}.${crypto.randomUUID()}.tmp`);
await io.writeFile(temp, JSON.stringify(value, null, 2) + '\n');
try {
try { await io.rename(temp, file); return; }
catch (error) {
if (!['EPERM', 'EACCES', 'EBUSY', 'EEXIST'].includes(error.code)) throw error;
}
// Windows may refuse rename-over-existing. Keep the old JSON recoverable
// until the replacement is safely in place; never delete it first.
const backup = path.join(folder, `.old-${name}-${crypto.randomUUID()}`);
await io.rename(file, backup);
try { await io.rename(temp, file); }
catch (error) {
try { await io.rename(backup, file); }
catch (restoreError) { error.message += `; previous JSON remains at ${backup}: ${restoreError.message}`; }
throw error;
}
await io.rm(backup, { force: true });
} finally { await io.rm(temp, { force: true }); }
}
module.exports = { writeJsonAtomic };