Socket
Socket
Sign inDemoInstall

better-sse

Package Overview
Dependencies
0
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.8.0 to 0.9.0

./build/index.js

40

build/Channel.d.ts
import { TypedEmitter, EventMap } from "./lib/TypedEmitter";
import { Session } from "./Session";
interface BroadcastOptions {
import { Session, DefaultSessionState } from "./Session";
interface BroadcastOptions<SessionState extends Record<string, unknown> = DefaultSessionState> {
/**

@@ -9,18 +9,24 @@ * Filter sessions that should receive the event.

*/
filter?: (session: Session) => boolean;
filter?: (session: Session<SessionState>) => boolean;
}
interface ChannelEvents extends EventMap {
"session-registered": (session: Session) => void;
"session-deregistered": (session: Session) => void;
"session-disconnected": (session: Session) => void;
interface ChannelEvents<SessionState extends Record<string, unknown> = DefaultSessionState> extends EventMap {
"session-registered": (session: Session<SessionState>) => void;
"session-deregistered": (session: Session<SessionState>) => void;
"session-disconnected": (session: Session<SessionState>) => void;
broadcast: (data: unknown, eventName: string, eventId: string) => void;
}
interface DefaultChannelState {
[key: string]: unknown;
}
/**
* A Channel is used to broadcast events to many sessions at once.
* A `Channel` is used to broadcast events to many sessions at once.
*
* It extends from the {@link https://nodejs.org/api/events.html#events_class_eventemitter | EventEmitter} class.
*
* You may use the second generic argument `SessionState` to enforce that only sessions with the same state type may be registered with this channel.
*/
declare class Channel<State extends Record<string, unknown> = Record<string, unknown>> extends TypedEmitter<ChannelEvents> {
declare class Channel<State extends Record<string, unknown> = DefaultChannelState, SessionState extends Record<string, unknown> = DefaultSessionState> extends TypedEmitter<ChannelEvents<SessionState>> {
/**
* Custom state for this channel.
*
* Use this object to safely store information related to the channel.

@@ -34,3 +40,3 @@ */

*/
get activeSessions(): ReadonlyArray<Session>;
get activeSessions(): ReadonlyArray<Session<SessionState>>;
/**

@@ -43,7 +49,7 @@ * Number of sessions subscribed to this channel.

*
* If the session is already registered this method does nothing.
* If the session was already registered to begin with this method does nothing.
*
* @param session - Session to register.
*/
register(session: Session): this;
register(session: Session<SessionState>): this;
/**

@@ -56,11 +62,11 @@ * Deregister a session so that it no longer receives events from this channel.

*/
deregister(session: Session): this;
deregister(session: Session<SessionState>): this;
/**
* Push an event to every active session on this channel.
* Broadcast an event with the given data and name to every active session registered with this channel.
*
* Takes the same arguments as the `Session#push` method.
* Note that the broadcasted event will have the same ID across all receiving sessions instead of generating a unique ID for each.
*/
broadcast: (data: unknown, eventName?: string, options?: BroadcastOptions) => this;
broadcast: (data: unknown, eventName?: string, options?: BroadcastOptions<SessionState>) => this;
}
export type { BroadcastOptions, ChannelEvents };
export type { BroadcastOptions, ChannelEvents, DefaultChannelState };
export { Channel };
import { Channel } from "./Channel";
declare const createChannel: <State extends Record<string, unknown>>() => Channel<State>;
declare const createChannel: <State extends Record<string, unknown>, SessionState extends Record<string, unknown>>() => Channel<State, SessionState>;
export { createChannel };

@@ -1,6 +0,6 @@

import { Session, SessionState } from "./Session";
import { Session } from "./Session";
/**
* Create a new session and return the session instance once it has connected.
*/
declare const createSession: <State extends Record<string, unknown> = SessionState>(req: import("http").IncomingMessage | import("http2").Http2ServerRequest, res: import("http").ServerResponse | import("http2").Http2ServerResponse, options?: import("./Session").SessionOptions | undefined) => Promise<Session<State>>;
declare const createSession: <State extends Record<string, unknown>>(req: import("http").IncomingMessage | import("http2").Http2ServerRequest, res: import("http").ServerResponse<import("http").IncomingMessage> | import("http2").Http2ServerResponse, options?: import("./Session").SessionOptions | undefined) => Promise<Session<State>>;
export { createSession };

@@ -25,3 +25,3 @@ /// <reference types="node" />

/**
* Whether to trust the last event ID given by the client in the `Last-Event-ID` request header.
* Whether to trust or ignore the last event ID given by the client in the `Last-Event-ID` request header.
*

@@ -59,3 +59,2 @@ * When set to `false`, the `lastId` property will always be initialized to an empty string.

* Event stream requests can be redirected using HTTP 301 and 307 status codes.
*
* Make sure to set `Location` header when using these status codes using the `headers` property.

@@ -89,3 +88,3 @@ *

}
interface SessionState {
interface DefaultSessionState {
[key: string]: unknown;

@@ -99,9 +98,16 @@ }

/**
* A Session represents an open connection between the server and a client.
* A `Session` represents an open connection between the server and a client.
*
* It extends from the {@link https://nodejs.org/api/events.html#events_class_eventemitter | EventEmitter} class.
*
* It emits the `connected` event after it has connected and flushed all headers to the client, and the
* `disconnected` event after client connection has been closed.
* It emits the `connected` event after it has connected and sent all headers to the client, and the
* `disconnected` event after the connection has been closed.
*
* Note that creating a new session will immediately send the initial status code and headers to the client.
* Attempting to write additional headers after you have created a new session will result in an error.
*
* As a performance optimisation, all events and data are first written to an internal buffer
* where it is stored until it is flushed to the client by calling the `flush` method. This is
* done for you when using the `push` helper method.
*
* @param req - The Node HTTP {@link https://nodejs.org/api/http.html#http_class_http_incomingmessage | ServerResponse} object.

@@ -111,8 +117,10 @@ * @param res - The Node HTTP {@link https://nodejs.org/api/http.html#http_class_http_serverresponse | IncomingMessage} object.

*/
declare class Session<State extends Record<string, unknown> = SessionState> extends TypedEmitter<SessionEvents> {
declare class Session<State extends Record<string, unknown> = DefaultSessionState> extends TypedEmitter<SessionEvents> {
/**
* The last ID sent to the client.
* The last event ID sent to the client.
*
* This is initialized to the last event ID given by the user, and otherwise is equal to the last number given to the `.id` method.
*
* For security reasons, keep in mind that the client can provide *any* initial ID here. Use the `trustClientEventId` to ignore the client-given initial ID.
*
* @readonly

@@ -122,3 +130,3 @@ */

/**
* Indicates whether the session and connection is open or not.
* Indicates whether the session and underlying connection is open or not.
*

@@ -132,2 +140,5 @@ * @readonly

* Use this object to safely store information related to the session and user.
*
* Use [module augmentation and declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)
* to safely add new properties to the `DefaultSessionState` interface.
*/

@@ -167,3 +178,3 @@ state: State;

/**
* Set the event to the given name (also referred to as "type" in the specification).
* Set the event to the given name (also referred to as the event "type" in the specification).
*

@@ -212,3 +223,3 @@ * @param type - Event name/type.

/**
* Create, dispatch and flush an event with the given data all at once.
* Create, write, dispatch and flush an event with the given data to the client all at once.
*

@@ -231,6 +242,7 @@ * This is equivalent to calling the methods `event`, `id`, `data`, `dispatch` and `flush` in that order.

*
* Each data emission by the stream emits a new event that is dispatched to the client.
* Each data emission by the stream pushes a new event to the client.
*
* This uses the `push` method under the hood.
*
* If no event name is given in the options object, the event name (type) is set to `"stream"`.
* If no event name is given in the options object, the event name is set to `"stream"`.
*

@@ -244,8 +256,9 @@ * @param stream - Readable stream to consume from.

/**
* Iterate over an iterable and send yielded values as data to the client.
* Iterate over an iterable and send yielded values to the client.
*
* Each yield emits a new event that is dispatched to the client.
* Each yield pushes a new event to the client.
*
* This uses the `push` method under the hood.
*
* If no event name is given in the options object, the event name (type) is set to `"iteration"`.
* If no event name is given in the options object, the event name is set to `"iteration"`.
*

@@ -258,3 +271,3 @@ * @param iterable - Iterable to consume data from.

}
export type { SessionOptions, StreamOptions, IterateOptions, SessionState, SessionEvents, };
export type { SessionOptions, StreamOptions, IterateOptions, SessionEvents, DefaultSessionState, };
export { Session };
{
"name": "better-sse",
"description": "Dead simple, dependency-less, spec-compliant server-side events implementation for Node, written in TypeScript.",
"version": "0.8.0",
"version": "0.9.0",
"main": "./build/index.js",

@@ -29,26 +29,23 @@ "types": "./build/index.d.ts",

"devDependencies": {
"@jest/types": "^28.1.0",
"@types/eventsource": "^1.1.8",
"@types/express": "^4.17.13",
"@types/jest": "^26.0.24",
"@types/node": "^17.0.36",
"@typescript-eslint/eslint-plugin": "^5.26.0",
"@typescript-eslint/parser": "^5.26.0",
"eslint": "^8.16.0",
"eslint-plugin-tsdoc": "^0.2.16",
"eventsource": "^1.1.1",
"jest": "^26.6.3",
"@types/eventsource": "^1.1.11",
"@types/express": "^4.17.16",
"@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "^5.49.0",
"@typescript-eslint/parser": "^5.49.0",
"eslint": "^8.32.0",
"eslint-plugin-tsdoc": "^0.2.17",
"eventsource": "^2.0.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.6.2",
"rimraf": "^3.0.2",
"ts-jest": "^26.5.6",
"ts-loader": "^9.3.0",
"ts-node": "^10.8.0",
"typescript": "^4.7.2",
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2"
"prettier": "^2.8.3",
"rimraf": "^4.1.2",
"ts-loader": "^9.4.2",
"ts-node": "^10.9.1",
"typescript": "^4.9.4",
"vitest": "^0.28.2",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
},
"scripts": {
"build": "webpack --env production",
"test": "jest",
"test": "vitest",
"clean": "rimraf ./build",

@@ -55,0 +52,0 @@ "format": "prettier --write ./src/**/*.ts",

@@ -12,3 +12,3 @@ # Better SSE

This package aims to be the easiest to use, most compliant and most streamlined solution to server-side events with Node that is framework agnostic and feature rich.
This package aims to be the easiest to use, most compliant and most streamlined solution to server-side events with Node that is framework-agnostic and feature-rich.

@@ -19,5 +19,5 @@ Please consider starring the project [on GitHub ⭐](https://github.com/MatthewWid/better-sse).

Server-sent events (SSE) is a standardised protocol that allows web-servers to push data to clients without the need for alternative mechanisms such as pinging or long-polling.
Server-sent events (SSE) is a standardised protocol that allows web-servers to push data to clients without the need for alternative mechanisms such as pinging, long-polling or [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API).
Using SSE can allow for significant savings in bandwidth and battery life on portable devices, and will work with your existing infrastructure as it operates directly over the HTTP protocol without the need for the connection upgrade that [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) require.
Using SSE can allow for significant savings in bandwidth and battery life on portable devices and will work with your existing infrastructure as it operates directly over the HTTP protocol without the need for the connection upgrade that WebSockets require.

@@ -37,8 +37,8 @@ Compared to WebSockets it has comparable performance and bandwidth usage, especially over HTTP/2, and natively includes event ID generation and automatic reconnection when clients are disconnected.

* [Channels](./docs/channels.md) allow you to broadcast events to many clients at once.
* Configurable reconnection time, message serialization and data sanitization (but with good defaults).
* Configurable reconnection time, message serialization and data sanitization (with good defaults).
* Trust or ignore the client-given last event ID.
* Automatically send keep-alive pings to keep connections open.
* Add or override the response status code and headers.
* Fine-grained control by either sending [individual fields](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#fields) of events or sending full events with simple helpers.
* Pipe [streams](https://nodejs.org/api/stream.html#stream_readable_streams) and [iterables](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators) directly from the server to the client as a stream of events.
* Fine-grained control by either sending [individual fields](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#fields) of events or by sending full events with simple helpers.
* Pipe [streams](https://nodejs.org/api/stream.html#stream_readable_streams) and [iterables](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators) directly from the server to the client as a series of events.
* Support for popular EventStream polyfills [`event-source-polyfill`](https://www.npmjs.com/package/event-source-polyfill) and [`eventsource-polyfill`](https://www.npmjs.com/package/eventsource-polyfill).

@@ -61,7 +61,7 @@

_Better SSE ships with types built in. No need to install from `@types` for TypeScript users!_
_Better SSE ships with types built in. No need to install from DefinitelyTyped for TypeScript users!_
# Usage
The following example shows usage with [Express](http://expressjs.com/), but Better SSE works with any web-server framework (that uses the underlying Node [HTTP module](https://nodejs.org/api/http.html)).
The following example shows usage with [Express](http://expressjs.com/), but Better SSE works with any web-server framework that uses the underlying Node [HTTP module](https://nodejs.org/api/http.html).

@@ -76,3 +76,3 @@ See the [Recipes](./docs/recipes.md) section of the documentation for use with other frameworks and libraries.

// Server
import {createSession} from "better-sse";
import { createSession } from "better-sse";

@@ -90,3 +90,3 @@ app.get("/sse", async (req, res) => {

sse.addEventListener("message", ({data}) => {
sse.addEventListener("message", ({ data }) => {
console.log(data);

@@ -101,3 +101,3 @@ });

```typescript
import {createSession, createChannel} from "better-sse";
import { createSession, createChannel } from "better-sse";

@@ -184,2 +184,2 @@ const channel = createChannel();

This project is licensed under the MIT license.
This project is licensed under the [MIT license](https://opensource.org/license/mit/).
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc