web-ext-run
Version:
A tool to open and run web extensions
124 lines (117 loc) • 3.13 kB
JavaScript
import { promisify } from 'util';
import tmp from 'tmp';
import { createLogger } from './logger.js';
import { multiArgsPromisedFn, promisifyCustom } from './promisify.js';
const log = createLogger(import.meta.url);
tmp.dir[promisifyCustom] = multiArgsPromisedFn(tmp.dir);
const createTempDir = promisify(tmp.dir);
/*
* Work with a self-destructing temporary directory in a promise chain.
*
* The directory will be destroyed when the promise chain is finished
* (whether there was an error or not).
*
* Usage:
*
* withTempDir(
* (tmpDir) =>
* doSomething(tmpDir.path())
* .then(...)
* );
*
*/
export function withTempDir(makePromise) {
const tmpDir = new TempDir();
return tmpDir.create().then(() => {
return makePromise(tmpDir);
}).catch(tmpDir.errorHandler()).then(tmpDir.successHandler());
}
/*
* Work with a self-destructing temporary directory object.
*
* It is safer to use withTempDir() instead but if you know
* what you're doing you can use it directly like:
*
* let tmpDir = new TempDir();
* tmpDir.create()
* .then(() => {
* // work with tmpDir.path()
* })
* .catch(tmpDir.errorHandler())
* .then(tmpDir.successHandler());
*
*/
export class TempDir {
_path;
_removeTempDir;
constructor() {
this._path = undefined;
this._removeTempDir = undefined;
}
/*
* Returns a promise that is fulfilled when the temp directory has
* been created.
*/
create() {
return createTempDir({
prefix: 'tmp-web-ext-',
// This allows us to remove a non-empty tmp dir.
unsafeCleanup: true
}).then(([tmpPath, removeTempDir]) => {
this._path = tmpPath;
this._removeTempDir = () => new Promise((resolve, reject) => {
// `removeTempDir` parameter is a `next` callback which
// is called once the dir has been removed.
const next = err => err ? reject(err) : resolve();
removeTempDir(next);
});
log.debug(`Created temporary directory: ${this.path()}`);
return this;
});
}
/*
* Get the absolute path of the temp directory.
*/
path() {
if (!this._path) {
throw new Error('You cannot access path() before calling create()');
}
return this._path;
}
/*
* Returns a callback that will catch an error, remove
* the temporary directory, and throw the error.
*
* This is intended for use in a promise like
* Promise().catch(tmp.errorHandler())
*/
errorHandler() {
return async error => {
await this.remove();
throw error;
};
}
/*
* Returns a callback that will remove the temporary direcotry.
*
* This is intended for use in a promise like
* Promise().then(tmp.successHandler())
*/
successHandler() {
return async promiseResult => {
await this.remove();
return promiseResult;
};
}
/*
* Remove the temp directory.
*/
remove() {
if (!this._removeTempDir) {
return;
}
log.debug(`Removing temporary directory: ${this.path()}`);
return this._removeTempDir && this._removeTempDir();
}
}
//# sourceMappingURL=temp-dir.js.map