A copy-on-write virtual filesystem layer over a pluggable backing store. Reads fall through to the underlying adapter; writes are captured in memory until explicitly applied or discarded.
- Copy-on-write semantics -- modifications are staged in memory, leaving the backing store untouched until you call
apply() - Pluggable adapters -- swap between local disk, SQLite, or your own
FsAdapterimplementation - Browser-compatible public API -- uses
Uint8Arrayinstead ofBuffer,ReadableStreaminstead of Node streams - POSIX-like interface --
readFile,writeFile,mkdir,rm,stat,chmod,chown,symlink,rename, and more - Change tracking -- inspect pending changes via
getChanges()andgetChangeDetail() - Atomic apply -- commit all pending changes to the backing adapter in one operation, with per-file error reporting
pnpm add @catmint-fs/coreimport { createLayer } from "@catmint-fs/core";
// Create a layer backed by the local filesystem
const layer = await createLayer({ root: "/path/to/project" });
// Read a file (falls through to disk)
const data = await layer.readFile("/src/index.ts");
// Write a file (captured in memory)
await layer.writeFile("/src/index.ts", "export default 42;\n");
// Inspect what changed
const changes = layer.getChanges();
// [{ type: "update", path: "/src/index.ts" }]
// Apply all pending changes to disk
const result = await layer.apply();
console.log(result.applied); // number of changes written
// Or discard everything
layer.reset();Factory function that creates a Layer instance.
interface CreateLayerOptions {
root: string; // Absolute path for the layer root
adapter?: FsAdapter; // Defaults to LocalAdapter (Node.js only)
}| Method | Signature |
|---|---|
readFile |
(path: string) => Promise<Uint8Array> |
createReadStream |
(path: string) => ReadableStream<Uint8Array> |
readdir |
(path: string) => Promise<DirentEntry[]> |
stat |
(path: string) => Promise<StatResult> |
lstat |
(path: string) => Promise<StatResult> |
readlink |
(path: string) => Promise<string> |
exists |
(path: string) => Promise<boolean> |
| Method | Signature |
|---|---|
writeFile |
(path: string, data: string | Uint8Array, options?: WriteOptions) => Promise<void> |
mkdir |
(path: string, options?: MkdirOptions) => Promise<void> |
rm |
(path: string, options?: RmOptions) => Promise<void> |
rmdir |
(path: string) => Promise<void> |
rename |
(from: string, to: string) => Promise<void> |
symlink |
(target: string, path: string) => Promise<void> |
| Method | Signature |
|---|---|
chmod |
(path: string, mode: number) => Promise<void> |
chown |
(path: string, uid: number, gid: number) => Promise<void> |
lchown |
(path: string, uid: number, gid: number) => Promise<void> |
getOwner |
(path: string) => Promise<{ uid: number; gid: number }> |
| Method | Signature |
|---|---|
getChanges |
() => ChangeEntry[] |
getChangeDetail |
(path: string) => Promise<ChangeDetail | null> |
| Method | Description |
|---|---|
apply(options?) |
Commits all pending changes to the backing adapter. Returns ApplyResult. |
reset() |
Discards all pending changes. |
dispose() |
Releases resources. The layer is unusable after this call. |
Implement this interface to create a custom backing store:
interface FsAdapter {
readFile(path: string): Promise<Uint8Array>;
createReadStream(path: string): ReadableStream<Uint8Array>;
readdir(path: string): Promise<DirentEntry[]>;
stat(path: string): Promise<StatResult>;
lstat(path: string): Promise<StatResult>;
readlink(path: string): Promise<string>;
exists(path: string): Promise<boolean>;
writeFile(path: string, data: Uint8Array, options?: WriteOptions): Promise<void>;
mkdir(path: string, options?: MkdirOptions): Promise<void>;
rm(path: string, options?: RmOptions): Promise<void>;
rmdir(path: string): Promise<void>;
rename(from: string, to: string): Promise<void>;
symlink(target: string, path: string): Promise<void>;
chmod(path: string, mode: number): Promise<void>;
chown(path: string, uid: number, gid: number): Promise<void>;
lchown(path: string, uid: number, gid: number): Promise<void>;
checkPermission(path: string, op: PermissionOp): Promise<void>;
capabilities(): AdapterCapabilities;
initialize?(root: string): Promise<void>;
}LocalAdapter-- Delegates to Node.jsfsmodule. Used by default when no adapter is specified. Node.js only.
The Layer class and the FsAdapter interface use only browser-safe types (Uint8Array, ReadableStream). To use @catmint-fs/core in a browser, provide a custom FsAdapter implementation -- LocalAdapter is Node.js only.
GPL-2.0 -- see LICENSE for details.