Skip to content

Commit

Permalink
reme, 2.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Aug 12, 2017
1 parent 87c85de commit e8d40b2
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 118 deletions.
69 changes: 65 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# memfs
# memfs 2.0

In-memory file-system with [Node's `fs` API](https://nodejs.org/api/fs.html).

Expand Down Expand Up @@ -113,10 +113,17 @@ import {vol, fs} from 'memfs';
```

`vol` is an instance of `Volume` constructor, it is a default volume created
for your convenience. `fs` in and *fs-like* object created from `vol` using
for your convenience. `fs` in an *fs-like* object created from `vol` using
`createFsFromVolume(vol)`, see reference below.

#### `Volume`
All contents of the `fs` object are also exported individually, so you can use
`memfs` just like you would `fs` module:

```js
import {readFileSync, F_OK, ReadStream} from 'memfs';
```

#### `Volume` Constructor

`Volume` is a constructor function for creating new volumes:

Expand Down Expand Up @@ -190,7 +197,30 @@ called on completion and may receive only one argument - an `Error` object.

A synchronous version of `vol.mkdirp`. This method throws.

#### FS API Status
#### `createFsFromVolume(vol)`

Returns an *fs-like* object created from a `Volume` instance `vol.

```js
import {createFsFromVolume, Volume} from 'memfs';

const vol = new Volume;
const fs = createFsFromVolume(vol);
```

The idea behind the *fs-like* object is to make it identical to the one
you get from `require('fs')`. Here are some things this function does:

- Binds all methods, so you can do:

```js
const {createFileSync, readFileSync} = fs;
```

- Adds constructor functions `fs.Stats`, `fs.ReadStream`, `fs.WriteStream`, `fs.FileWatcher`, `fs.FSWatcher`.
- Adds constants `fs.constants`, `fs.F_OK`, etc.

# API Status

- [x] Constants
- [x] `FSWatcher`
Expand Down Expand Up @@ -283,3 +313,34 @@ A synchronous version of `vol.mkdirp`. This method throws.
[unionfs]: https://github.com/streamich/unionfs
[linkfs]: https://github.com/streamich/linkfs
[fs-monkey]: https://github.com/streamich/fs-monkey





# License

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

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 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.

For more information, please refer to <http://unlicense.org/>
10 changes: 10 additions & 0 deletions demo/mountSync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Volume} from '../src/index';


const vol = new Volume;
vol.mountSync('/test', {
'foo': 'bar',
});


console.log(vol.toJSON());
52 changes: 19 additions & 33 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,31 @@ var __assign = (this && this.__assign) || Object.assign || function(t) {
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("./constants");
var node_1 = require("./node");
var volume_1 = require("./volume");
exports.constants = constants_1.constants;
exports.F_OK = constants_1.constants.F_OK;
exports.R_OK = constants_1.constants.R_OK;
exports.W_OK = constants_1.constants.W_OK;
exports.X_OK = constants_1.constants.X_OK;
var volume = require("./volume");
var _a = require('fs-money/lib/util/lists'), fsSyncMethods = _a.fsSyncMethods, fsAsyncMethods = _a.fsAsyncMethods;
var constants_1 = require("./constants");
var F_OK = constants_1.constants.F_OK, R_OK = constants_1.constants.R_OK, W_OK = constants_1.constants.W_OK, X_OK = constants_1.constants.X_OK;
exports.Volume = volume_1.Volume;
// Default volume.
exports.vol = new volume_1.Volume;
// List of `fs.js` methods, used to export bound (`.bind`) method list, just like `require('fs')` would do.
var FS_METHODS = [
'open', 'openSync',
'close', 'closeSync',
'readFile', 'readFileSync',
'write', 'writeSync',
'writeFile', 'writeFileSync',
'link', 'linkSync',
'unlink', 'unlinkSync',
'symlink', 'symlinkSync',
'realpath', 'realpathSync',
'stat', 'statSync',
'lstat', 'lstatSync',
'fstat', 'fstatSync',
'rename', 'renameSync',
'exists', 'existsSync',
'access', 'accessSync',
'readdir', 'readdirSync',
'watchFile', 'unwatchFile',
'createReadStream',
];
function createFsFromVolume(volume) {
var fs = {};
function createFsFromVolume(vol) {
var fs = { F_OK: F_OK, R_OK: R_OK, W_OK: W_OK, X_OK: X_OK, constants: constants_1.constants, Stats: node_1.Stats };
// Bind FS methods.
for (var _i = 0, FS_METHODS_1 = FS_METHODS; _i < FS_METHODS_1.length; _i++) {
var method = FS_METHODS_1[_i];
fs[method] = volume[method].bind(volume);
for (var _i = 0, fsSyncMethods_1 = fsSyncMethods; _i < fsSyncMethods_1.length; _i++) {
var method = fsSyncMethods_1[_i];
fs[method] = vol[method].bind(vol);
}
for (var _a = 0, fsAsyncMethods_1 = fsAsyncMethods; _a < fsAsyncMethods_1.length; _a++) {
var method = fsAsyncMethods_1[_a];
fs[method] = vol[method].bind(vol);
}
fs.Stats = node_1.Stats;
fs.StatWatcher = volume_1.StatWatcher.bind(null, vol);
fs.FSWatcher = volume_1.FSWatcher.bind(null, vol);
fs.WriteStream = volume.WriteStream.bind(null, vol);
fs.ReadStream = volume.ReadStream.bind(null, vol);
fs._toUnixTimestamp = volume_1.toUnixTimestamp;
return fs;
}
exports.createFsFromVolume = createFsFromVolume;
Expand Down
107 changes: 80 additions & 27 deletions lib/volume.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,10 @@ var getRealpathOptions = optsGenerator(realpathDefaults);
var getRealpathOptsAndCb = optsAndCbGenerator(getRealpathOptions);
// ---------------------------------------- Utility functions
function pathToFilename(path) {
// TODO: Add support for the new URL object.
if ((typeof path !== 'string') && !buffer_1.Buffer.isBuffer(path))
throw new TypeError(ERRSTR.PATH_STR);
if ((typeof path !== 'string') && !buffer_1.Buffer.isBuffer(path)) {
if (!require('url') || !(path instanceof require('url').URL))
throw new TypeError(ERRSTR.PATH_STR);
}
var pathString = String(path);
nullCheck(pathString);
return pathString;
Expand Down Expand Up @@ -319,6 +320,7 @@ function toUnixTimestamp(time) {
}
throw new Error('Cannot parse time: ' + time);
}
exports.toUnixTimestamp = toUnixTimestamp;
/**
* Returns optional argument and callback
* @param arg Argument or callback value
Expand Down Expand Up @@ -435,14 +437,46 @@ var Volume = (function () {
throwError(ENOENT, funcName, filename);
return link;
};
// Just like `getLink`, but also dereference/resolves symbolic links.
Volume.prototype.getResolvedLink = function (filenameOrSteps) {
var steps = typeof filenameOrSteps === 'string'
? filenameToSteps(filenameOrSteps)
: filenameOrSteps;
var link = this.root;
var i = 0;
while (i < steps.length) {
var step = steps[i];
link = link.getChild(step);
if (!link)
return null;
var node = link.getNode();
if (node.isSymlink()) {
steps = node.symlink.concat(steps.slice(i + 1));
link = this.root;
i = 0;
continue;
}
i++;
}
return link;
};
// Just like `getLinkOrThrow`, but also dereference/resolves symbolic links.
Volume.prototype.getResolvedLinkOrThrow = function (filename, funcName) {
var link = this.getLinkOrThrow(filename, funcName);
link = this.resolveSymlinks(link);
var link = this.getResolvedLink(filename);
if (!link)
throwError(ENOENT, funcName, filename);
return link;
};
Volume.prototype.resolveSymlinks = function (link) {
// let node: Node = link.getNode();
// while(link && node.isSymlink()) {
// link = this.getLink(node.symlink);
// if(!link) return null;
// node = link.getNode();
// }
// return link;
return this.getResolvedLink(link.steps.slice(1));
};
// Just like `getLinkOrThrow`, but also verifies that the link is a directory.
Volume.prototype.getLinkAsDirOrThrow = function (filename, funcName) {
var link = this.getLinkOrThrow(filename, funcName);
Expand All @@ -463,16 +497,6 @@ var Volume = (function () {
throwError(ENOTDIR, funcName, path_1.sep + steps.join(path_1.sep));
return link;
};
Volume.prototype.resolveSymlinks = function (link) {
var node = link.getNode();
while (link && node.isSymlink()) {
link = this.getLink(node.symlink);
if (!link)
return null;
node = link.getNode();
}
return link;
};
Volume.prototype.getFileByFd = function (fd) {
return this.fds[String(fd)];
};
Expand Down Expand Up @@ -520,23 +544,50 @@ var Volume = (function () {
}
});
};
Volume.prototype._toJSON = function (link, json) {
Volume.prototype._toJSON = function (link, json, path) {
if (link === void 0) { link = this.root; }
if (json === void 0) { json = {}; }
for (var name_2 in link.children) {
var child = link.getChild(name_2);
var node = child.getNode();
if (node.isFile()) {
json[child.getPath()] = node.getString();
var filename = child.getPath();
if (path)
filename = path_1.relative(path, filename);
json[filename] = node.getString();
}
else if (node.isDirectory()) {
this._toJSON(child, json);
this._toJSON(child, json, path);
}
}
return json;
};
Volume.prototype.toJSON = function () {
return this._toJSON();
Volume.prototype.toJSON = function (paths, json, isRelative) {
if (json === void 0) { json = {}; }
if (isRelative === void 0) { isRelative = false; }
var links = [];
if (paths) {
if (!(paths instanceof Array))
paths = [paths];
for (var _i = 0, paths_1 = paths; _i < paths_1.length; _i++) {
var path_2 = paths_1[_i];
var filename = pathToFilename(path_2);
var link = this.getResolvedLink(filename);
if (!link)
continue;
links.push(link);
}
}
else {
links.push(this.root);
}
if (!links.length)
return json;
for (var _a = 0, links_1 = links; _a < links_1.length; _a++) {
var link = links_1[_a];
this._toJSON(link, json, isRelative ? link.getPath() : '');
}
return json;
};
// fromJSON(json: {[filename: string]: string}, cwd: string = '/') {
Volume.prototype.fromJSON = function (json, cwd) {
Expand All @@ -552,9 +603,9 @@ var Volume = (function () {
this.writeFileSync(filename, data);
}
};
// Legacy interface
Volume.prototype.mountSync = function (mountpoint, json) {
var json2 = {};
// this.importJSON(json);
this.fromJSON(json, mountpoint);
};
Volume.prototype.openLink = function (link, flagsNum, resolveSymlinks) {
if (resolveSymlinks === void 0) { resolveSymlinks = true; }
Expand All @@ -577,13 +628,15 @@ var Volume = (function () {
file.truncate();
return file;
};
Volume.prototype.openFile = function (fileName, flagsNum, modeNum, resolveSymlinks) {
Volume.prototype.openFile = function (filename, flagsNum, modeNum, resolveSymlinks) {
if (resolveSymlinks === void 0) { resolveSymlinks = true; }
var steps = filenameToSteps(fileName);
var link = this.getLink(steps);
var steps = filenameToSteps(filename);
// let link: Link = this.getLink(steps);
var link = this.getResolvedLink(steps);
// Try creating a new file, if it does not exist.
if (!link) {
var dirLink = this.getLinkParent(steps);
// const dirLink: Link = this.getLinkParent(steps);
var dirLink = this.getResolvedLink(steps.slice(0, steps.length - 1));
if ((flagsNum & O_CREAT) && (typeof modeNum === 'number')) {
link = this.createLink(dirLink, steps[steps.length - 1], false, modeNum);
}
Expand All @@ -595,7 +648,7 @@ var Volume = (function () {
if (resolveSymlinks === void 0) { resolveSymlinks = true; }
var file = this.openFile(filename, flagsNum, modeNum, resolveSymlinks);
if (!file)
throw createError(ENOENT, 'open', filename);
throwError(ENOENT, 'open', filename);
return file.fd;
};
Volume.prototype.openSync = function (path, flags, mode) {
Expand Down
Loading

0 comments on commit e8d40b2

Please sign in to comment.