diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..8c52ff9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100755 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..62562b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +coverage +node_modules diff --git a/.travis.yml b/.travis.yml new file mode 100755 index 0000000..29b9328 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +sudo: false +git: + depth: 1 +branches: + except: /^v\d/ +language: node_js +node_js: stable +script: + - npm run-script pretest + - npm run-script coverage +after_script: + - npm install istanbul-coveralls + - node node_modules/.bin/istanbul-coveralls +notifications: + email: false diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a469a41 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Shinnosuke Watanabe + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100755 index 0000000..eecbcbe --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +# realpaths + +[![NPM version](https://img.shields.io/npm/v/realpaths.svg)](https://www.npmjs.com/package/realpaths) +[![Build Status](https://travis-ci.org/shinnn/realpaths.svg?branch=master)](https://travis-ci.org/shinnn/realpaths) +[![Coverage Status](https://img.shields.io/coveralls/shinnn/realpaths.svg)](https://coveralls.io/github/shinnn/realpaths) +[![Dependency Status](https://david-dm.org/shinnn/realpaths.svg)](https://david-dm.org/shinnn/realpaths) +[![devDependency Status](https://david-dm.org/shinnn/realpaths/dev-status.svg)](https://david-dm.org/shinnn/realpaths#info=devDependencies) + +Like [fs.realpath][realpath], but resolves multiple paths at once + +```javascript +const realpaths = require('realpaths'); + +// symlink1 <<===>> /path/to/foo.txt +// symlink2 <<===>> /path/to/bar.txt + +realpaths(['symlink1', 'symlink2']).then(paths => { + paths; //=> ['/path/to/foo.txt', '/path/to/bar.txt'] +}); +``` + +## Installation + +[Use npm.](https://docs.npmjs.com/cli/install) + +``` +npm install realpaths +``` + +## API + +```javascript +const realpaths = require('realpaths'); +``` + +### realpaths(*paths* [, *cache*]) + +*paths*: `Array` of strings (file paths) +*options*: `Object` (used as [`fs.realpath`](https://github.com/nodejs/node/blob/c339fa36f5493c2bd2e108463910122ef82843c4/lib/fs.js#L1568-L1570) cache) +Return: [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise) instance + +It runs [`fs.realpath`][realpath] for each path and returns a `Promise` instance. + +When it finishes resolving all paths, it will be [fulfilled](https://promisesaplus.com/#point-26) with an array of resolved paths. + +When it fails to resolve at least one of the paths, it will be [rejected](https://promisesaplus.com/#point-30). + +```javascript +'use strict'; + +const path = require('path'); +const realpaths = require('realpaths-callback'); + +realpaths(['symlink1', 'symlink2'], { + cache: { + [path.resolve('symlink1')]: '/path/to/foo.txt', + [path.resolve('symlink2')]: '/path/to/bar.txt' + } +}).then(paths => { + paths; //=> ['/path/to/foo.txt', '/path/to/bar.txt'] +}); +``` + +## Related projects + +* [realpaths-callback](https://github.com/shinnn/realpaths-callback) ([Callback](http://thenodeway.io/posts/understanding-error-first-callbacks/)-style version) + +## License + +Copyright (c) 2015 [Shinnosuke Watanabe](https://github.com/shinnn) + +Licensed under [the MIT License](./LICENSE). + +[realpath]: https://nodejs.org/api/fs.html#fs_fs_realpath_path_cache_callback diff --git a/index.js b/index.js new file mode 100755 index 0000000..6855782 --- /dev/null +++ b/index.js @@ -0,0 +1,20 @@ +/*! + * realpaths | MIT (c) Shinnosuke Watanabe + * https://github.com/shinnn/realpaths +*/ +'use strict'; + +const reapathsCallback = require('realpaths-callback'); + +module.exports = function realpaths(paths, cache) { + return new Promise(function executor(resolve, reject) { + reapathsCallback(paths, cache, function callback(err, results) { + if (err) { + reject(err); + return; + } + + resolve(results); + }); + }); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..e3ac9c9 --- /dev/null +++ b/package.json @@ -0,0 +1,46 @@ +{ + "name": "realpaths", + "version": "1.0.0", + "description": "Like [fs.realpath][realpath], but resolves multiple paths at once", + "repository": "shinnn/realpaths", + "author": "Shinnosuke Watanabe (https://github.com/shinnn)", + "scripts": { + "pretest": "eslint --config @shinnn/node index.js test.js", + "test": "node --strong_mode test.js", + "coverage": "node --strong_mode node_modules/.bin/istanbul cover test.js" + }, + "license": "MIT", + "files": [ + "index.js" + ], + "keywords": [ + "file", + "files", + "fs", + "path", + "paths", + "realpath", + "resolve", + "absolute", + "canonical", + "multi", + "multiple", + "array", + "then", + "promise", + "promises", + "async", + "asynchronous", + "asynchronously" + ], + "dependencies": { + "realpaths-callback": "^1.0.0" + }, + "devDependencies": { + "@shinnn/eslint-config-node": "^1.0.1", + "eslint": "^1.8.0", + "graceful-fs": "^4.1.2", + "istanbul": "^0.4.0", + "tape": "^4.2.2" + } +} diff --git a/test.js b/test.js new file mode 100755 index 0000000..05b4272 --- /dev/null +++ b/test.js @@ -0,0 +1,30 @@ +'use strict'; + +const assert = require('assert'); +const path = require('path'); + +const fs = require('graceful-fs'); +const realpaths = require('.'); +const test = require('tape'); + +fs.symlink(__filename, 'tmp', symlinkErr => { + assert.ifError(symlinkErr); + + test('realpaths()', t => { + t.plan(3); + + t.equal(realpaths.name, 'realpaths', 'should have a function name.'); + + realpaths(['tmp']).then(paths => { + t.deepEqual(paths, [__filename], 'should expand symbolic links.'); + }).catch(t.fail); + + realpaths(['foo', 'tmp', 'bar'], {[path.resolve('foo')]: '/foo'}).then(t.fail, err => { + t.equal(err.path, path.resolve('bar'), 'should fail when it cannot resolve paths.'); + }).catch(t.fail); + + t.on('end', () => fs.unlink('tmp', unlinkErr => { + assert.ifError(unlinkErr); + })); + }); +});