diff --git a/README.md b/README.md index dcea5439..9ae901ff 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,12 @@ BrowserFS is highly extensible, and ships with many filesystem backends: * `WorkerFS`: Lets you mount the BrowserFS file system configured in the main thread in a WebWorker, or the other way around! * `MountableFileSystem`: Lets you mount multiple file systems into a single directory hierarchy, as in *nix-based OSes. * `OverlayFS`: Mount a read-only file system as read-write by overlaying a writable file system on top of it. Like Docker's overlayfs, it will only write changed files to the writable file system. -* `AsyncMirrorFS`: Use an asynchronous backend synchronously. Invaluable for Emscripten; let your Emscripten applications write to larger file stores with no additional effort! +* `AsyncMirror`: Use an asynchronous backend synchronously. Invaluable for Emscripten; let your Emscripten applications write to larger file stores with no additional effort! * Note: Loads the entire contents of the file system into a synchronous backend during construction. Performs synchronous operations in-memory, and enqueues them to be mirrored onto the asynchronous backend. * `FolderAdapter`: Wraps a file system, and scopes all interactions to a subfolder of that file system. * `Emscripten`: Lets you mount Emscripten file systems inside BrowserFS. -More backends can be defined by separate libraries, so long as they extend the `BaseFileSystem`. Multiple backends can be active at once at different locations in the directory hierarchy. +More backends can be defined by separate libraries, so long as they extend the `BaseFileSystem` class. Multiple backends can be active at once at different locations in the directory hierarchy. For more information, see the [API documentation for BrowserFS](https://jvilk.com/browserfs/1.3.0/index.html). @@ -52,6 +52,8 @@ and re-build. ### Using +Using `BrowserFS.configure()`, you can easily configure BrowserFS to use a variety of file system types. + Here's a simple usage example using the LocalStorage-backed file system: ```html @@ -64,10 +66,16 @@ Here's a simple usage example using the LocalStorage-backed file system: // You can pass in an arbitrary object if you do not wish to pollute // the global namespace. BrowserFS.install(window); - // Constructs an instance of the LocalStorage-backed file system. - var lsfs = new BrowserFS.FileSystem.LocalStorage(); - // Initialize it as the root file system. - BrowserFS.initialize(lsfs); + // Configures BrowserFS to use the LocalStorage file system. + BrowserFS.configure({ + fs: "LocalStorage" + }, function(e) { + if (e) { + // An error happened! + throw e; + } + // Otherwise, BrowserFS is ready-to-use! + }); ``` @@ -82,6 +90,38 @@ fs.writeFile('/test.txt', 'Cool, I can do this in the browser!', function(err) { }); ``` +The following code mounts a zip file to `/zip`, in-memory storage to `/tmp`, and IndexedDB browser-local storage to `/home`: + +```js +// Note: This is the new fetch API in the browser. You can use XHR too. +fetch('mydata.zip').then(function(response) { + return response.arraybuffer(); +}).then(function(zipData) { + var Buffer = BrowserFS.BFSRequire('buffer').Buffer; + + BrowserFS.configure({ + fs: "MountableFileSystem", + options: { + "/zip": { + fs: "ZipFS", + options: { + // Wrap as Buffer object. + zipData: Buffer.from(zipData) + } + }, + "/tmp": { fs: "InMemory" }, + "/home": { fs: "IndexedDB" } + } + }, function(e) { + if (e) { + // An error occurred. + throw e; + } + // Otherwise, BrowserFS is ready to use! + }); +}); +``` + ### Using with Browserify and Webpack BrowserFS is published as a UMD module, so you can either include it on your webpage in a `script` tag or bundle it with your favorite @@ -154,17 +194,13 @@ simply `require('browserfs/dist/node/index')` instead. You can use any *synchronous* BrowserFS file systems with Emscripten! Persist particular folders in the Emscripten file system to `localStorage`, or enable Emscripten to synchronously download files from another folder as they are requested. -Include `browserfs.min.js` into the page, and add code similar to the following to your `Module`'s `preRun` array: +Include `browserfs.min.js` into the page, and configure BrowserFS prior to running your Emscripten code. Then, add code similar to the following to your `Module`'s `preRun` array: ```javascript /** * Mounts a localStorage-backed file system into the /data folder of Emscripten's file system. */ function setupBFS() { - // Constructs an instance of the LocalStorage-backed file system. - var lsfs = new BrowserFS.FileSystem.LocalStorage(); - // Initialize it as the root file system. - BrowserFS.initialize(lsfs); // Grab the BrowserFS Emscripten FS plugin. var BFS = new BrowserFS.EmscriptenFS(); // Create the folder that we'll turn into a mount point. @@ -184,20 +220,24 @@ If you wish to use an asynchronous BrowserFS backend with Emscripten (e.g. Dropb * @param dropboxClient An authenticated DropboxJS client. */ function asyncSetup(dropboxClient, cb) { - var dbfs = new BrowserFS.FileSystem.Dropbox(dropboxClient); - // Wrap in AsyncMirrorFS. - var asyncMirror = new BrowserFS.FileSystem.AsyncMirror( - new BrowserFS.FileSystem.InMemory(), dbfs); - - // Downloads the entire contents of the Dropbox backend into memory. - // You'll probably want to use an app folder, and check that you - // aren't pulling in a huge amount of data here. - asyncMirror.initialize(function(err) { - // Initialize it as the root file system. - BrowserFS.initialize(asyncMirror); - // BFS is ready for Emscripten! - cb(); - }); + // This wraps Dropbox in the AsyncMirror file system. + // BrowserFS will download all of Dropbox into an + // InMemory file system, and mirror operations to + // the two to keep them in sync. + BrowserFS.configure({ + fs: "AsyncMirror", + options: { + sync: { + fs: "InMemory" + }, + async: { + fs: "Dropbox", + options: { + client: dropboxClient + } + } + } + }, cb); } function setupBFS() { // Grab the BrowserFS Emscripten FS plugin. diff --git a/package.json b/package.json index eb675f7f..eca7c909 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "test": "npm-run-all test:prepare test:karma", "watch-test": "npm-run-all test:prepare --parallel watch:scripts test:watch test:karma", "prepublish": "npm run dist", - "docs": "typedoc --mode file --out doc --excludePrivate --readme src/DOCS.md --name BrowserFS src" + "docs": "typedoc --mode modules --out doc --excludePrivate --readme src/DOCS.md --name BrowserFS --module umd src" }, "dependencies": { "async": "^2.1.4", diff --git a/src/DOCS.md b/src/DOCS.md index 147854a3..0006ac82 100644 --- a/src/DOCS.md +++ b/src/DOCS.md @@ -4,16 +4,118 @@ BrowserFS is an in-browser file system that emulates the [Node JS file system AP The [README](https://github.com/jvilk/browserfs) provides an overview of how to integrate BrowserFS into your project. This API documentation will focus on how to use BrowserFS once you have added it to your project. -## BrowserFS Interface +## Configuring BrowserFS -The main BrowserFS interface is [documented here](interfaces/browserfs.html). +The main BrowserFS interface is [documented here](modules/_core_browserfs_.html). -Before you can use BrowserFS, you must initialize it with a single root file system backend using `BrowserFS.initialize`. Think of this as your "storage device". +Before you can use BrowserFS, you need to answer the following questions: -If you need to use multiple "storage devices", instantiate multiple file system backend types, mount them into a `MountableFileSystem` backend, and then use that as the root file system for BrowserFS. +1. **What file system backends do I want to use?** +2. **What configuration options do I pass to each?** + +### What Backend(s) to Use? + +Before you can use BrowserFS, you must initialize it with a single root file system backend. Think of each backend +as a "storage device". It can be read-only (a zip file or an ISO), read-write (browser-local IndexedDB storage), +and it can even be cloud storage (Dropbox). + +If you need to use multiple "storage devices", you can use the `MountableFileSystem` backend to "mount" backends at +different locations in the directory hierarchy. There are all sorts of adapter file systems available to make it easy to access files stored in Emscripten, files stored in a different context (e.g., a web worker), isolate file operations to a particular folder, access asynchronous storage backends synchronously, and more! +Check out the "Overview" of backends below for a list of backends and their capabilities. + +### What Configuration Options For Each? + +Different backends require different configuration options. Review the documentation page for each backend you want to use, and note the options passed to its `Create()` method. Some are optional, others are required. + +### Putting It All Together + +Once you know the backend(s) you want to use, and the options to pass to each, you can configure BrowserFS with a single configuration object: + +```javascript +BrowserFS.configure({ + fs: "name of file system type" // from Backends table below, + options: { + // options for the file system + } +}, function (e) { + if (e) { + // An error occurred. + throw e; + } + // Otherwise, you can interact with the configured backends via our Node FS polyfill! + var fs = BrowserFS.BFSRequire('fs'); + fs.readdir('/', function(e, contents) { + // etc. + }); +}); +``` + +In the case where a file system's options object takes another file system, you can nest another configuration object +in place of the actual file system object: + +```javascript +var Buffer = BrowserFS.BFSRequire('buffer').Buffer; +BrowserFS.configure({ + fs: "OverlayFS", + options: { + readable: { + fs: "ZipFS", + options: { + zipData: Buffer.from(zipDataAsArrayBuffer) + } + }, + writable: { + fs: "LocalStorage" + } + } +}, function(e) { + +}); +``` + +Using this method, it's easy to configure mount points in the `MountableFileSystem`: + +```javascript +BrowserFS.configure({ + fs: "MountableFileSystem", + options: { + '/tmp': { fs: "InMemory" }, + '/home': { fs: "IndexedDB" }, + '/mnt/usb0': { fs: "LocalStorage" } + } +}, function(e) { + +}); +``` + +### Advanced Usage + +If `BrowserFS.configure` is not to your liking, you can manually instantiate file system backends and pass the root backend to BrowserFS via its `BrowserFS.initialize()` function. + +```javascript +BrowserFS.FileSystem.LocalStorage.Create(function(e, lsfs) { + BrowserFS.FileSystem.InMemory.Create(function(e, inMemory) { + BrowserFS.FileSystem.IndexedDB.Create({}, function(e, idbfs) { + BrowserFS.FileSystem.MountableFileSystem.Create({ + '/tmp': inMemory, + '/home': idbfs, + '/mnt/usb0': lsfs + }, function(e, mfs) { + BrowserFS.initialize(mfs); + // BFS is now ready to use! + }); + }); + }); +}); +``` + +## Usage with Emscripten + +Once you have configured BrowserFS, you can mount it into the Emscripten file system. More details are in the BrowserFS [README](https://github.com/jvilk/browserfs). + ## Overview of Backends **Key:** @@ -22,7 +124,7 @@ There are all sorts of adapter file systems available to make it easy to access * ✗ means 'no' * ? means 'depends on configuration' -Note that any asynchronous file system can be accessed synchronously using the [AsyncMirror](classes/asyncmirror.html) file system. +Note that any asynchronous file system can be accessed synchronously using the [AsyncMirror](classes/_backend_asyncmirror_.asyncmirror.html) file system at the cost of preloading the entire file system into some synchronous backend (e.g., `InMemory`). @@ -38,98 +140,98 @@ Note that any asynchronous file system can be accessed synchronously using the [ - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/src/backend/AsyncMirror.ts b/src/backend/AsyncMirror.ts index 2f9f6af4..22348880 100644 --- a/src/backend/AsyncMirror.ts +++ b/src/backend/AsyncMirror.ts @@ -35,6 +35,9 @@ class MirrorFile extends PreloadFile implements File { } } +/** + * Configuration options for the AsyncMirror file system. + */ export interface AsyncMirrorOptions { // The synchronous file system to mirror the asynchronous file system to. sync: FileSystem; @@ -58,16 +61,35 @@ export interface AsyncMirrorOptions { * IndexedDB synchronously. * * ```javascript - * new BrowserFS.FileSystem.IndexedDB(function (e, idbfs) { - * var inMemory = new BrowserFS.FileSystem.InMemory(); - * var mirrored = new BrowserFS.FileSystem.AsyncMirror(inMemory, idbfs); - * mirrored.initialize(function (e) { - * BrowserFS.initialized(mirrored); + * BrowserFS.configure({ + * fs: "AsyncMirror", + * options: { + * sync: { fs: "InMemory" }, + * async: { fs: "IndexedDB" } + * } + * }, function(e) { + * // BrowserFS is initialized and ready-to-use! + * }); + * ``` + * + * Or, alternatively: + * + * ```javascript + * BrowserFS.FileSystem.IndexedDB.Create(function(e, idbfs) { + * BrowserFS.FileSystem.InMemory.Create(function(e, inMemory) { + * BrowserFS.FileSystem.AsyncMirror({ + * sync: inMemory, async: idbfs + * }, function(e, mirrored) { + * BrowserFS.initialize(mirrored); + * }); * }); * }); * ``` */ export default class AsyncMirror extends SynchronousFileSystem implements FileSystem { + /** + * Constructs and initializes an AsyncMirror file system with the given options. + */ public static Create(opts: AsyncMirrorOptions, cb: BFSCallback): void { try { const fs = new AsyncMirror(opts.sync, opts.async, false); @@ -98,6 +120,8 @@ export default class AsyncMirror extends SynchronousFileSystem implements FileSy private _initializeCallbacks: ((e?: ApiError) => void)[] = []; /** + * **Deprecated; use AsyncMirror.Create() method instead.** + * * Mirrors the synchronous file system into the asynchronous file system. * * **IMPORTANT**: You must call `initialize` on the file system before it can be used. diff --git a/src/backend/Dropbox.ts b/src/backend/Dropbox.ts index 9fde97f2..f43e3bfd 100644 --- a/src/backend/Dropbox.ts +++ b/src/backend/Dropbox.ts @@ -336,7 +336,11 @@ export class DropboxFile extends PreloadFile implements File } } +/** + * Options for the Dropbox file system. + */ export interface DropboxFileSystemOptions { + // An *authenticated* Dropbox client. Must be from the 0.10 JS SDK. client: Dropbox.Client; } @@ -348,6 +352,10 @@ export interface DropboxFileSystemOptions { * NOTE: You must use the v0.10 version of the [Dropbox JavaScript SDK](https://www.npmjs.com/package/dropbox). */ export default class DropboxFileSystem extends BaseFileSystem implements FileSystem { + /** + * Creates a new DropboxFileSystem instance with the given options. + * Must be given an *authenticated* DropboxJS client from the old v0.10 version of the Dropbox JS SDK. + */ public static Create(opts: DropboxFileSystemOptions, cb: BFSCallback): void { cb(null, new DropboxFileSystem(opts.client, false)); } @@ -361,6 +369,8 @@ export default class DropboxFileSystem extends BaseFileSystem implements FileSys private _client: CachedDropboxClient; /** + * **Deprecated. Please use Dropbox.Create() method instead.** + * * Constructs a Dropbox-backed file system using the *authenticated* DropboxJS client. * * Note that you must use the old v0.10 version of the Dropbox JavaScript SDK. diff --git a/src/backend/Emscripten.ts b/src/backend/Emscripten.ts index 32b189d9..1dfe6258 100644 --- a/src/backend/Emscripten.ts +++ b/src/backend/Emscripten.ts @@ -180,8 +180,11 @@ export class EmscriptenFile extends BaseFile implements File { } } +/** + * Configuration options for Emscripten file systems. + */ export interface EmscriptenFileSystemOptions { - // The Emscripten file system (`FS`) + // The Emscripten file system to use (`FS`) FS: any; } @@ -189,6 +192,9 @@ export interface EmscriptenFileSystemOptions { * Mounts an Emscripten file system into the BrowserFS file system. */ export default class EmscriptenFileSystem extends SynchronousFileSystem { + /** + * Create an EmscriptenFileSystem instance with the given options. + */ public static Create(opts: EmscriptenFileSystemOptions, cb: BFSCallback): void { cb(null, new EmscriptenFileSystem(opts.FS)); } diff --git a/src/backend/FolderAdapter.ts b/src/backend/FolderAdapter.ts index b3fbbbab..f4265cd7 100644 --- a/src/backend/FolderAdapter.ts +++ b/src/backend/FolderAdapter.ts @@ -2,6 +2,9 @@ import {BaseFileSystem, FileSystem, BFSCallback} from '../core/file_system'; import * as path from 'path'; import {ApiError} from '../core/api_error'; +/** + * Configuration options for a FolderAdapter file system. + */ export interface FolderAdapterOptions { // The folder to use as the root directory. folder: string; @@ -11,8 +14,26 @@ export interface FolderAdapterOptions { /** * The FolderAdapter file system wraps a file system, and scopes all interactions to a subfolder of that file system. + * + * Example: Given a file system `foo` with folder `bar` and file `bar/baz`... + * + * ```javascript + * BrowserFS.configure({ + * fs: "FolderAdapter", + * options: { + * folder: "bar", + * wrapped: foo + * } + * }, function(e) { + * var fs = BrowserFS.BFSRequire('fs'); + * fs.readdirSync('/'); // ['baz'] + * }); + * ``` */ export default class FolderAdapter extends BaseFileSystem implements FileSystem { + /** + * Creates a FolderAdapter instance with the given options. + */ public static Create(opts: FolderAdapterOptions, cb: BFSCallback): void { cb(null, new FolderAdapter(opts.folder, opts.wrapped)); } @@ -25,12 +46,7 @@ export default class FolderAdapter extends BaseFileSystem implements FileSystem /** * Wraps a file system, and uses the given folder as its root. * - * Example: Given a file system `foo` with folder `bar` and file `bar/baz`... * - * ```javascript - * var adapter = new BrowserFS.FileSystem.FolderAdapter('bar', foo); - * adapter.readdirSync('/'); // ['baz'] - * ``` * * @param folder The folder to use as the root directory. * @param wrapped The file system to wrap. diff --git a/src/backend/HTML5FS.ts b/src/backend/HTML5FS.ts index 49e9baea..12b8a941 100644 --- a/src/backend/HTML5FS.ts +++ b/src/backend/HTML5FS.ts @@ -156,6 +156,9 @@ export interface HTML5FSOptions { * only available in Chrome. */ export default class HTML5FS extends BaseFileSystem implements IFileSystem { + /** + * Creates an HTML5FS instance with the given options. + */ public static Create(opts: HTML5FSOptions, cb: BFSCallback): void { const fs = new HTML5FS(opts.size, opts.type, false); fs.allocate((e) => e ? cb(e) : cb(null, fs), false); @@ -169,6 +172,8 @@ export default class HTML5FS extends BaseFileSystem implements IFileSystem { private size: number; private type: number; /** + * **Deprecated. Please use HTML5FS.Create() method instead.** + * * Creates a new HTML5 FileSystem-backed BrowserFS file system of the given size * and storage type. * @@ -207,6 +212,8 @@ export default class HTML5FS extends BaseFileSystem implements IFileSystem { } /** + * **Deprecated. Please use Create() method instead to create and allocate an HTML5FS.** + * * Requests a storage quota from the browser to back this FS. * Must be called before file system can be used! */ diff --git a/src/backend/InMemory.ts b/src/backend/InMemory.ts index dfb9eef2..f0d074c1 100644 --- a/src/backend/InMemory.ts +++ b/src/backend/InMemory.ts @@ -36,6 +36,9 @@ export class InMemoryStore implements SyncKeyValueStore, SimpleSyncStore { * Files are not persisted across page loads. */ export default class InMemoryFileSystem extends SyncKeyValueFileSystem { + /** + * Creates an InMemoryFileSystem instance. + */ public static Create(cb: BFSCallback): void; public static Create(options: any, cb: BFSCallback): void; public static Create(options: any, cb?: any): void { diff --git a/src/backend/IndexedDB.ts b/src/backend/IndexedDB.ts index 52571f71..fca8300f 100644 --- a/src/backend/IndexedDB.ts +++ b/src/backend/IndexedDB.ts @@ -188,6 +188,9 @@ export class IndexedDBStore implements AsyncKeyValueStore { } } +/** + * Configuration options for the IndexedDB file system. + */ export interface IndexedDBFileSystemOptions { // The name of this file system. You can have multiple IndexedDB file systems operating // at once, but each must have a different name. @@ -198,9 +201,15 @@ export interface IndexedDBFileSystemOptions { * A file system that uses the IndexedDB key value file system. */ export default class IndexedDBFileSystem extends AsyncKeyValueFileSystem { - public static Create(opts: IndexedDBFileSystemOptions, cb: BFSCallback): void { + /** + * Constructs an IndexedDB file system with the given options. + */ + public static Create(cb: BFSCallback): void; + public static Create(opts: IndexedDBFileSystemOptions, cb: BFSCallback): void; + public static Create(opts: any, cb?: any): void { + const normalizedCb = cb ? cb : opts; // tslint:disable-next-line:no-unused-new - new IndexedDBFileSystem(cb, opts.storeName, false); + new IndexedDBFileSystem(normalizedCb, cb && opts ? opts['storeName'] : undefined, false); // tslint:enable-next-line:no-unused-new } public static isAvailable(): boolean { @@ -215,6 +224,8 @@ export default class IndexedDBFileSystem extends AsyncKeyValueFileSystem { } } /** + * **Deprecated. Use IndexedDB.Create() method instead.** + * * Constructs an IndexedDB file system. * @param cb Called once the database is instantiated and ready for use. * Passes an error if there was an issue instantiating the database. diff --git a/src/backend/IsoFS.ts b/src/backend/IsoFS.ts index 99b11eaf..4e1a5983 100644 --- a/src/backend/IsoFS.ts +++ b/src/backend/IsoFS.ts @@ -1139,6 +1139,9 @@ class JolietDirectory extends Directory { } } +/** + * Options for IsoFS file system instances. + */ export interface IsoFSOptions { // The ISO file in a buffer. data: Buffer; @@ -1154,6 +1157,9 @@ export interface IsoFSOptions { * * Microsoft Joliet and Rock Ridge extensions to the ISO9660 standard */ export default class IsoFS extends SynchronousFileSystem implements FileSystem { + /** + * Creates an IsoFS instance with the given options. + */ public static Create(opts: IsoFSOptions, cb: BFSCallback): void { let fs: IsoFS | undefined; let e: ApiError | undefined; @@ -1175,6 +1181,8 @@ export default class IsoFS extends SynchronousFileSystem implements FileSystem { private _name: string; /** + * **Deprecated. Please use IsoFS.Create() method instead.** + * * Constructs a read-only file system from the given ISO. * @param data The ISO file in a buffer. * @param name The name of the ISO (optional; used for debug messages / identification via getName()). diff --git a/src/backend/LocalStorage.ts b/src/backend/LocalStorage.ts index d0213f9a..23464b2c 100644 --- a/src/backend/LocalStorage.ts +++ b/src/backend/LocalStorage.ts @@ -82,6 +82,9 @@ export class LocalStorageStore implements SyncKeyValueStore, SimpleSyncStore { * LocalStorageStore to our SyncKeyValueFileSystem. */ export default class LocalStorageFileSystem extends SyncKeyValueFileSystem { + /** + * Creates a LocalStorageFileSystem instance. + */ public static Create(cb: BFSCallback): void; public static Create(options: any, cb: BFSCallback): void; public static Create(options: any, cb?: any): void { diff --git a/src/backend/MountableFileSystem.ts b/src/backend/MountableFileSystem.ts index 617fd809..6a488098 100644 --- a/src/backend/MountableFileSystem.ts +++ b/src/backend/MountableFileSystem.ts @@ -5,6 +5,9 @@ import fs from '../core/node_fs'; import * as path from 'path'; import {mkdirpSync} from '../core/util'; +/** + * Configuration options for the MountableFileSystem backend. + */ export interface MountableFileSystemOptions { // Locations of mount points. Can be empty. [mountPoint: string]: FileSystem; @@ -19,11 +22,35 @@ export interface MountableFileSystemOptions { * For example, if a file system is mounted at /mnt/blah, and a request came in * for /mnt/blah/foo.txt, the file system would see a request for /foo.txt. * - * You can mount file systems like so: + * You can mount file systems when you configure the file system: * ```javascript - * var mfs = new BrowserFS.FileSystem.MountableFileSystem(); - * mfs.mount('/data', new BrowserFS.FileSystem.XmlHttpRequest()); - * mfs.mount('/home', new BrowserFS.FileSystem.LocalStorage()); + * BrowserFS.configure({ + * fs: "MountableFileSystem", + * options: { + * '/data': { fs: 'XmlHttpRequest', options: { index: "http://mysite.com/files/index.json" } }, + * '/home': { fs: 'LocalStorage' } + * } + * }, function(e) { + * + * }); + * ``` + * + * For advanced users, you can also mount file systems *after* MFS is constructed: + * ```javascript + * BrowserFS.FileSystem.XmlHttpRequest.Create({ + * index: "http://mysite.com/files/index.json" + * }, function(e, xhrfs) { + * BrowserFS.FileSystem.MountableFileSystem.Create({ + * '/data': xhrfs + * }, function(e, mfs) { + * BrowserFS.initialize(mfs); + * + * // Added after-the-fact... + * BrowserFS.FileSystem.LocalStorage.Create(function(e, lsfs) { + * mfs.mount('/home', lsfs); + * }); + * }); + * }); * ``` * * Since MountableFileSystem simply proxies requests to mounted file systems, it supports all of the operations that the mounted file systems support. @@ -31,6 +58,9 @@ export interface MountableFileSystemOptions { * With no mounted file systems, `MountableFileSystem` acts as a simple `InMemory` filesystem. */ export default class MountableFileSystem extends BaseFileSystem implements FileSystem { + /** + * Creates a MountableFileSystem instance with the given options. + */ public static Create(opts: MountableFileSystemOptions, cb: BFSCallback): void { const fs = new MountableFileSystem(); Object.keys(opts).forEach((mountPoint) => { diff --git a/src/backend/OverlayFS.ts b/src/backend/OverlayFS.ts index b0994787..96285015 100644 --- a/src/backend/OverlayFS.ts +++ b/src/backend/OverlayFS.ts @@ -971,6 +971,9 @@ export class UnlockedOverlayFS extends BaseFileSystem implements FileSystem { } } +/** + * Configuration options for OverlayFS instances. + */ export interface OverlayFSOptions { // The file system to write modified files to. writable: FileSystem; @@ -984,6 +987,9 @@ export interface OverlayFSOptions { * file system. */ export default class OverlayFS extends LockedFS { + /** + * Constructs and initializes an OverlayFS instance with the given options. + */ public static Create(opts: OverlayFSOptions, cb: BFSCallback): void { try { const fs = new OverlayFS(opts.writable, opts.readable, false); @@ -999,6 +1005,7 @@ export default class OverlayFS extends LockedFS { } /** + * **Deprecated. Please use OverlayFS.Create() method instead.** * @param writable The file system to write modified files to. * @param readable The file system that initially populates this file system. */ @@ -1007,6 +1014,9 @@ export default class OverlayFS extends LockedFS { deprecationMessage(deprecateMsg, "OverlayFS", {readable: "readable file system", writable: "writable file system"}); } + /** + * **Deprecated. Please use OverlayFS.Create() to construct and initialize OverlayFS instances.** + */ public initialize(cb: BFSOneArgCallback, deprecateMsg = true): void { if (deprecateMsg) { console.warn(`[OverlayFS] OverlayFS.initialize() is deprecated and will be removed in the next major release. Please use 'OverlayFS.Create({readable: readable file system instance, writable: writable file system instance}, cb)' to create and initialize OverlayFS instances.`); diff --git a/src/backend/WorkerFS.ts b/src/backend/WorkerFS.ts index 9bb5736d..fed3433c 100644 --- a/src/backend/WorkerFS.ts +++ b/src/backend/WorkerFS.ts @@ -457,7 +457,7 @@ class WorkerFile extends PreloadFile { } export interface WorkerFSOptions { - // The target worker hosting a file system that you want to connect to. + // The target worker that you want to connect to, or the current worker if in a worker context. worker: Worker; } @@ -480,7 +480,9 @@ export interface WorkerFSOptions { * * ```javascript * // Set the remote file system as the root file system. - * BrowserFS.initialize(new BrowserFS.FileSystem.WorkerFS(self)); + * BrowserFS.configure({ fs: "WorkerFS", options: { worker: self }}, function(e) { + * // Ready! + * }); * ``` * * Note that synchronous operations are not permitted on the WorkerFS, regardless @@ -673,6 +675,8 @@ export default class WorkerFS extends BaseFileSystem implements FileSystem { private _supportProps: boolean = false; /** + * **Deprecated. Please use WorkerFS.Create() method instead.** + * * Constructs a new WorkerFS instance that connects with BrowserFS running on * the specified worker. */ @@ -700,6 +704,8 @@ export default class WorkerFS extends BaseFileSystem implements FileSystem { } /** + * **Deprecated. Please use WorkerFS.Create() method to construct and initialize WorkerFS instances.** + * * Called once both local and remote sides are set up. */ public initialize(cb: () => void): void { diff --git a/src/backend/XmlHttpRequest.ts b/src/backend/XmlHttpRequest.ts index 84ef4096..431e2fed 100644 --- a/src/backend/XmlHttpRequest.ts +++ b/src/backend/XmlHttpRequest.ts @@ -22,8 +22,11 @@ function tryToString(buff: Buffer, encoding: string, cb: BFSCallback) { } } +/** + * Configuration options for an XmlHttpRequest file system. + */ export interface XmlHttpRequestOptions { - // URL to a file index or a file index object, generated with the make_xhrfs_index script + // URL to a file index as a JSON file or the file index object itself, generated with the make_xhrfs_index script index: string | object; // Used as the URL prefix for fetched files. // Default: Fetch files relative to `url`. @@ -31,9 +34,37 @@ export interface XmlHttpRequestOptions { } /** - * A simple filesystem backed by XMLHttpRequests. + * A simple filesystem backed by XMLHttpRequests. You must create a directory listing using the + * `make_xhrfs_index` tool provided by BrowserFS. + * + * If you install BrowserFS globally with `npm i -g browserfs`, you can generate a listing by + * running `make_xhrfs_index` in your terminal in the directory you would like to index: + * + * ``` + * make_xhrfs_index > index.json + * ``` + * + * Listings objects look like the following: + * + * ```json + * { + * "home": { + * "jvilk": { + * "someFile.txt": null, + * "someDir": { + * // Empty directory + * } + * } + * } + * } + * ``` + * + * *This example has the folder `/home/jvilk` with subfile `someFile.txt` and subfolder `someDir`.* */ export default class XmlHttpRequest extends BaseFileSystem implements FileSystem { + /** + * Construct an XmlHttpRequest file system backend with the given options. + */ public static Create(opts: XmlHttpRequestOptions, cb: BFSCallback): void { if (typeof(opts.index) === "string") { XmlHttpRequest.FromURL(opts.index, cb, opts.baseUrl, false); @@ -45,6 +76,8 @@ export default class XmlHttpRequest extends BaseFileSystem implements FileSystem return typeof(XMLHttpRequest) !== "undefined" && XMLHttpRequest !== null; } /** + * **Deprecated. Please use XmlHttpRequest.Create() method instead to construct XmlHttpRequest objects.** + * * Constructs an XmlHttpRequest object using the directory listing at the given URL. * Uses the base URL as the URL prefix for fetched files. * @param cb Called when the file system has been instantiated, or if an error occurs. @@ -65,39 +98,11 @@ export default class XmlHttpRequest extends BaseFileSystem implements FileSystem public readonly prefixUrl: string; private _index: FileIndex<{}>; /** + * **Deprecated. Please use XmlHttpRequest.Create() method instead to construct XmlHttpRequest objects.** + * * Constructs the file system. You must provide the directory listing as a JSON object * produced by the `make_xhrfs_index` script. * - * If you install BrowserFS globally with `npm i -g browserfs`, you can generate a listing by - * running `make_xhrfs_index` in your terminal in the directory you would like to index: - * - * ``` - * make_xhrfs_index > index.json - * ``` - * - * Listings objects look like the following: - * - * ```json - * { - * "home": { - * "jvilk": { - * "someFile.txt": null, - * "someDir": { - * // Empty directory - * } - * } - * } - * } - * ``` - * - * *This example has the folder `/home/jvilk` with subfile `someFile.txt` and subfolder `someDir`.* - * - * Alternatively, you can construct an XmlHttpRequest object by calling the static `FromURL` function: - * - * ```javascript - * BrowserFS.FileSystem.XmlHttpRequest.FromURL('http://example.com/files/index.json'); - * ``` - * * **DEPRECATED:** You may pass a URL to the file index to the constructor, which will fetch the file index * *synchronously* and may freeze up the web page. This behavior will be removed in the next major version * of BrowserFS. diff --git a/src/backend/ZipFS.ts b/src/backend/ZipFS.ts index 7d286854..ff14cf95 100644 --- a/src/backend/ZipFS.ts +++ b/src/backend/ZipFS.ts @@ -469,6 +469,9 @@ export class ZipTOC { } } +/** + * Configuration options for a ZipFS file system. + */ export interface ZipFSOptions { // The zip file as a binary buffer. zipData: Buffer; @@ -523,6 +526,9 @@ export default class ZipFS extends SynchronousFileSystem implements FileSystem { public static readonly CompressionMethod = CompressionMethod; /* tslint:enable:variable-name */ + /** + * Constructs a ZipFS instance with the given options. + */ public static Create(opts: ZipFSOptions, cb: BFSCallback): void { try { ZipFS.computeIndex(opts.zipData, (zipTOC) => { @@ -540,6 +546,9 @@ export default class ZipFS extends SynchronousFileSystem implements FileSystem { decompressionMethods[m] = fcn; } + /** + * **Deprecated. Please use ZipFS.Create() method instead.** + */ public static computeIndex(data: Buffer, cb: (zipTOC: ZipTOC) => void, deprecateMsg = true) { // TODO: Refactor to plumb errors through. Right now, they throw. if (deprecateMsg) { @@ -625,22 +634,7 @@ export default class ZipFS extends SynchronousFileSystem implements FileSystem { private data: Buffer; /** - * Constructs a ZipFS from the given zip file data. Name is optional, and is - * used primarily for our unit tests' purposes to differentiate different - * test zip files in test output. - * - * To avoid webpage responsiveness issues with large zip files, you can - * call the static function `computeIndex` first to construct the zipfile's - * table of contents, and then pass that object into the constructor: - * - * ```javascript - * BrowserFS.FileSystem.ZipFS.computeIndex(myLargeZipFile, function(zipTOC) { - * var myZipFs = new BrowserFS.FileSystem.ZipFS(zipTOC); - * }); - * ``` - * - * `computeIndex` will process the zip file in chunks to keep your webpage - * responsive. + * **Deprecated. Please use ZipFS.Create() method to construct ZipFS objects.** */ constructor(input: Buffer | ZipTOC, private name: string = '', deprecateMsg = true) { super(); diff --git a/src/core/browserfs.ts b/src/core/browserfs.ts index 95b8631e..5a4641d1 100644 --- a/src/core/browserfs.ts +++ b/src/core/browserfs.ts @@ -18,7 +18,8 @@ if (( process)['initializeTTYs']) { } /** - * @hidden + * Installs BFSRequire as global `require`, a Node Buffer polyfill as the global `Buffer` variable, + * and a Node process polyfill as the global `process` variable. */ export function install(obj: any) { obj.Buffer = Buffer; @@ -43,7 +44,7 @@ export function registerFileSystem(name: string, fs: FileSystemConstructor) { } /** - * @hidden + * Polyfill for CommonJS `require()`. For example, can call `BFSRequire('fs')` to get a 'fs' module polyfill. */ export function BFSRequire(module: 'fs'): typeof fs; export function BFSRequire(module: 'path'): typeof path; @@ -70,15 +71,15 @@ export function BFSRequire(module: string): any { } /** - * @hidden + * Initializes BrowserFS with the given root file system. */ export function initialize(rootfs: FileSystem) { return fs.initialize(rootfs); } /** - * Configure BrowserFS with an object containing file system names and configurations. - * @hidden + * Creates a file system with the given configuration, and initializes BrowserFS with it. + * See the FileSystemConfiguration type for more info on the configuration object. */ export function configure(config: FileSystemConfiguration, cb: BFSOneArgCallback): void { getFileSystem(config, (e, fs?) => { @@ -91,11 +92,37 @@ export function configure(config: FileSystemConfiguration, cb: BFSOneArgCallback }); } +/** + * Specifies a file system backend type and its options. + * + * Individual options can recursively contain FileSystemConfiguration objects for + * option values that require file systems. + * + * For example, to mirror Dropbox to LocalStorage with AsyncMirror, use the following + * object: + * + * ```javascript + * var config = { + * fs: "AsyncMirror", + * options: { + * sync: {fs: "LocalStorage"}, + * async: {fs: "Dropbox", options: {client: anAuthenticatedDropboxSDKClient }} + * } + * }; + * ``` + * + * The option object for each file system corresponds to that file system's option object passed to its `Create()` method. + */ export interface FileSystemConfiguration { fs: string; options: any; } +/** + * Retrieve a file system with the given configuration. + * @param config A FileSystemConfiguration object. See FileSystemConfiguration for details. + * @param cb Called when the file system is constructed, or when an error occurs. + */ export function getFileSystem(config: FileSystemConfiguration, cb: BFSCallback): void { const fsName = config['fs']; if (!fsName) {
Links
AsyncMirrorAsyncMirror
DropboxDropbox
EmscriptenEmscripten
FolderAdapterFolderAdapter ? ? ?
HTML5FSHTML5FS
IndexedDBIndexedDB
InMemoryInMemory
IsoFSIsoFS
LocalStorageLocalStorage
MountableFileSystemMountableFileSystem ? ? ? ?
OverlayFSOverlayFS ? ?
XmlHttpRequestXmlHttpRequest
WorkerFSWorkerFS ? ? ?
ZipFSZipFS