uniconnect
v0.1.1
Published
Zero-dependency universal connectors between Events, EventTargets and AsyncIterables with lightweight operators.
Downloads
7
Maintainers
Readme
Additional Examples
Debounce rapid events:
import { fromEventEmitter, debounceTime, pipe } from 'uniconnect';
const it = pipe(fromEventEmitter(emitter, 'data'), debounceTime(200));
for await (const v of it) console.log(v);Throttle with trailing:
import { fromEventEmitter, throttleTime, pipe } from 'uniconnect';
const it = pipe(fromEventEmitter(emitter, 'data'), throttleTime(500, { leading: true, trailing: true }));
for await (const v of it) console.log(v);Merge two streams:
import { merge, take } from 'uniconnect';
for await (const v of take(merge(streamA, streamB), 5)) console.log(v);Zip two streams:
import { zip, take } from 'uniconnect';
for await (const pair of take(zip(streamA, streamB), 3)) console.log(pair);Accumulate with scan:
import { scan, pipe } from 'uniconnect';
const sums = pipe(numbers, scan((acc, x) => acc + x, 0));
for await (const s of sums) console.log(s);uniconnect
Zero-dependency universal connectors between Events, EventTargets and AsyncIterables with lightweight operators. Node 18+.
Universal, zero-dependency building blocks to connect Node/EventTarget event sources with modern AsyncIterables and compose them via tiny operators.
Table of Contents
- Features
- Requirements
- Quick Start
- Install
- Usage
- API
- Abort & Error Handling
- Compatibility Notes
- Contributing
- License
Features
- Minimal, zero-dependency, ESM-first
- Connect
EventEmitterandEventTargettoAsyncIterable - Compose with
pipe()and tiny operators:map,filter,take,buffer - Convert back with
toEventEmitter() - Abort-friendly via
AbortController
Requirements
- Node.js 18+
Quick Start
import { fromEventEmitter, pipe, take } from 'uniconnect';
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
const iterable = pipe(fromEventEmitter(ee, 'data'), take(3));
(async () => {
ee.emit('data', 'a');
ee.emit('data', 'b');
ee.emit('data', 'c');
})();
for await (const v of iterable) console.log(v);Install
npm install uniconnectUsage
From EventEmitter to AsyncIterable
import { fromEventEmitter, take, pipe } from 'uniconnect';
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
async function main() {
const it = pipe(
fromEventEmitter(emitter, 'data'),
take(3),
);
(async () => {
emitter.emit('data', 1);
emitter.emit('data', 2);
emitter.emit('data', 3);
emitter.emit('data', 4);
})();
for await (const v of it) {
console.log('got', v);
}
}
main();From EventTarget to AsyncIterable
import { fromEventTarget } from 'uniconnect';
const ac = new AbortController();
const { signal } = ac;
const target = new EventTarget();
const iterable = fromEventTarget(target, 'ping', { signal });
(async () => {
target.dispatchEvent(new Event('ping'));
ac.abort();
})();
for await (const ev of iterable) {
console.log('event', ev.type);
}Operators
import { pipe, map, filter, buffer } from 'uniconnect';
const processed = pipe(
sourceIterable,
map(x => x * 2),
filter(x => x % 3 === 0),
buffer(5),
);
for await (const chunk of processed) {
// chunks of size 5
}Retry
import { retryIterable } from 'uniconnect';
const src = () => someFlakyAsyncIterable();
for await (const v of retryIterable(src, { attempts: 5, delay: 200 })) {
// values...
}API
fromEventTarget(target, eventName, { signal }) -> AsyncIterable- Connects any
EventTarget(e.g. DOM/EventTarget polyfills) to anAsyncIterable. - Params:
target: EventTarget,eventName: string,options?: { signal?: AbortSignal } - Returns:
AsyncIterable<Event>
- Connects any
fromEventEmitter(emitter, eventName, { signal }) -> AsyncIterable- Connects Node.js
EventEmitterto anAsyncIterable. - Params:
emitter: EventEmitter,eventName: string,options?: { signal?: AbortSignal } - Returns:
AsyncIterable<any>
- Connects Node.js
toEventEmitter(asyncIterable, emitter, eventName) -> Promise<void>- Consumes an
AsyncIterableand re-emits values as events on the target emitter.
- Consumes an
toAsyncIterable(source, eventName, options)- Shortcut: detects the source type and calls
fromEventTargetorfromEventEmitteraccordingly.
- Shortcut: detects the source type and calls
pipe(iterable, ...ops) -> AsyncIterable- Chain composition helper for async operators.
Operators
map(fn),filter(fn),take(n),buffer(n)scan(reducer, seed?),distinctUntilChanged(equals?)debounceTime(ms),throttleTime(ms, { leading, trailing })
Utilities
retryIterable(factory, { attempts, delay }),timeout(ms, { error? })
Example: toEventEmitter
import { toEventEmitter } from 'uniconnect';
import { EventEmitter } from 'node:events';
async function* src() { yield 1; yield 2; }
const ee = new EventEmitter();
ee.on('data', v => console.log('data', v));
await toEventEmitter(src(), ee, 'data');Abort & Error Handling
- You can cancel streams with an
AbortControllerviaoptions.signal. - Sources that emit an
errorevent will propagate the error to the iterator. - On abort or error, listeners are automatically cleaned up.
import { fromEventTarget } from 'uniconnect';
const ac = new AbortController();
const iterable = fromEventTarget(new EventTarget(), 'tick', { signal: ac.signal });
const it = iterable[Symbol.asyncIterator]();
ac.abort(); // iterator will close with AbortErrorCompatibility Notes
EventEmittersupported via standard methods:on/offoraddListener/removeListenerandemit.EventTargetrequiresaddEventListener/removeEventListener.- ESM-only package. In CommonJS, use dynamic
import()or configure transpilation.
Contributing
- Issues and PRs are welcome. Please include a minimal test (Node's built-in
node:test) for any new functionality.
Testing
- This project uses Node's built-in test runner.
- Run all tests:
npm testTest files live under test/ and use the .test.mjs suffix.
Versioning & Release
- Follows Semantic Versioning (SemVer):
MAJOR.MINOR.PATCH. - Common flows:
- Patch:
npm version patch - Minor:
npm version minor - Major:
npm version major
- Patch:
- Publish to npm (public):
npm publish --access public- Push tags and code to GitHub:
git push origin main --follow-tagsLicense
MIT
Changelog
See GitHub Releases for notable changes.
