2.8 KiB
2.8 KiB
node-fs
(no submodules)
Purpose
Provides the default NodeFsLike implementation backed by node:fs/promises and the two stream constructors from node:fs. The factory is the single binding point between this package and Node's filesystem APIs — every other module talks to the structural NodeFsLike interface so tests can substitute real in-memory or hooked adapters without vi.mock.
Features
- Returns a fresh
NodeFsLikeobject per call so callers can spread-and-override individual methods without mutating shared state. - Forwards
readFileresults throughnew Uint8Array(buffer, byteOffset, byteLength)so consumers get a stableUint8Arrayview regardless of the underlying Buffer subclass. - Wraps
node:fs/promises.openso the returned handle matches the structuralNodeFsFileHandleLikeinterface (onlyread+close). - Translates
readdir(path, { recursive: true, withFileTypes: true })Dirent entries into the lighterNodeFsReaddirEntryshape exposed to the rest of the package. - Translates
statinto the lighterNodeFsStatLikeshape exposing only the four fields the adapter reads.
Usage: Basic Example
import { defaultNodeFs } from "@suaveplan/storage-file";
const fs = defaultNodeFs();
await fs.mkdir("/tmp/store", { recursive: true });
await fs.writeFile("/tmp/store/hello.data", new TextEncoder().encode("hi"));
const data = await fs.readFile("/tmp/store/hello.data");
Usage: Advanced Example
import { defaultNodeFs, NodeFsStorage } from "@suaveplan/storage-file";
import type { NodeFsLike } from "@suaveplan/storage-file/types";
const base = defaultNodeFs();
// Wrap stat to ensure mtimes never go backwards under wall-clock skew.
const monotonicStat: NodeFsLike = {
...base,
async stat(path) {
const s = await base.stat(path);
return { ...s, mtimeMs: Math.max(s.mtimeMs, Date.now()) };
},
};
const storage = new NodeFsStorage({ rootDir: "/tmp/store", fs: monotonicStat });
API Reference
defaultNodeFs(): NodeFsLike— returns a fresh adapter object.
Every method on the returned object forwards to its node:fs/promises counterpart with minimal shape translation. See fs-adapter.types.md for the full method list.
Implementation Notes
- The factory pattern (vs a module-level singleton) is deliberate: returning a fresh object lets tests construct independent adapters per
it(...)block and verify ownership semantics. - The factory is dependency-free at module evaluation time — every Node import is at the top of the file, but
defaultNodeFs()itself doesn't reach into globals or open any handles. Callers can build the storage adapter at import time without paying any filesystem cost. - The lazy buffer-view translation in
readFileavoids a copy when callers operate on the result via DataView or pass it back into a hash function.