fs-zoo
Version:
File system abstractions and implementations
92 lines (91 loc) • 3.05 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.OverlayCrud = void 0;
const util_1 = require("../crud/util");
const RouterCrud_1 = require("../router/RouterCrud");
class OverlayRouter {
constructor(layers) {
this.layers = layers;
}
resolve(path) {
const parts = (0, util_1.parseParts)(path);
const normalized = parts.join('/');
const normalizedLength = normalized.length;
let matchedFs;
let rest = '';
for (const [key, fs] of Object.entries(this.layers)) {
if (!key) {
if (!matchedFs) {
matchedFs = fs;
rest = normalized;
}
continue;
}
if (!normalized.startsWith(key))
continue;
if (normalizedLength - key.length < rest.length) {
matchedFs = fs;
rest = normalized.slice(key.length);
}
}
if (!matchedFs)
throw new Error('NO_OVERLAY');
return [rest, matchedFs];
}
nested(path) {
const entries = Object.entries(this.layers);
if (!path)
return entries;
const matches = [];
for (const [key, fs] of entries) {
if (key.startsWith(path)) {
matches.push([key.slice(path.length + 1), fs]);
}
}
return matches;
}
}
/**
* An "overlay" file system, which can combine multiple CRUD-fs file systems
* into one. Accepts one default file system and any number of additional
* file systems to overlay on top at specific paths.
*
* A layer mounted at `''` (or `[]`) will be the default file system, it will
* receive all requests that do not match any other layer.
*
* Example:
*
* ```
* const fs = new OverlayCrud();
* fs.overlay([], root);
* fs.overlay(['usr', 'virtual'], userHome);
* ```
*/
class OverlayCrud extends RouterCrud_1.RouterCrud {
constructor(layers = {}) {
const router = new OverlayRouter(layers);
super(router);
this._router = router;
}
mount(path, fs) {
const collection = (0, util_1.parseParts)(path);
const isRoot = collection.length === 0 || (collection.length === 1 && collection[0] === '');
if (!isRoot)
(0, util_1.assertType)(collection, 'overlay', 'crudfs');
const key = isRoot ? '' : collection.join('/');
const layers = this._router.layers;
if (key in layers)
throw new Error(`Layer already exists: /${key}`);
this._router.layers[key] = fs;
}
unmount(path) {
const collection = (0, util_1.parseParts)(path);
const isRoot = collection.length === 0 || (collection.length === 1 && collection[0] === '');
const key = isRoot ? '' : collection.join('/');
const layers = this._router.layers;
const exists = key in layers;
delete layers[key];
return exists;
}
}
exports.OverlayCrud = OverlayCrud;
;