Stackline Open Source maintained continuation

Node.js filesystem streams · ISC

@stackline/fstream

Walk files and directory trees as stat-bearing stream objects, then pipe them into metadata-aware writers—without abandoning the established fstream@1.0.12 contract.

npm install @stackline/fstream

Keep an existing import unchanged with fstream: npm:@stackline/fstream in your dependencies.

01 / Object-stream model

One tree, observable at every level.

A Reader discovers the filesystem type, exposes stat metadata, and selects the matching file, directory, link, socket, or proxy reader. A directory emits direct entry objects and recursive child objects. Pipe the root into a Writer to recreate the tree and supported metadata.

02 / Quick start

Copy a directory tree.

The destination type can be inferred. Attach error listeners before the stream begins changing the filesystem.

const fstream = require('@stackline/fstream')

const reader = fstream.Reader({
  path: 'source',
  sort: 'alpha'
})
const writer = fstream.Writer('destination')

reader.on('error', console.error)
writer.on('error', console.error)
reader.pipe(writer)

03 / Public API

Small surface, rich entries.

Open the complete API reference →

Reader(pathOrOptions[, stat])

Inspect and stream

Callable with or without new. Returns the specialized reader and exposes path, type, size, props, parent/root context, and lifecycle events.

Writer(pathOrOptions[, stat])

Create and preserve

Creates files, directories, symbolic links, and hard links; creates missing parents; and applies requested mode, ownership, and timestamps where the host permits.

collect(stream)

Stage before piping

Pauses a compatible legacy stream and buffers data and entries until its replacement pipe() is called. Destinationless replay remains supported.

AbstractReaderWriterFileDirLinkProxycollect

04 / Lifecycle

Ready means metadata is ready.

Typed readers begin with ready === false. Stat metadata is copied before ready; directory entries follow. Successful completion emits end and then close. A successful close is terminal.

With follow: true, descendant links are followed. A link that revisits an ancestor remains observable, emits one ELOOP warning, and ends only that branch.

  1. 01
    statFilesystem metadata discovered
  2. 02
    readyEntry metadata is complete
  3. 03
    entries / entry / child / dataType-specific stream activity
  4. 04
    warn or errorRecoverable or terminal observations
  5. 05
    end → closeTerminal success sequence

05 / Migration

Choose the size of your diff.

Full migration checklist →
Lowest change

Alias the dependency

"fstream": "npm:@stackline/fstream@1.0.0"

Existing require('fstream') calls stay unchanged. Commit the manifest and lockfile together.

Explicit adoption

Use the scoped name

import { Reader, Writer } from
  '@stackline/fstream'

Real ESM and first-party TypeScript declarations are additive. The default ESM export is the CommonJS namespace object.

Re-test in your application symlink cycleshard linksfilters and orderingread-only entriespermissions and timestampsclose handling

06 / Filesystem boundary

Compatibility is not containment.

Writers mutate caller-selected paths and clobber incompatible destinations by default. Link following may leave the lexical source tree. Validate source and destination paths, enforce an allowed root, and apply size, depth, entry-count, and timeout limits around untrusted input.

Cycle detection prevents ancestor recursion; it is not a sandbox or archive extraction policy. The package has no browser build and makes no browser filesystem claim.

Read the complete safe-use boundary →

07 / Reference files

The contract is inspectable.