ai-resumable-stream 1.2.1 → 1.3.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.
package/README.md CHANGED
@@ -309,6 +309,7 @@ await subscriber.quit();
309
309
  async function createResumableUIMessageStream(options: CreateResumableUIMessageStream): Promise<{
310
310
  startStream: (
311
311
  stream: ReadableStream<UIMessageChunk>,
312
+ options?: { onFlush?: () => void | Promise<void> },
312
313
  ) => Promise<AsyncIterableStream<UIMessageChunk>>;
313
314
  resumeStream: () => Promise<AsyncIterableStream<UIMessageChunk> | null>;
314
315
  stopStream: () => Promise<void>;
@@ -330,11 +331,14 @@ type CreateResumableUIMessageStream = {
330
331
  ```typescript
331
332
  async function startStream(
332
333
  stream: ReadableStream<UIMessageChunk>,
334
+ options?: { onFlush?: () => void | Promise<void> },
333
335
  ): Promise<AsyncIterableStream<UIMessageChunk>>;
334
336
  ```
335
337
 
336
338
  Starts a new resumable stream. A single drain loop reads from the source and sends chunks to both the client and Redis simultaneously. If the client disconnects, chunks continue flowing to Redis for resumability.
337
339
 
340
+ The optional `onFlush` callback is invoked after the stream finishes draining to Redis and cleanup is complete, regardless of how the stream ended (complete, error, or abort). Use it for cleanup tasks like removing the active stream ID from the database. Errors thrown by `onFlush` are silently caught.
341
+
338
342
  #### `resumeStream`
339
343
 
340
344
  ```typescript
package/dist/index.d.mts CHANGED
@@ -40,7 +40,9 @@ type CreateResumableUIMessageStream = {
40
40
  * eagerly and enqueues directly to the output stream.
41
41
  */
42
42
  declare function createResumableUIMessageStream(options: CreateResumableUIMessageStream): Promise<{
43
- startStream: (stream: ReadableStream<UIMessageChunk>) => Promise<AsyncIterableStream<UIMessageChunk>>;
43
+ startStream: (stream: ReadableStream<UIMessageChunk>, options?: {
44
+ onFlush?: () => void | Promise<void>;
45
+ }) => Promise<AsyncIterableStream<UIMessageChunk>>;
44
46
  resumeStream: () => Promise<AsyncIterableStream<UIMessageChunk> | null>;
45
47
  stopStream: () => Promise<void>;
46
48
  }>;
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import { createResumableStreamContext } from "resumable-stream";
6
6
  /**
7
7
  * Converts an SSE stream to a UI message stream.
8
8
  */
9
- function convertSSEToUIMessageStream(stream, onComplete) {
9
+ function convertSSEToUIMessageStream(stream, onFlush) {
10
10
  return parseJsonEventStream({
11
11
  stream: stream.pipeThrough(new TextEncoderStream()),
12
12
  schema: uiMessageChunkSchema
@@ -15,7 +15,7 @@ function convertSSEToUIMessageStream(stream, onComplete) {
15
15
  if (result.success) controller.enqueue(result.value);
16
16
  },
17
17
  flush() {
18
- onComplete?.();
18
+ onFlush?.();
19
19
  }
20
20
  }));
21
21
  }
@@ -69,7 +69,8 @@ async function createResumableUIMessageStream(options) {
69
69
  * 3. Sends SSE to Redis stream → resumable-stream → Redis
70
70
  * 4. Propagates errors to both streams
71
71
  */
72
- async function startStream(stream) {
72
+ async function startStream(stream, options) {
73
+ const { onFlush } = options ?? {};
73
74
  /**
74
75
  * Track client disconnect to avoid unbounded memory growth
75
76
  */
@@ -139,6 +140,9 @@ async function createResumableUIMessageStream(options) {
139
140
  try {
140
141
  await unsubscribe();
141
142
  } catch {}
143
+ try {
144
+ await onFlush?.();
145
+ } catch {}
142
146
  }
143
147
  })();
144
148
  return createAsyncIterableStream(clientStream);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-resumable-stream",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "AI SDK: resume and stop UI message streams",
5
5
  "keywords": [
6
6
  "ai",