### Install fastify-sse-v2 Source: https://github.com/mpetrunic/fastify-sse-v2/blob/master/README.md Install the plugin using yarn. ```bash yarn add fastify-sse-v2 ``` -------------------------------- ### SsePluginOptions — Plugin Configuration Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Configure global SSE behavior by passing options when registering the `FastifySSEPlugin`. Key options include `retryDelay` to set the browser's reconnection delay and `highWaterMark` to manage the internal Node.js stream buffer size. Examples show how to set these options. ```APIDOC ## `SsePluginOptions` — Plugin Configuration Options passed when registering the plugin to configure global SSE behavior. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; import type { SsePluginOptions } from "fastify-sse-v2/lib/types"; // or import directly from src const options: SsePluginOptions = { /** * retryDelay: milliseconds the browser waits before reconnecting after a dropped connection. * Default: 3000 * Set to `false` to omit the "retry:" line entirely from the stream header. */ retryDelay: 3000, /** * highWaterMark: internal Node.js stream buffer size in bytes before back-pressure is applied. * Default: 16384 (16kb) * Lower for low-latency scenarios; higher for high-throughput batch scenarios. */ highWaterMark: 16384, }; const server = fastify(); server.register(FastifySSEPlugin, options); server.listen({ port: 3000 }); ``` ``` -------------------------------- ### reply.sseContext.source - Direct Pushable Stream Access Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt The `sseContext.source` property allows direct access to the `Pushable` stream. This enables pushing events from external sources like event emitters or message queues and explicitly ending the stream. The example demonstrates initializing SSE, pushing events from an EventEmitter, and cleaning up listeners and the stream on client disconnection. ```APIDOC ## `reply.sseContext.source` — Direct Pushable Stream Access The `sseContext.source` property exposes the underlying `Pushable` stream created on the first `reply.sse()` call. This enables pushing events from outside the route handler (e.g., from event emitters, database watchers, or message queues) and explicitly ending the stream. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; import { EventEmitter } from "events"; const server = fastify(); server.register(FastifySSEPlugin); const emitter = new EventEmitter(); server.get("/live", function (req, reply) { // Initialize SSE context by sending a bootstrap event reply.sse({ comment: " stream open" }); // Push events from an external emitter const onData = (payload: unknown) => { reply.sseContext.source.push({ event: "data", data: JSON.stringify(payload), }); }; emitter.on("data", onData); // Clean up listener and close stream when client disconnects req.socket.on("close", () => { emitter.off("data", onData); reply.sseContext.source.end(); }); }); // Elsewhere in your app — push events to connected clients: emitter.emit("data", { user: "alice", action: "login" }); server.listen({ port: 3000 }); ``` ``` -------------------------------- ### EventMessage Interface — SSE Event Fields Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt The `EventMessage` interface defines the structure for Server-Sent Events, including optional fields like `id`, `event`, `data`, `retry`, and `comment`. The `data` field supports multi-line strings, which are correctly formatted according to the SSE specification. Examples show a full event, a minimal event with only data, and a keep-alive comment. ```APIDOC ## `EventMessage` Interface — SSE Event Fields The `EventMessage` interface describes all standard SSE fields. All fields are optional. `data` supports multi-line strings (newlines are correctly split into multiple `data:` lines per the SSE spec). ```typescript import { EventMessage } from "fastify-sse-v2"; // Full event with all fields const fullEvent: EventMessage = { id: "42", // Last-Event-ID for client reconnect resume event: "priceUpdate", // Custom event type (client listens with addEventListener) data: "line one\nline two", // Multi-line data — serialized as two "data:" lines retry: 2000, // Instruct client to reconnect after 2s comment: " keep-alive ping", // SSE comment line (starts with ':') }; // Serialized wire format produced internally: // id: 42 // event: priceUpdate // data: line one // data: line two // retry: 2000 // : keep-alive ping // ← blank line terminates the event // Minimal event (data only) const simpleEvent: EventMessage = { data: "hello world", }; // Keep-alive comment (no data, prevents proxy timeouts) const keepAlive: EventMessage = { comment: " ping", }; ``` ``` -------------------------------- ### serializeSSEEvent(chunk: EventMessage): string — Internal Serialization Utility Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt The `serializeSSEEvent` function is an internal utility that converts an `EventMessage` object into a raw SSE-formatted string. It handles multi-line data and comments correctly. This function can be used directly if manual serialization is required. Examples demonstrate its usage with various `EventMessage` structures. ```APIDOC ## `serializeSSEEvent(chunk: EventMessage): string` — Internal Serialization Utility Converts an `EventMessage` object into a raw SSE-formatted string. This is an internal utility exported from `src/sse.ts` and can be used directly if manual serialization is needed. ```typescript import { serializeSSEEvent } from "fastify-sse-v2/src/sse"; console.log(serializeSSEEvent({ id: "1", event: "msg", data: "hello" })); // id: 1 // event: msg // data: hello // // (trailing blank line included) console.log(serializeSSEEvent({ data: "line1\nline2" })); // data: line1 // data: line2 // console.log(serializeSSEEvent({ comment: " keep-alive" })); // : keep-alive // // Empty message returns empty string (no output written) console.log(serializeSSEEvent({})); // "" ``` ``` -------------------------------- ### SsePluginOptions for Plugin Configuration Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Configure global SSE behavior by passing `SsePluginOptions` when registering the plugin. Options include `retryDelay` for client reconnection timing and `highWaterMark` for internal stream buffer size, which can be tuned for latency or throughput. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; import type { SsePluginOptions } from "fastify-sse-v2/lib/types"; // or import directly from src const options: SsePluginOptions = { /** * retryDelay: milliseconds the browser waits before reconnecting after a dropped connection. * Default: 3000 * Set to `false` to omit the "retry:" line entirely from the stream header. */ retryDelay: 3000, /** * highWaterMark: internal Node.js stream buffer size in bytes before back-pressure is applied. * Default: 16384 (16kb) * Lower for low-latency scenarios; higher for high-throughput batch scenarios. */ highWaterMark: 16384, }; const server = fastify(); server.register(FastifySSEPlugin, options); server.listen({ port: 3000 }); ``` -------------------------------- ### Register fastify-sse-v2 Plugin Source: https://github.com/mpetrunic/fastify-sse-v2/blob/master/README.md Register the plugin with your Fastify instance. ```javascript import { FastifySSEPlugin } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin); ``` -------------------------------- ### Plugin Registration - FastifySSEPlugin Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Registers the SSE plugin with a Fastify instance. Accepts optional SsePluginOptions to control retry behavior and buffer size. Must be registered before defining routes that use reply.sse(). ```APIDOC ## Plugin Registration — `FastifySSEPlugin` Registers the SSE plugin with a Fastify instance. Accepts optional `SsePluginOptions` to control retry behavior and buffer size. Must be registered before defining routes that use `reply.sse()`. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; // Default registration (retryDelay = 3000ms, highWaterMark = 16384 bytes) const server = fastify(); server.register(FastifySSEPlugin); // With custom options const server2 = fastify(); server2.register(FastifySSEPlugin, { retryDelay: 5000, // Client waits 5 seconds before reconnecting highWaterMark: 1024, // Flush buffer at 1kb instead of the default 16kb }); // Disable automatic retry header entirely const server3 = fastify(); server3.register(FastifySSEPlugin, { retryDelay: false, // No retry: directive sent to client }); server.listen({ port: 3000 }, (err, address) => { if (err) throw err; console.log(`Server running at ${address}`); }); ``` ``` -------------------------------- ### Register Fastify SSE Plugin Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Register the SSE plugin with default or custom options. Ensure registration before defining SSE routes. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; // Default registration (retryDelay = 3000ms, highWaterMark = 16384 bytes) const server = fastify(); server.register(FastifySSEPlugin); // With custom options const server2 = fastify(); server2.register(FastifySSEPlugin, { retryDelay: 5000, // Client waits 5 seconds before reconnecting highWaterMark: 1024, // Flush buffer at 1kb instead of the default 16kb }); // Disable automatic retry header entirely const server3 = fastify(); server3.register(FastifySSEPlugin, { retryDelay: false, // No retry: directive sent to client }); server.listen({ port: 3000 }, (err, address) => { if (err) throw err; console.log(`Server running at ${address}`); }); ``` -------------------------------- ### reply.sse(event: EventMessage) — Sending Individual Events Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Sends a single EventMessage immediately. On the first call, the SSE connection is established and an internal pushable stream is created. Subsequent calls push further events to that same stream. The connection stays open until reply.sseContext.source.end() is called explicitly. ```APIDOC ## `reply.sse(event: EventMessage)` — Sending Individual Events Sends a single `EventMessage` immediately. On the first call, the SSE connection is established and an internal pushable stream is created (accessible at `reply.sseContext.source`). Subsequent calls push further events to that same stream. The connection stays open until `reply.sseContext.source.end()` is called explicitly. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin); server.get("/events", async function (req, reply) { // First call opens the SSE connection reply.sse({ id: "1", event: "message", data: "First event" }); await new Promise((r) => setTimeout(r, 1000)); reply.sse({ id: "2", event: "message", data: "Second event" }); await new Promise((r) => setTimeout(r, 1000)); reply.sse({ id: "3", event: "notification", data: JSON.stringify({ level: "info", text: "Done" }), retry: 5000, // Override client reconnect delay for this event }); // Explicitly close the stream reply.sseContext.source.end(); }); server.listen({ port: 3000 }); ``` ``` -------------------------------- ### Direct Pushable Stream Access with reply.sseContext.source Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Use `reply.sseContext.source` to push events from outside the route handler and explicitly end the stream. This is useful for integrating with external event sources like emitters or message queues. Ensure cleanup listeners are attached to handle client disconnections. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; import { EventEmitter } from "events"; const server = fastify(); server.register(FastifySSEPlugin); const emitter = new EventEmitter(); server.get("/live", function (req, reply) { // Initialize SSE context by sending a bootstrap event reply.sse({ comment: " stream open" }); // Push events from an external emitter const onData = (payload: unknown) => { reply.sseContext.source.push({ event: "data", data: JSON.stringify(payload), }); }; emitter.on("data", onData); // Clean up listener and close stream when client disconnects req.socket.on("close", () => { emitter.off("data", onData); reply.sseContext.source.end(); }); }); // Elsewhere in your app — push events to connected clients: emitter.emit("data", { user: "alice", action: "login" }); server.listen({ port: 3000 }); ``` -------------------------------- ### Configure Server Send Retry Behavior Source: https://github.com/mpetrunic/fastify-sse-v2/blob/master/README.md Customize the server send retry delay. Set `retryDelay` to `false` to disable retries or to a specific millisecond value to override the default 3000ms. ```javascript import { FastifySSEPlugin } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin) // retryDelay default 3000 server.register(FastifySSEPlugin, { retryDelay: false // disable retryDelay retryDelay: 5000 // override 5000 }) ``` -------------------------------- ### Configure Default HighWaterMark Source: https://github.com/mpetrunic/fastify-sse-v2/blob/master/README.md Set the buffer size in bytes for the stream. The default is 16384 bytes (16kb). ```javascript import { FastifySSEPlugin } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin) // highWaterMark defaults to 16384 bytes (16kb) server.register(FastifySSEPlugin, { highWaterMark: 1024 // override default setting of 16384 (16kb) with 1024 (1kb) }) ``` -------------------------------- ### Send Individual SSE Events Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Send single SSE events using `reply.sse()`. The first call establishes the connection. Explicitly close the stream using `reply.sseContext.source.end()` when done. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin); server.get("/events", async function (req, reply) { // First call opens the SSE connection reply.sse({ id: "1", event: "message", data: "First event" }); await new Promise((r) => setTimeout(r, 1000)); reply.sse({ id: "2", event: "message", data: "Second event" }); await new Promise((r) => setTimeout(r, 1000)); reply.sse({ id: "3", event: "notification", data: JSON.stringify({ level: "info", text: "Done" }), retry: 5000, // Override client reconnect delay for this event }); // Explicitly close the stream reply.sseContext.source.end(); }); server.listen({ port: 3000 }); ``` -------------------------------- ### serializeSSEEvent Utility for Manual Serialization Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt The `serializeSSEEvent` function from `fastify-sse-v2/src/sse` allows manual conversion of an `EventMessage` object into an SSE-formatted string. It handles multi-line data, comments, and ensures the correct trailing blank line for event termination. An empty message results in an empty string. ```typescript import { serializeSSEEvent } from "fastify-sse-v2/src/sse"; console.log(serializeSSEEvent({ id: "1", event: "msg", data: "hello" })); // id: 1 // event: msg // data: hello // // (trailing blank line included) console.log(serializeSSEEvent({ data: "line1\nline2" })); // data: line1 // data: line2 // console.log(serializeSSEEvent({ comment: " keep-alive" })); // : keep-alive // // Empty message returns empty string (no output written) console.log(serializeSSEEvent({})); // "" ``` -------------------------------- ### Send Individual Events Source: https://github.com/mpetrunic/fastify-sse-v2/blob/master/README.md Send individual Server-Sent Events. The connection is kept open until `reply.sseContext.source.end()` is called. ```javascript import { FastifySSEPlugin } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin); server.get("/", async function (req, res) { for (let i = 0; i < 10; i++) { await sleep(2000); res.sse({ id: String(i), data: "Some message" }); } }); fastify.get("/listenForChanges", {}, (request, reply) => { const listenStream = fastify.db .watch("doc-uuid") .on("data", (data) => reply.sse({ data: JSON.stringify(data) })) .on("delete", () => reply.sse({ event: "close" })); request.socket.on("close", () => listenStream.end()); }); ``` -------------------------------- ### reply.sse(source: AsyncIterable) — Streaming from Async Iterable Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Passes an AsyncIterable (or async generator) to reply.sse(). The plugin consumes the iterable and serializes each emitted EventMessage to the SSE stream. The connection closes automatically when the iterable is exhausted. ```APIDOC ## `reply.sse(source: AsyncIterable)` — Streaming from Async Iterable Passes an `AsyncIterable` (or async generator) to `reply.sse()`. The plugin consumes the iterable and serializes each emitted `EventMessage` to the SSE stream. The connection closes automatically when the iterable is exhausted. ```typescript import fastify from "fastify"; import { FastifySSEPlugin, EventMessage } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin); // Async generator as event source server.get("/stream", function (req, reply) { reply.sse( (async function* (): AsyncIterable { for (let i = 0; i < 5; i++) { await new Promise((resolve) => setTimeout(resolve, 1000)); yield { id: String(i), event: "update", data: JSON.stringify({ count: i, timestamp: Date.now() }), }; } // Stream ends naturally when generator returns — client connection closes })() ); }); // Client-side usage (browser): // const es = new EventSource("/stream"); // es.addEventListener("update", (e) => console.log(JSON.parse(e.data))); // // Output: { count: 0, timestamp: 1700000000000 } // // Output: { count: 1, timestamp: 1700000001000 } // // ... server.listen({ port: 3000 }); ``` ``` -------------------------------- ### Send Events from AsyncIterable Source Source: https://github.com/mpetrunic/fastify-sse-v2/blob/master/README.md Send Server-Sent Events by providing an AsyncIterable as the source. The connection remains open until the iterable is exhausted. ```javascript import { FastifySSEPlugin } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin); server.get("/", function (req, res) { res.sse( (async function* source() { for (let i = 0; i < 10; i++) { sleep(2000); yield { id: String(i), data: "Some message" }; } })() ); }); ``` -------------------------------- ### EventMessage Interface for SSE Event Fields Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt The `EventMessage` interface defines standard SSE fields like `id`, `event`, `data`, `retry`, and `comment`. The `data` field supports multi-line strings, which are correctly serialized into multiple `data:` lines. Minimal and keep-alive events can also be constructed. ```typescript import { EventMessage } from "fastify-sse-v2"; // Full event with all fields const fullEvent: EventMessage = { id: "42", // Last-Event-ID for client reconnect resume event: "priceUpdate", // Custom event type (client listens with addEventListener) data: "line one\nline two", // Multi-line data — serialized as two "data:" lines retry: 2000, // Instruct client to reconnect after 2s comment: " keep-alive ping", // SSE comment line (starts with ':') }; // Serialized wire format produced internally: // id: 42 // event: priceUpdate // data: line one // data: line two // retry: 2000 // : keep-alive ping // ← blank line terminates the event // Minimal event (data only) const simpleEvent: EventMessage = { data: "hello world", }; // Keep-alive comment (no data, prevents proxy timeouts) const keepAlive: EventMessage = { comment: " ping", }; ``` -------------------------------- ### Integrate EventEmitter with SSE Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Bridge Node.js EventEmitter events into an SSE stream using the `events.on` async iterator adapter. Requires Node.js ≥ 12.16. Ensure to abort the async iterator when the client disconnects to free up listeners. ```typescript import fastify from "fastify"; import { FastifySSEPlugin } from "fastify-sse-v2"; import { on, EventEmitter } from "events"; const server = fastify(); server.register(FastifySSEPlugin); const bus = new EventEmitter(); server.get("/bus", function (req, reply) { const abortController = new AbortController(); reply.sse( (async function* () { for await (const [event] of on(bus, "update", { signal: abortController.signal })) { yield { event: event.type as string, data: JSON.stringify(event), }; } })() ); // Abort the async iterator when client disconnects to free listeners req.socket.on("close", () => abortController.abort()); }); // Emit events from anywhere in the application setInterval(() => { bus.emit("update", { type: "tick", time: new Date().toISOString() }); }, 2000); server.listen({ port: 3000 }); ``` -------------------------------- ### Send Events from EventEmitters Source: https://github.com/mpetrunic/fastify-sse-v2/blob/master/README.md Send Server-Sent Events by listening to events from an EventEmitter. Ensure compatibility with your Node.js version. ```javascript import { FastifySSEPlugin } from "fastify-sse-v2"; import { on } from "events"; const server = fastify(); server.register(FastifySSEPlugin); server.get("/", function (req, res) { res.sse( (async function* () { for await (const [event] of on(eventEmmitter, "update")) { yield { event: event.name, data: JSON.stringify(event), }; } })() ); }); ``` -------------------------------- ### Stream SSE Events from Async Iterable Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Consume an AsyncIterable (like an async generator) to stream SSE events. The connection closes when the iterable is exhausted. ```typescript import fastify from "fastify"; import { FastifySSEPlugin, EventMessage } from "fastify-sse-v2"; const server = fastify(); server.register(FastifySSEPlugin); // Async generator as event source server.get("/stream", function (req, reply) { reply.sse( (async function* (): AsyncIterable { for (let i = 0; i < 5; i++) { await new Promise((resolve) => setTimeout(resolve, 1000)); yield { id: String(i), event: "update", data: JSON.stringify({ count: i, timestamp: Date.now() }), }; } // Stream ends naturally when generator returns — client connection closes })() ); }); // Client-side usage (browser): // const es = new EventSource("/stream"); // es.addEventListener("update", (e) => console.log(JSON.parse(e.data))); // // Output: { count: 0, timestamp: 1700000000000 } // // Output: { count: 1, timestamp: 1700000001000 } // // ... server.listen({ port: 3000 }); ``` -------------------------------- ### Check if a value is an AsyncIterable Source: https://context7.com/mpetrunic/fastify-sse-v2/llms.txt Use `isAsyncIterable` to determine if a value implements the AsyncIterable protocol. This is useful for differentiating between stream and single event inputs. ```typescript import { isAsyncIterable } from "fastify-sse-v2/src/util"; import pushable from "it-pushable"; import { EventEmitter } from "events"; console.log(isAsyncIterable(null)); // false console.log(isAsyncIterable({})); // false console.log(isAsyncIterable(new EventEmitter())); // false console.log(isAsyncIterable(pushable())); // true async function* gen() { yield 1; } console.log(isAsyncIterable(gen())); // true // Practical usage: routing to different handlers function handleSource(source: AsyncIterable | unknown) { if (isAsyncIterable(source)) { console.log("Streaming from async iterable"); } else { console.log("Single event object"); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.