UNPKG

browserfs

Version:

A filesystem in your browser!

117 lines (107 loc) 3.81 kB
import {BaseFileSystem, FileSystem} from '../core/file_system'; import path = require('path'); import {ApiError} from '../core/api_error'; /** * The FolderAdapter file system wraps a file system, and scopes all interactions to a subfolder of that file system. */ export default class FolderAdapter extends BaseFileSystem implements FileSystem { private _wrapped: FileSystem; private _folder: string; constructor(folder: string, wrapped: FileSystem) { super(); this._folder = folder; this._wrapped = wrapped; } /** * Initialize the file system. Ensures that the wrapped file system * has the given folder. */ public initialize(cb: (e?: ApiError) => void) { this._wrapped.exists(this._folder, (exists: boolean) => { if (exists) { cb(); } else if (this._wrapped.isReadOnly()) { cb(ApiError.ENOENT(this._folder)); } else { this._wrapped.mkdir(this._folder, 0x1ff, cb); } }); } public getName(): string { return this._wrapped.getName(); } public isReadOnly(): boolean { return this._wrapped.isReadOnly(); } public supportsProps(): boolean { return this._wrapped.supportsProps(); } public supportsSynch(): boolean { return this._wrapped.supportsSynch(); } public supportsLinks(): boolean { return false; } public static isAvailable(): boolean { return true; } } function translateError(folder: string, e: any): any { if (e !== null && typeof e === 'object') { let err = <ApiError> e; let p = err.path; if (p) { p = '/' + path.relative(folder, p); err.message = err.message.replace(err.path, p); err.path = p; } } return e; } function wrapCallback(folder: string, cb: any): any { if (typeof cb === 'function') { return function(err) { if (arguments.length > 0) { arguments[0] = translateError(folder, err); } (<Function> cb).apply(null, arguments); }; } else { return cb; } } function wrapFunction(name: string, wrapFirst: boolean, wrapSecond: boolean): Function { if (name.slice(name.length - 4) !== 'Sync') { // Async function. Translate error in callback. return function() { if (arguments.length > 0) { if (wrapFirst) { arguments[0] = path.join(this._folder, arguments[0]); } if (wrapSecond) { arguments[1] = path.join(this._folder, arguments[1]); } arguments[arguments.length - 1] = wrapCallback(this._folder, arguments[arguments.length - 1]); } return this._wrapped[name].apply(this._wrapped, arguments); }; } else { // Sync function. Translate error in catch. return function() { try { if (wrapFirst) { arguments[0] = path.join(this._folder, arguments[0]); } if (wrapSecond) { arguments[1] = path.join(this._folder, arguments[1]); } return this._wrapped[name].apply(this._wrapped, arguments); } catch (e) { throw translateError(this._folder, e); } }; } } // First argument is a path. ['diskSpace', 'stat', 'statSync', 'open', 'openSync', 'unlink', 'unlinkSync', 'rmdir', 'rmdirSync' ,'mkdir', 'mkdirSync', 'readdir', 'readdirSync', 'exists', 'existsSync', 'realpath', 'realpathSync', 'truncate', 'truncateSync', 'readFile', 'readFileSync', 'writeFile', 'writeFileSync', 'appendFile', 'appendFileSync', 'chmod', 'chmodSync', 'chown', 'chownSync', 'utimes', 'utimesSync', 'readlink', 'readlinkSync'].forEach((name: string) => { FolderAdapter.prototype[name] = wrapFunction(name, true, false); }); // First and second arguments are paths. ['rename', 'renameSync', 'link', 'linkSync', 'symlink', 'symlinkSync'].forEach((name: string) => { FolderAdapter.prototype[name] = wrapFunction(name, true, true); });