commits
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add tsconfig.build.json for emitting JS + declarations to dist/
- Add build script and publishConfig exports for dist/
- Source exports preserved for local development
- Add build step to publish workflow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI runs on all pushes and PRs. Publish runs only on push to main,
with lint/typecheck/test as gates before the publish step.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add prettier for linting with lint/lint:fix scripts
- Add @changesets/cli for version management and npm publishing
- Add .tangled/workflows/ci.yaml (lint, typecheck, test on push/PR)
- Add .tangled/workflows/publish.yaml (changeset version + publish on main)
- Format codebase with prettier
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Streaming section to README covering streaming moroutines,
channel() fan-out, and pipeline chaining
- Add @param/@returns TSDoc to mo(), channel(), Runner, Task,
StreamTask, ChannelOptions, and transfer()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add channel-fanout example demonstrating work-stealing fan-out
- Add benchmark example measuring roundtrip channel throughput
- Remove channel() from pipeline example (auto-detection handles it)
- Fix Moroutine type to use Awaited<R> so async tasks resolve correctly
- Fix channel-fanout test types to use destructuring instead of any[]
- Add new examples to README
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds auto-detection in prepareArg so AsyncGenerator and StreamTask
values are automatically piped via MessageChannel without needing
a channel() wrapper.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix worker ref/unref lifecycle so dedicated workers don't hold the event
loop open when idle: setupWorker before unref (so unref wins), then
ref/unref around each execute() call and for the duration of each
dispatchStream(). Streaming port1 is unref'd after its listener is
added, so stream completion triggers natural exit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Opens a SQLite database once on the worker via a task-arg. All
subsequent queries receive the cached db instance — the DatabaseSync
object never crosses thread boundaries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The first overload shows clean parameter types (no Arg<T> wrappers).
The second overload accepts Task<T> args as a fallback. IDEs display
the clean signature by default.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a Task is passed as an argument to another moroutine, the worker
resolves it on first encounter and caches the result by task uid.
Subsequent calls with the same task reuse the cached value. This enables
worker-local context patterns — the resolved value never crosses thread
boundaries, so it can hold complex non-serializable state like database
connections or compiled indexes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
run() now accepts either a single Task or an array of Tasks.
With an array, it returns Promise<[R1, R2, ...]> with proper
tuple typing. Replaces Promise.all([run(a), run(b)]) pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Demonstrates multiple workers updating a shared struct position
protected by a mutex to prevent read-modify-write races.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Node 24 supports TypeScript type stripping natively. The flag is kept
in package.json test script for backward compatibility but removed
from example comments.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use Simplify<T> and & {} to force TypeScript to eagerly evaluate
mapped types, showing { x: number; y: number } instead of
FieldValues<{ x: Int32; y: Int32 }> in IDE tooltips.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Overloaded shared() so that:
- shared(int32) returns Int32
- shared({ x: int32, y: int32 }) returns SharedStruct<{ x: Int32, y: Int32 }>
- shared([int32, int64]) returns Tuple<[Int32, Int64]>
- shared(42) returns Int32
- shared(0n) returns Int64
- shared(true) returns Bool
- shared(bytes(n)) returns Bytes
- shared(string(n)) returns SharedString
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add prettier for linting with lint/lint:fix scripts
- Add @changesets/cli for version management and npm publishing
- Add .tangled/workflows/ci.yaml (lint, typecheck, test on push/PR)
- Add .tangled/workflows/publish.yaml (changeset version + publish on main)
- Format codebase with prettier
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add channel-fanout example demonstrating work-stealing fan-out
- Add benchmark example measuring roundtrip channel throughput
- Remove channel() from pipeline example (auto-detection handles it)
- Fix Moroutine type to use Awaited<R> so async tasks resolve correctly
- Fix channel-fanout test types to use destructuring instead of any[]
- Add new examples to README
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix worker ref/unref lifecycle so dedicated workers don't hold the event
loop open when idle: setupWorker before unref (so unref wins), then
ref/unref around each execute() call and for the duration of each
dispatchStream(). Streaming port1 is unref'd after its listener is
added, so stream completion triggers natural exit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a Task is passed as an argument to another moroutine, the worker
resolves it on first encounter and caches the result by task uid.
Subsequent calls with the same task reuse the cached value. This enables
worker-local context patterns — the resolved value never crosses thread
boundaries, so it can hold complex non-serializable state like database
connections or compiled indexes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Overloaded shared() so that:
- shared(int32) returns Int32
- shared({ x: int32, y: int32 }) returns SharedStruct<{ x: Int32, y: Int32 }>
- shared([int32, int64]) returns Tuple<[Int32, Int64]>
- shared(42) returns Int32
- shared(0n) returns Int64
- shared(true) returns Bool
- shared(bytes(n)) returns Bytes
- shared(string(n)) returns SharedString
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>