npm package: @silyze/next-sse
Description: Server Sent Events implementation for @mojsoski/next-endpoint
Author: Mihail Mojsoski
Latest version: 1.0.0

# Next SSE

Server-Sent Events implementation for `@mojsoski/next-endpoint`, providing a simple API to stream SSE responses in Next.js endpoints.

## Installation

```bash
npm install @silyze/next-sse
```

## Usage

Import and use in your Next.js API route to create an SSE stream:

```ts
import createServerSentEvents from "@silyze/next-sse";
import { createApiEndpoint } from "@mojsoski/next-endpoint";
import { NextResponse } from "next/server";

export const GET = createApiEndpoint(({ request }) => {
  return createServerSentEvents(
    (write) => {
      // Send a simple data message
      void write({ data: "Hello, World!" });

      // Optionally return a cleanup function
      return () => {
        // Clean up timers or subscriptions here
      };
    },
    {
      request,
      Response: NextResponse,
      keepAliveInterval: 1000, // milliseconds between comment pings
    }
  );
}, [] as const);
```

## API Reference

### `createServerSentEvents(handler, options)`

Creates a streaming SSE response.

- `handler: ServerSentEventsHandler`
  Function invoked with a `write` callback to send SSE messages. May return a cleanup function.

- `options: ServerSentEventsOptions<TRequest, TResponse>`
  Either the incoming `Request` object or an object with:

  - `request`: the incoming request
  - `Response`: a response constructor (e.g. `NextResponse`)
  - `keepAliveInterval?`: interval in milliseconds to send SSE comments (`":"` ping) to keep the connection alive (default: `1000`)

Returns an instance of `Response` (or the provided `Response` constructor) with headers:

- `Content-Type: text/event-stream`
- `Cache-Control: no-cache`
- `Connection: keep-alive`

### Types

#### `ServerSentData`

```ts
export type ServerSentData = {
  data: string;
  id?: string;
  event?: string;
  type?: "data" | undefined;
};
```

- **data**: The message payload (string).
- **id**: Optional message identifier (`id:` field).
- **event**: Optional custom event type (`event:` field).
- **type**: Message type; normally omitted or set to `"data"`.

#### `ServerSentComment`

```ts
export type ServerSentComment = {
  type: "comment";
  text: string;
};
```

- **type**: `"comment"` to send an SSE comment.
- **text**: Comment text; each line will be prefixed with `": "`.

#### `ServerSentRetry`

```ts
export type ServerSentRetry = {
  type: "retry";
  time: number;
};
```

- **type**: `"retry"` to adjust reconnection time.
- **time**: Milliseconds the client should wait before retrying.

#### `ServerSentMessage`

```ts
export type ServerSentMessage =
  | ServerSentData
  | ServerSentRetry
  | ServerSentComment;
```

Union of all supported message types.

#### `ServerSentEventsWrite`

```ts
export type ServerSentEventsWrite = (
  message: ServerSentMessage
) => Promise<void>;
```

Function to send a single SSE message.

#### `ServerSentEventsHandler`

```ts
export type ServerSentEventsHandler = (
  write: ServerSentEventsWrite
) => (() => void) | void;
```

Function that receives the `write` callback. Can return an optional cleanup function that is called when the connection is closed or aborted.

#### `ServerSentEventsOptions<TRequest, TResponse>`

```ts
export type ServerSentEventsOptions<
  TRequest extends Request,
  TResponse extends Response
> =
  | TRequest
  | {
      request: TRequest;
      Response: new (body?: BodyInit | null, init?: ResponseInit) => TResponse;
      keepAliveInterval?: number;
    };
```

Options to configure the SSE stream:

- Pass the raw `Request` if using standard web APIs.
- Or supply an object with `request`, a custom `Response` constructor, and optional `keepAliveInterval`.

## Examples

### Custom Event and ID

```ts
return createServerSentEvents((write) => {
  void write({
    data: JSON.stringify({ count: 1 }),
    id: "1",
    event: "tick",
  });
});
```

### Retry Directive

```ts
return createServerSentEvents((write) => {
  // Instruct client to retry after 5 seconds on disconnect
  void write({ type: "retry", time: 5000 });
});
```

### Comments for Keep-Alive

```ts
return createServerSentEvents((write) => {
  // Send a comment ping manually
  void write({ type: "comment", text: "heartbeat" });
});
```