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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Jan 3, 2019
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 37 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,27 @@ backend storage providers, for example `Memory`. See the section on [Storage Pro
<a name="overviewExample"></a>

```js
var fs = new Filer.FileSystem();
fs.open('/myfile', 'w+', function(err, fd) {
if (err) throw err;
fs.close(fd, function(err) {
if (err) throw err;
fs.stat('/myfile', function(err, stats) {
if (err) throw err;
console.log('stats: ' + JSON.stringify(stats));
const { fs, path } = require('filer');

fs.mkdir('/docs', (err) => {
if (err) {
return console.error('Unable to create /docs dir', err);
}

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);
});
});
});
Expand Down Expand Up @@ -125,9 +138,13 @@ fs.writeFile('/myfile', 'some data')

#### Filer.FileSystem(options, callback) constructor

File system constructor, invoked to open an existing file system or create a new one.
Accepts two arguments: an `options` object, and an optional `callback`. The `options`
object can specify a number of optional arguments, including:
In most cases, using `Filer.fs` will be sufficient, and provide a working filesystem.
However, if you need more control over the filesystem, you can also use the `FileSystem`
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'`
* `flags`: an Array of one or more flags to use when creating/opening the file system:
Expand Down Expand Up @@ -228,15 +245,16 @@ Buffer.allocUnsafe(size)

#### 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
identical to the node.js (see [https://github.com/browserify/path-browserify](https://github.com/browserify/path-browserify)) version with the following differences:
The node.js [path module](http://nodejs.org/api/path.html) is available via `Filer.path` or
`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 `/`
* No support for Windows style paths (assume you are on a POSIX system)
* Additional utility methods (see below)

```javascript
var path = Filer.Path;
var path = Filer.path;
var dir = path.dirname('/foo/bar/baz/asdf/quux');
// dir is now '/foo/bar/baz/asdf'

Expand Down Expand Up @@ -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:

```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)
Expand Down
19 changes: 18 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
module.exports = {
let fs = null;
let Filer = null;

module.exports = Filer = {
FileSystem: require('./filesystem/interface.js'),
Buffer: Buffer,
// We previously called this Path, but node calls it path. Do both
Path: require('./path.js'),
path: require('./path.js'),
Errors: require('./errors.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;
}
});
3 changes: 3 additions & 0 deletions tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,6 @@ require('./bugs/issue267.js');
require('./bugs/issue270.js');
require('./bugs/rename-dir-trailing-slash.js');
require('./bugs/issue357.js');

// Sample code from README
require('./spec/readme.example.spec');
33 changes: 31 additions & 2 deletions tests/spec/filer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,37 @@ describe('Filer', 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() {
expect(typeof Filer.Shell).to.equal('function');
});
Expand All @@ -24,8 +55,6 @@ describe('Filer', function() {
var Provider;
if(providers.IndexedDB.isSupported()) {
Provider = providers.IndexedDB;
} else if(providers.WebSQL.isSupported()) {
Provider = providers.WebSQL;
} else {
Provider = providers.Memory;
}
Expand Down
43 changes: 43 additions & 0 deletions tests/spec/readme.example.spec.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
});