diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2eab8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history diff --git a/README.md b/README.md new file mode 100644 index 0000000..fa87476 --- /dev/null +++ b/README.md @@ -0,0 +1,277 @@ +# tmp-promise + +A simple utility for creating temporary files or directories. + +The [tmp](https://github.com/raszi/node-tmp) package with promises support. + +This documentation is mostly copied from that package's - but with promise usage instead of callback usage adapted. + +## About + +This adds promises support to a [widely used library][2]. This package is used to create temporary files and directories in a [node.js][1] environment. + +Tmp-promise offers both an asynchronous and a synchronous API. For all API calls, all +the parameters are optional. + +Internally, tmp uses crypto for determining random file names, or, when using templates, a six letter random identifier. And just in case that you do not have that much entropy left on your system, Tmp will fall back to pseudo random numbers. + +You can set whether you want to remove the temporary file on process exit or not, and the destination directory can also be set. + +Tmp-promise also uses promise disposers to provide a nice way to perform cleanup when you're done working with the files. + +## Usage (API Reference) + +### Asynchronous file creation + +Simple temporary file creation, the file will be closed and unlinked on process exit. + +```javascript +var tmp = require('tmp-promise'); + +tmp.file().then(o => { + console.log("File: ", o.path); + console.log("Filedescriptor: ", o.fd); + + // If we don't need the file anymore we could manually call cleanup + // But that is not necessary if we didn't pass the keep option because the library + // will clean after itself. + cleanup(); +}); +``` + +Simple temporary file creation with a disposer: + +```js +tmp.withFile(o => { + console.log("File: ", o.path); + console.log("Filedescriptor: ", o.fd); + // the file remains opens until the below promise resolves + return somePromiseReturningFn(); +}).then(v => { + // file is closed here automatically, v is the value of somePromiseReturningFn +}); +``` + + +### Synchronous file creation + +A synchronous version of the above. + +```javascript +var tmp = require('tmp-promise'); + +var tmpobj = tmp.fileSync(); +console.log("File: ", tmpobj.name); +console.log("Filedescriptor: ", tmpobj.fd); + +// If we don't need the file anymore we could manually call the removeCallback +// But that is not necessary if we didn't pass the keep option because the library +// will clean after itself. +tmpobj.removeCallback(); +``` + +Note that this might throw an exception if either the maximum limit of retries +for creating a temporary name fails, or, in case that you do not have the permission +to write to the directory where the temporary file should be created in. + +### Asynchronous directory creation + +Simple temporary directory creation, it will be removed on process exit. + +If the directory still contains items on process exit, then it won't be removed. + +```javascript +var tmp = require('tmp-promise'); + +tmp.dir().then(o => { + console.log("Dir: ", path); + + // Manual cleanup + o.cleanup(); +}); +``` + +If you want to cleanup the directory even when there are entries in it, then +you can pass the `unsafeCleanup` option when creating it. + +You can also use a disposer here which takes care of cleanup automatically: + +```javascript +var tmp = require('tmp-promise'); + +tmp.withDir(o => { + console.log("Dir: ", path); + + // automatic cleanup when the below promise resolves + return somePromiseReturningFn(); +}).then(v => { + // the directory has been cleaned here +}); +``` + +### Synchronous directory creation + +A synchronous version of the above. + +```javascript +var tmp = require('tmp-promise'); + +var tmpobj = tmp.dirSync(); +console.log("Dir: ", tmpobj.name); +// Manual cleanup +tmpobj.removeCallback(); +``` + +Note that this might throw an exception if either the maximum limit of retries +for creating a temporary name fails, or, in case that you do not have the permission +to write to the directory where the temporary directory should be created in. + +### Asynchronous filename generation + +It is possible with this library to generate a unique filename in the specified +directory. + +```javascript +var tmp = require('tmp-promise'); + +tmp.tmpName().then(path => + console.log("Created temporary filename: ", path); +}); +``` + +### Synchronous filename generation + +A synchronous version of the above. + +```javascript +var tmp = require('tmp-promise'); + +var name = tmp.tmpNameSync(); +console.log("Created temporary filename: ", name); +``` + +## Advanced usage + +### Asynchronous file creation + +Creates a file with mode `0644`, prefix will be `prefix-` and postfix will be `.txt`. + +```javascript +var tmp = require('tmp-promise'); + +tmp.file({ mode: 0644, prefix: 'prefix-', postfix: '.txt' }).then(o => { + console.log("File: ", o.path); + console.log("Filedescriptor: ", o.fd); +}); +``` + +### Synchronous file creation + +A synchronous version of the above. + +```javascript +var tmp = require('tmp-promise'); + +var tmpobj = tmp.fileSync({ mode: 0644, prefix: 'prefix-', postfix: '.txt' }); +console.log("File: ", tmpobj.name); +console.log("Filedescriptor: ", tmpobj.fd); +``` + +### Asynchronous directory creation + +Creates a directory with mode `0755`, prefix will be `myTmpDir_`. + +```javascript +var tmp = require('tmp-promise'); + +tmp.dir({ mode: 0750, prefix: 'myTmpDir_' }).then(o => { + console.log("Dir: ", o.path); +}); +``` + +### Synchronous directory creation + +Again, a synchronous version of the above. + +```javascript +var tmp = require('tmp-promise'); + +var tmpobj = tmp.dirSync({ mode: 0750, prefix: 'myTmpDir_' }); +console.log("Dir: ", tmpobj.name); +``` + + +### mkstemps like, asynchronously + +Creates a new temporary directory with mode `0700` and filename like `/tmp/tmp-nk2J1u`. + +```javascript +var tmp = require('tmp-promise'); +tmp.dir({ template: '/tmp/tmp-XXXXXX' }).then(console.log); +``` + + +### mkstemps like, synchronously + +This will behave similarly to the asynchronous version. + +```javascript +var tmp = require('tmp-promise'); + +var tmpobj = tmp.dirSync({ template: '/tmp/tmp-XXXXXX' }); +console.log("Dir: ", tmpobj.name); +``` + +### Asynchronous filename generation + +The `tmpName()` function accepts the `prefix`, `postfix`, `dir`, etc. parameters also: + +```javascript +var tmp = require('tmp-promise'); + +tmp.tmpName({ template: '/tmp/tmp-XXXXXX' }).then(path => + console.log("Created temporary filename: ", path); +); +``` + +### Synchronous filename generation + +The `tmpNameSync()` function works similarly to `tmpName()`. + +```javascript +var tmp = require('tmp-promise'); +var tmpname = tmp.tmpNameSync({ template: '/tmp/tmp-XXXXXX' }); +console.log("Created temporary filename: ", tmpname); +``` + + +## Graceful cleanup + +One may want to cleanup the temporary files even when an uncaught exception +occurs. To enforce this, you can call the `setGracefulCleanup()` method: + +```javascript +var tmp = require('tmp'); + +tmp.setGracefulCleanup(); +``` + +## Options + +All options are optional :) + + * `mode`: the file mode to create with, it fallbacks to `0600` on file creation and `0700` on directory creation + * `prefix`: the optional prefix, fallbacks to `tmp-` if not provided + * `postfix`: the optional postfix, fallbacks to `.tmp` on file creation + * `template`: [`mkstemps`][3] like filename template, no default + * `dir`: the optional temporary directory, fallbacks to system default (guesses from environment) + * `tries`: how many times should the function try to get a unique filename before giving up, default `3` + * `keep`: signals that the temporary file or directory should not be deleted on exit, default is `false`, means delete + * Please keep in mind that it is recommended in this case to call the provided `cleanupCallback` function manually. + * `unsafeCleanup`: recursively removes the created temporary directory, even when it's not empty. default is `false` + + + +[1]: http://nodejs.org/ +[2]: https://www.npmjs.com/browse/depended/tmp +[3]: http://www.kernel.org/doc/man-pages/online/pages/man3/mkstemp.3.html diff --git a/example-usage.js b/example-usage.js new file mode 100644 index 0000000..1ea9ca5 --- /dev/null +++ b/example-usage.js @@ -0,0 +1,9 @@ +var tmp = require("./index.js"); +var Promise = require("bluebird"); // just for delay, this works with native promises +// disposer +tmp.withFile((path) => { + console.log("Created at path", path); + return Promise.delay(1000); +}).then(() => { + console.log("File automatically disposed"); +}); \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..8eb4333 --- /dev/null +++ b/index.js @@ -0,0 +1,49 @@ +var tmp = require("tmp"); +var Promise = require("bluebird"); + + +// file +module.exports.fileSync = tmp.fileSync; +var file = Promise.promisify(tmp.file, {multiArgs: true}); +module.exports.file = function file$promise() { + return file.apply(tmp, arguments).spread(function (path, fd, cleanup) { + return {path: path, fd: fd, cleanup : cleanup }; + }); +}; + +module.exports.withFile = function withFile(fn) { + var cleanup; + return module.exports.file.apply(tmp, arguments).then(function context(o) { + cleanup = o.cleanup; + delete o.cleanup; + return fn(o); + }).finally(cleanup); +} + +// directory +module.exports.dirSync = tmp.dirSync; +var dir = Promise.promisify(tmp.dir, {multiArgs: true}); +module.exports.dir = function dir$promise() { + return dir.apply(tmp, arguments).spread(function (path, fd, cleanup) { + return {path: path, fd: fd, cleanup : cleanup }; + }); +} + +module.exports.withDir = function withDir(fn) { + var cleanup; + return module.exports.dir.apply(tmp, arguments).then(function context(o) { + cleanup = o.cleanup; + delete o.cleanup; + return fn(o); + }).finally(cleanup); +} + +// name generation +module.exports.tmpNameSync = tmp.tmpNameSync; +module.exports.tmpName = Promise.promisify(tmp.tmpName); + + +module.exports.tmpdir = tmp.tmpdir; + + +module.exports.setGracefulCleanup = tmp.setGracefulCleanup; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..ba83fdd --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "tmp-promise", + "version": "1.0.0", + "description": "The tmp package with promises support and disposers.", + "main": "index.js", + "scripts": { + "test": "" + }, + "keywords": [ + "tmp", + "promise", + "tempfile", + "mkdtemp", + "mktemp" + ], + "author": "Benjamin Gruenbaum", + "license": "MIT", + "dependencies": { + "bluebird": "^3.3.1", + "tmp": "0.0.28" + } +}