@uploadista/event-broadcaster-memory 0.0.3

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.
@@ -0,0 +1,5 @@
1
+
2
+ 
3
+ > @uploadista/event-broadcaster-memory@0.0.2 build /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/event-broadcasters/memory
4
+ > tsc -b
5
+
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 uploadista
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,468 @@
1
+ # @uploadista/event-broadcaster-memory
2
+
3
+ In-memory event broadcaster for Uploadista. Broadcasts events within a single process for development and single-server deployments.
4
+
5
+ ## Overview
6
+
7
+ The memory event broadcaster uses JavaScript Maps to distribute events within a single process. Perfect for:
8
+
9
+ - **Development & Testing**: No external services needed
10
+ - **Single-Process Servers**: All instances in same process
11
+ - **WebSocket Servers**: Real-time updates to connected clients
12
+ - **Prototyping**: Quick experimentation with event flows
13
+
14
+ Events are only broadcast to subscribers in the same process. For distributed systems, use [Redis](#see-also) or [Cloudflare Durable Objects](#see-also).
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @uploadista/event-broadcaster-memory
20
+ # or
21
+ pnpm add @uploadista/event-broadcaster-memory
22
+ ```
23
+
24
+ ### Prerequisites
25
+
26
+ - Node.js 18+
27
+ - No external services required
28
+
29
+ ## Quick Start
30
+
31
+ ```typescript
32
+ import { memoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
33
+ import { Effect } from "effect";
34
+
35
+ // Use the memory broadcaster layer
36
+ const program = Effect.gen(function* () {
37
+ // Event broadcaster is automatically available
38
+ });
39
+
40
+ Effect.runSync(
41
+ program.pipe(
42
+ Effect.provide(memoryEventBroadcaster),
43
+ // ... other layers
44
+ )
45
+ );
46
+ ```
47
+
48
+ ## Features
49
+
50
+ - ✅ **Zero Setup**: Works out of the box
51
+ - ✅ **Sub-Millisecond Latency**: In-memory operations (~100μs)
52
+ - ✅ **Synchronous Broadcasting**: Events delivered immediately
53
+ - ✅ **Type Safe**: Full TypeScript support
54
+ - ✅ **Simple API**: Publish/subscribe pattern
55
+
56
+ ## API Reference
57
+
58
+ ### Main Exports
59
+
60
+ #### `memoryEventBroadcaster: Layer<EventBroadcasterService>`
61
+
62
+ Pre-configured Effect layer providing the `EventBroadcasterService` with in-memory broadcasting.
63
+
64
+ ```typescript
65
+ import { memoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
66
+
67
+ const layer = memoryEventBroadcaster;
68
+ // Type: Layer<never, never, EventBroadcasterService>
69
+ ```
70
+
71
+ #### `createMemoryEventBroadcaster(): EventBroadcaster`
72
+
73
+ Factory function to create a new broadcaster instance.
74
+
75
+ ```typescript
76
+ import { createMemoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
77
+
78
+ const broadcaster = createMemoryEventBroadcaster();
79
+ ```
80
+
81
+ ### Available Operations
82
+
83
+ The memory broadcaster implements the `EventBroadcaster` interface:
84
+
85
+ #### `publish(channel: string, message: string): Effect<void>`
86
+
87
+ Broadcast a message to all subscribers on a channel.
88
+
89
+ ```typescript
90
+ const program = Effect.gen(function* () {
91
+ yield* broadcaster.publish("uploads:complete", JSON.stringify({
92
+ uploadId: "abc123",
93
+ status: "completed",
94
+ }));
95
+ });
96
+ ```
97
+
98
+ #### `subscribe(channel: string, handler: (message: string) => void): Effect<void>`
99
+
100
+ Subscribe to a channel and receive messages.
101
+
102
+ ```typescript
103
+ const program = Effect.gen(function* () {
104
+ yield* broadcaster.subscribe("uploads:complete", (message: string) => {
105
+ const event = JSON.parse(message);
106
+ console.log(`Upload complete: ${event.uploadId}`);
107
+ });
108
+ });
109
+ ```
110
+
111
+ #### `unsubscribe(channel: string): Effect<void>`
112
+
113
+ Unsubscribe from a channel (removes all handlers).
114
+
115
+ ```typescript
116
+ const program = Effect.gen(function* () {
117
+ yield* broadcaster.unsubscribe("uploads:complete");
118
+ });
119
+ ```
120
+
121
+ ## Configuration
122
+
123
+ The memory broadcaster requires no configuration:
124
+
125
+ ```typescript
126
+ import { memoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
127
+ import { uploadServer } from "@uploadista/server";
128
+ import { Effect } from "effect";
129
+
130
+ const program = Effect.gen(function* () {
131
+ const server = yield* uploadServer;
132
+ // Broadcaster is automatically available
133
+ });
134
+
135
+ Effect.runSync(
136
+ program.pipe(
137
+ Effect.provide(memoryEventBroadcaster),
138
+ // ... other layers
139
+ )
140
+ );
141
+ ```
142
+
143
+ ## Examples
144
+
145
+ ### Example 1: Upload Progress Notifications
146
+
147
+ ```typescript
148
+ import { createMemoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
149
+ import { Effect } from "effect";
150
+
151
+ const broadcaster = createMemoryEventBroadcaster();
152
+
153
+ interface UploadEvent {
154
+ uploadId: string;
155
+ status: "started" | "progress" | "completed" | "failed";
156
+ progress?: number;
157
+ error?: string;
158
+ }
159
+
160
+ const program = Effect.gen(function* () {
161
+ // Subscribe to upload events
162
+ yield* broadcaster.subscribe("uploads:*", (message: string) => {
163
+ const event: UploadEvent = JSON.parse(message);
164
+ console.log(`[${event.status}] Upload ${event.uploadId}`);
165
+
166
+ if (event.progress !== undefined) {
167
+ console.log(` Progress: ${(event.progress * 100).toFixed(1)}%`);
168
+ }
169
+
170
+ if (event.error) {
171
+ console.log(` Error: ${event.error}`);
172
+ }
173
+ });
174
+
175
+ // Simulate upload events
176
+ yield* broadcaster.publish("uploads:*", JSON.stringify({
177
+ uploadId: "upl_123",
178
+ status: "started",
179
+ }));
180
+
181
+ yield* broadcaster.publish("uploads:*", JSON.stringify({
182
+ uploadId: "upl_123",
183
+ status: "progress",
184
+ progress: 0.5,
185
+ }));
186
+
187
+ yield* broadcaster.publish("uploads:*", JSON.stringify({
188
+ uploadId: "upl_123",
189
+ status: "completed",
190
+ }));
191
+ });
192
+
193
+ Effect.runSync(program);
194
+ ```
195
+
196
+ ### Example 2: Flow Job Status Updates
197
+
198
+ ```typescript
199
+ import { createMemoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
200
+ import { Effect } from "effect";
201
+
202
+ const broadcaster = createMemoryEventBroadcaster();
203
+
204
+ interface FlowEvent {
205
+ jobId: string;
206
+ stage: "queued" | "processing" | "completed";
207
+ duration?: number;
208
+ }
209
+
210
+ const trackFlowJob = (jobId: string) =>
211
+ Effect.gen(function* () {
212
+ // Subscribe to job events
213
+ yield* broadcaster.subscribe(`flow:${jobId}`, (message: string) => {
214
+ const event: FlowEvent = JSON.parse(message);
215
+ console.log(`Job ${event.jobId}: ${event.stage}`);
216
+
217
+ if (event.duration) {
218
+ console.log(` Duration: ${event.duration}ms`);
219
+ }
220
+ });
221
+
222
+ // Emit events
223
+ yield* broadcaster.publish(
224
+ `flow:${jobId}`,
225
+ JSON.stringify({ jobId, stage: "queued" })
226
+ );
227
+
228
+ yield* Effect.sleep("1 seconds");
229
+
230
+ yield* broadcaster.publish(
231
+ `flow:${jobId}`,
232
+ JSON.stringify({ jobId, stage: "processing" })
233
+ );
234
+
235
+ yield* Effect.sleep("3 seconds");
236
+
237
+ yield* broadcaster.publish(
238
+ `flow:${jobId}`,
239
+ JSON.stringify({ jobId, stage: "completed", duration: 4000 })
240
+ );
241
+ });
242
+
243
+ const program = Effect.gen(function* () {
244
+ yield* trackFlowJob("job_abc123");
245
+ });
246
+
247
+ Effect.runSync(program);
248
+ ```
249
+
250
+ ### Example 3: Integration with WebSocket
251
+
252
+ ```typescript
253
+ import { createMemoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
254
+ import { webSocketEventEmitter } from "@uploadista/event-emitter-websocket";
255
+ import { Effect } from "effect";
256
+
257
+ const broadcaster = createMemoryEventBroadcaster();
258
+
259
+ // In your WebSocket handler
260
+ const handleUploadEvent = (
261
+ uploadId: string,
262
+ clientWebSocket: WebSocket
263
+ ) =>
264
+ Effect.gen(function* () {
265
+ // Subscribe to upload events
266
+ yield* broadcaster.subscribe(`uploads:${uploadId}`, (message: string) => {
267
+ // Send to WebSocket client
268
+ clientWebSocket.send(message);
269
+ });
270
+ });
271
+ ```
272
+
273
+ ## Performance Characteristics
274
+
275
+ | Operation | Latency | Throughput |
276
+ |-----------|---------|-----------|
277
+ | publish() | ~100μs | 10,000+ events/sec |
278
+ | subscribe() | ~100μs | N/A |
279
+ | unsubscribe() | ~100μs | N/A |
280
+
281
+ All operations are synchronous and complete in microseconds.
282
+
283
+ ## Limitations
284
+
285
+ - **Single Process Only**: No distribution across servers
286
+ - **No Persistence**: Events are lost if not immediately processed
287
+ - **No Pattern Matching**: Cannot use wildcards in channel names
288
+ - **Memory Grows**: Subscribers accumulate in memory
289
+ - **No TTL**: Subscriptions persist until explicitly removed
290
+
291
+ ## Use Cases
292
+
293
+ ✅ **Perfect For**:
294
+ - Local development
295
+ - Unit/integration testing
296
+ - Single-server deployments
297
+ - Real-time WebSocket updates
298
+ - Prototyping event flows
299
+
300
+ ❌ **Not Recommended For**:
301
+ - Distributed systems (use Redis)
302
+ - Event persistence (use database)
303
+ - Pub/Sub patterns with many subscribers
304
+ - High-throughput production systems (>1000 events/sec)
305
+
306
+ ## Best Practices
307
+
308
+ ### 1. Use Consistent Channel Naming
309
+
310
+ ```typescript
311
+ // Good: Hierarchical naming
312
+ "uploads:started"
313
+ "uploads:progress"
314
+ "uploads:completed"
315
+ "flows:abc123:status"
316
+
317
+ // Avoid: Generic names
318
+ "events", "updates", "status"
319
+ ```
320
+
321
+ ### 2. Clean Up Subscriptions
322
+
323
+ ```typescript
324
+ const program = Effect.gen(function* () {
325
+ // Subscribe
326
+ yield* broadcaster.subscribe("uploads:*", handler);
327
+
328
+ // Do work...
329
+
330
+ // Clean up when done
331
+ yield* broadcaster.unsubscribe("uploads:*");
332
+ });
333
+ ```
334
+
335
+ ### 3. Handle Synchronous Publishing
336
+
337
+ Events are delivered immediately and synchronously:
338
+
339
+ ```typescript
340
+ // This handler runs immediately
341
+ yield* broadcaster.subscribe("channel", (msg) => {
342
+ console.log("Received:", msg);
343
+ });
344
+
345
+ // This publishes immediately to handler above
346
+ yield* broadcaster.publish("channel", "test");
347
+ // "Received: test" is printed before publish() completes
348
+ ```
349
+
350
+ ## Deployment
351
+
352
+ ### Single-Server Node.js
353
+
354
+ ```typescript
355
+ import { memoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
356
+ import { uploadServer } from "@uploadista/server";
357
+ import { Effect } from "effect";
358
+
359
+ const program = Effect.gen(function* () {
360
+ const server = yield* uploadServer;
361
+ // Use broadcaster for WebSocket updates
362
+ });
363
+
364
+ Effect.runSync(
365
+ program.pipe(
366
+ Effect.provide(memoryEventBroadcaster),
367
+ // ... other layers
368
+ )
369
+ );
370
+ ```
371
+
372
+ ### Docker Single Container
373
+
374
+ ```dockerfile
375
+ FROM node:18-alpine
376
+
377
+ WORKDIR /app
378
+ COPY . .
379
+ RUN npm ci --omit=dev && npm run build
380
+
381
+ ENV NODE_ENV=production
382
+ CMD ["node", "dist/server.js"]
383
+ ```
384
+
385
+ ```yaml
386
+ version: "3"
387
+ services:
388
+ app:
389
+ build: .
390
+ ports:
391
+ - "3000:3000"
392
+ # Single instance only
393
+ ```
394
+
395
+ ## Limitations & Workarounds
396
+
397
+ ### Multiple Instances Don't Share Events
398
+
399
+ If you scale to multiple processes, they won't communicate:
400
+
401
+ ```typescript
402
+ // Server 1: Publishes to memory broadcaster
403
+ yield* broadcaster.publish("channel", "message1");
404
+
405
+ // Server 2: Will NOT receive message1 (different process)
406
+ // Solution: Use Redis broadcaster instead
407
+ ```
408
+
409
+ ### High Subscriber Count
410
+
411
+ If many subscribers accumulate, unsubscribe to clean up:
412
+
413
+ ```typescript
414
+ // Create isolated broadcaster instances
415
+ const createIsolatedBroadcaster = () => createMemoryEventBroadcaster();
416
+
417
+ // Use separate instance per namespace
418
+ const uploadBroadcaster = createIsolatedBroadcaster();
419
+ const flowBroadcaster = createIsolatedBroadcaster();
420
+ ```
421
+
422
+ ## Troubleshooting
423
+
424
+ ### Events Not Received
425
+
426
+ Ensure subscribers are registered before publishing:
427
+
428
+ ```typescript
429
+ // ❌ Wrong: Subscribe after publish
430
+ yield* broadcaster.publish("channel", "message");
431
+ yield* broadcaster.subscribe("channel", handler); // Won't receive above
432
+
433
+ // ✅ Correct: Subscribe first
434
+ yield* broadcaster.subscribe("channel", handler);
435
+ yield* broadcaster.publish("channel", "message");
436
+ ```
437
+
438
+ ### Memory Leaks
439
+
440
+ Unsubscribe when no longer needed:
441
+
442
+ ```typescript
443
+ // ❌ Don't do this in loops
444
+ for (let i = 0; i < 1000; i++) {
445
+ yield* broadcaster.subscribe("channel", handler);
446
+ }
447
+
448
+ // ✅ Clean up explicitly
449
+ yield* broadcaster.unsubscribe("channel");
450
+ ```
451
+
452
+ ## Related Packages
453
+
454
+ - [@uploadista/core](../../core) - Core types
455
+ - [@uploadista/event-broadcaster-redis](../event-broadcasters/redis) - Distributed Redis broadcaster
456
+ - [@uploadista/event-emitter-websocket](../event-emitters/websocket) - WebSocket real-time events
457
+ - [@uploadista/server](../../servers/server) - Upload server with events
458
+ - [@uploadista/kv-store-memory](../../kv-stores/memory) - In-memory KV store
459
+
460
+ ## License
461
+
462
+ See [LICENSE](../../../LICENSE) in the main repository.
463
+
464
+ ## See Also
465
+
466
+ - [EVENT_SYSTEM.md](./EVENT_SYSTEM.md) - Architecture and patterns
467
+ - [Server Setup Guide](../../../SERVER_SETUP.md#events) - Using broadcasters in servers
468
+ - [WebSocket Event Emitter](../event-emitters/websocket/README.md) - Real-time WebSocket events
@@ -0,0 +1,2 @@
1
+ export * from "./memory-event-broadcaster";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./memory-event-broadcaster";
@@ -0,0 +1,14 @@
1
+ import type { EventBroadcaster } from "@uploadista/core/types";
2
+ import { EventBroadcasterService } from "@uploadista/core/types";
3
+ import { Layer } from "effect";
4
+ /**
5
+ * In-memory event broadcaster for single-instance deployments.
6
+ * Events are only broadcast within the same process/instance.
7
+ * Use this for development or single-server deployments.
8
+ */
9
+ export declare function createMemoryEventBroadcaster(): EventBroadcaster;
10
+ /**
11
+ * Layer for in-memory event broadcaster
12
+ */
13
+ export declare const memoryEventBroadcaster: Layer.Layer<EventBroadcasterService, never, never>;
14
+ //# sourceMappingURL=memory-event-broadcaster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-event-broadcaster.d.ts","sourceRoot":"","sources":["../src/memory-event-broadcaster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEvC;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,gBAAgB,CA2B/D;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,oDAGlC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { EventBroadcasterService } from "@uploadista/core/types";
2
+ import { Effect, Layer } from "effect";
3
+ /**
4
+ * In-memory event broadcaster for single-instance deployments.
5
+ * Events are only broadcast within the same process/instance.
6
+ * Use this for development or single-server deployments.
7
+ */
8
+ export function createMemoryEventBroadcaster() {
9
+ const handlers = new Map();
10
+ return {
11
+ publish: (channel, message) => Effect.sync(() => {
12
+ const channelHandlers = handlers.get(channel);
13
+ if (channelHandlers) {
14
+ for (const handler of channelHandlers) {
15
+ handler(message);
16
+ }
17
+ }
18
+ }),
19
+ subscribe: (channel, handler) => Effect.sync(() => {
20
+ if (!handlers.has(channel)) {
21
+ handlers.set(channel, new Set());
22
+ }
23
+ handlers.get(channel)?.add(handler);
24
+ }),
25
+ unsubscribe: (channel) => Effect.sync(() => {
26
+ handlers.delete(channel);
27
+ }),
28
+ };
29
+ }
30
+ /**
31
+ * Layer for in-memory event broadcaster
32
+ */
33
+ export const memoryEventBroadcaster = Layer.sync(EventBroadcasterService, createMemoryEventBroadcaster);
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@uploadista/event-broadcaster-memory",
3
+ "type": "module",
4
+ "version": "0.0.3",
5
+ "description": "Memory event broadcaster for Uploadista",
6
+ "license": "MIT",
7
+ "author": "Uploadista",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "dependencies": {
16
+ "effect": "3.18.4",
17
+ "@uploadista/core": "0.0.3"
18
+ },
19
+ "devDependencies": {
20
+ "@uploadista/typescript-config": "0.0.3"
21
+ },
22
+ "scripts": {
23
+ "build": "tsc -b",
24
+ "format": "biome format --write ./src",
25
+ "lint": "biome lint --write ./src",
26
+ "check": "biome check --write ./src"
27
+ }
28
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./memory-event-broadcaster";
@@ -0,0 +1,45 @@
1
+ import type { EventBroadcaster } from "@uploadista/core/types";
2
+ import { EventBroadcasterService } from "@uploadista/core/types";
3
+ import { Effect, Layer } from "effect";
4
+
5
+ /**
6
+ * In-memory event broadcaster for single-instance deployments.
7
+ * Events are only broadcast within the same process/instance.
8
+ * Use this for development or single-server deployments.
9
+ */
10
+ export function createMemoryEventBroadcaster(): EventBroadcaster {
11
+ const handlers = new Map<string, Set<(message: string) => void>>();
12
+
13
+ return {
14
+ publish: (channel: string, message: string) =>
15
+ Effect.sync(() => {
16
+ const channelHandlers = handlers.get(channel);
17
+ if (channelHandlers) {
18
+ for (const handler of channelHandlers) {
19
+ handler(message);
20
+ }
21
+ }
22
+ }),
23
+
24
+ subscribe: (channel: string, handler: (message: string) => void) =>
25
+ Effect.sync(() => {
26
+ if (!handlers.has(channel)) {
27
+ handlers.set(channel, new Set());
28
+ }
29
+ handlers.get(channel)?.add(handler);
30
+ }),
31
+
32
+ unsubscribe: (channel: string) =>
33
+ Effect.sync(() => {
34
+ handlers.delete(channel);
35
+ }),
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Layer for in-memory event broadcaster
41
+ */
42
+ export const memoryEventBroadcaster = Layer.sync(
43
+ EventBroadcasterService,
44
+ createMemoryEventBroadcaster,
45
+ );
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "@uploadista/typescript-config/server.json",
3
+ "compilerOptions": {
4
+ "baseUrl": "./",
5
+ "paths": {
6
+ "@/*": ["./src/*"]
7
+ },
8
+ "outDir": "./dist",
9
+ "rootDir": "./src",
10
+ "typeRoots": ["../../../../node_modules/@types"],
11
+ "lib": ["ES2022", "WebWorker"]
12
+ },
13
+ "include": ["src"]
14
+ }
@@ -0,0 +1 @@
1
+ {"root":["./src/index.ts","./src/memory-event-broadcaster.ts"],"version":"5.9.3"}