pushstream-client 0.1.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/LICENSE +21 -0
- package/README.md +294 -0
- package/dist/pushstream.cjs.js +534 -0
- package/dist/pushstream.cjs.js.map +1 -0
- package/dist/pushstream.esm.js +528 -0
- package/dist/pushstream.esm.js.map +1 -0
- package/dist/pushstream.js +540 -0
- package/dist/pushstream.js.map +1 -0
- package/dist/pushstream.min.js +8 -0
- package/dist/pushstream.min.js.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dishu Mavi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# pushstream-js
|
|
2
|
+
|
|
3
|
+
A lightweight, zero-dependency JavaScript client for consuming Server-Sent Events (SSE) with automatic reconnection, event subscriptions, and connection state management.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Zero dependencies** - Pure JavaScript, no external libraries
|
|
8
|
+
- **Tiny footprint** - Less than 5KB minified
|
|
9
|
+
- **Auto-reconnection** - Exponential backoff with jitter to prevent thundering herd
|
|
10
|
+
- **Event-driven API** - Familiar `on()`/`off()` subscription pattern
|
|
11
|
+
- **JSON parsing** - Automatic payload parsing
|
|
12
|
+
- **Connection state** - Track connection status with built-in events
|
|
13
|
+
- **Universal** - Works in browsers and Node.js
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### npm / yarn / pnpm
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install pushstream-js
|
|
21
|
+
# or
|
|
22
|
+
yarn add pushstream-js
|
|
23
|
+
# or
|
|
24
|
+
pnpm add pushstream-js
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### CDN / Script Tag
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<script src="https://unpkg.com/pushstream-js/dist/pushstream.min.js"></script>
|
|
31
|
+
<script>
|
|
32
|
+
const client = new PushStream.EventClient('/events');
|
|
33
|
+
</script>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import { EventClient } from 'pushstream-js';
|
|
40
|
+
|
|
41
|
+
// Create client
|
|
42
|
+
const client = new EventClient('/events');
|
|
43
|
+
|
|
44
|
+
// Subscribe to events
|
|
45
|
+
client.on('task.progress', (data) => {
|
|
46
|
+
console.log(`Task ${data.taskId}: ${data.percentage}%`);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
client.on('task.complete', (data) => {
|
|
50
|
+
console.log(`Task ${data.taskId} completed!`);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Handle errors
|
|
54
|
+
client.on('stream.error', (error) => {
|
|
55
|
+
console.error('Connection error:', error.message);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Connect
|
|
59
|
+
client.connect();
|
|
60
|
+
|
|
61
|
+
// Later: disconnect
|
|
62
|
+
client.disconnect();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
### `new EventClient(url, options?)`
|
|
68
|
+
|
|
69
|
+
Creates a new EventClient instance.
|
|
70
|
+
|
|
71
|
+
**Parameters:**
|
|
72
|
+
- `url` (string) - The SSE endpoint URL (relative or absolute)
|
|
73
|
+
- `options` (object, optional):
|
|
74
|
+
- `reconnect` (boolean, default: `true`) - Enable automatic reconnection
|
|
75
|
+
- `reconnectInterval` (number, default: `1000`) - Base delay in milliseconds
|
|
76
|
+
- `maxReconnectAttempts` (number, default: `10`) - Maximum retry attempts
|
|
77
|
+
- `maxReconnectDelay` (number, default: `30000`) - Maximum backoff delay
|
|
78
|
+
- `withCredentials` (boolean, default: `false`) - Include cookies in CORS requests
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
const client = new EventClient('/events', {
|
|
82
|
+
reconnect: true,
|
|
83
|
+
reconnectInterval: 2000,
|
|
84
|
+
maxReconnectAttempts: 5
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### `connect()`
|
|
89
|
+
|
|
90
|
+
Establish an SSE connection to the server. This method is idempotent - calling it while already connected has no effect.
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
client.connect();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `disconnect()`
|
|
97
|
+
|
|
98
|
+
Close the SSE connection. After calling `disconnect()`, no automatic reconnection will be attempted.
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
client.disconnect();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### `on(event, callback)`
|
|
105
|
+
|
|
106
|
+
Subscribe to an event. Returns the client instance for chaining.
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
client
|
|
110
|
+
.on('task.progress', handleProgress)
|
|
111
|
+
.on('task.complete', handleComplete);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### `off(event, callback?)`
|
|
115
|
+
|
|
116
|
+
Unsubscribe from an event. If `callback` is omitted, removes all listeners for that event.
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
// Remove specific callback
|
|
120
|
+
client.off('task.progress', handleProgress);
|
|
121
|
+
|
|
122
|
+
// Remove all callbacks for event
|
|
123
|
+
client.off('task.progress');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `state` (property)
|
|
127
|
+
|
|
128
|
+
Get the current connection state.
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
console.log(client.state); // 'disconnected' | 'connecting' | 'connected'
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Built-in Events
|
|
135
|
+
|
|
136
|
+
| Event | Description | Payload |
|
|
137
|
+
|-------|-------------|---------|
|
|
138
|
+
| `stream.open` | Connection established | `{ url: string }` |
|
|
139
|
+
| `stream.close` | Connection closed | `{ manual: boolean }` |
|
|
140
|
+
| `stream.error` | Error occurred | `{ message: string, ... }` |
|
|
141
|
+
| `stream.statechange` | State changed | `{ previousState, currentState }` |
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
client.on('stream.open', () => {
|
|
145
|
+
console.log('Connected!');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
client.on('stream.close', ({ manual }) => {
|
|
149
|
+
console.log(manual ? 'Disconnected by user' : 'Connection lost');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
client.on('stream.error', ({ message }) => {
|
|
153
|
+
console.error('Error:', message);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
client.on('stream.statechange', ({ previousState, currentState }) => {
|
|
157
|
+
console.log(`State: ${previousState} -> ${currentState}`);
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Connection States
|
|
162
|
+
|
|
163
|
+
| State | Description |
|
|
164
|
+
|-------|-------------|
|
|
165
|
+
| `disconnected` | Not connected to server |
|
|
166
|
+
| `connecting` | Attempting to establish connection |
|
|
167
|
+
| `connected` | Connected and receiving events |
|
|
168
|
+
|
|
169
|
+
## Reconnection Behavior
|
|
170
|
+
|
|
171
|
+
By default, the client automatically reconnects when the connection is lost:
|
|
172
|
+
|
|
173
|
+
1. Uses **exponential backoff**: delays increase with each failed attempt
|
|
174
|
+
2. Adds **jitter** (random delay) to prevent all clients reconnecting simultaneously
|
|
175
|
+
3. Respects **max attempts**: stops after `maxReconnectAttempts` failures
|
|
176
|
+
4. **Preserves subscriptions**: no need to re-register event handlers after reconnection
|
|
177
|
+
|
|
178
|
+
To disable auto-reconnection:
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
const client = new EventClient('/events', { reconnect: false });
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Authentication
|
|
185
|
+
|
|
186
|
+
Since `EventSource` cannot send custom headers, use query parameters for authentication:
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
const client = new EventClient('/events?token=your-jwt-token');
|
|
190
|
+
client.connect();
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
For cookie-based auth with CORS:
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
const client = new EventClient('https://api.example.com/events', {
|
|
197
|
+
withCredentials: true
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Browser Support
|
|
202
|
+
|
|
203
|
+
| Browser | Version |
|
|
204
|
+
|---------|---------|
|
|
205
|
+
| Chrome | 60+ |
|
|
206
|
+
| Firefox | 55+ |
|
|
207
|
+
| Safari | 11+ |
|
|
208
|
+
| Edge | 79+ |
|
|
209
|
+
|
|
210
|
+
## Node.js Support
|
|
211
|
+
|
|
212
|
+
For Node.js 18+, use with an EventSource polyfill:
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
import { EventSource } from 'eventsource';
|
|
216
|
+
globalThis.EventSource = EventSource;
|
|
217
|
+
|
|
218
|
+
import { EventClient } from 'pushstream-js';
|
|
219
|
+
// ... use as normal
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Examples
|
|
223
|
+
|
|
224
|
+
### Progress Tracking
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
const client = new EventClient('/api/upload/events?uploadId=abc123');
|
|
228
|
+
|
|
229
|
+
client.on('upload.progress', ({ percentage, bytesUploaded }) => {
|
|
230
|
+
updateProgressBar(percentage);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
client.on('upload.complete', ({ fileUrl }) => {
|
|
234
|
+
showSuccess(fileUrl);
|
|
235
|
+
client.disconnect();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
client.on('upload.error', ({ message }) => {
|
|
239
|
+
showError(message);
|
|
240
|
+
client.disconnect();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
client.connect();
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Live Notifications
|
|
247
|
+
|
|
248
|
+
```javascript
|
|
249
|
+
const client = new EventClient('/api/notifications');
|
|
250
|
+
|
|
251
|
+
client.on('notification', ({ title, body, type }) => {
|
|
252
|
+
showNotification(title, body, type);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
client.on('stream.error', () => {
|
|
256
|
+
showOfflineIndicator();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
client.on('stream.open', () => {
|
|
260
|
+
hideOfflineIndicator();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
client.connect();
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## TypeScript
|
|
267
|
+
|
|
268
|
+
TypeScript definitions are planned for a future release. For now, you can create a basic `.d.ts` file:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
declare module 'pushstream-js' {
|
|
272
|
+
export class EventClient {
|
|
273
|
+
constructor(url: string, options?: EventClientOptions);
|
|
274
|
+
connect(): void;
|
|
275
|
+
disconnect(): void;
|
|
276
|
+
on(event: string, callback: (data: any) => void): this;
|
|
277
|
+
off(event: string, callback?: (data: any) => void): this;
|
|
278
|
+
readonly state: 'disconnected' | 'connecting' | 'connected';
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface EventClientOptions {
|
|
282
|
+
reconnect?: boolean;
|
|
283
|
+
reconnectInterval?: number;
|
|
284
|
+
maxReconnectAttempts?: number;
|
|
285
|
+
maxReconnectDelay?: number;
|
|
286
|
+
withCredentials?: boolean;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## License
|
|
292
|
+
|
|
293
|
+
MIT
|
|
294
|
+
|