@rvettori/elysia-broadcast 0.2.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 +361 -0
- package/dist/client.js +142 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17837 -0
- package/dist/manager.d.ts +116 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/plugin.d.ts +128 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/stream.d.ts +101 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/types.d.ts +67 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +51 -0
- package/src/client.js +142 -0
package/README.md
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# @rvettori/elysia-broadcast
|
|
2
|
+
|
|
3
|
+
Broadcast and Server-Sent Events (SSE) system for Elysia with multi-channel per-user support.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Multiple channels per user** - Each user can connect to multiple channels simultaneously
|
|
8
|
+
- ✅ **Type-safe** - Fully typed with TypeScript
|
|
9
|
+
- ✅ **SSE out-of-the-box** - Ready-to-use Server-Sent Events plugin with client library
|
|
10
|
+
- ✅ **Alpine.js compatible** - Works seamlessly with Alpine.morph and x-sync
|
|
11
|
+
- ✅ **Flexible** - Use `BroadcastManager` standalone or as an Elysia plugin
|
|
12
|
+
- ✅ **Lightweight** - Zero dependencies besides Elysia
|
|
13
|
+
- ✅ **Tested** - Complete test coverage
|
|
14
|
+
|
|
15
|
+
## 📦 Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun add @rvettori/elysia-broadcast
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 🎯 Basic Usage
|
|
22
|
+
|
|
23
|
+
### Server Setup
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { Elysia } from 'elysia';
|
|
27
|
+
import { broadcastPlugin, streamPlugin } from '@rvettori/elysia-broadcast';
|
|
28
|
+
|
|
29
|
+
const app = new Elysia()
|
|
30
|
+
.use(broadcastPlugin())
|
|
31
|
+
.use(streamPlugin({
|
|
32
|
+
authMiddleware: yourAuthMiddleware,
|
|
33
|
+
getUserId: (ctx) => ctx.store.user.userId
|
|
34
|
+
}))
|
|
35
|
+
.post('/todos', ({ store }) => {
|
|
36
|
+
// Create todo...
|
|
37
|
+
|
|
38
|
+
// Broadcast to user's 'todos' channel
|
|
39
|
+
store.broadcast.broadcast('todos', userId, {
|
|
40
|
+
type: 'todo.created',
|
|
41
|
+
data: { id: 1, task: 'New task' },
|
|
42
|
+
html: '<div x-sync id="todo-list">...</div>' // Alpine-compatible
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return { success: true };
|
|
46
|
+
})
|
|
47
|
+
.listen(3000);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Client Setup
|
|
51
|
+
|
|
52
|
+
The `streamPlugin` automatically provides a client library at `/vendor/elysia-sse.js`:
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<!-- Load the client library -->
|
|
56
|
+
<script src="/vendor/elysia-sse.js"></script>
|
|
57
|
+
|
|
58
|
+
<!-- Connect to a channel -->
|
|
59
|
+
<script>
|
|
60
|
+
ElysiaSSE.connect('todos');
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<!-- Elements with x-sync and id will be auto-updated -->
|
|
64
|
+
<div x-sync id="todo-list">
|
|
65
|
+
<!-- Content here will be updated via SSE -->
|
|
66
|
+
</div>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### BroadcastManager Standalone
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { BroadcastManager } from '@rvettori/elysia-broadcast';
|
|
73
|
+
|
|
74
|
+
const manager = new BroadcastManager();
|
|
75
|
+
|
|
76
|
+
// Subscribe
|
|
77
|
+
const unsubscribe = manager.subscribe('notifications', 123, (event) => {
|
|
78
|
+
console.log('Event received:', event.type, event.data);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Broadcast to specific user
|
|
82
|
+
manager.broadcast('notifications', 123, {
|
|
83
|
+
type: 'notification.new',
|
|
84
|
+
data: { message: 'Hello!' }
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Broadcast to ALL users in channel
|
|
88
|
+
manager.broadcast('notifications', {
|
|
89
|
+
type: 'system.announcement',
|
|
90
|
+
data: { message: 'System maintenance at 3pm' }
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Cleanup
|
|
94
|
+
unsubscribe();
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 📚 API
|
|
98
|
+
|
|
99
|
+
### `broadcastPlugin(options?)`
|
|
100
|
+
|
|
101
|
+
Elysia plugin that injects `BroadcastManager` into the store.
|
|
102
|
+
|
|
103
|
+
**Options:**
|
|
104
|
+
- `stateName?: string` - State name (default: `'broadcast'`)
|
|
105
|
+
|
|
106
|
+
**Example:**
|
|
107
|
+
```typescript
|
|
108
|
+
app.use(broadcastPlugin({ stateName: 'events' }));
|
|
109
|
+
|
|
110
|
+
app.get('/trigger', ({ store }) => {
|
|
111
|
+
store.events.broadcast('channel', userId, { ... });
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### `streamPlugin(options?)`
|
|
116
|
+
|
|
117
|
+
Plugin that creates a generic SSE route.
|
|
118
|
+
|
|
119
|
+
**Options:**
|
|
120
|
+
```typescript
|
|
121
|
+
interface StreamPluginOptions {
|
|
122
|
+
basePath?: string; // Default: '/stream'
|
|
123
|
+
userStoreName?: string; // Default: 'user'
|
|
124
|
+
userIdField?: string; // Default: 'userId'
|
|
125
|
+
getUserId?: (context) => number | string;
|
|
126
|
+
authMiddleware?: any;
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Example:**
|
|
131
|
+
```typescript
|
|
132
|
+
app.use(streamPlugin({
|
|
133
|
+
basePath: '/events',
|
|
134
|
+
authMiddleware: sessionAuth,
|
|
135
|
+
getUserId: (ctx) => ctx.store.currentUser.id
|
|
136
|
+
}));
|
|
137
|
+
|
|
138
|
+
// Client: GET /events/todos
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `BroadcastManager`
|
|
142
|
+
|
|
143
|
+
Main event management class.
|
|
144
|
+
|
|
145
|
+
#### Methods
|
|
146
|
+
|
|
147
|
+
**`subscribe(channel, userId, callback)`**
|
|
148
|
+
|
|
149
|
+
Register a listener.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const unsubscribe = manager.subscribe('todos', 123, (event) => {
|
|
153
|
+
console.log(event.type, event.data);
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**`broadcast(channel, userId, event)`** | **`broadcast(channel, event)`**
|
|
158
|
+
|
|
159
|
+
Send event to all listeners on the channel/user. Omit userId to broadcast to all users in the channel.
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// Broadcast to specific user
|
|
163
|
+
manager.broadcast('todos', 123, {
|
|
164
|
+
type: 'update',
|
|
165
|
+
data: { id: 1 },
|
|
166
|
+
html: '<div>...</div>' // Optional
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Broadcast to ALL users in channel (no userId)
|
|
170
|
+
manager.broadcast('todos', {
|
|
171
|
+
type: 'system.announcement',
|
|
172
|
+
data: { message: 'New feature available!' }
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**`getConnectionCount(channel, userId)`**
|
|
177
|
+
|
|
178
|
+
Returns number of active connections for channel/user.
|
|
179
|
+
|
|
180
|
+
**`getTotalConnections()`**
|
|
181
|
+
|
|
182
|
+
Returns total number of connections.
|
|
183
|
+
|
|
184
|
+
**`getActiveChannels()`**
|
|
185
|
+
|
|
186
|
+
Lists all active channels.
|
|
187
|
+
|
|
188
|
+
**`clearChannel(channel, userId)`**
|
|
189
|
+
|
|
190
|
+
Removes all connections from a channel.
|
|
191
|
+
|
|
192
|
+
**`clearAll()`**
|
|
193
|
+
|
|
194
|
+
Removes all connections.
|
|
195
|
+
|
|
196
|
+
## 🎨 Frontend Integration
|
|
197
|
+
|
|
198
|
+
### Alpine.js + SSE (Recommended)
|
|
199
|
+
|
|
200
|
+
```html
|
|
201
|
+
<!-- 1. Load libraries -->
|
|
202
|
+
<script src="/vendor/elysia-sse.js"></script>
|
|
203
|
+
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
|
|
204
|
+
|
|
205
|
+
<!-- 2. Connect to SSE channel -->
|
|
206
|
+
<script>
|
|
207
|
+
ElysiaSSE.connect('todos');
|
|
208
|
+
</script>
|
|
209
|
+
|
|
210
|
+
<!-- 3. Elements with x-sync and id will be auto-updated -->
|
|
211
|
+
<div x-sync id="todo-list" x-data="{ todos: [] }">
|
|
212
|
+
<template x-for="todo in todos">
|
|
213
|
+
<div x-text="todo.task"></div>
|
|
214
|
+
</template>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<!-- Multiple elements can be updated simultaneously -->
|
|
218
|
+
<div x-sync id="todo-stats">Total: 5</div>
|
|
219
|
+
<div x-sync id="user-badge">👤 John</div>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Vanilla JavaScript
|
|
223
|
+
|
|
224
|
+
```html
|
|
225
|
+
<script src="/vendor/elysia-sse.js"></script>
|
|
226
|
+
<script>
|
|
227
|
+
// Basic connection
|
|
228
|
+
ElysiaSSE.connect('notifications');
|
|
229
|
+
|
|
230
|
+
// With custom handler
|
|
231
|
+
ElysiaSSE.connect('messages', {
|
|
232
|
+
onUpdate: (data) => {
|
|
233
|
+
console.log('New message:', data);
|
|
234
|
+
// Custom DOM manipulation
|
|
235
|
+
},
|
|
236
|
+
onConnect: () => console.log('Connected!'),
|
|
237
|
+
onError: (err) => console.error('Error:', err)
|
|
238
|
+
});
|
|
239
|
+
</script>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### HTMX + SSE
|
|
243
|
+
|
|
244
|
+
```html
|
|
245
|
+
<div x-data="{ todos: [] }" x-sync id="todo-list">
|
|
246
|
+
<template x-for="todo in todos">
|
|
247
|
+
<div x-text="todo.task"></div>
|
|
248
|
+
</template>
|
|
249
|
+
</div>
|
|
250
|
+
|
|
251
|
+
<script>
|
|
252
|
+
const eventSource = new EventSource('/stream/todos');
|
|
253
|
+
|
|
254
|
+
eventSource.onmessage = (event) => {
|
|
255
|
+
const { type, html, data } = JSON.parse(event.data);
|
|
256
|
+
|
|
257
|
+
// With Alpine AJAX: updates elements by ID
|
|
258
|
+
if (html) {
|
|
259
|
+
Alpine.morph(document.getElementById('todo-list'), html);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
</script>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### HTMX + SSE
|
|
266
|
+
|
|
267
|
+
```html
|
|
268
|
+
<div hx-ext="sse" sse-connect="/stream/todos">
|
|
269
|
+
<div id="todo-list" sse-swap="message">
|
|
270
|
+
<!-- Todo list -->
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## 🔧 Use Cases
|
|
276
|
+
|
|
277
|
+
### Real-time Dashboard
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
app.post('/analytics/track', ({ store, body }) => {
|
|
281
|
+
// Process event...
|
|
282
|
+
|
|
283
|
+
store.broadcast.broadcast('dashboard', userId, {
|
|
284
|
+
type: 'metric.updated',
|
|
285
|
+
data: { visitors: 1234, sales: 5678 }
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Notifications
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// Send to specific user
|
|
294
|
+
app.post('/notifications/send', ({ store, body }) => {
|
|
295
|
+
store.broadcast.broadcast('notifications', recipientId, {
|
|
296
|
+
type: 'notification.new',
|
|
297
|
+
data: {
|
|
298
|
+
title: 'New comment',
|
|
299
|
+
message: 'Someone commented on your post'
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// Send to all users (system announcement)
|
|
305
|
+
app.post('/admin/announce', ({ store, body }) => {
|
|
306
|
+
store.broadcast.broadcast('notifications', {
|
|
307
|
+
type: 'system.announcement',
|
|
308
|
+
data: {
|
|
309
|
+
title: 'System Update',
|
|
310
|
+
message: 'New features available!'
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Chat/Messages
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
app.post('/messages', ({ store, body }) => {
|
|
320
|
+
// Save message...
|
|
321
|
+
|
|
322
|
+
// Notify recipient
|
|
323
|
+
store.broadcast.broadcast('messages', recipientId, {
|
|
324
|
+
type: 'message.new',
|
|
325
|
+
data: { from: senderId, text: body.text }
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## 🧪 Testing
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
bun test
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## 📝 Types
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
interface BroadcastEvent {
|
|
340
|
+
type: string;
|
|
341
|
+
data: any;
|
|
342
|
+
html?: string;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
type BroadcastCallback = (event: BroadcastEvent) => void;
|
|
346
|
+
type UnsubscribeFunction = () => void;
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## 🛠️ Build
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
bun run build
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## 📄 License
|
|
356
|
+
|
|
357
|
+
MIT
|
|
358
|
+
|
|
359
|
+
## 🤝 Contributing
|
|
360
|
+
|
|
361
|
+
Contributions are welcome! Open an issue or PR.
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE (Server-Sent Events) client for elysia-broadcast
|
|
3
|
+
*
|
|
4
|
+
* 🎯 FULL COMPATIBILITY WITH ALPINE-AJAX:
|
|
5
|
+
* Processes elements with 'x-sync' attribute and updates using Alpine.morph,
|
|
6
|
+
* maintaining parity with alpine-ajax behavior in synchronous requests.
|
|
7
|
+
*
|
|
8
|
+
* @module elysia-broadcast/client
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Connects to an SSE channel and manages automatic DOM updates
|
|
13
|
+
*
|
|
14
|
+
* @param {string} channel - SSE channel name
|
|
15
|
+
* @param {Object} options - Configuration options
|
|
16
|
+
* @param {string} options.basePath - SSE base path (default: '/stream')
|
|
17
|
+
* @param {Function} options.onUpdate - Custom handler for events
|
|
18
|
+
* @param {Function} options.onConnect - Callback when connected
|
|
19
|
+
* @param {Function} options.onError - Callback when error occurs
|
|
20
|
+
* @param {Function} options.onDisconnect - Callback when disconnected
|
|
21
|
+
* @returns {EventSource} EventSource instance
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Basic usage
|
|
25
|
+
* ElysiaSSE.connect('todos');
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // With callbacks
|
|
29
|
+
* ElysiaSSE.connect('todos', {
|
|
30
|
+
* onConnect: () => console.log('Connected!'),
|
|
31
|
+
* onUpdate: (data) => console.log('Updated:', data)
|
|
32
|
+
* });
|
|
33
|
+
*/
|
|
34
|
+
window.ElysiaSSE = {
|
|
35
|
+
connect: function (channel, options = {}) {
|
|
36
|
+
const {
|
|
37
|
+
basePath = '/stream',
|
|
38
|
+
onUpdate = null,
|
|
39
|
+
onConnect = null,
|
|
40
|
+
onError = null,
|
|
41
|
+
onDisconnect = null
|
|
42
|
+
} = options;
|
|
43
|
+
|
|
44
|
+
const url = basePath + '/' + channel;
|
|
45
|
+
const eventSource = new EventSource(url);
|
|
46
|
+
|
|
47
|
+
eventSource.onopen = function () {
|
|
48
|
+
console.log('🔌 [SSE] Conectado ao canal:', channel);
|
|
49
|
+
if (onConnect) onConnect();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
eventSource.onmessage = function (event) {
|
|
53
|
+
try {
|
|
54
|
+
const data = JSON.parse(event.data);
|
|
55
|
+
|
|
56
|
+
// Custom handler has priority
|
|
57
|
+
if (onUpdate && typeof onUpdate === 'function') {
|
|
58
|
+
onUpdate(data);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Default processing: multiple elements with x-sync (like alpine-ajax)
|
|
63
|
+
if (data.html) {
|
|
64
|
+
const parser = new DOMParser();
|
|
65
|
+
const doc = parser.parseFromString(data.html, 'text/html');
|
|
66
|
+
|
|
67
|
+
// Search ALL elements with x-sync attribute (alpine-ajax compatibility)
|
|
68
|
+
const elementsWithSync = doc.querySelectorAll('[x-sync]');
|
|
69
|
+
|
|
70
|
+
if (elementsWithSync.length === 0) {
|
|
71
|
+
console.error('❌ [SSE] Nenhum elemento com atributo x-sync encontrado');
|
|
72
|
+
console.error('💡 [SSE] Adicione x-sync e id="..." nos elementos');
|
|
73
|
+
console.error('💡 [SSE] Exemplo: <div x-sync id="meu-elemento">...</div>');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let updatedCount = 0;
|
|
78
|
+
let errors = [];
|
|
79
|
+
|
|
80
|
+
// Process each element (compatible with alpine-ajax multi-target)
|
|
81
|
+
elementsWithSync.forEach(function (newElement) {
|
|
82
|
+
const targetId = newElement.getAttribute('id');
|
|
83
|
+
|
|
84
|
+
if (!targetId) {
|
|
85
|
+
errors.push('Element ' + newElement.tagName + ' without id');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const existingElement = document.getElementById(targetId);
|
|
90
|
+
|
|
91
|
+
if (!existingElement) {
|
|
92
|
+
errors.push('ID not found: ' + targetId);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Use Alpine.morph to preserve reactive state
|
|
97
|
+
if (window.Alpine && window.Alpine.morph) {
|
|
98
|
+
Alpine.morph(existingElement, newElement.outerHTML);
|
|
99
|
+
} else {
|
|
100
|
+
// Fallback: direct replacement
|
|
101
|
+
existingElement.outerHTML = newElement.outerHTML;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
updatedCount++;
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (updatedCount > 0) {
|
|
108
|
+
console.log('✨ [SSE] ' + updatedCount + ' element(s) updated - ' + data.type);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (errors.length > 0) {
|
|
112
|
+
console.error('❌ [SSE] Erros:', errors.join(', '));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error('❌ [SSE] Erro ao processar evento:', error);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
eventSource.onerror = function (error) {
|
|
121
|
+
console.error('❌ [SSE] Connection error:', error);
|
|
122
|
+
|
|
123
|
+
if (eventSource.readyState === EventSource.CLOSED) {
|
|
124
|
+
console.log('🔄 [SSE] Reconnecting in 5 seconds...');
|
|
125
|
+
setTimeout(function () {
|
|
126
|
+
window.location.reload();
|
|
127
|
+
}, 5000);
|
|
128
|
+
|
|
129
|
+
if (onError) onError(error);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Close connection when page is unloaded
|
|
134
|
+
window.addEventListener('beforeunload', function () {
|
|
135
|
+
eventSource.close();
|
|
136
|
+
console.log('👋 [SSE] Desconectado do canal:', channel);
|
|
137
|
+
if (onDisconnect) onDisconnect();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return eventSource;
|
|
141
|
+
}
|
|
142
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* elysia-broadcast
|
|
3
|
+
*
|
|
4
|
+
* Broadcast and SSE (Server-Sent Events) system for Elysia
|
|
5
|
+
* with support for multiple channels per user
|
|
6
|
+
*
|
|
7
|
+
* @module elysia-broadcast
|
|
8
|
+
*/
|
|
9
|
+
export { BroadcastManager } from './manager';
|
|
10
|
+
export { broadcastPlugin, broadcastManager, alpineRequest } from './plugin';
|
|
11
|
+
export { streamPlugin } from './stream';
|
|
12
|
+
export type { BroadcastEvent, BroadcastCallback, UnsubscribeFunction, BroadcastPluginOptions, StreamPluginOptions } from './types';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,SAAS,CAAC"}
|