https://github.com/boneskull/snapshot-fs
Create a snapshot of a directory for use with memfs
https://github.com/boneskull/snapshot-fs
filesystem fixture json memfs snapshot testing
Last synced: 4 months ago
JSON representation
Create a snapshot of a directory for use with memfs
- Host: GitHub
- URL: https://github.com/boneskull/snapshot-fs
- Owner: boneskull
- License: apache-2.0
- Created: 2024-03-05T01:06:55.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-10-10T16:48:48.000Z (4 months ago)
- Last Synced: 2025-10-10T18:02:57.324Z (4 months ago)
- Topics: filesystem, fixture, json, memfs, snapshot, testing
- Language: TypeScript
- Homepage:
- Size: 1.33 MB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# snapshot-fs
> Create a snapshot of a directory for use with `memfs`
>
> 
## About
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`.
## 🎁 _New in v5.0.0_
- The command-line options have changed; see [Usage](#usage) below.
- The default input/output format is now CJSON.
- CBOR snapshots are now supported.
- The `export` subcommand got a `--dry-run` flag.
## 🎁 _New in v2.0.0_
- The command-line options have changed; see [Usage](#usage) below.
- `snapshot-fs` can now re-create a directory on the filesystem from a _JSON snapshot_.
- `loadSnapshot()` is now `readSnapshot()`
- Export functionality exposed via `exportSnapshot()`
## Install
**`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.
## Usage
```text
snapshot-fs [dest]
Create memfs snapshot from filesystem
Commands:
snapshot-fs create [dest] Create memfs snapshot from filesystem
[default]
snapshot-fs export [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][Compact JSON] format.
```sh
snapshot-fs --source /some/dir /path/to/output.json
```
This is equivalent to:
```sh
snapshot-fs create --source /some/dir /path/to/output.json --format=cjson
```
In your code, you can use the resulting file using `memfs` directly:
```ts
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;
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`:
```ts
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;
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:
```sh
snapshot-fs --source /some/dir /path/to/output.json --format=cbor
```
In your code, you can use the resulting file using `memfs` directly:
```ts
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;
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`:
```ts
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;
const vol = await readCBORSnapshot(data);
console.log(vol.toTree());
```
### `create` w/ `DirectoryJSON` Snapshots
> [!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](#export)). For a directory full of text files, this is fine; for anything else, use CJSON or CBOR.
```sh
snapshot-fs --source /some/dir /path/to/output.json --format=json
```
This can be read into a `memfs` `Volume` like so:
```js
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);
```
### `export`
This allows you to re-create a directory on the filesystem from a snapshot. Handy!
```text
snapshot-fs export [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:
```sh
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.
## API
Some potentially-useful stuff exported from `snapshot-fs`:
- `createSnapshot()`/`createDirectoryJSONSnapshot()`/`createCJSONSnapshot()`/`createCBORSNapshot()` - Create a JSON snapshot from a real or virtual FS
- `readSnapshot()`/`readDirectoryJSONSnapshot()`/`readCBORSnapshot()`/`readCJSONSnapshot()` - Read a snapshot from a file and load it into a real or virtual FS
- `exportSnapshot()` - Alias for `readSnapshot()` defaulting to the real FS
See the typings for more information.
## License
Copyright 2024 [Christopher Hiller](https://github.com/boneskull). Licensed Apache-2.0
[memfs]: https://npm.im/memfs
[Compact JSON]: https://jsonjoy.com/specs/compact-json
[CBOR]: https://en.wikipedia.org/wiki/CBOR
[DirectoryJSON]: https://github.com/streamich/memfs/blob/2c6a6ca55ad2e661f40e488fe5ea4087438bae0e/src/volume.ts#L196-L198