Nozzle Development Guide
Adding New Functions
Checklist
- Create
src/transforms/yourFunction.ts - Export from
src/transforms/index.ts - Add method to Pipeline class in
src/pipeline.ts - Create tests in
test/yourFunction.test.ts - Add JSDoc with
@grouptag (Timing, Buffering, Filtering, Transformation, or Utilities) - Run
pnpm test && pnpm lint && pnpm build-fast
Basic Pattern
export async function* yourFunction<T>(source: AsyncIterable<T>, param: P): AsyncGenerator<T> {
for await (const item of source) {
yield transformedItem
}
}
Reference Examples
- Simple transforms:
map.ts,filter.ts - Timing:
minInterval.ts,throttle.ts - Buffering:
buffer.ts,chunk.ts - String-specific:
split.ts,replace.ts
Async Error Handling
Critical rule: Errors must be thrown during await ticks, not in callbacks.
Errors in setTimeout/Promise.race callbacks escape user try/catch blocks. Instead, store errors and rethrow on the next await:
export async function* myTimingFunction<T>(source: AsyncIterable<T>) {
let error: Error | null = null
const consumer = (async () => {
try {
for await (const item of source) {
/* ... */
}
} catch (err) {
error = err instanceof Error ? err : new Error(String(err))
}
})()
while (true) {
if (error) throw error // Thrown during await tick - catchable by user
// ... yield logic
}
}
When to apply: Any function using setTimeout, setInterval, Promise.race, or background async operations.
Reference: buffer.ts has the canonical error handling pattern.
Testing Requirements
- Basic functionality with typical inputs
- Edge cases: empty sources, single items, boundaries
- Error handling: source errors must be catchable
- Return value preservation: verify with
consume().return() - Timing behavior (if applicable): use
test/timing-helpers.ts
Gotchas
- Return types: Functions like
tap()must pass through parent's return type, not just yield type - Forgetting exports: Add to both
transforms/index.tsANDpipeline.ts - Pipeline integration: Generic methods go first in Pipeline class; string-specific methods go in second section with type constraints