Browse API

API · v0.39.1 · changelog

fs

Standard library filesystem

Runtime support

  • Node
  • Deno
  • Bun
  • Browser

Browser: Imports safely, but filesystem operations are unavailable.

Member signatures use schematic object.member(...) API notation. Exported type declarations are valid TypeScript.

Portable filesystem operations and FileRef construction.

Node, Deno, and Bun use native filesystem implementations. Browser bundles are safe to import: reference construction and lexical operations work, while disk operations throw when called.

ts
import fs from "@rcompat/fs";
import type {
  DirectoryOptions, FileInfo, FileRef, FileType, Filter, ListOptions, GlobOptions, LinkOptions, NamedStreamable, Path, RemoveOptions, SpoolOptions, SpoolSnapshot, Streamable, WritableInput,
} from "@rcompat/fs";

fs.streamable#

Protocol key for objects that provide a web ReadableStream.

Registered globally as Symbol.for("std:symbol/stream"), preserving identity across runtimes, separately loaded copies, and the legacy @rcompat/symbol.stream export.

ts
fs.streamable: unique symbol;

fs.ref#

Creates a FileRef for a filesystem path.

Parameters

  • path — A native path, file URL, or existing reference.

Returns: A FileRef preserving the supplied native path spelling.

ts
fs.ref(path: Path): FileRef;

Example

ts
const config = fs.ref("config.json");
await config.writeJSON({ enabled: true });
await config.json(); // { enabled: true }

fs.isRef#

Checks whether a value is a compatible FileRef.

Parameters

  • value — The value to inspect.
ts
fs.isRef(value: unknown): value is FileRef;

fs.isStream#

Checks whether a value can provide a readable stream.

Parameters

  • value — The value to inspect.
ts
fs.isStream(value: unknown): value is Streamable;

fs.isNamedStream#

Checks whether a streamable value also has a name.

Parameters

  • value — The value to inspect.
ts
fs.isNamedStream(value: unknown): value is NamedStreamable;

fs.cwd#

Returns the current working directory as an absolute reference.

ts
fs.cwd(): FileRef;

fs.createDirectory#

Creates a directory.

Parameters

  • path — Directory path to create.
  • options — Directory creation options.

Default: options.recursive is true.

ts
fs.createDirectory(path: Path, options?: DirectoryOptions): Promise<void>;

fs.createFile#

Creates an empty file exclusively, without creating parents.

ts
fs.createFile(path: Path): Promise<void>;

Creates a symbolic link at linkPath, storing target.

ts
fs.createLink(
    linkPath: Path, target: Exclude<Path, URL>, options?: LinkOptions,
  ): Promise<void>;

fs.resolve#

Resolves a path from the current working directory.

Parameters

  • path — Path to resolve, or the current directory when omitted.
ts
fs.resolve(path?: Path): FileRef;

fs.list#

Lists immediate or recursive directory entries.

Parameters

  • path — Directory to list.
  • options — Recursion and filtering options.
ts
fs.list(path: Path, options?: ListOptions): Promise<FileRef[]>;

fs.files#

Lists file entries in a directory.

Parameters

  • path — Directory to list.
  • options — Recursion and filtering options.
ts
fs.files(path: Path, options?: ListOptions): Promise<FileRef[]>;

fs.dirs#

Lists directory entries in a directory.

Parameters

  • path — Directory to list.
  • options — Recursion and filtering options.
ts
fs.dirs(path: Path, options?: ListOptions): Promise<FileRef[]>;

fs.glob#

Lazily yields files matching a portable relative glob pattern.

Supports *, ?, ** path segments, and bracket classes. Brace expansion and extglobs are not supported. / is always the pattern separator. Wildcards do not match a leading dot in a path segment unless that segment starts with .. Symbolic links are not followed or yielded.

Results are absolute references beneath the resolved cwd and retain the runtime's native directory iteration order. Missing or non-directory roots produce no results; other filesystem errors reject iteration.

Parameters

  • pattern — Relative portable glob pattern.
  • options — Root directory and cancellation options.

Throws: A SyntaxError for malformed or unsupported patterns. Iteration also rejects on cancellation or filesystem errors other than a missing or non-directory root.

ts
fs.glob(pattern: string, options?: GlobOptions): AsyncIterable<FileRef>;

fs.exists#

Checks whether a path exists.

ts
fs.exists(path: Path): Promise<boolean>;

fs.empty#

Checks whether a file or directory is empty.

ts
fs.empty(path: Path): Promise<boolean>;

fs.arrayBuffer#

Reads a file into an array buffer.

ts
fs.arrayBuffer(path: Path): Promise<ArrayBuffer>;

fs.bytes#

Reads a file into an unsigned byte array.

ts
fs.bytes(path: Path): Promise<Uint8Array>;

fs.text#

Reads a UTF-8 text file.

ts
fs.text(path: Path): Promise<string>;

fs.json#

Reads and parses a JSON file.

ts
fs.json(path: Path): Promise<JSONValue>;

fs.stream#

Returns a readable stream for a path or streamable value.

ts
fs.stream(target: Path | Streamable): ReadableStream<unknown>;

fs.write#

Writes text, bytes, blobs, responses, or readable streams to a path.

ts
fs.write(path: Path, value: WritableInput): Promise<void>;

fs.spool#

Copies a byte stream to a private disposable file while incrementally computing its SHA-256 digest.

This operation uses backpressure and never buffers the complete input. It resolves only after source EOF, completed file writes, digest finalization, and optional expectedDigest verification. The returned snapshot reads the saved bytes rather than the original source.

spool() takes ownership of source while it runs. Abort, source or file failure, digest-finalization failure, and digest mismatch close resources, delete the partial file, and reject without returning a snapshot. Without expectedDigest, the returned digest is computed but not externally verified. Supply a trusted expected value before using this operation to gate delivery of an artifact.

The caller owns the result. Its one-shot stream removes the backing file after EOF or cancellation. Call dispose() if no consumer receives the stream, or to terminate an active read. Do not dispose immediately after constructing a streaming Response; allow its body to finish or be cancelled by the HTTP host. An abandoned, uncancelled body can retain its snapshot like any other open stream.

Browser bundles remain safe to import, but calling this disk-backed operation in a browser throws a clear unavailable-filesystem error.

Parameters

  • source — Byte stream to consume exactly once.
  • options — Digest verification and spooling cancellation options.

Throws: On invalid options, abort, source or file I/O failure, digest mismatch, digest finalization failure, or unsupported runtime.

ts
fs.spool(
    source: ReadableStream<Uint8Array>,
    options?: SpoolOptions,
  ): Promise<SpoolSnapshot>;

Example

ts
const snapshot = await fs.spool(response.body!, {
  expectedDigest: trustedDigest,
});
const verified = new Response(snapshot.stream(), {
  headers: { "content-length": String(snapshot.size) },
});

fs.writeJSON#

Writes a value as indented JSON.

ts
fs.writeJSON(path: Path, value: JSONValue): Promise<void>;

fs.size#

Returns a file's size in bytes.

ts
fs.size(path: Path): Promise<number>;

fs.webpath#

Converts a path to forward-slash separators.

ts
fs.webpath(path: Path): string;

fs.join#

Joins path segments into a new reference.

ts
fs.join(path: Path, ...paths: Exclude<Path, URL>[]): FileRef;

fs.normalize#

Lexically normalizes a path without accessing the filesystem.

ts
fs.normalize(path: Path): FileRef;

fs.isAbsolute#

Checks whether a path is absolute in native syntax.

ts
fs.isAbsolute(path: Path): boolean;

fs.relativeTo#

Returns a portable lexical path from base to path.

ts
fs.relativeTo(path: Path, base: Path): string;

fs.discover#

Walks upward until a directory containing a filename is found.

ts
fs.discover(path: Path, filename: string): Promise<FileRef>;

fs.type#

Returns the filesystem entry type, or null when it is missing.

ts
fs.type(path: Path): Promise<FileType>;

Types#

DirectoryOptions#

Options for creating a directory.

ts
interface DirectoryOptions {
  // Create missing parent directories.
  // Default: `true`
  recursive?: boolean;
}

FileInfo#

Information supplied to directory-entry filters.

This closed data shape remains an object type alias so it is assignable to consumers accepting Record<string, unknown>.

ts
type FileInfo = {
  // Native filesystem path for the entry.
  path: string;
  // Final path component including extensions.
  name: string;
  // Last extension including its leading dot.
  extension: string;
  // All extensions beginning at the first dot.
  fullExtension: string;
  // Kind of filesystem entry.
  type: "file" | "directory" | "link";
};

FileRef#

A pathlib-inspired reference to a file or directory.

Construct references through fs.ref() when possible. Methods perform filesystem work only when called; creating a reference does not access disk.

ts
declare class FileRef {}

Constructor#

new FileRef()#

Creates a reference without accessing the filesystem.

ts
constructor(path: Path)

Static methods#

FileRef.is()#

Checks whether a value carries the compatible FileRef brand.

ts
static is(x: unknown): x is FileRef

Instance properties#

file.path#

The native path spelling used to create this reference.

ts
get path(): string

file.name#

The final path component including its extension.

ts
get name(): string

file.base#

The final path component without its last extension.

ts
get base(): string

file.extension#

The last filename extension including its leading dot.

ts
get extension(): string

file.fullExtension#

All filename extensions beginning at the first dot.

ts
get fullExtension(): string

file.directory#

A reference to the parent directory.

ts
get directory(): FileRef

file.core#

The final path component without any extension.

ts
get core(): string

Instance methods#

file.join()#

Joins relative segments without lexical normalization. Absolute paths, drive-qualified operands and URLs are not join operands.

ts
join(...paths: Exclude<Path, URL>[]): FileRef

file.normalize()#

Explicitly normalizes . and .. into a new reference.

ts
normalize(): FileRef

file.isAbsolute()#

Checks whether this reference has an absolute native path.

ts
isAbsolute(): boolean

file.relativeTo()#

Returns a /-separated lexical path from base to this reference. Returns "." for the same location and rejects incompatible roots. This is not a containment or filesystem-identity check.

ts
relativeTo(base: Path): string

file.webpath()#

Converts native separators to forward slashes.

ts
webpath(): string

file.toURL()#

Converts this filesystem path to a native file: URL.

Relative paths are resolved from the current working directory according to the running host's pathToFileURL semantics.

ts
toURL(): URL

file.append()#

Appends text directly to the path.

ts
append(suffix: string): FileRef

file.bare()#

Removes the final extension and optionally appends text.

ts
bare(append?: string): FileRef

file.text()#

Reads the file as UTF-8 text.

ts
text(): Promise<string>

file.json()#

Reads and parses the file as JSON.

ts
json<T extends JSONValue>(): Promise<T>

file.bytes()#

Reads the file as bytes.

ts
bytes(): Promise<Uint8Array>

file.arrayBuffer()#

Reads the file into an array buffer.

ts
arrayBuffer(): Promise<ArrayBuffer>

file.stream()#

Opens a readable byte stream for the file.

Wrap the result in a Response and call response.text() to decode UTF-8 text.

ts
stream(): ReadableStream<Uint8Array>

file.size()#

Returns the file size in bytes.

ts
size(): Promise<number>

file.write()#

Writes supported text, binary, blob, response, or stream input.

ts
write(input: WritableInput): Promise<void>

file.writeJSON()#

Writes a value as indented JSON.

ts
writeJSON(input: JSONValue): Promise<void>

file.exists()#

Checks whether the referenced path exists.

ts
exists(): Promise<boolean>

file.type()#

Returns the entry type, or null when the path is missing.

ts
type(): Promise<FileType>

file.modified()#

Returns the modification time as Unix milliseconds.

ts
modified(): Promise<number>

file.empty()#

Checks whether a file has zero bytes or a directory has no entries.

ts
empty(): Promise<boolean>

file.list()#

Lists immediate or recursive directory entries.

ts
list(options?: ListOptions): Promise<FileRef[]>

file.files()#

Lists only file entries.

ts
files(options?: ListOptions): Promise<FileRef[]>

file.dirs()#

Lists only directory entries.

ts
dirs(options?: ListOptions): Promise<FileRef[]>

file.createDirectory()#

Creates this directory.

Default: options.recursive is true.

ts
createDirectory(options?: DirectoryOptions): Promise<void>

file.createFile()#

Exclusively creates an empty file, without creating parents.

ts
createFile(): Promise<void>

Creates a symbolic link at this reference, storing target unchanged. A relative target is interpreted from the link's directory when followed. Existing destinations and missing parents fail; dangling targets are valid.

ts
createLink(
    target: Exclude<Path, URL>, options?: LinkOptions,
  ): Promise<void>

file.remove()#

Removes this path.

Default: Missing paths do not fail unless options.fail is true.

ts
remove(options?: RemoveOptions): Promise<void>

file.copy()#

Copies this file or directory to another reference.

ts
copy(to: FileRef, filter?: Filter): Promise<void>

file.hash()#

Hashes the file contents.

Parameters

  • algorithm — A Web Crypto digest algorithm.

Default: "SHA-256"

ts
hash(algorithm?: string): Promise<string>

file.import()#

Dynamically imports the file, optionally returning one named export.

ts
import(name?: string): Promise<any>

file.discover()#

Walks upward to find a directory containing a filename.

ts
discover(filename: string): Promise<FileRef>

file.sibling()#

Returns a named reference in the same directory.

ts
sibling(name: string): FileRef

file.or()#

Returns this reference when it exists, otherwise a fallback value.

ts
or<T>(fallback: () => T): Promise<this | T>

file.toString()#

Returns the normalized path.

ts
toString(): string

Protocol members#

file[Symbol.replace]()#

Replaces this reference's string value inside another string.

ts
[Symbol.replace](
    string: string,
    replacement: string | StringReplacer,
  ): string

file[fs.streamable]()#

Returns the file's stream through fs.streamable.

ts
[fs.streamable](): ReadableStream<Uint8Array>

file[util.inspect.custom]()#

Formats the reference for Node-compatible object inspection.

ts
[util.inspect.custom](): string

file.Name protocol property#

The stable class name used by shared protocols.

ts
get Name(): "FileRef"

FileType#

The recognized kind of a filesystem entry, or null when it is missing.

ts
type FileType = "directory" | "file" | "link" | null;

Filter#

Selects directory entries synchronously or asynchronously.

Parameters

  • info — Information about the candidate entry.
ts
type Filter = (info: FileInfo) => MaybePromise<boolean>;

ListOptions#

Options for listing directory entries.

This remains an object type alias so options are assignable to broad Record<string, unknown> consumers. Consumers can still extend the shape through an interface or intersection.

ts
type ListOptions = {
  // Visit entries in nested directories.
  // Default: `false`
  recursive?: boolean;
  // Keep entries accepted by a regular expression or callback.
  filter?: RegExp | Filter;
};

GlobOptions#

Options for lazy filesystem glob scanning.

This remains an object type alias so options are assignable to broad Record<string, unknown> consumers. Consumers can still extend the shape through an interface or intersection.

ts
type GlobOptions = {
  // Directory against which the relative pattern is evaluated.
  cwd?: string;
  // Cancels traversal and causes the iterator to reject.
  signal?: AbortSignal;
};

LinkOptions#

Options for creating a symbolic link.

ts
type LinkOptions = {
  // Only symbolic links are supported.
  // Default: `"symbolic"`
  type?: "symbolic";
  // Windows target-kind hint; ignored by POSIX filesystems.
  targetType?: "file" | "directory";
};

NamedStreamable#

A streamable value with a filename or other display name.

Type parameters

  • T — The chunks produced by the stream.
ts
type NamedStreamable<T = unknown> = Streamable<T> & { name: string };

Path#

A complete filesystem path accepted by @rcompat/fs operations.

Native path strings and file:// strings are accepted. Strings beginning with a non-file <scheme>://, such as https://example.com/file.txt, are rejected before filesystem access. Drive-letter paths, including paths using doubled forward slashes such as C://Temp/file.txt, and ordinary filenames containing a colon remain native paths. URL objects must use the file: protocol. Filesystem helpers never fetch network resources.

APIs for relative path segments, such as FileRef.join(), exclude URL objects from this complete-path contract.

ts
type Path = FileRef | URL | string;

RemoveOptions#

Options for removing a filesystem entry.

ts
interface RemoveOptions extends DirectoryOptions {
  // Fail when the entry does not exist.
  // Default: `false`
  fail?: boolean;
  // Remove directory contents recursively.
  // Default: `true`
  recursive?: boolean;
}

SpoolOptions#

Options for creating a disposable streamed file snapshot.

This remains an object type alias so options are assignable to broad Record<string, unknown> consumers. Consumers can still extend the shape through an interface or intersection.

ts
type SpoolOptions = {
  // Digest algorithm. Only `SHA-256` is currently supported.
  algorithm?: "SHA-256";
  // Trusted 64-character hexadecimal SHA-256 digest to verify.
  expectedDigest?: string;
  // Aborts only the spooling phase.
  signal?: AbortSignal;
};

SpoolSnapshot#

An owned, disposable snapshot created by fs.spool().

ts
type SpoolSnapshot = {
  // Lowercase hexadecimal SHA-256 digest of the saved bytes.
  readonly digest: string;
  // Number of bytes saved.
  readonly size: number;
  // Opens the snapshot for its single read.
  stream(): ReadableStream<Uint8Array>;
  // Closes an active read and removes the backing file.
  // Safe to call repeatedly, including after stream completion.
  dispose(): Promise<void>;
};

Streamable#

A value that can provide a web ReadableStream.

Objects can expose streams through fs.streamable.

Type parameters

  • T — The chunks produced by the stream.
ts
type Streamable<T = unknown> =
  | Blob
  | ReadableStream<T>
  | { [fs.streamable](): ReadableStream<T> }
  ;

WritableInput#

Content accepted by filesystem write operations.

ts
type WritableInput =
  | ArrayBuffer
  | Uint8Array
  | Blob
  | ReadableStream
  | Response
  | string
  ;