Create a snapshot of a directory for use with
memfs
I wanted something to help convert directories of test fixtures on-disk to a format usable by an in-memory filesystem (memfs).
To that end, the snapshot-fs
package ships a CLI, snapshot-fs
, which converts a directory tree to a Compact JSON, CBOR or DirectoryJSON snapshot for use with memfs
.
- The command-line options have changed; see Usage below.
- The default input/output format is now CJSON.
- CBOR snapshots are now supported.
- The
export
subcommand got a--dry-run
flag.
- The command-line options have changed; see Usage below.
snapshot-fs
can now re-create a directory on the filesystem from a JSON snapshot.loadSnapshot()
is nowreadSnapshot()
- Export functionality exposed via
exportSnapshot()
snapshot-fs
requires Node.js v22.13.0 or newer.
snapshot-fs
can be run via npx snapshot-fs
or installed globally via npm install -g snapshot-fs
. Or however else you want to consume it.
snapshot-fs
exports both CommonJS and ES modules.
snapshot-fs [dest]
Create memfs snapshot from filesystem
Commands:
snapshot-fs create [dest] Create memfs snapshot from filesystem
[default]
snapshot-fs export <snapshot> [dest] Export a JSON snapshot to the filesystem
Output:
--separator, --sep Path separator
[choices: "posix", "win32"] [default: "posix"]
-f, --format Snapshot format
[string] [choices: "cbor", "cjson", "json"] [default: "cjson"]
Positionals:
dest Path to output file
Input:
-s, --source File or directory to snapshot
[string] [default: (current directory)]
Options:
--version Show version number [boolean]
--help Show help [boolean]
For more information, visit https://github.com/boneskull/snapshot-fs
When run without a subcommand, create
will be invoked.
create
w/ Compact JSON Snapshots
By default (as of v5.0.0), snapshot-fs
will create a snapshot in CJSON/Compact JSON format.
snapshot-fs --source /some/dir /path/to/output.json
This is equivalent to:
snapshot-fs create --source /some/dir /path/to/output.json --format=cjson
In your code, you can use the resulting file using memfs
directly:
import { type JsonUint8Array, type SnapshotNode, fromJsonSnapshot } from 'memfs/lib/snapshot/index.js';
import { memfs } from 'memfs';
const data = (await readFile(
'/path/to/output.json',
)) as unknown as JsonUint8Array<SnapshotNode>;
const {vol} = memfs()
await fromJsonSnapshot(data, fs: vol.promises);
console.log(vol.toTree());
// ... do your thing
...or you can use the readCJSONSnapshot()
helper from snapshot-fs
:
import type { JsonUint8Array, SnapshotNode } from 'memfs/lib/snapshot/index.js';
import { readCJSONSnapshot } from 'snapshot-fs';
const data = (await readFile(
'/path/to/output.json',
)) as unknown as JsonUint8Array<SnapshotNode>;
const vol = await readCJSONSnapshot(data);
console.log(vol.toTree());
This is fast; JSON.parse()
is never called!
(but we can get faster...)
create
w/ CBOR Snapshots
Similar to the above, you can create a CBOR-formatted snapshot this way:
snapshot-fs --source /some/dir /path/to/output.json --format=cbor
In your code, you can use the resulting file using memfs
directly:
import { type SnapshotNode, fromBinarySnapshot } from 'memfs/lib/snapshot/index.js';
import type { CborUint8Array } from '@jsonjoy.com/json-pack/lib/cbor/types.js';
import { memfs } from 'memfs';
const data = (await readFile(
'/path/to/output.json',
)) as unknown as CborUint8Array<SnapshotNode>;
const {vol} = memfs()
await fromBinarySnapshot(data, fs: vol.promises);
console.log(vol.toTree());
// ... do your thing
...or you can use the readCBORSnapshot()
helper from snapshot-fs
:
import {
type SnapshotNode,
fromBinarySnapshot,
} from 'memfs/lib/snapshot/index.js';
import type { CborUint8Array } from '@jsonjoy.com/json-pack/lib/cbor/types.js';
import { readCBORSnapshot } from 'snapshot-fs';
const data = (await readFile(
'/path/to/output.json',
)) as unknown as CborUint8Array<SnapshotNode>;
const vol = await readCBORSnapshot(data);
console.log(vol.toTree());
Caution
DirectoryJSON
is somewhat lossy and should be avoided if you ever want to re-create snapshots on your real filesystem (e.g., using export). For a directory full of text files, this is fine; for anything else, use CJSON or CBOR.
snapshot-fs --source /some/dir /path/to/output.json --format=json
This can be read into a memfs
Volume
like so:
import { readFile } from 'node:fs/promises';
import { memfs } from 'memfs';
const directoryJson = JSON.parse(
await readFile('/path/to/output.json', 'utf8'),
);
const { vol } = memfs();
vol.fromJSON(directoryJson);
This allows you to re-create a directory on the filesystem from a snapshot. Handy!
snapshot-fs export <snapshot> [dest]
Export a JSON snapshot to the filesystem
Positionals:
snapshot Path to snapshot file (CBOR/CJSON/DirectoryJSON) [required]
dest Destination directory [default: Current working directory]
Output:
--separator, --sep Path separator
[choices: "posix", "win32"] [default: "posix"]
Options:
--version Show version number [boolean]
--help Show help [boolean]
-D, --dry-run Print what would be written to the filesystem [boolean]
-f, --format Snapshot format
[string] [choices: "cbor", "cjson", "json"] [default: "cjson"]
If you have a snapshot (either format) and you want to re-create snapshot on the filesystem, use the export
subcommand:
snapshot-fs export /path/to/snapshot.json /path/to/output
The destination directory will be created if it doesn't exist.
Tip
Use the --dry-run
flag with export
to see what would be written to the filesystem.
Some potentially-useful stuff exported from snapshot-fs
:
createSnapshot()
/createDirectoryJSONSnapshot()
/createCJSONSnapshot()
/createCBORSNapshot()
- Create a JSON snapshot from a real or virtual FSreadSnapshot()
/readDirectoryJSONSnapshot()
/readCBORSnapshot()
/readCJSONSnapshot()
- Read a snapshot from a file and load it into a real or virtual FSexportSnapshot()
- Alias forreadSnapshot()
defaulting to the real FS
See the typings for more information.
Copyright 2024 Christopher Hiller. Licensed Apache-2.0