@m4trix/core 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/stream/Pump.ts","../../src/stream/utility/pipe-transformers/response.ts","../../src/stream/utility/rechunker/ensure-full-words.ts"],"names":["out","window"],"mappings":"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","sourcesContent":["/**\n * StreamChunk is the base interface for all streams.\n * It can hold voice and text chunks.\n *\n * @template T The type of data contained in the chunk\n */\nexport interface StreamChunk<T> {\n sequence: number;\n data: T;\n done: boolean;\n}\n\n/**\n * MessageStream represents an asynchronous iterable stream of chunks.\n * Used as the core stream representation throughout the Pump library.\n *\n * @template T The type of data contained in the chunks of the stream\n */\nexport type MessageStream<T> = AsyncIterable<StreamChunk<T>>;\n\n/**\n * Represents any source that can be converted to a stream.\n * This includes AsyncIterable and ReadableStream sources.\n *\n * @template T The type of data contained in the source\n */\nexport type Source<T> =\n | AsyncIterable<T>\n | ReadableStream<T>\n | NodeJS.ReadableStream;\n\n/**\n * A transformer for stream data that also provides a response.\n * Used primarily to transform and consume stream data while producing a response object.\n *\n * @template T The type of data being transformed\n * @template R The type of the response (defaults to Response)\n */\nexport type StreamTransformer<T, R = Response> = {\n transform(data: T): T;\n close(): void;\n response: R;\n};\n\n/**\n * Pump is an asynchronous stream processing pipeline with fluent operators.\n * It provides a comprehensive set of operations for transforming, filtering, batching,\n * combining, and consuming stream data.\n *\n * The Pump class follows a builder pattern where each operation returns a new Pump instance,\n * allowing for chaining of operations to build complex stream processing pipelines.\n *\n * @template T The type of data contained in the stream\n */\nexport class Pump<T> {\n constructor(private readonly src: MessageStream<T>) {}\n\n /**\n * Wrap an existing AsyncIterable or Readable stream into a Pump\n *\n * @template U The type of data in the source stream\n * @param source The source stream to convert to a Pump (AsyncIterable, ReadableStream, or NodeJS.ReadableStream)\n * @returns A new Pump instance that wraps the source\n */\n static from<U>(source: Source<U>): Pump<U> {\n async function* gen(): AsyncGenerator<StreamChunk<U>> {\n let seq = 0;\n\n // Type guard functions to narrow the type\n function isAsyncIterable(obj: Source<U>): obj is AsyncIterable<U> {\n return Symbol.asyncIterator in obj;\n }\n\n function isWebReadableStream(obj: Source<U>): obj is ReadableStream {\n return 'getReader' in obj && typeof obj.getReader === 'function';\n }\n\n function isNodeReadableStream(\n obj: Source<U>\n ): obj is NodeJS.ReadableStream {\n return (\n 'pipe' in obj &&\n 'on' in obj &&\n typeof obj.pipe === 'function' &&\n typeof obj.on === 'function'\n );\n }\n\n if (isAsyncIterable(source)) {\n // Handle AsyncIterable\n const iterator = source[Symbol.asyncIterator]();\n try {\n while (true) {\n const result = await iterator.next();\n if (result.done) break;\n yield {\n sequence: seq++,\n data: result.value,\n done: false,\n };\n }\n } finally {\n // No need to clean up AsyncIterator\n }\n } else if (isWebReadableStream(source)) {\n // Handle Web API ReadableStream\n const reader = source.getReader();\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n yield {\n sequence: seq++,\n data: result.value as U,\n done: false,\n };\n }\n } finally {\n reader.releaseLock();\n }\n } else if (isNodeReadableStream(source)) {\n // Handle Node.js ReadableStream\n try {\n // Convert Node stream to an AsyncIterable\n for await (const chunk of source) {\n yield {\n sequence: seq++,\n data: chunk as U,\n done: false,\n };\n }\n } catch (error) {\n console.error('Error reading from Node.js stream:', error);\n throw error;\n }\n }\n\n // final done signal\n yield { sequence: seq, data: undefined as unknown as U, done: true };\n }\n return new Pump<U>(gen()) as Pump<U>;\n }\n\n /**\n * Sync or async map over the data portion of each chunk\n *\n * @template U The output type after transformation\n * @param fn The mapping function that transforms each chunk\n * @returns A new Pump instance with the transformed data\n */\n map<U>(fn: (data: T) => U | Promise<U>): Pump<U> {\n async function* gen(this: Pump<T>): AsyncGenerator<StreamChunk<U>> {\n for await (const { sequence, data, done } of this.src) {\n if (done) {\n const out = data !== undefined ? await fn(data) : undefined;\n yield { sequence, data: out as unknown as U, done };\n break;\n }\n\n const out = await fn(data);\n yield { sequence, data: out, done };\n }\n }\n return new Pump<U>(gen.call(this));\n }\n\n /**\n * Stateful map allows processing stream chunks with a persistent context object.\n *\n * The context is initialized when the first chunk arrives and can be updated with each chunk.\n * This is useful for maintaining state across the stream processing.\n *\n * If you plan to use sockets you should rather opt for asyncStatefulMap.\n *\n * The pipe closes only after all processing is complete, including any final operations in onClose.\n *\n * TODO: Un-tested\n *\n * @param handlers Object containing callback functions for stream processing\n * @param handlers.onFirstChunk Function called when the first chunk arrives, initializes the context\n * @param handlers.onChunk Function called for each subsequent chunk, updates the context\n * @param handlers.onClose Optional function called when the stream closes, allows final processing\n * @returns A new Pump instance with transformed data\n */\n statefulMap<Context, U = T>(handlers: {\n onFirstChunk(\n chunk: T,\n yieldData: (data: U) => void\n ): Context | Promise<Context>;\n onChunk(\n chunk: T,\n context: Context,\n yieldData: (data: U) => void\n ): Context | Promise<Context>;\n onClose?(\n lastChunk: T | undefined,\n context: Context,\n yieldData: (data: U) => void\n ): void | Promise<void>;\n }): Pump<U> {\n const { src } = this;\n\n const gen = async function* (): AsyncGenerator<StreamChunk<U>> {\n let context: Context | undefined;\n let initialized = false;\n let lastChunk: T | undefined;\n let seq = 0;\n\n const queue: U[] = [];\n const yieldData = (data: U): void => {\n queue.push(data);\n };\n\n // <- here ->\n\n for await (const { data, done } of src) {\n if (done) {\n if (context && handlers.onClose) {\n await handlers.onClose(lastChunk, context, yieldData);\n }\n\n while (queue.length > 0) {\n yield { sequence: seq++, data: queue.shift()!, done: false };\n }\n\n yield {\n sequence: seq++,\n data: undefined as unknown as U,\n done: true,\n };\n break;\n }\n if (!initialized) {\n context = await handlers.onFirstChunk(data, yieldData);\n initialized = true;\n } else if (context) {\n context = await handlers.onChunk(data, context, yieldData);\n }\n\n lastChunk = data;\n\n while (queue.length > 0) {\n yield { sequence: seq++, data: queue.shift()!, done: false };\n }\n }\n };\n\n return new Pump<U>(gen());\n }\n\n /**\n * Async map means that each incoming chunk is causing an async operation that when it completes\n * should yield a new chunk.\n * The pipe closes only after you unlock the pipe by using the unlockCloseEvent callback.\n *\n * Stateful refers to the fact that you can create your own small context object that is passed in the subsequent callbacks.\n * This allows you to keep track of things like a socket connection.\n *\n * Why is this nice? Well if you use things like a socket the pipe might have received the close event,\n * before you got any or all of your socket responses. Sockets don't fit into the standard promise pattern,\n * which makes it harder to wait for them.\n *\n * TODO: Un-tested\n *\n * @param handlers Object containing callback functions for stream processing\n * @param handlers.onFirstChunk Function called when the first chunk arrives, initializes the context\n * @param handlers.onChunk Function called for each subsequent chunk, updates the context\n * @param handlers.onClose Optional function called when the stream closes, allows final processing\n * @returns A new Pump instance with transformed data\n */\n asyncStatefulMap<Context, U = T>(handlers: {\n onFirstChunk(\n chunk: T,\n yieldData: (data: U) => void,\n unlockCloseEvent: () => void\n ): Context | Promise<Context>;\n onChunk(\n chunk: T,\n context: Context,\n yieldData: (data: U) => void,\n unlockCloseEvent: () => void\n ): Context | Promise<Context>;\n onClose?(\n lastChunk: T | undefined,\n context: Context,\n yieldData: (data: U) => void,\n unlockCloseEvent: () => void\n ): void | Promise<void>;\n }): Pump<U> {\n const { src } = this;\n\n const gen = async function* (): AsyncGenerator<StreamChunk<U>> {\n let context: Context | undefined;\n let initialized = false;\n let lastChunk: T | undefined;\n let seq = 0;\n let lockedCloseEvent = true;\n\n const queue: U[] = [];\n const yieldData = (data: U): void => {\n queue.push(data);\n };\n const unlockCloseEvent = (): void => {\n lockedCloseEvent = false;\n };\n\n for await (const { data, done } of src) {\n if (done) {\n if (context && handlers.onClose) {\n await handlers.onClose(\n lastChunk,\n context,\n yieldData,\n unlockCloseEvent\n );\n }\n\n const timestamp = Date.now();\n // wait until the pipe is unlocked\n while (lockedCloseEvent && Date.now() - timestamp < 10_000) {\n // First emit all data in the queue\n while (queue.length > 0) {\n yield { sequence: seq++, data: queue.shift()!, done: false };\n }\n // put on top of event loop / call stack\n await new Promise((resolve) => setTimeout(resolve, 5));\n }\n\n // First emit all data in the queue\n while (queue.length > 0) {\n yield { sequence: seq++, data: queue.shift()!, done: false };\n }\n\n yield {\n sequence: seq++,\n data: undefined as unknown as U,\n done: true,\n };\n break;\n }\n if (!initialized) {\n context = await handlers.onFirstChunk(\n data,\n yieldData,\n unlockCloseEvent\n );\n initialized = true;\n } else if (context) {\n context = await handlers.onChunk(\n data,\n context,\n yieldData,\n unlockCloseEvent\n );\n }\n\n lastChunk = data;\n\n while (queue.length > 0) {\n yield { sequence: seq++, data: queue.shift()!, done: false };\n }\n }\n };\n\n return new Pump<U>(gen());\n }\n\n /**\n * Filter items based on a predicate\n *\n * @param predicate A function that determines whether to keep each chunk\n * @returns A new Pump instance containing only chunks that passed the predicate\n */\n filter(predicate: (data: T) => boolean | Promise<boolean>): Pump<T> {\n async function* gen(this: Pump<T>): AsyncGenerator<StreamChunk<T>> {\n for await (const { sequence, data, done } of this.src) {\n if (done) {\n yield { sequence, data, done: true };\n break;\n }\n\n const keep = await predicate(data);\n if (keep) {\n yield { sequence, data, done: false };\n }\n }\n }\n return new Pump<T>(gen.call(this));\n }\n\n /**\n * Bundles (accumulates) chunks together based on a condition rather than a fixed size.\n *\n * This is useful when you need to group chunks dynamically based on their content or other criteria.\n *\n * Example: Bundling text chunks with a maximum character limit\n *\n * Input chunks: [\"Hello\", \" this\", \" is\", \" a few\", \" chunks\", \" of text\"]\n * With max size of 10 characters:\n * - First bundle: [\"Hello\", \" this\"] (10 chars)\n * - Second bundle: [\" is\", \" a few\"] (8 chars)\n * - Third bundle: [\" chunks\", \" of text\"] (13 chars)\n *\n * @param closeBundleCondition - Function that determines when to close the current bundle\n * Returns true when the current bundle should be emitted\n * Parameters:\n * - chunk: The current chunk being processed\n * - accumulatedChunks: Array of chunks in the current bundle\n *\n * @returns A pump that emits arrays of bundled items\n */\n bundle(\n closeBundleCondition: (\n chunk: T,\n accumulatedChunks: Array<T>\n ) => boolean | Promise<boolean>\n ): Pump<Array<T>> {\n async function* gen(this: Pump<T>): AsyncGenerator<StreamChunk<Array<T>>> {\n let buffer: Array<T> = [];\n let lastSequence = 0;\n\n for await (const { sequence, data, done } of this.src) {\n lastSequence = sequence;\n\n if (done) {\n // Emit any remaining items in the buffer when the stream ends\n if (buffer.length > 0) {\n yield { sequence, data: [...buffer], done: false };\n }\n // Emit the termination signal\n yield {\n sequence: lastSequence,\n data: undefined as unknown as Array<T>,\n done: true,\n };\n break;\n }\n\n const shouldClose = await closeBundleCondition(data, buffer);\n buffer.push(data);\n\n if (shouldClose) {\n yield {\n sequence: lastSequence,\n data: [...buffer],\n done: false,\n };\n buffer = [];\n }\n }\n }\n return new Pump<Array<T>>(gen.call(this));\n }\n\n /**\n * Tap into each chunk without altering it\n *\n * @param fn A function that receives each chunk but doesn't affect the stream\n * @returns The same pump instance with unmodified data\n */\n onChunk(fn: (chunk: T) => void | Promise<void>): Pump<T> {\n async function* gen(this: Pump<T>): AsyncGenerator<StreamChunk<T>> {\n for await (const chunk of this.src) {\n if (chunk.data === undefined && chunk.done) {\n // Yield early since we don't need to tap into a closing signal (unless it contains data)\n yield chunk;\n }\n\n await fn(chunk.data);\n yield chunk;\n }\n }\n return new Pump<T>(gen.call(this));\n }\n\n /**\n * Collect all chunks in the stream and run a callback when the stream is done.\n * The callback receives an array of all chunks that passed through.\n *\n * This is useful for analytics, logging, or processing the complete stream history\n * after all chunks have been received.\n *\n * @param fn - Callback function that receives the array of all chunks when the stream is complete\n * @returns The same pump, for chaining\n */\n onClose(fn: (history: T[]) => void | Promise<void>): Pump<T> {\n async function* gen(this: Pump<T>): AsyncGenerator<StreamChunk<T>> {\n const history: T[] = [];\n\n for await (const chunk of this.src) {\n // Add non-done chunks to history\n if (chunk.data !== undefined) {\n history.push(chunk.data);\n }\n\n // If we've reached the end, run the callback\n if (chunk.done) {\n await fn(history);\n }\n\n // Pass through the chunk unchanged\n yield chunk;\n }\n }\n return new Pump<T>(gen.call(this));\n }\n\n /**\n * Batch `n` chunks into arrays before emitting\n *\n * @param n The number of chunks to batch together\n * @returns A new Pump instance that emits arrays of batched chunks\n */\n batch(n: number): Pump<Array<T>> {\n async function* gen(this: Pump<T>): AsyncGenerator<StreamChunk<Array<T>>> {\n let buffer: StreamChunk<T>[] = [];\n\n for await (const chunk of this.src) {\n if (chunk.done) {\n // Termination signal edge case handling\n if (chunk.data === undefined) {\n // Flush the rest\n yield {\n sequence: buffer[0].sequence,\n data: buffer.map((c) => c.data),\n done: false,\n };\n\n // and then emit the termination signal\n yield {\n sequence: chunk.sequence,\n data: undefined as unknown as Array<T>,\n done: true,\n };\n buffer = [];\n } else {\n // in that case the termination signal contains data\n // so we need to emit this as a closing singal with the rest of the buffer\n buffer.push(chunk);\n yield {\n sequence: buffer[0].sequence,\n data: buffer.map((c) => c.data),\n done: true,\n };\n }\n\n break;\n }\n\n // Normal case\n\n buffer.push(chunk);\n\n if (buffer.length === n) {\n yield {\n sequence: buffer[0].sequence,\n data: buffer.map((c) => c.data),\n done: chunk.done,\n };\n buffer = [];\n }\n }\n }\n return new Pump<Array<T>>(gen.call(this));\n }\n\n /**\n * If you want to prevent chunk starvation, you can buffer the chunks.\n * Chunks will not be bundled into arrays or object but kept as is,\n * but the pipeline will not progress at that segment until the buffer is filled up.\n * Once a buffer is filled up it will drain and never buffer again.\n *\n * @param n The number of chunks to buffer before processing continues\n * @returns A new Pump instance with buffering behavior\n */\n buffer(n: number): Pump<T> {\n async function* gen(this: Pump<T>): AsyncGenerator<StreamChunk<T>> {\n let buffer: StreamChunk<T>[] = [];\n let bufferFilled = false;\n\n for await (const chunk of this.src) {\n if (!bufferFilled) {\n if (!chunk.done) {\n buffer.push(chunk);\n }\n\n // If buffer is filled or we've reached the end of the stream\n if (buffer.length >= n || chunk.done) {\n bufferFilled = true;\n // Yield all buffered chunks\n for (const bufferedChunk of buffer) {\n yield bufferedChunk;\n }\n if (chunk.done) {\n yield {\n sequence: chunk.sequence,\n data: undefined as unknown as T,\n done: true,\n };\n break;\n }\n buffer = [];\n }\n } else {\n // After buffer is filled, just pass chunks through\n yield chunk;\n }\n }\n\n // Yield any remaining chunks in the buffer\n for (const bufferedChunk of buffer) {\n yield bufferedChunk;\n }\n }\n return new Pump<T>(gen.call(this));\n }\n\n /**\n * Rechunk the stream: transform one chunk into zero, one, or many output chunks.\n * The handler function receives the current buffer of chunks, a push function to emit new chunks,\n * and a flag indicating if this is the last chunk in the stream.\n *\n * @param handler Function that transforms chunks and pushes new ones\n * @returns A new Pump instance with rechunked data\n */\n rechunk(\n handler: (params: {\n buffer: T[];\n push: (chunk: T) => void;\n lastChunk: boolean;\n setBuffer: (buffer: T[]) => void;\n }) => void | Promise<void>\n ): Pump<T> {\n async function* gen(this: Pump<T>): AsyncGenerator<StreamChunk<T>> {\n let buffer: Array<T> = [];\n let seq = 0;\n const pending: Array<T> = [];\n\n const push = (chunk: T): void => {\n pending.push(chunk);\n };\n\n for await (const { data, done } of this.src) {\n if (!done) {\n if (data !== undefined) {\n buffer.push(data);\n }\n await handler({\n buffer,\n push,\n lastChunk: false,\n setBuffer: (b: T[]) => {\n buffer = b;\n },\n });\n } else {\n await handler({\n buffer,\n push,\n lastChunk: true,\n setBuffer: (b: T[]) => {\n buffer = b;\n },\n });\n }\n\n while (pending.length > 0) {\n const out = pending.shift()!;\n yield { sequence: seq++, data: out, done: false };\n }\n\n if (done) {\n break;\n }\n }\n\n yield { sequence: seq, data: undefined as unknown as T, done: true };\n }\n\n return new Pump<T>(gen.call(this));\n }\n\n /**\n * Emit sliding windows of the last `size` items with step `step`.\n * Each window is an array [current, previous1, ..., previous(size-1)].\n * Optionally, map each window through a function.\n *\n * | Step | Window | Resulting Window |\n * |------|--------|------------------|\n * | 1 | ▪︎▪︎[▪︎▫︎▫︎] | ▪︎▫︎▫︎ |\n * | 2 | ▪︎[▪︎▪︎▫︎] | ▪︎▪︎▫︎ |\n * | 3 | [▪︎▪︎▪︎] | ▪︎▪︎▪︎ |\n * | 4 | [▫︎▪︎▪︎] | ▫︎▪︎▪︎ |\n * | 5 | [▫︎▫︎▪︎] | ▫︎▫︎▪ |\n *\n * @param size The size of each window\n * @param step The number of items to move between windows\n * @returns A Pump that emits arrays representing sliding windows\n */\n slidingWindow(size: number, step: number): Pump<Array<T | undefined>>;\n /**\n * Emit sliding windows of the last `size` items with step `step`,\n * and map each window using the provided function.\n *\n * @template N The size type parameter (extends number)\n * @template U The output type after window transformation\n * @param size The size of each window\n * @param step The number of items to move between windows\n * @param fn A function to transform each window\n * @returns A Pump that emits transformed sliding windows\n */\n slidingWindow<N extends number, U>(\n size: N,\n step: number,\n fn: (window: Array<T | undefined>) => U | Promise<U>\n ): Pump<U>;\n slidingWindow<U>(\n size: number,\n step: number,\n fn?: (window: Array<T | undefined>) => U | Promise<U>\n ): Pump<Array<T | undefined>> | Pump<U> {\n async function* gen(\n this: Pump<T>\n ): AsyncGenerator<StreamChunk<Array<T | undefined>>> {\n const history: Array<T> = [];\n let offset = 0;\n let lastSeq = 0;\n\n function buildWindow(\n _offset: number,\n _size: number,\n _history: Array<T>\n ): Array<T | undefined> {\n const window: Array<T | undefined> = Array(_size).fill(undefined);\n let windowIndex = 0;\n\n for (let i = _offset; i > _offset - _size; i -= step) {\n if (i >= history.length) {\n windowIndex++;\n // we can skip this since we are filling the blank spots with undefined\n continue;\n }\n\n if (i < 0) {\n break;\n }\n\n window[windowIndex] = _history[i]; // the window follows the analoy so its filled reversed from the graphic\n windowIndex++;\n }\n\n return window;\n }\n\n for await (const { sequence, data, done } of this.src) {\n if (done) {\n // if we are done that means we are not receiving any more signals to push the window\n // so we have to emit the last window steps\n // [▪︎▪︎▫︎]\n // [▪︎▫︎▫︎]\n for (let i = 0; i < size - 1; i++) {\n const window = buildWindow(offset + i, size, history);\n yield { sequence: lastSeq, data: window, done: false };\n }\n\n if (data === undefined) {\n // final done signal\n yield {\n sequence: lastSeq,\n data: undefined as unknown as Array<T>,\n done: true,\n };\n } else {\n // final done signal\n yield {\n sequence: lastSeq,\n data: [\n history[history.length - 2] ?? undefined,\n history[history.length - 3] ?? undefined,\n history[history.length - 1],\n ],\n done: true,\n };\n }\n break;\n }\n\n lastSeq = sequence;\n history.push(data);\n\n // the rolling window goes from the oldest to the newest and pushes it self\n // with a step length. The analogy of the pipe shifts the window from right to left\n // but the array appends to the end. So in this implementation we are shifting from left to right.\n\n // lets calculate the window indexes\n // [▫︎▫︎▪︎]▪︎▪︎\n // [▫︎▪︎▪︎]▪︎\n // [▪︎▪︎▪︎]\n // [▪︎▪︎▫︎] <- this case is handled above\n // [▪︎▫︎▫︎] <- this case is handled above\n const window = buildWindow(offset, size, history);\n\n yield { sequence, data: window, done: false };\n offset++;\n }\n }\n const base = new Pump<Array<T | undefined>>(gen.call(this));\n // If fn is provided, map over the window, otherwise return the window as is\n return fn\n ? base.map(fn as (window: Array<T | undefined>) => U)\n : (base as Pump<Array<T | undefined>>);\n }\n\n /**\n * Sequentially flatten inner stream sources emitted by the pipeline.\n * Works with any Source type (AsyncIterable or ReadableStream).\n * This method is only available when the current Pump contains Source elements.\n *\n * @template U The type of data in the inner streams\n * @template F The type of inner stream source (extends Source<U>)\n * @returns A Pump instance with flattened stream data\n */\n sequenceStreams<U, F extends Source<U>>(this: Pump<F>): Pump<U> {\n async function* gen(this: Pump<F>): AsyncGenerator<StreamChunk<U>> {\n let seq = 0;\n\n for await (const { data: innerSource, done: outerDone } of this.src) {\n if (outerDone) break;\n\n // Convert the inner source to a pump first\n const innerPump = Pump.from(innerSource as unknown as Source<U>);\n\n // Then extract all items from it\n for await (const { data, done } of innerPump.src) {\n if (done) break;\n yield { sequence: seq++, data: data as U, done: false };\n }\n }\n\n yield { sequence: seq, data: undefined as unknown as U, done: true };\n }\n return new Pump<U>(gen.call(this));\n }\n\n /**\n * Fork the stream: two independent Pump<T> consumers\n * Both resulting Pumps will receive the same data, allowing for divergent processing paths.\n *\n * @returns An array containing two independent Pump instances with the same source data\n */\n fork(): [Pump<T>, Pump<T>] {\n const buffers: StreamChunk<T>[][] = [[], []];\n let done = false;\n const srcIter = this.src[Symbol.asyncIterator]();\n\n async function fill(): Promise<void> {\n const { value, done: streamDone } = await srcIter.next();\n if (streamDone) {\n done = true;\n return;\n }\n buffers.forEach((q) => q.push(value));\n if (value.done) done = true;\n }\n\n function makeStream(buf: StreamChunk<T>[]): MessageStream<T> {\n return {\n [Symbol.asyncIterator](): AsyncIterator<StreamChunk<T>> {\n return {\n async next(): Promise<IteratorResult<StreamChunk<T>>> {\n while (buf.length === 0 && !done) {\n await fill();\n }\n if (buf.length === 0)\n return {\n done: true,\n value: undefined as unknown as StreamChunk<T>,\n };\n return { done: false, value: buf.shift()! };\n },\n };\n },\n };\n }\n\n return [new Pump(makeStream(buffers[0])), new Pump(makeStream(buffers[1]))];\n }\n\n /**\n * Drain the pipeline, consuming all chunks.\n * Returns a Promise that resolves when all chunks have been consumed.\n *\n * @returns A Promise that resolves when all chunks have been consumed\n */\n drain(): Promise<void> {\n return (async (): Promise<void> => {\n for await (const { done } of this.src) {\n if (done) break;\n }\n })();\n }\n\n /**\n * Drain the pipeline to a StreamTransformer.\n * Applies transform() to each data chunk, then closes the transformer,\n * and returns its response (which can be of any type defined by the transformer).\n *\n * Example with httpStreamResponse:\n * ```\n * const { transform, response, close } = httpStreamResponse(options);\n * return Pump.from(messageStream).drainTo({ transform, close, response });\n * ```\n *\n * @template U The type of data expected by the transformer (extends T)\n * @template R The response type produced by the transformer\n * @param transformer The StreamTransformer to drain to\n * @returns The response from the transformer\n */\n drainTo<U extends T, R>(transformer: StreamTransformer<U, R>): R {\n (async (): Promise<void> => {\n for await (const { data, done } of this.src) {\n if (done) break;\n transformer.transform(data as unknown as U);\n }\n transformer.close();\n })();\n return transformer.response;\n }\n}\n\n// ----------------------------------------------------------\n// Example usage in Next.js App Router (e.g. app/api/stream/route.ts)\n//\n// import { NextRequest } from 'next/server';\n// import { Pump } from '@m4trix/core/stream';\n// import { /*...*/ } from '@/lib';\n\n// export async function POST(req: NextRequest) {\n// // Process the incoming audio request\n// const formData = await req.formData();\n// const transcript = await transcribeFormData(formData);\n// const agentStream = await getAgentResponse(transcript);\n\n// // Process and return the stream\n// return await Pump.from(agentStream)\n// .filter(shouldChunkBeStreamed)\n// .map(messageToText)\n// .bundle(intoChunksOfMinLength(40))\n// .map((text) => text.join(\"\")) // convert array of strings to string\n// .rechunk(ensureFullWords)\n// .rechunk(fixBrokenWords)\n// .onClose(handleCompletedAgentResponse)\n// .slidingWindow(10, 1)\n// .filter(filterOutIrrelevantWindows)\n// .buffer(5)\n// .map(textToSpeech)\n// .sequenceStreams()\n// .drainTo(httpStreamResponse());\n// }\n","import { StreamTransformer } from '../..';\n\nexport interface HttpStreamOptions<T> {\n /** HTTP ResponseInit (status, headers, etc.) */\n init?: ResponseInit;\n /** Encode each chunk of type T into bytes or string */\n encoder?: (data: T) => Uint8Array | string;\n}\n\n/**\n * Create a streaming HTTP response transformer.\n * Returns an object with:\n * - transform: function to write each chunk into the response\n * - response: the Fetch API Response ready to return\n * - close: function to close the stream when done\n *\n * Usage in a Next.js route:\n * ```\n * // With the new drainTo API:\n * const transformer = httpStreamResponse(options);\n * return Pump.from(messageStream).drainTo(transformer);\n *\n * // Or with manual control:\n * const { transform, response, close } = httpStreamResponse(options);\n * await Pump.from(messageStream).map(transform).drain();\n * close();\n * return response;\n * ```\n */\nexport function httpStreamResponse<T>(\n options: HttpStreamOptions<T> = {}\n): StreamTransformer<T, Response> {\n const { init, encoder } = options;\n const encodeFn =\n encoder ??\n ((d: T): Uint8Array | string => {\n if (d instanceof Uint8Array) return d;\n if (typeof d === 'string') return d;\n return JSON.stringify(d);\n });\n\n // Create a transform stream of Uint8Array\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n const response = new Response(readable, init);\n\n const transform = (chunk: T): T => {\n const encoded = encodeFn(chunk);\n const bytes =\n typeof encoded === 'string' ? new TextEncoder().encode(encoded) : encoded;\n writer.write(bytes);\n return chunk;\n };\n\n const close = (): void => {\n writer.close();\n };\n\n return { transform, response, close };\n}\n","/**\n * A helper to be used with Pump.rechunk that ensures full word chunks.\n * Aggregates incoming chunks and emits only when a full word boundary is reached.\n */\nexport async function ensureFullWords({\n buffer,\n push,\n lastChunk,\n}: {\n buffer: string[];\n push: (chunk: string) => void;\n lastChunk: boolean;\n}): Promise<void> {\n const combined = buffer.join('');\n const lastBoundary = Math.max(\n combined.lastIndexOf(' '),\n combined.lastIndexOf('\\n'),\n combined.lastIndexOf('\\t')\n );\n\n if (lastBoundary !== -1 || lastChunk) {\n const emitPart =\n lastBoundary !== -1 ? combined.slice(0, lastBoundary + 1) : combined;\n const leftoverPart =\n lastBoundary !== -1 ? combined.slice(lastBoundary + 1) : '';\n\n if (emitPart.trim().length > 0) {\n push(emitPart);\n }\n\n buffer.length = 0;\n if (leftoverPart.length > 0) {\n buffer.push(leftoverPart);\n }\n }\n}\n"]}
@@ -0,0 +1,304 @@
1
+ /**
2
+ * StreamChunk is the base interface for all streams.
3
+ * It can hold voice and text chunks.
4
+ *
5
+ * @template T The type of data contained in the chunk
6
+ */
7
+ interface StreamChunk<T> {
8
+ sequence: number;
9
+ data: T;
10
+ done: boolean;
11
+ }
12
+ /**
13
+ * MessageStream represents an asynchronous iterable stream of chunks.
14
+ * Used as the core stream representation throughout the Pump library.
15
+ *
16
+ * @template T The type of data contained in the chunks of the stream
17
+ */
18
+ type MessageStream<T> = AsyncIterable<StreamChunk<T>>;
19
+ /**
20
+ * Represents any source that can be converted to a stream.
21
+ * This includes AsyncIterable and ReadableStream sources.
22
+ *
23
+ * @template T The type of data contained in the source
24
+ */
25
+ type Source<T> = AsyncIterable<T> | ReadableStream<T> | NodeJS.ReadableStream;
26
+ /**
27
+ * A transformer for stream data that also provides a response.
28
+ * Used primarily to transform and consume stream data while producing a response object.
29
+ *
30
+ * @template T The type of data being transformed
31
+ * @template R The type of the response (defaults to Response)
32
+ */
33
+ type StreamTransformer<T, R = Response> = {
34
+ transform(data: T): T;
35
+ close(): void;
36
+ response: R;
37
+ };
38
+ /**
39
+ * Pump is an asynchronous stream processing pipeline with fluent operators.
40
+ * It provides a comprehensive set of operations for transforming, filtering, batching,
41
+ * combining, and consuming stream data.
42
+ *
43
+ * The Pump class follows a builder pattern where each operation returns a new Pump instance,
44
+ * allowing for chaining of operations to build complex stream processing pipelines.
45
+ *
46
+ * @template T The type of data contained in the stream
47
+ */
48
+ declare class Pump<T> {
49
+ private readonly src;
50
+ constructor(src: MessageStream<T>);
51
+ /**
52
+ * Wrap an existing AsyncIterable or Readable stream into a Pump
53
+ *
54
+ * @template U The type of data in the source stream
55
+ * @param source The source stream to convert to a Pump (AsyncIterable, ReadableStream, or NodeJS.ReadableStream)
56
+ * @returns A new Pump instance that wraps the source
57
+ */
58
+ static from<U>(source: Source<U>): Pump<U>;
59
+ /**
60
+ * Sync or async map over the data portion of each chunk
61
+ *
62
+ * @template U The output type after transformation
63
+ * @param fn The mapping function that transforms each chunk
64
+ * @returns A new Pump instance with the transformed data
65
+ */
66
+ map<U>(fn: (data: T) => U | Promise<U>): Pump<U>;
67
+ /**
68
+ * Stateful map allows processing stream chunks with a persistent context object.
69
+ *
70
+ * The context is initialized when the first chunk arrives and can be updated with each chunk.
71
+ * This is useful for maintaining state across the stream processing.
72
+ *
73
+ * If you plan to use sockets you should rather opt for asyncStatefulMap.
74
+ *
75
+ * The pipe closes only after all processing is complete, including any final operations in onClose.
76
+ *
77
+ * TODO: Un-tested
78
+ *
79
+ * @param handlers Object containing callback functions for stream processing
80
+ * @param handlers.onFirstChunk Function called when the first chunk arrives, initializes the context
81
+ * @param handlers.onChunk Function called for each subsequent chunk, updates the context
82
+ * @param handlers.onClose Optional function called when the stream closes, allows final processing
83
+ * @returns A new Pump instance with transformed data
84
+ */
85
+ statefulMap<Context, U = T>(handlers: {
86
+ onFirstChunk(chunk: T, yieldData: (data: U) => void): Context | Promise<Context>;
87
+ onChunk(chunk: T, context: Context, yieldData: (data: U) => void): Context | Promise<Context>;
88
+ onClose?(lastChunk: T | undefined, context: Context, yieldData: (data: U) => void): void | Promise<void>;
89
+ }): Pump<U>;
90
+ /**
91
+ * Async map means that each incoming chunk is causing an async operation that when it completes
92
+ * should yield a new chunk.
93
+ * The pipe closes only after you unlock the pipe by using the unlockCloseEvent callback.
94
+ *
95
+ * Stateful refers to the fact that you can create your own small context object that is passed in the subsequent callbacks.
96
+ * This allows you to keep track of things like a socket connection.
97
+ *
98
+ * Why is this nice? Well if you use things like a socket the pipe might have received the close event,
99
+ * before you got any or all of your socket responses. Sockets don't fit into the standard promise pattern,
100
+ * which makes it harder to wait for them.
101
+ *
102
+ * TODO: Un-tested
103
+ *
104
+ * @param handlers Object containing callback functions for stream processing
105
+ * @param handlers.onFirstChunk Function called when the first chunk arrives, initializes the context
106
+ * @param handlers.onChunk Function called for each subsequent chunk, updates the context
107
+ * @param handlers.onClose Optional function called when the stream closes, allows final processing
108
+ * @returns A new Pump instance with transformed data
109
+ */
110
+ asyncStatefulMap<Context, U = T>(handlers: {
111
+ onFirstChunk(chunk: T, yieldData: (data: U) => void, unlockCloseEvent: () => void): Context | Promise<Context>;
112
+ onChunk(chunk: T, context: Context, yieldData: (data: U) => void, unlockCloseEvent: () => void): Context | Promise<Context>;
113
+ onClose?(lastChunk: T | undefined, context: Context, yieldData: (data: U) => void, unlockCloseEvent: () => void): void | Promise<void>;
114
+ }): Pump<U>;
115
+ /**
116
+ * Filter items based on a predicate
117
+ *
118
+ * @param predicate A function that determines whether to keep each chunk
119
+ * @returns A new Pump instance containing only chunks that passed the predicate
120
+ */
121
+ filter(predicate: (data: T) => boolean | Promise<boolean>): Pump<T>;
122
+ /**
123
+ * Bundles (accumulates) chunks together based on a condition rather than a fixed size.
124
+ *
125
+ * This is useful when you need to group chunks dynamically based on their content or other criteria.
126
+ *
127
+ * Example: Bundling text chunks with a maximum character limit
128
+ *
129
+ * Input chunks: ["Hello", " this", " is", " a few", " chunks", " of text"]
130
+ * With max size of 10 characters:
131
+ * - First bundle: ["Hello", " this"] (10 chars)
132
+ * - Second bundle: [" is", " a few"] (8 chars)
133
+ * - Third bundle: [" chunks", " of text"] (13 chars)
134
+ *
135
+ * @param closeBundleCondition - Function that determines when to close the current bundle
136
+ * Returns true when the current bundle should be emitted
137
+ * Parameters:
138
+ * - chunk: The current chunk being processed
139
+ * - accumulatedChunks: Array of chunks in the current bundle
140
+ *
141
+ * @returns A pump that emits arrays of bundled items
142
+ */
143
+ bundle(closeBundleCondition: (chunk: T, accumulatedChunks: Array<T>) => boolean | Promise<boolean>): Pump<Array<T>>;
144
+ /**
145
+ * Tap into each chunk without altering it
146
+ *
147
+ * @param fn A function that receives each chunk but doesn't affect the stream
148
+ * @returns The same pump instance with unmodified data
149
+ */
150
+ onChunk(fn: (chunk: T) => void | Promise<void>): Pump<T>;
151
+ /**
152
+ * Collect all chunks in the stream and run a callback when the stream is done.
153
+ * The callback receives an array of all chunks that passed through.
154
+ *
155
+ * This is useful for analytics, logging, or processing the complete stream history
156
+ * after all chunks have been received.
157
+ *
158
+ * @param fn - Callback function that receives the array of all chunks when the stream is complete
159
+ * @returns The same pump, for chaining
160
+ */
161
+ onClose(fn: (history: T[]) => void | Promise<void>): Pump<T>;
162
+ /**
163
+ * Batch `n` chunks into arrays before emitting
164
+ *
165
+ * @param n The number of chunks to batch together
166
+ * @returns A new Pump instance that emits arrays of batched chunks
167
+ */
168
+ batch(n: number): Pump<Array<T>>;
169
+ /**
170
+ * If you want to prevent chunk starvation, you can buffer the chunks.
171
+ * Chunks will not be bundled into arrays or object but kept as is,
172
+ * but the pipeline will not progress at that segment until the buffer is filled up.
173
+ * Once a buffer is filled up it will drain and never buffer again.
174
+ *
175
+ * @param n The number of chunks to buffer before processing continues
176
+ * @returns A new Pump instance with buffering behavior
177
+ */
178
+ buffer(n: number): Pump<T>;
179
+ /**
180
+ * Rechunk the stream: transform one chunk into zero, one, or many output chunks.
181
+ * The handler function receives the current buffer of chunks, a push function to emit new chunks,
182
+ * and a flag indicating if this is the last chunk in the stream.
183
+ *
184
+ * @param handler Function that transforms chunks and pushes new ones
185
+ * @returns A new Pump instance with rechunked data
186
+ */
187
+ rechunk(handler: (params: {
188
+ buffer: T[];
189
+ push: (chunk: T) => void;
190
+ lastChunk: boolean;
191
+ setBuffer: (buffer: T[]) => void;
192
+ }) => void | Promise<void>): Pump<T>;
193
+ /**
194
+ * Emit sliding windows of the last `size` items with step `step`.
195
+ * Each window is an array [current, previous1, ..., previous(size-1)].
196
+ * Optionally, map each window through a function.
197
+ *
198
+ * | Step | Window | Resulting Window |
199
+ * |------|--------|------------------|
200
+ * | 1 | ▪︎▪︎[▪︎▫︎▫︎] | ▪︎▫︎▫︎ |
201
+ * | 2 | ▪︎[▪︎▪︎▫︎] | ▪︎▪︎▫︎ |
202
+ * | 3 | [▪︎▪︎▪︎] | ▪︎▪︎▪︎ |
203
+ * | 4 | [▫︎▪︎▪︎] | ▫︎▪︎▪︎ |
204
+ * | 5 | [▫︎▫︎▪︎] | ▫︎▫︎▪ |
205
+ *
206
+ * @param size The size of each window
207
+ * @param step The number of items to move between windows
208
+ * @returns A Pump that emits arrays representing sliding windows
209
+ */
210
+ slidingWindow(size: number, step: number): Pump<Array<T | undefined>>;
211
+ /**
212
+ * Emit sliding windows of the last `size` items with step `step`,
213
+ * and map each window using the provided function.
214
+ *
215
+ * @template N The size type parameter (extends number)
216
+ * @template U The output type after window transformation
217
+ * @param size The size of each window
218
+ * @param step The number of items to move between windows
219
+ * @param fn A function to transform each window
220
+ * @returns A Pump that emits transformed sliding windows
221
+ */
222
+ slidingWindow<N extends number, U>(size: N, step: number, fn: (window: Array<T | undefined>) => U | Promise<U>): Pump<U>;
223
+ /**
224
+ * Sequentially flatten inner stream sources emitted by the pipeline.
225
+ * Works with any Source type (AsyncIterable or ReadableStream).
226
+ * This method is only available when the current Pump contains Source elements.
227
+ *
228
+ * @template U The type of data in the inner streams
229
+ * @template F The type of inner stream source (extends Source<U>)
230
+ * @returns A Pump instance with flattened stream data
231
+ */
232
+ sequenceStreams<U, F extends Source<U>>(this: Pump<F>): Pump<U>;
233
+ /**
234
+ * Fork the stream: two independent Pump<T> consumers
235
+ * Both resulting Pumps will receive the same data, allowing for divergent processing paths.
236
+ *
237
+ * @returns An array containing two independent Pump instances with the same source data
238
+ */
239
+ fork(): [Pump<T>, Pump<T>];
240
+ /**
241
+ * Drain the pipeline, consuming all chunks.
242
+ * Returns a Promise that resolves when all chunks have been consumed.
243
+ *
244
+ * @returns A Promise that resolves when all chunks have been consumed
245
+ */
246
+ drain(): Promise<void>;
247
+ /**
248
+ * Drain the pipeline to a StreamTransformer.
249
+ * Applies transform() to each data chunk, then closes the transformer,
250
+ * and returns its response (which can be of any type defined by the transformer).
251
+ *
252
+ * Example with httpStreamResponse:
253
+ * ```
254
+ * const { transform, response, close } = httpStreamResponse(options);
255
+ * return Pump.from(messageStream).drainTo({ transform, close, response });
256
+ * ```
257
+ *
258
+ * @template U The type of data expected by the transformer (extends T)
259
+ * @template R The response type produced by the transformer
260
+ * @param transformer The StreamTransformer to drain to
261
+ * @returns The response from the transformer
262
+ */
263
+ drainTo<U extends T, R>(transformer: StreamTransformer<U, R>): R;
264
+ }
265
+
266
+ interface HttpStreamOptions<T> {
267
+ /** HTTP ResponseInit (status, headers, etc.) */
268
+ init?: ResponseInit;
269
+ /** Encode each chunk of type T into bytes or string */
270
+ encoder?: (data: T) => Uint8Array | string;
271
+ }
272
+ /**
273
+ * Create a streaming HTTP response transformer.
274
+ * Returns an object with:
275
+ * - transform: function to write each chunk into the response
276
+ * - response: the Fetch API Response ready to return
277
+ * - close: function to close the stream when done
278
+ *
279
+ * Usage in a Next.js route:
280
+ * ```
281
+ * // With the new drainTo API:
282
+ * const transformer = httpStreamResponse(options);
283
+ * return Pump.from(messageStream).drainTo(transformer);
284
+ *
285
+ * // Or with manual control:
286
+ * const { transform, response, close } = httpStreamResponse(options);
287
+ * await Pump.from(messageStream).map(transform).drain();
288
+ * close();
289
+ * return response;
290
+ * ```
291
+ */
292
+ declare function httpStreamResponse<T>(options?: HttpStreamOptions<T>): StreamTransformer<T, Response>;
293
+
294
+ /**
295
+ * A helper to be used with Pump.rechunk that ensures full word chunks.
296
+ * Aggregates incoming chunks and emits only when a full word boundary is reached.
297
+ */
298
+ declare function ensureFullWords({ buffer, push, lastChunk, }: {
299
+ buffer: string[];
300
+ push: (chunk: string) => void;
301
+ lastChunk: boolean;
302
+ }): Promise<void>;
303
+
304
+ export { type HttpStreamOptions, type MessageStream, Pump, type Source, type StreamChunk, type StreamTransformer, ensureFullWords, httpStreamResponse };