Using ZenFS
This is the full usage guide for ZenFS. If you just want to get something running, start with the quick start.
The default filesystem
Section titled “The default filesystem”A single InMemory backend is created by default and mounted on /, so fs works with no setup:
import { fs } from '@zenfs/core'; // You can also use the default export
fs.writeFileSync('/test.txt', 'You can do this anywhere, including browsers!');
const contents = fs.readFileSync('/test.txt', 'utf-8');console.log(contents);Using different and/or multiple backends
Section titled “Using different and/or multiple backends”You can configure ZenFS to use a different backend and mount multiple backends. It is strongly
recommended to do so using the configure function.
You can use multiple backends by passing an object to configure which maps paths to file systems.
The following example mounts a zip file to /mnt/zip, in-memory storage to /tmp, and IndexedDB to
/home. / has the default in-memory backend.
import { configure, InMemory } from '@zenfs/core';import { IndexedDB } from '@zenfs/dom';import { Zip } from '@zenfs/archives';
const res = await fetch('mydata.zip');
await configure({ mounts: { '/mnt/zip': { backend: Zip, data: await res.arrayBuffer() }, '/tmp': InMemory, '/home': IndexedDB, },});You aren’t required to use absolute paths for the keys of mounts, but it is a good
practice to do so.
If you only need a single backend mounted at /, configureSingle is more direct. Here is an
example that mounts the WebStorage backend from @zenfs/dom:
import { configureSingle, fs } from '@zenfs/core';import { WebStorage } from '@zenfs/dom';
await configureSingle({ backend: WebStorage });
if (!fs.existsSync('/test.txt')) { fs.writeFileSync('/test.txt', 'This will persist across reloads!');}
const contents = fs.readFileSync('/test.txt', 'utf-8');console.log(contents);For everything configure accepts (including permissions), see Configuration.
FS promises
Section titled “FS promises”The FS promises API is exposed as promises.
import { configureSingle } from '@zenfs/core';import { exists, writeFile } from '@zenfs/core/promises';import { IndexedDB } from '@zenfs/dom';
await configureSingle({ backend: IndexedDB });
if (!(await exists('/myfile.txt'))) { await writeFile('/myfile.txt', 'Lots of persistent data');}Mounting and unmounting, creating backends
Section titled “Mounting and unmounting, creating backends”If you would like to create backends without configure (e.g. to do something dynamic at runtime),
you may do so by importing the backend and calling resolveMountConfig with it.
You can then mount and unmount the backend instance by using mount and umount.
import { configure, resolveMountConfig, InMemory, fs } from '@zenfs/core';import { IndexedDB } from '@zenfs/dom';import { Zip } from '@zenfs/archives';
await configure({ mounts: { '/tmp': InMemory, '/home': IndexedDB, },});
fs.mkdirSync('/mnt/zip', { recursive: true });
const res = await fetch('mydata.zip');const zipfs = await resolveMountConfig({ backend: Zip, data: await res.arrayBuffer() });fs.mount('/mnt/zip', zipfs);
// do stuff with the mounted zip
fs.umount('/mnt/zip'); // finished using the zipnode:* emulation
Section titled “node:* emulation”ZenFS also includes emulation of some other node: modules for various reasons, importable from
@zenfs/core/<name>:
node:pathnode:readline
For example:
import * as path from '@zenfs/core/path';Bundling
Section titled “Bundling”ZenFS exports a drop-in for Node’s fs module, so you can use it for your bundler of preference
using the default export.