Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise support #403

Merged
merged 4 commits into from Apr 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 16 additions & 25 deletions README.md
@@ -1,7 +1,7 @@
Node.js: fs-extra
=================

`fs-extra` adds file system methods that aren't included in the native `fs` module. It is a drop in replacement for `fs`.
`fs-extra` adds file system methods that aren't included in the native `fs` module and adds promise support to the `fs` methods. It should be a drop in replacement for `fs`.

[![npm Package](https://img.shields.io/npm/v/fs-extra.svg?style=flat-square)](https://www.npmjs.org/package/fs-extra)
[![build status](https://api.travis-ci.org/jprichardson/node-fs-extra.svg)](http://travis-ci.org/jprichardson/node-fs-extra)
Expand Down Expand Up @@ -30,7 +30,7 @@ Installation
Usage
-----

`fs-extra` is a drop in replacement for native `fs`. All methods in `fs` are unmodified and attached to `fs-extra`.
`fs-extra` is a drop in replacement for native `fs`. All methods in `fs` are attached to `fs-extra`. All `fs` methods return promises if the callback isn't passed.

You don't ever need to include the original `fs` module again:

Expand Down Expand Up @@ -60,7 +60,7 @@ const fse = require('fs-extra')

Sync vs Async
-------------
Most methods are async by default (they take a callback with an `Error` as first argument).
Most methods are async by default. All async methods will return a promise if the callback isn't passed.

Sync methods on the other hand will throw if an error occurs.

Expand All @@ -69,14 +69,23 @@ Example:
```js
const fs = require('fs-extra')

// Async with promises:
fs.copy('/tmp/myfile', '/tmp/mynewfile')
.then(() => console.log('success!'))
.catch(err => {
// Handle error
})

// Async with callbacks:
fs.copy('/tmp/myfile', '/tmp/mynewfile', err => {
if (err) return console.error(err)
console.log("success!")
});
console.log('success!')
})

// Sync:
try {
fs.copySync('/tmp/myfile', '/tmp/mynewfile')
console.log("success!")
console.log('success!')
} catch (err) {
console.error(err)
}
Expand Down Expand Up @@ -119,7 +128,7 @@ Methods
- [writeJsonSync](docs/writeJson-sync.md)


**NOTE:** You can still use the native Node.js methods. They are copied over to `fs-extra`.
**NOTE:** You can still use the native Node.js methods. They are promisified and copied over to `fs-extra`.

### What happened to `walk()` and `walkSync()`?

Expand All @@ -129,24 +138,6 @@ They were removed from `fs-extra` in v2.0.0. If you need the functionality, `wal
Third Party
-----------

### Promises

Use [Bluebird](https://github.com/petkaantonov/bluebird). See https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification. `fs-extra` is
explicitly listed as supported.

```js
const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs-extra'))
```

Or you can use a dedicated package:

- [`fs-extra-promise`](https://github.com/overlookmotel/fs-extra-promise) uses Bluebird.
- [`fs-promise`](https://github.com/kevinbeaty/fs-promise) uses
[Any Promise](https://github.com/kevinbeaty/any-promise) and also covers
[`mz/fs`](https://github.com/normalize/mz/blob/master/fs.js).
- [`fs-p`](https://github.com/grammarly/fs-p) - TypeScript-friendly promises implementation


### TypeScript

Expand Down
11 changes: 10 additions & 1 deletion docs/copy.md
@@ -1,4 +1,4 @@
# copy(src, dest, [options], callback)
# copy(src, dest, [options, callback])

Copy a file or directory. The directory can have contents. Like `cp -r`.

Expand Down Expand Up @@ -28,6 +28,15 @@ fs.copy('/tmp/mydir', '/tmp/mynewdir', err => {

console.log('success!')
}) // copies directory, even if it has subdirectories or files

// Promise usage:
fs.copy('/tmp/myfile', '/tmp/mynewfile')
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```

**Using filter function**
Expand Down
9 changes: 9 additions & 0 deletions docs/emptyDir.md
Expand Up @@ -18,4 +18,13 @@ fs.emptyDir('/tmp/some/dir', err => {

console.log('success!')
})

// With promises
fs.emptyDir('/tmp/some/dir')
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```
11 changes: 10 additions & 1 deletion docs/ensureDir.md
@@ -1,4 +1,4 @@
# ensureDir(dir, callback)
# ensureDir(dir, [callback])

Ensures that the directory exists. If the directory structure does not exist, it is created. Like `mkdir -p`.

Expand All @@ -17,4 +17,13 @@ fs.ensureDir(dir, err => {
console.log(err) // => null
// dir has now been created, including the directory it is to be placed in
})

// With Promises:
fs.ensureDir(dir)
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```
11 changes: 10 additions & 1 deletion docs/ensureFile.md
@@ -1,4 +1,4 @@
# ensureFile(file, callback)
# ensureFile(file, [callback])

Ensures that the file exists. If the file that is requested to be created is in directories that do not exist, these directories are created. If the file already exists, it is **NOT MODIFIED**.

Expand All @@ -17,4 +17,13 @@ fs.ensureFile(file, err => {
console.log(err) // => null
// file has now been created, including the directory it is to be placed in
})

// With Promises:
fs.ensureFile(file)
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```
11 changes: 10 additions & 1 deletion docs/ensureLink.md
@@ -1,4 +1,4 @@
# ensureLink(srcpath, dstpath, callback)
# ensureLink(srcpath, dstpath, [callback])

Ensures that the link exists. If the directory structure does not exist, it is created.

Expand All @@ -17,4 +17,13 @@ fs.ensureLink(srcpath, dstpath, err => {
console.log(err) // => null
// link has now been created, including the directory it is to be placed in
})

// With Promises:
fs.ensureLink(srcpath, dstpath)
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```
11 changes: 10 additions & 1 deletion docs/ensureSymlink.md
@@ -1,4 +1,4 @@
# ensureSymlink(srcpath, dstpath, [type], callback)
# ensureSymlink(srcpath, dstpath, [type, callback])

Ensures that the symlink exists. If the directory structure does not exist, it is created.

Expand All @@ -18,4 +18,13 @@ fs.ensureSymlink(srcpath, dstpath, err => {
console.log(err) // => null
// symlink has now been created, including the directory it is to be placed in
})

// With Promises:
fs.ensureSymlink(srcpath, dstpath)
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```
10 changes: 9 additions & 1 deletion docs/move.md
@@ -1,4 +1,4 @@
# move(src, dest, [options], callback)
# move(src, dest, [options, callback])

Moves a file or directory, even across devices.

Expand All @@ -18,6 +18,14 @@ fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile', err => {

console.log('success!')
})

fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile')
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```

**Using `overwrite` option**
Expand Down
12 changes: 11 additions & 1 deletion docs/outputFile.md
@@ -1,4 +1,4 @@
# outputFile(file, data, [options], callback)
# outputFile(file, data, [options, callback])

Almost the same as `writeFile` (i.e. it [overwrites](http://pages.citebite.com/v2o5n8l2f5reb)), except that if the parent directory does not exist, it's created. `file` must be a file path (a buffer or a file descriptor is not allowed). `options` are what you'd pass to [`fs.writeFile()`](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback).

Expand All @@ -20,4 +20,14 @@ fs.outputFile(file, 'hello!', err => {
console.log(data) // => hello!
})
})

// With Promises:
fs.outputFile(file, 'hello!')
.then(() => fs.readFile(file, 'utf8'))
.then(data => {
console.log(data) // => hello!
})
.catch(err => {
// handle error
})
```
12 changes: 11 additions & 1 deletion docs/outputJson.md
@@ -1,4 +1,4 @@
# outputJson(file, object, [options], callback)
# outputJson(file, object, [options, callback])

Almost the same as [`writeJson`](writeJson.md), except that if the directory does not exist, it's created.
`options` are what you'd pass to [`jsonFile.writeFile()`](https://github.com/jprichardson/node-jsonfile#writefilefilename-options-callback).
Expand All @@ -23,4 +23,14 @@ fs.outputJson(file, {name: 'JP'}, err => {
console.log(data.name) // => JP
})
})

// With Promises:
fs.outputJson(file, {name: 'JP'})
.then(() => fs.readJson(file))
.then(data => {
console.log(data.name) // => JP
})
.catch(err => {
// handle error
})
```
22 changes: 20 additions & 2 deletions docs/readJson.md
@@ -1,4 +1,4 @@
# readJson(file, [options], callback)
# readJson(file, [options, callback])

Reads a JSON file and then parses it into an object. `options` are the same
that you'd pass to [`jsonFile.readFile`](https://github.com/jprichardson/node-jsonfile#readfilefilename-options-callback).
Expand All @@ -16,9 +16,18 @@ const fs = require('fs-extra')

fs.readJson('./package.json', (err, packageObj) => {
if (err) console.error(err)

console.log(packageObj.version) // => 0.1.3
})

// Promise Usage
fs.readJson('./package.json')
.then(packageObj => {
console.log(packageObj.version) // => 0.1.3
})
.catch(err => {
// handle error
})
```

---
Expand All @@ -37,4 +46,13 @@ fs.readJson(file, { throws: false }, (err, obj) => {

console.log(obj) // => null
})

// Promise Usage
fs.readJson(file, { throws: false })
.then(obj => {
console.log(obj) // => null
})
.catch(err => {
// Not called
})
```
11 changes: 10 additions & 1 deletion docs/remove.md
@@ -1,4 +1,4 @@
# remove(path, callback)
# remove(path, [callback])

Removes a file or directory. The directory can have contents. Like `rm -rf`.

Expand All @@ -22,4 +22,13 @@ fs.remove('/home/jprichardson', err => {

console.log('success!') // I just deleted my entire HOME directory.
})

// Promise Usage
fs.remove('/tmp/myfile')
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```
11 changes: 10 additions & 1 deletion docs/writeJson.md
@@ -1,4 +1,4 @@
# writeJson(file, object, [options], callback)
# writeJson(file, object, [options, callback])

Writes an object to a JSON file. `options` are the same that
you'd pass to [`jsonFile.writeFile()`](https://github.com/jprichardson/node-jsonfile#writefilefilename-options-callback).
Expand All @@ -20,6 +20,15 @@ fs.writeJson('./package.json', {name: 'fs-extra'}, err => {

console.log('success!')
})

// With Promises
fs.writeJson('./package.json', {name: 'fs-extra'})
.then(() => {
console.log('success!')
})
.catch(err => {
// handle error
})
```

---
Expand Down
29 changes: 29 additions & 0 deletions lib/__tests__/promise.test.js
@@ -0,0 +1,29 @@
'use strict'

/* eslint-env mocha */

const fse = require('..')

const methods = [
'copy',
'emptyDir',
'ensureFile',
'ensureDir',
'ensureLink',
'ensureSymlink',
'mkdirs',
'move',
'readJson',
'readJSON',
'remove',
'writeJson',
'writeJSON'
]

describe('promise support', () => {
methods.forEach(method => {
it(method, done => {
fse[method]().catch(() => done())
})
})
})
3 changes: 2 additions & 1 deletion lib/copy/index.js
@@ -1,3 +1,4 @@
const u = require('universalify').fromCallback
module.exports = {
copy: require('./copy')
copy: u(require('./copy'))
}