-
Notifications
You must be signed in to change notification settings - Fork 2
Release notes
Eugene Lazutkin edited this page May 22, 2026
·
4 revisions
Bundled major rewrite. Replaces the single 1.x Fork class with three functional primitives (fork, route, filter) and a picker helper layer, ships the whole package as ESM, and adds a parallel Web Streams flavor at stream-fork/web. None of the 2.x work-in-progress was published before the rewrite landed, so this is the first 2.x on npm.
- The package exports three primitives:
fork(broadcast, the default export),route(per-chunk single-target dispatch), andfilter(per-chunk predicate-per-output subset). All three are sinks (Writable on the Node side, WritableStream on the Web side) and gate upstream backpressure on the receiving downstreams' write completions — forforkevery live output, forroutethe single picked one, forfilterthe predicate-matched subset. - All primitives expose
.outputs(read-only snapshot of the live downstreams) and.isEmpty()(trueonce every downstream has failed). Dead downstreams are filtered out of subsequent writes automatically. - All primitives accept
options.ignoreErrors: when truthy, downstream errors are silently swallowed and the failing stream is dropped from the live set; when falsy (default), the first error per round is surfaced upstream (Node:'error'event; Web: upstreampipeTorejects). - New picker helpers under
stream-fork/utils/:-
pickRoundRobin(count)— load-balance. -
pickByHash(keyFn, count)— stable shard via djb2 (numeric keys used directly modulocount). -
pickByKey(keyFn, table)— explicit key→index lookup (plain object orMap). -
pickFirstMatch(predicates)— first-true predicate's index; append() => truefor catch-all. Picker helpers are pure functions, shared between the Node and Web trees.
-
-
Node Streams (
stream-fork, default entry) wrapsWritable. The three primitives are built on a shared internalmakeStreamPusher(stream)(src/stream-pusher.js) that wrapsstream.write/stream.endin a Promise-based interface and installs its own'error'listener so Node never crashes on otherwise-unhandled downstream errors. Mirrorsstream-join'smakeStreamPullersubstrate. -
Web Streams (
stream-fork/web) wrapsWritableStreamwith the same options surface. The Webforkis a backpressure-preserving generalization ofReadableStream.tee()to N outputs — unliketee, it does not buffer per branch (a slow branch slows upstream rather than ballooning a per-branch queue). Built on a parallel internalmakeWebStreamPusherthat acquires a writer, awaitswriter.readybefore eachwriter.write, and listens onwriter.closedfor async errors.
-
Functional API.
new Fork(outputs, options)from 1.x becomesfork(outputs, options)— nonew, no class. The staticFork.fork(...)factory is gone (the function IS the factory). - Node 22+ required. 1.x supported Node 6+ via the old CI matrix.
-
ESM-only (
"type": "module"). 1.x consumers usingrequire()must switch toimport(orawait import()from a CommonJS host).// before (1.x, CommonJS) const Fork = require('stream-fork'); // after (2.x, ESM) import fork from 'stream-fork';
-
Subpath imports for non-default primitives.
routeandfilterimport asstream-fork/route.jsandstream-fork/filter.js; picker helpers asstream-fork/utils/<name>.js; the Web flavor atstream-fork/web(or per-primitivestream-fork/web/route.jsetc.). The default export remainsfork(import fork from 'stream-fork'orimport fork from 'stream-fork/web') for back-compat with 1.x callers who imported the constructor under the nameFork.
-
src/layout with.jssource and hand-written.d.tssidecar per file (// @ts-self-types="./<name>.d.ts"directive at the top of each.js). - Default-export + named mirror applied across every public module: every
export default Xis paired withexport {X}so CJS hosts can destructure viaawait import(const {fork} = await import('stream-fork')). - Added:
AGENTS.md,CLAUDE.md,.github/COPILOT-INSTRUCTIONS.md, byte-identical.windsurfrules/.cursorrules/.clinerules,llms.txt,llms-full.txt,ARCHITECTURE.md,LICENSE. - Paired
.claude/commands/+.windsurf/workflows/forai-docs-updateandrelease-check. - Tests migrated from
heya-unittotape-six, restructured intotests/node/+tests/web/. Browser test workflow viatape-six-playwright(npm run test:browser). - CI: Node 22, 24, 26 on
ubuntu-latest,windows-latest,macos-latest;actions/checkout@v6+actions/setup-node@v6; runsts-check+js-checkin addition to tests. - Added
.github/dependabot.yml(npm + github-actions, weekly, grouped, npmversioning-strategy: increase-if-necessary). - Added
.github/FUNDING.yml. - Wiki content refreshed and the wiki repository is mounted as a submodule in the package repo.
No functional changes; metadata only. Safe to skip.
- Errors from downstream streams are now forwarded correctly. Thanks to dbubovych.
Republished to support Node 14.
Switched from _final() to the 'finish' event so the package would work on Node 6.
Documentation polish; no behavior change.
First public release. A single Fork class — a Writable that broadcast every chunk to every output, with proper backpressure handling.