* adding promise-based filedescriptor * fixing promisify dep * promisifying shell * deprecating 'exists' method on fs * adding docs * fixing docs * removing redundant code.
This commit is contained in:
parent
de45918cbc
commit
353290a08f
|
@ -3,6 +3,7 @@ bower_components
|
||||||
.env
|
.env
|
||||||
*~
|
*~
|
||||||
dist/filer-issue225.js
|
dist/filer-issue225.js
|
||||||
|
.vscode
|
||||||
|
|
||||||
# Parcel build dirs
|
# Parcel build dirs
|
||||||
.cache
|
.cache
|
||||||
|
|
16
README.md
16
README.md
|
@ -80,6 +80,7 @@ instance. By default, a new [IndexedDB](https://developer.mozilla.org/en/docs/I
|
||||||
database is created for each file system. The file system can also use other
|
database is created for each file system. The file system can also use other
|
||||||
backend storage providers, for example [WebSQL](http://en.wikipedia.org/wiki/Web_SQL_Database)
|
backend storage providers, for example [WebSQL](http://en.wikipedia.org/wiki/Web_SQL_Database)
|
||||||
or even RAM (i.e., for temporary storage). See the section on [Storage Providers](#providers).
|
or even RAM (i.e., for temporary storage). See the section on [Storage Providers](#providers).
|
||||||
|
<a name="overviewExample"></a>
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var fs = new Filer.FileSystem();
|
var fs = new Filer.FileSystem();
|
||||||
|
@ -110,6 +111,21 @@ Like node.js, callbacks for methods that accept them are optional but suggested
|
||||||
you omit the callback, errors will be thrown as exceptions). The first callback parameter is
|
you omit the callback, errors will be thrown as exceptions). The first callback parameter is
|
||||||
reserved for passing errors. It will be `null` if no errors occurred and should always be checked.
|
reserved for passing errors. It will be `null` if no errors occurred and should always be checked.
|
||||||
|
|
||||||
|
#### Support for Promises
|
||||||
|
The Promise based API mimics the way Node [implements](https://nodejs.org/api/fs.html#fs_fs_promises_api) them. Both `Shell` and `FileSystem` now have a `promises` object attached alongside the regular callback style methods. Method names are identical to their callback counterparts with the difference that instead of receiving a final argument as a callback, they return a Promise that is resolved or rejected based on the success of method execution.
|
||||||
|
> Please note that `exists` method will always throw, since it was [deprecated](https://nodejs.org/api/fs.html#fs_fs_exists_path_callback) by Node.
|
||||||
|
|
||||||
|
See example below:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const fs = new Filer.FileSystem().promises;
|
||||||
|
fs.open('/myfile', 'w+')
|
||||||
|
.then(fd => fs.close(fd))
|
||||||
|
.then(() => fs.stat('/myfile'))
|
||||||
|
.then(stats => { console.log(`stats: ${JSON.stringify(stats)}`); })
|
||||||
|
.catch(err => { console.error(err); })
|
||||||
|
```
|
||||||
|
> The callback style usage could be found [here](#overviewExample).
|
||||||
#### Filer.FileSystem(options, callback) constructor
|
#### Filer.FileSystem(options, callback) constructor
|
||||||
|
|
||||||
File system constructor, invoked to open an existing file system or create a new one.
|
File system constructor, invoked to open an existing file system or create a new one.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -35,6 +35,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"base64-arraybuffer": "^0.1.5",
|
"base64-arraybuffer": "^0.1.5",
|
||||||
|
"es6-promisify": "^6.0.0",
|
||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -1901,6 +1901,7 @@ function exists(fs, context, path, callback) {
|
||||||
function cb(err) {
|
function cb(err) {
|
||||||
callback(err ? false : true);
|
callback(err ? false : true);
|
||||||
}
|
}
|
||||||
|
console.warn('This method is deprecated. For more details see https://nodejs.org/api/fs.html#fs_fs_exists_path_callback');// eslint-disable-line no-console
|
||||||
stat(fs, context, path, cb);
|
stat(fs, context, path, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
var _ = require('../../lib/nodash.js');
|
var _ = require('../../lib/nodash.js');
|
||||||
|
var { promisify } = require('es6-promisify');
|
||||||
|
|
||||||
var isNullPath = require('../path.js').isNull;
|
var isNullPath = require('../path.js').isNull;
|
||||||
var nop = require('../shared.js').nop;
|
var nop = require('../shared.js').nop;
|
||||||
|
@ -262,94 +263,97 @@ function FileSystem(options, callback) {
|
||||||
impl.ensureRootDirectory(context, complete);
|
impl.ensureRootDirectory(context, complete);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
FileSystem.prototype.promises = {};
|
||||||
|
/**
|
||||||
|
* Public API for FileSystem
|
||||||
|
*/
|
||||||
|
[
|
||||||
|
'open',
|
||||||
|
'chmod',
|
||||||
|
'fchmod',
|
||||||
|
'chown',
|
||||||
|
'fchown',
|
||||||
|
'close',
|
||||||
|
'mknod',
|
||||||
|
'mkdir',
|
||||||
|
'rmdir',
|
||||||
|
'stat',
|
||||||
|
'fstat',
|
||||||
|
'link',
|
||||||
|
'unlink',
|
||||||
|
'read',
|
||||||
|
'readFile',
|
||||||
|
'write',
|
||||||
|
'writeFile',
|
||||||
|
'appendFile',
|
||||||
|
'exists',
|
||||||
|
'lseek',
|
||||||
|
'readdir',
|
||||||
|
'rename',
|
||||||
|
'readlink',
|
||||||
|
'symlink',
|
||||||
|
'lstat',
|
||||||
|
'truncate',
|
||||||
|
'ftruncate',
|
||||||
|
'utimes',
|
||||||
|
'futimes',
|
||||||
|
'setxattr',
|
||||||
|
'getxattr',
|
||||||
|
'fsetxattr',
|
||||||
|
'fgetxattr',
|
||||||
|
'removexattr',
|
||||||
|
'fremovexattr'
|
||||||
|
].forEach(function(methodName) {
|
||||||
|
FileSystem.prototype[methodName] = function() {
|
||||||
|
var fs = this;
|
||||||
|
var args = Array.prototype.slice.call(arguments, 0);
|
||||||
|
var lastArgIndex = args.length - 1;
|
||||||
|
|
||||||
|
// We may or may not get a callback, and since node.js supports
|
||||||
|
// fire-and-forget style fs operations, we have to dance a bit here.
|
||||||
|
var missingCallback = typeof args[lastArgIndex] !== 'function';
|
||||||
|
var callback = maybeCallback(args[lastArgIndex]);
|
||||||
|
|
||||||
|
var error = fs.queueOrRun(function() {
|
||||||
|
var context = fs.provider.openReadWriteContext();
|
||||||
|
|
||||||
|
// Fail early if the filesystem is in an error state (e.g.,
|
||||||
|
// provider failed to open.
|
||||||
|
if(FS_ERROR === fs.readyState) {
|
||||||
|
var err = new Errors.EFILESYSTEMERROR('filesystem unavailable, operation canceled');
|
||||||
|
return callback.call(fs, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap the callback so we can explicitly close the context
|
||||||
|
function complete() {
|
||||||
|
context.close();
|
||||||
|
callback.apply(fs, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Either add or replace the callback with our wrapper complete()
|
||||||
|
if(missingCallback) {
|
||||||
|
args.push(complete);
|
||||||
|
} else {
|
||||||
|
args[lastArgIndex] = complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward this call to the impl's version, using the following
|
||||||
|
// call signature, with complete() as the callback/last-arg now:
|
||||||
|
// fn(fs, context, arg0, arg1, ... , complete);
|
||||||
|
var fnArgs = [fs, context].concat(args);
|
||||||
|
impl[methodName].apply(null, fnArgs);
|
||||||
|
});
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FileSystem.prototype.promises[methodName] = promisify(FileSystem.prototype[methodName].bind(fs));
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose storage providers on FileSystem constructor
|
// Expose storage providers on FileSystem constructor
|
||||||
FileSystem.providers = providers;
|
FileSystem.providers = providers;
|
||||||
|
|
||||||
/**
|
|
||||||
* Public API for FileSystem
|
|
||||||
*/
|
|
||||||
[
|
|
||||||
'open',
|
|
||||||
'chmod',
|
|
||||||
'fchmod',
|
|
||||||
'chown',
|
|
||||||
'fchown',
|
|
||||||
'close',
|
|
||||||
'mknod',
|
|
||||||
'mkdir',
|
|
||||||
'rmdir',
|
|
||||||
'stat',
|
|
||||||
'fstat',
|
|
||||||
'link',
|
|
||||||
'unlink',
|
|
||||||
'read',
|
|
||||||
'readFile',
|
|
||||||
'write',
|
|
||||||
'writeFile',
|
|
||||||
'appendFile',
|
|
||||||
'exists',
|
|
||||||
'lseek',
|
|
||||||
'readdir',
|
|
||||||
'rename',
|
|
||||||
'readlink',
|
|
||||||
'symlink',
|
|
||||||
'lstat',
|
|
||||||
'truncate',
|
|
||||||
'ftruncate',
|
|
||||||
'utimes',
|
|
||||||
'futimes',
|
|
||||||
'setxattr',
|
|
||||||
'getxattr',
|
|
||||||
'fsetxattr',
|
|
||||||
'fgetxattr',
|
|
||||||
'removexattr',
|
|
||||||
'fremovexattr'
|
|
||||||
].forEach(function(methodName) {
|
|
||||||
FileSystem.prototype[methodName] = function() {
|
|
||||||
var fs = this;
|
|
||||||
var args = Array.prototype.slice.call(arguments, 0);
|
|
||||||
var lastArgIndex = args.length - 1;
|
|
||||||
|
|
||||||
// We may or may not get a callback, and since node.js supports
|
|
||||||
// fire-and-forget style fs operations, we have to dance a bit here.
|
|
||||||
var missingCallback = typeof args[lastArgIndex] !== 'function';
|
|
||||||
var callback = maybeCallback(args[lastArgIndex]);
|
|
||||||
|
|
||||||
var error = fs.queueOrRun(function() {
|
|
||||||
var context = fs.provider.openReadWriteContext();
|
|
||||||
|
|
||||||
// Fail early if the filesystem is in an error state (e.g.,
|
|
||||||
// provider failed to open.
|
|
||||||
if(FS_ERROR === fs.readyState) {
|
|
||||||
var err = new Errors.EFILESYSTEMERROR('filesystem unavailable, operation canceled');
|
|
||||||
return callback.call(fs, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap the callback so we can explicitly close the context
|
|
||||||
function complete() {
|
|
||||||
context.close();
|
|
||||||
callback.apply(fs, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Either add or replace the callback with our wrapper complete()
|
|
||||||
if(missingCallback) {
|
|
||||||
args.push(complete);
|
|
||||||
} else {
|
|
||||||
args[lastArgIndex] = complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward this call to the impl's version, using the following
|
|
||||||
// call signature, with complete() as the callback/last-arg now:
|
|
||||||
// fn(fs, context, arg0, arg1, ... , complete);
|
|
||||||
var fnArgs = [fs, context].concat(args);
|
|
||||||
impl[methodName].apply(null, fnArgs);
|
|
||||||
});
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = FileSystem;
|
module.exports = FileSystem;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
var {promisify} = require('es6-promisify');
|
||||||
var Path = require('../path.js');
|
var Path = require('../path.js');
|
||||||
var Errors = require('../errors.js');
|
var Errors = require('../errors.js');
|
||||||
var Environment = require('./environment.js');
|
var Environment = require('./environment.js');
|
||||||
|
@ -56,6 +57,24 @@ function Shell(fs, options) {
|
||||||
this.pwd = function() {
|
this.pwd = function() {
|
||||||
return cwd;
|
return cwd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.promises = {};
|
||||||
|
/**
|
||||||
|
* Public API for Shell converted to Promise based
|
||||||
|
*/
|
||||||
|
[
|
||||||
|
'cd',
|
||||||
|
'exec',
|
||||||
|
'touch',
|
||||||
|
'cat',
|
||||||
|
'ls',
|
||||||
|
'rm',
|
||||||
|
'tempDir',
|
||||||
|
'mkdirp',
|
||||||
|
'find'
|
||||||
|
].forEach((methodName)=>{
|
||||||
|
this.promises[methodName] = promisify(this[methodName].bind(this));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue