UNPKG

fs-zoo

Version:

File system abstractions and implementations

92 lines (91 loc) 3.05 kB
"use strict"; 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;