import fs from 'fs'; import {join} from 'path'; import {tmpdir} from 'os'; import {promisify} from 'util'; import tmp from 'tmp'; import mkdirp from 'mkdirp'; import esMain from 'es-main'; const removeCallbacks = []; const open = promisify(fs.open); const close = promisify(fs.close); const exists = promisify(fs.exists); const unlink = promisify(fs.unlink); function garbageCollector() { while (removeCallbacks.length) removeCallbacks.shift()(); process.removeListener('exit', garbageCollector); } let hookedUpListeners = false; function hookupListeners() { if (!hookedUpListeners) { hookedUpListeners = true; process.addListener('exit', garbageCollector); } } export default async function genFile(opts) { opts = opts || {}; if (opts.filename) { opts.tmpdir = opts.tmpdir || tmpdir(); if (!(await exists(opts.tmpdir))) throw new Error('tmpdir does not exist'); const dir = join(opts.tmpdir, opts.dirname || '.'); await mkdirp(dir); const name = join(dir, opts.filename); const fd = await open(name, fs.constants.O_CREAT); hookupListeners(); let closed = false; const garbageHandler = () => { if (closed) return; fs.closeSync(fd); closed = true; if (!opts.keep) fs.unlinkSync(name); }; removeCallbacks.unshift(garbageHandler); return { fd, name, removeCallback: async () => { if (closed) return; await close(fd); closed = true; await unlink(name); removeCallbacks.splice(removeCallbacks.indexOf(garbageHandler), 1); }, }; } return new Promise((res, rej) => tmp.file(opts, (err, name, fd, removeCallback) => (err ? rej(err) : res({fd, name, removeCallback}))), ); } async function test() { const filename = 'freyr_mgr_temp_file'; async function testMgr() { const file = await genFile({filename}); console.log('mgr>', file); file.removeCallback(); } async function testTmp() { const file = await genFile({name: filename}); console.log('tmp>', file); file.removeCallback(); } await testMgr(); await testTmp(); } if (esMain(import.meta)) test().catch(err => console.error('cli>', err));