@rvettori/elysia-broadcast 0.2.0 → 0.3.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 CHANGED
@@ -8,6 +8,7 @@ Broadcast and Server-Sent Events (SSE) system for Elysia with multi-channel per-
8
8
  - ✅ **Type-safe** - Fully typed with TypeScript
9
9
  - ✅ **SSE out-of-the-box** - Ready-to-use Server-Sent Events plugin with client library
10
10
  - ✅ **Alpine.js compatible** - Works seamlessly with Alpine.morph and x-sync
11
+ - ✅ **JSON events** - Dispatches native `CustomEvent` on `document` for JSON-only broadcasts
11
12
  - ✅ **Flexible** - Use `BroadcastManager` standalone or as an Elysia plugin
12
13
  - ✅ **Lightweight** - Zero dependencies besides Elysia
13
14
  - ✅ **Tested** - Complete test coverage
@@ -227,7 +228,7 @@ Removes all connections.
227
228
  // Basic connection
228
229
  ElysiaSSE.connect('notifications');
229
230
 
230
- // With custom handler
231
+ // With custom handler (receives the full event object)
231
232
  ElysiaSSE.connect('messages', {
232
233
  onUpdate: (data) => {
233
234
  console.log('New message:', data);
@@ -239,6 +240,49 @@ Removes all connections.
239
240
  </script>
240
241
  ```
241
242
 
243
+ ### JSON Events (CustomEvent)
244
+
245
+ When a broadcast includes a `data` payload, the client automatically dispatches a native `CustomEvent` on `document` with the name `sse:<type>`. This works regardless of whether `html` is also present.
246
+
247
+ **Server:**
248
+ ```typescript
249
+ store.broadcast.broadcast('notifications', userId, {
250
+ type: 'notification.new',
251
+ data: { title: 'New comment', message: 'Someone replied to your post' }
252
+ });
253
+ ```
254
+
255
+ **Client — Vanilla JS:**
256
+ ```html
257
+ <script src="/vendor/elysia-sse.js"></script>
258
+ <script>
259
+ ElysiaSSE.connect('notifications');
260
+
261
+ document.addEventListener('sse:notification.new', (e) => {
262
+ const { title, message } = e.detail.data;
263
+ console.log(title, message);
264
+ });
265
+ </script>
266
+ ```
267
+
268
+ **Client — Alpine.js:**
269
+ ```html
270
+ <div x-data="{ count: 0 }" @sse:notification.new.document="count++">
271
+ <span x-text="count"></span> unread
272
+ </div>
273
+ ```
274
+
275
+ When `html` and `data` are sent together, both are processed: the DOM is updated via Alpine.morph **and** the `CustomEvent` is dispatched.
276
+
277
+ ```typescript
278
+ // Both html update and CustomEvent will fire
279
+ store.broadcast.broadcast('todos', userId, {
280
+ type: 'todo.created',
281
+ data: { id: 1, task: 'New task' },
282
+ html: '<div x-sync id="todo-list">...</div>'
283
+ });
284
+ ```
285
+
242
286
  ### HTMX + SSE
243
287
 
244
288
  ```html
package/dist/client.js CHANGED
@@ -112,6 +112,14 @@ window.ElysiaSSE = {
112
112
  console.error('❌ [SSE] Erros:', errors.join(', '));
113
113
  }
114
114
  }
115
+
116
+ // Dispatch native CustomEvent whenever data payload is present
117
+ if (data.data !== undefined) {
118
+ document.dispatchEvent(new CustomEvent('sse:' + data.type, {
119
+ detail: data,
120
+ bubbles: true
121
+ }));
122
+ }
115
123
  } catch (error) {
116
124
  console.error('❌ [SSE] Erro ao processar evento:', error);
117
125
  }
package/dist/index.js CHANGED
@@ -4,25 +4,43 @@ var __getProtoOf = Object.getPrototypeOf;
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
7
12
  var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
8
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
9
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
22
  for (let key of __getOwnPropNames(mod))
11
23
  if (!__hasOwnProp.call(to, key))
12
24
  __defProp(to, key, {
13
- get: () => mod[key],
25
+ get: __accessProp.bind(mod, key),
14
26
  enumerable: true
15
27
  });
28
+ if (canCache)
29
+ cache.set(mod, to);
16
30
  return to;
17
31
  };
18
32
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
33
+ var __returnValue = (v) => v;
34
+ function __exportSetter(name, newValue) {
35
+ this[name] = __returnValue.bind(null, newValue);
36
+ }
19
37
  var __export = (target, all) => {
20
38
  for (var name in all)
21
39
  __defProp(target, name, {
22
40
  get: all[name],
23
41
  enumerable: true,
24
42
  configurable: true,
25
- set: (newValue) => all[name] = () => newValue
43
+ set: __exportSetter.bind(all, name)
26
44
  });
27
45
  };
28
46
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -6631,7 +6649,6 @@ __export(exports_type3, {
6631
6649
 
6632
6650
  // node_modules/@sinclair/typebox/build/esm/type/type/index.mjs
6633
6651
  var Type = exports_type3;
6634
-
6635
6652
  // node_modules/@sinclair/typebox/build/esm/errors/function.mjs
6636
6653
  function DefaultErrorFunction(error) {
6637
6654
  switch (error.errorType) {
@@ -7909,6 +7926,7 @@ function Errors(...args) {
7909
7926
  const iterator = args.length === 3 ? Visit6(args[0], args[1], "", args[2]) : Visit6(args[0], [], "", args[1]);
7910
7927
  return new ValueErrorIterator(iterator);
7911
7928
  }
7929
+
7912
7930
  // node_modules/@sinclair/typebox/build/esm/value/assert/assert.mjs
7913
7931
  var __classPrivateFieldSet = function(receiver, state, value, kind, f) {
7914
7932
  if (kind === "m")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rvettori/elysia-broadcast",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Broadcast and SSE system for Elysia with support for multiple channels per user",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
package/src/client.js CHANGED
@@ -112,6 +112,14 @@ window.ElysiaSSE = {
112
112
  console.error('❌ [SSE] Erros:', errors.join(', '));
113
113
  }
114
114
  }
115
+
116
+ // Dispatch native CustomEvent whenever data payload is present
117
+ if (data.data !== undefined) {
118
+ document.dispatchEvent(new CustomEvent('sse:' + data.type, {
119
+ detail: data,
120
+ bubbles: true
121
+ }));
122
+ }
115
123
  } catch (error) {
116
124
  console.error('❌ [SSE] Erro ao processar evento:', error);
117
125
  }