Skip to content

Migrate the monorepo to Node.js#104

Merged
taras merged 101 commits into
mainfrom
tm/bdd-node-support
Jan 18, 2026
Merged

Migrate the monorepo to Node.js#104
taras merged 101 commits into
mainfrom
tm/bdd-node-support

Conversation

@taras
Copy link
Copy Markdown
Member

@taras taras commented Dec 11, 2025

Motivation

Complete the Node.js migration for the effectionx repository, enabling all packages to run in Node.js environments. This also consolidates CI workflows for better maintainability and fixes Windows-specific process handling issues.

Approach

Effection Compatibility Testing

Added a compatibility test runner that tests packages against the minimum and maximum Effection versions declared by each package's peerDependencies.

┌─────────────────────────────────────────────────────────────────────────────┐
│                     Effection Compatibility Test Runner                     │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  1. RESOLVE VERSION GROUPS                                                  │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  Read pnpm-workspace.yaml                                              │ │
│  │       │                                                                │ │
│  │       ▼                                                                │ │
│  │  For each package:                                                     │ │
│  │    • Read package.json → peerDependencies.effection                    │ │
│  │    • Fetch all effection versions from npm                             │ │
│  │    • Resolve min (semver.minVersion) and max (semver.maxSatisfying)    │ │
│  │       │                                                                │ │
│  │       ▼                                                                │ │
│  │  Group packages by version:                                            │ │
│  │    version 3.0.0 → [pkg-a, pkg-b, pkg-c, ...]                          │ │
│  │    version 4.0.0 → [pkg-a, pkg-b, pkg-c, ...]                          │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  2. FOR EACH VERSION GROUP                                                  │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │                         ┌──────────────────┐                           │ │
│  │                         │ Version: 3.0.0   │                           │ │
│  │                         │ Packages: [...]  │                           │ │
│  │                         └────────┬─────────┘                           │ │
│  │                                  │                                     │ │
│  │    ┌─────────────────────────────┼─────────────────────────────┐       │ │
│  │    │                             ▼                             │       │ │
│  │    │  [1/3] Set pnpm override                                  │       │ │
│  │    │        pnpm config set pnpm.overrides.effection=3.0.0     │       │ │
│  │    │                             │                             │       │ │
│  │    │                             ▼                             │       │ │
│  │    │  [2/3] Install dependencies                               │       │ │
│  │    │        pnpm install --no-frozen-lockfile                  │       │ │
│  │    │                             │                             │       │ │
│  │    │                             ▼                             │       │ │
│  │    │  [3/3] Run tests with TAP output                          │       │ │
│  │    │        node --test packages/**/test/*.test.ts             │       │ │
│  │    └─────────────────────────────┬─────────────────────────────┘       │ │
│  │                                  │                                     │ │
│  │                                  ▼                                     │ │
│  │                         ┌──────────────────┐                           │ │
│  │                         │ Version: 4.0.0   │                           │ │
│  │                         │ Packages: [...]  │                           │ │
│  │                         └────────┬─────────┘                           │ │
│  │                                  │                                     │ │
│  │                            (repeat...)                                 │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  3. CLEANUP                                                                 │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │  • Remove .npmrc (created by pnpm config set)                          │ │
│  │  • Reinstall with original lockfile                                    │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘

New Packages

  • @effectionx/stream-yaml - Streaming YAML document parser for parsing multi-document YAML streams from string chunks
  • @effectionx/fs - File and directory operations based on node:fs
  • @effectionx/node - Node specific operations like fromReadable and on/once event emitter
  • @effectionx/converge - Imported convergence library from BigTest 1.0 to use when convergence in tests.

Stream Helpers: fromReadable()

Added fromReadable() to @effectionx/stream-helpers for converting Node.js Readable streams to Effection Streams. This enables easy integration with Node.js file streams, HTTP responses, and other Readable streams.

import fs from "node:fs";
import { fromReadable } from "@effectionx/stream-helpers";
import { each } from "effection";

function* example() {
  const fileStream = fs.createReadStream("./data.txt");

  for (const chunk of yield* each(fromReadable(fileStream))) {
    console.log(new TextDecoder().decode(chunk));
    yield* each.next();
  }
}

Key features

  • Added TAP parser (.internal/tap-parser.ts) for real-time test failure reporting
  • Shows failures as they happen with detailed error info (stack traces, expected vs actual)
  • Tests against both Effection 3.x and 4.x versions
  • Summary table at end with pass/fail counts per version

CI Workflow Consolidation

  • Consolidated verify-posix.yaml, verify-windows.yaml, and effection-compat.yaml into single test.yaml
  • All jobs (lint, test-posix, test-windows) now run in parallel
  • Windows tests use CMD shell instead of bash (fixes graceful process shutdown issues)
test.yaml
├── lint          (ubuntu) - fmt, lint, typecheck, tsrefs
├── test-posix    (ubuntu, macos) - build, test, test:effection
└── test-windows  (windows/cmd) - build, test, test:effection

Windows Process Handling Fixes

  • Fixed EPIPE errors when killing processes on Windows
  • Added error handler on stdin to suppress EPIPE during cleanup
  • Added error handler on stdout/stderr readable streams

Internal Tooling

  • Moved build scripts from tasks/ to .internal/
  • Added sync-tsrefs.ts for managing TypeScript project references
  • Improved publish workflow with matrix generation

Testing

  • All 153+ tests pass on Ubuntu, macOS, and Windows
  • Effection compatibility tests pass for both 3.x and 4.x

@taras taras force-pushed the tm/bdd-node-support branch 6 times, most recently from f4d0329 to ed141d1 Compare December 11, 2025 02:37
Copy link
Copy Markdown
Member

@cowboyd cowboyd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. My only question is if we should extends the packages to be compatible with e4

Comment thread context-api/package.json Outdated
Comment thread bdd/package.json Outdated
taras added 14 commits January 16, 2026 15:46
- Extract shared BDD logic into bdd.ts with createBDD factory function
- Add mod.deno.ts for Deno with SanitizeOptions support
- Add mod.node.ts for Node.js using node:test
- Add package.json with conditional exports for Node/Deno
- Update deno.json to export mod.deno.ts
- Add root package.json with npm workspaces for bdd and test-adapter
- Add test-adapter/package.json for Node.js resolution
- Update bdd/package.json to use npm-compatible dependency syntax
- Add node_modules and package-lock.json to .gitignore
- Add verify-node.yaml workflow for Node.js CI on ubuntu/macos with Node 20/22
- Add bdd/bdd.test.ts for testing the BDD package
- Add test scripts using npm workspaces (npm test --workspaces --if-present)
- Update README with Node.js testing documentation
- Add nodeModulesDir: "none" to deno.json to prevent Deno from
  using node_modules when package.json is present
- Add pnpm-workspace.yaml for pnpm workspace configuration
- Add package.json with Volta pinned versions and packageManager field
- Update bdd/package.json to use workspace:* for local deps
- Update CI to use pnpm/action-setup and actions/setup-node
- Update README with Volta installation instructions
- Create package.json with npm exports and dependencies
- Add tinyexec to pnpm workspace
Explicitly use --frozen-lockfile to ensure reproducible builds
and fail CI if lockfile is out of sync with package.json files.
- Create package.json with npm exports and dependencies
- Add timebox to pnpm workspace
- Create package.json with npm exports and dependencies
- Add context-api to pnpm workspace
- Create package.json with npm exports and dependencies
- Add fx to pnpm workspace
- Create package.json with npm exports and dependencies
- Add signals to pnpm workspace
- Add afterEachTest hook to BDD for assertion state cleanup
- Implement assertion state checking in mod.node.ts
- Add @std/expect and @std/internal via JSR registry (.npmrc)
- Add test scripts to context-api, fx, signals, timebox packages
- All 43 tests now pass on Node.js with expect.assertions() support
@taras taras force-pushed the tm/bdd-node-support branch from cbac99e to 60debac Compare January 16, 2026 20:49
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jan 16, 2026

Open in StackBlitz

@effectionx/bdd

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/bdd@104

@effectionx/chain

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/chain@104

@effectionx/context-api

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/context-api@104

@effectionx/converge

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/converge@104

@effectionx/fs

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/fs@104

@effectionx/fx

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/fx@104

@effectionx/jsonl-store

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/jsonl-store@104

@effectionx/node

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/node@104

@effectionx/process

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/process@104

@effectionx/raf

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/raf@104

@effectionx/signals

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/signals@104

@effectionx/stream-helpers

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/stream-helpers@104

@effectionx/stream-yaml

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/stream-yaml@104

@effectionx/task-buffer

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/task-buffer@104

@effectionx/test-adapter

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/test-adapter@104

@effectionx/timebox

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/timebox@104

@effectionx/tinyexec

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/tinyexec@104

@effectionx/watch

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/watch@104

@effectionx/websocket

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/websocket@104

@effectionx/worker

npm i https://pkg.pr.new/thefrontside/effectionx/@effectionx/worker@104

commit: 475da13

taras added 6 commits January 16, 2026 16:32
- Add engines >= 22 requirement
- Add strict pnpm peer dependency rules
- Add main/types fields for legacy compat
- Enable Biome for JSON files
- Integrate sync-tsrefs.ts for auto-generating tsconfig references
- Add check:tsrefs to CI workflow
- Add effection-based fs helpers plan (ensureDir, exists, emptyDir, walk)
- Add fromFileUrl/toFileUrl replacements
- Update test glob to exclude dist/node_modules
- Add JSDoc example updates for jsonl-store
- Add tsconfig.test.json for test file detection (Phase 1.4)
- Document all three sync-tsrefs modes: update, fix, check
- Add note about pnpm-workspace.yaml requiring explicit paths (no globs)
- Update package tsconfig template: include **/*.ts, exclude **/*.test.ts
- Renumber Phase 1 sections (1.4 biome → 1.5, etc.)
- Fix test glob: use './**/*.test.ts' instead of extglob syntax
  (Node's test runner doesn't support extglob '!()')
- Add note that sync:tsrefs skips packages without tsconfig.json
- Clarify that tsconfig.json must be created before running sync:tsrefs
- Note that root tsconfig.test.json is used as fallback for test detection
- Clarify tsconfig.test.json location (repository root) and mark as required
- Document sync-tsrefs subcommand modes (update/fix/check)
- Explain devDependencies vs dependencies classification for workspace imports
- Add workspace:* version format to dependency examples
- Emphasize prerequisites: tsconfig.json and tsconfig.test.json must exist
- Explain tsconfig.test.json include/exclude pattern matching for test file classification
- Document sync-tsrefs.ts subcommands (update/fix/check) in Phase 5.4
- Note that fix mode updates package.json dependencies
- Explain why --experimental-strip-types is used for task scripts
- Biome config already doesn't ignore JSON (verified consistent with decisions)
taras added 8 commits January 17, 2026 19:25
- Implement yamlDocuments() stream helper using yaml package Parser/Composer
- Properly exhaust composer.next() generators to update internal state
- Support multi-document YAML streams (documents separated by ---)
- Forward close value from upstream stream
- Add comprehensive test suite (6 tests)
…rting

- Move lines() helper from process to stream-helpers, fix FIFO ordering bug
- Add tap-parser.ts for streaming TAP output parsing with YAML metadata
- Update effection-compat.ts to show failures in real-time
- Add summary table and detailed failure output at end
- Use --test-reporter=tap and --log-order=grouped for structured output
- Use node --test with glob patterns instead of pnpm turbo run test
- Fix test counting to include tests without type metadata
- Skip suite-level failures (subtestsFailed) to avoid double-counting
When a process is killed on Windows, the stream may emit an 'error' event
with EPIPE before 'end'. This is treated as a normal close since the
process was intentionally terminated.
Add error handler on stdin stream to suppress EPIPE errors that occur
when the child process exits before we finish writing to it. This is
expected during cleanup when killing processes on Windows.
@taras taras force-pushed the tm/bdd-node-support branch from 67213ef to 47e71eb Compare January 18, 2026 02:38
@taras taras changed the title Add Node.js support to @effectionx/bdd package Migrate everything to Node Jan 18, 2026
- Combine verify-posix, verify-windows, and effection-compat into test.yaml
- Run lint, test-posix, and test-windows jobs in parallel
- Windows tests use CMD shell (fixes graceful shutdown issues with bash)
- Each test job runs both unit tests and effection compatibility tests
- Update publish.yaml to depend on consolidated test workflow
@taras taras force-pushed the tm/bdd-node-support branch from 7741ad4 to 78066eb Compare January 18, 2026 02:51
@taras taras changed the title Migrate everything to Node Node.js Migration with BDD Support and CI Consolidation Jan 18, 2026
@taras taras changed the title Node.js Migration with BDD Support and CI Consolidation Migrate the monorepo to Node.js Jan 18, 2026
taras and others added 13 commits January 17, 2026 22:17
- Add fromReadable() to @effectionx/stream-helpers for converting Node.js
  Readable streams to Effection Streams
- Add tests and documentation for fromReadable()
- Update @effectionx/process to use fromReadable from stream-helpers
- Fix type annotation in watch/main.ts
Consolidate Node.js-specific utilities into a new @effectionx/node package with
sub-exports for streams and events:
- /stream: fromReadable (moved from stream-helpers)
- /events: once, on (moved from node-events)

Changes:
- Create node/ package with stream.ts, events.ts, and mod.ts
- Delete node-events package (not yet published)
- Remove fromReadable from stream-helpers
- Update process package to import from @effectionx/node
- Remove unused node-events dependency from worker package
- Update workspace and TypeScript configurations
- Update root devDependency to effection ^4
- Update .internal dependency to effection ^4
- Update all package peerDependencies from '^3 || ^4.0.0-0' to '^3 || ^4'
- Cherry-pick fx v4 compatibility changes from fx-v4 branch
- Port when() and always() from @bigtest/convergence as Effection Operations
- when(): converge when assertion passes within timeout
- always(): converge if assertion passes throughout timeout
- Both return stats object with timing info and run count
- Update worker shutdown test to use when() for reliable file content checks
- Fixes flaky test by properly converging on expected file content
- Use writeFileSync in shutdown-worker.ts finally block to ensure file
  write completes before worker exits (async writes may not complete
  during task halt on Windows)
- Remove shell: true from effection-compat.ts and pass arguments
  separately to exec() since shell: true doesn't work properly on
  Windows with cross-spawn
@taras taras merged commit c671a75 into main Jan 18, 2026
6 checks passed
@taras taras deleted the tm/bdd-node-support branch January 18, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants