Add Filer.fs to support creating a filesystem like node.js (#651)

* Add Filer.fs to support

* Update README code examples, add tests, also expose Path as path
This commit is contained in:
David Humphrey 2019-01-02 21:21:25 -05:00 committed by GitHub
parent 85a8c21dc1
commit f4ff2e9ed9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 18 deletions

View File

@ -81,14 +81,27 @@ backend storage providers, for example `Memory`. See the section on [Storage Pro
<a name="overviewExample"></a> <a name="overviewExample"></a>
```js ```js
var fs = new Filer.FileSystem(); const { fs, path } = require('filer');
fs.open('/myfile', 'w+', function(err, fd) {
if (err) throw err; fs.mkdir('/docs', (err) => {
fs.close(fd, function(err) { if (err) {
if (err) throw err; return console.error('Unable to create /docs dir', err);
fs.stat('/myfile', function(err, stats) { }
if (err) throw err;
console.log('stats: ' + JSON.stringify(stats)); const filename = path.join('/docs', 'first.txt');
const data = 'Hello World!\n';
fs.writeFile(filename, data, (err) => {
if (err) {
return console.error('Unable to write /docs/first.txt', err);
}
fs.stat(filename, (err, stats) => {
if (err) {
return console.error('Unable to stat /docs/first.txt', err);
}
console.log('Stats for /docs/first.txt:', stats);
}); });
}); });
}); });
@ -125,9 +138,13 @@ fs.writeFile('/myfile', 'some data')
#### 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. In most cases, using `Filer.fs` will be sufficient, and provide a working filesystem.
Accepts two arguments: an `options` object, and an optional `callback`. The `options` However, if you need more control over the filesystem, you can also use the `FileSystem`
object can specify a number of optional arguments, including: constructor, invoked to open an existing file system or create a new one.
`Filer.FileSystem()` It accepts two arguments: an `options` object, and an optional
`callback` function. The `options` object can specify a number of optional arguments,
including:
* `name`: the name of the file system, defaults to `'"local'` * `name`: the name of the file system, defaults to `'"local'`
* `flags`: an Array of one or more flags to use when creating/opening the file system: * `flags`: an Array of one or more flags to use when creating/opening the file system:
@ -228,15 +245,16 @@ Buffer.allocUnsafe(size)
#### Filer.Path<a name="FilerPath"></a> #### Filer.Path<a name="FilerPath"></a>
The node.js [path module](http://nodejs.org/api/path.html) is available via the `Filer.Path` object. It is The node.js [path module](http://nodejs.org/api/path.html) is available via `Filer.path` or
identical to the node.js (see [https://github.com/browserify/path-browserify](https://github.com/browserify/path-browserify)) version with the following differences: `Filer.Path` (both are supported for historical reasons, and to match node). The Filer `path`
module is identical to the node.js version (see [https://github.com/browserify/path-browserify](https://github.com/browserify/path-browserify)), with the following differences:
* The CWD always defaults to `/` * The CWD always defaults to `/`
* No support for Windows style paths (assume you are on a POSIX system) * No support for Windows style paths (assume you are on a POSIX system)
* Additional utility methods (see below) * Additional utility methods (see below)
```javascript ```javascript
var path = Filer.Path; var path = Filer.path;
var dir = path.dirname('/foo/bar/baz/asdf/quux'); var dir = path.dirname('/foo/bar/baz/asdf/quux');
// dir is now '/foo/bar/baz/asdf' // dir is now '/foo/bar/baz/asdf'
@ -324,7 +342,11 @@ Once a `FileSystem` is created, it has the following methods. NOTE: code example
a `FileSystem` instance named `fs` has been created like so: a `FileSystem` instance named `fs` has been created like so:
```javascript ```javascript
var fs = new Filer.FileSystem(); // 1. Using Filer.fs for a default filesystem
const { fs } = require('filer');
// 2. Or via the FileSystem constructor with specified options
const fs = new Filer.FileSystem(options, callback);
``` ```
* [fs.rename(oldPath, newPath, callback)](#rename) * [fs.rename(oldPath, newPath, callback)](#rename)

View File

@ -1,7 +1,24 @@
module.exports = { let fs = null;
let Filer = null;
module.exports = Filer = {
FileSystem: require('./filesystem/interface.js'), FileSystem: require('./filesystem/interface.js'),
Buffer: Buffer, Buffer: Buffer,
// We previously called this Path, but node calls it path. Do both
Path: require('./path.js'), Path: require('./path.js'),
path: require('./path.js'),
Errors: require('./errors.js'), Errors: require('./errors.js'),
Shell: require('./shell/shell.js') Shell: require('./shell/shell.js')
}; };
// Add a getter for the `fs` instance, which returns
// a Filer FileSystem instance, using the default provider/flags.
Object.defineProperty(Filer, 'fs', {
enumerable: true,
get() {
if(!fs) {
fs = new Filer.FileSystem();
}
return fs;
}
});

View File

@ -85,3 +85,6 @@ require('./bugs/issue267.js');
require('./bugs/issue270.js'); require('./bugs/issue270.js');
require('./bugs/rename-dir-trailing-slash.js'); require('./bugs/rename-dir-trailing-slash.js');
require('./bugs/issue357.js'); require('./bugs/issue357.js');
// Sample code from README
require('./spec/readme.example.spec');

View File

@ -10,6 +10,37 @@ describe('Filer', function() {
expect(typeof Filer.FileSystem).to.equal('function'); expect(typeof Filer.FileSystem).to.equal('function');
}); });
it('has Buffer constructor', function() {
expect(typeof Filer.Buffer).to.equal('function');
});
it('has Path and path objects', function() {
expect(typeof Filer.Path).to.equal('object');
expect(typeof Filer.path).to.equal('object');
expect(Filer.Path).to.equal(Filer.path);
});
it('has Errors object', function() {
expect(typeof Filer.Errors).to.equal('object');
});
it('has an fs object that returns a Filer.FileSystem', function() {
// Depends on IndexedDB being available, since we can't
// configure our own test provider.
if(!Filer.FileSystem.providers.IndexedDB.isSupported()) {
this.skip();
}
expect(typeof Filer.fs).to.equal('object');
const fs1 = Filer.fs;
const fs2 = Filer.fs;
expect(fs1).to.be.an.instanceof(Filer.FileSystem);
expect(fs2).to.be.an.instanceof(Filer.FileSystem);
expect(fs1).to.equal(fs2);
});
it('has Shell constructor', function() { it('has Shell constructor', function() {
expect(typeof Filer.Shell).to.equal('function'); expect(typeof Filer.Shell).to.equal('function');
}); });
@ -24,8 +55,6 @@ describe('Filer', function() {
var Provider; var Provider;
if(providers.IndexedDB.isSupported()) { if(providers.IndexedDB.isSupported()) {
Provider = providers.IndexedDB; Provider = providers.IndexedDB;
} else if(providers.WebSQL.isSupported()) {
Provider = providers.WebSQL;
} else { } else {
Provider = providers.Memory; Provider = providers.Memory;
} }

View File

@ -0,0 +1,43 @@
const { path } = require('../../src');
var util = require('../lib/test-utils.js');
var expect = require('chai').expect;
describe('README example code', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should run the code in the README overview example', function(done) {
// Slightly modified version of the first example code in the README
// See <a name="overviewExample"></a>
const fs = util.fs();
fs.mkdir('/docs', (err) => {
if (err) throw err;
const filename = path.join('/docs', 'first.txt');
const data = 'Hello World!\n';
fs.writeFile(filename, data, (err) => {
if (err) throw err;
fs.stat(filename, (err, stats) => {
if (err) throw err;
expect(stats.size).to.equal(data.length);
done();
});
});
});
});
it('should run the fsPromises example code', function() {
const fs = util.fs().promises;
const filename = '/myfile';
const data = 'some data';
return fs.writeFile(filename, data)
.then(() => fs.stat(filename))
.then(stats => {
expect(stats.size).to.equal(data.length);
});
});
});