Files
skills/docs/persistence/storage/storage-file/src/node-fs/node-fs.md
2026-05-29 08:20:56 +01:00

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 NodeFsLike object per call so callers can spread-and-override individual methods without mutating shared state.
  • Forwards readFile results through new Uint8Array(buffer, byteOffset, byteLength) so consumers get a stable Uint8Array view regardless of the underlying Buffer subclass.
  • Wraps node:fs/promises.open so the returned handle matches the structural NodeFsFileHandleLike interface (only read + close).
  • Translates readdir(path, { recursive: true, withFileTypes: true }) Dirent entries into the lighter NodeFsReaddirEntry shape exposed to the rest of the package.
  • Translates stat into the lighter NodeFsStatLike shape 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 readFile avoids a copy when callers operate on the result via DataView or pass it back into a hash function.