@thalesrc/hermes 6.1.1 → 7.0.1

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.
Files changed (112) hide show
  1. package/README.md +417 -57
  2. package/broadcast/default-channel-name.cjs +4 -0
  3. package/broadcast/default-channel-name.js +2 -0
  4. package/broadcast/default-channel-name.js.map +1 -0
  5. package/broadcast/index.cjs +13 -0
  6. package/broadcast/index.js +2 -0
  7. package/broadcast/index.js.map +1 -0
  8. package/broadcast/message-client.cjs +26 -0
  9. package/broadcast/message-client.js +2 -0
  10. package/broadcast/message-client.js.map +1 -0
  11. package/broadcast/message-host.cjs +27 -0
  12. package/broadcast/message-host.js +2 -0
  13. package/broadcast/message-host.js.map +1 -0
  14. package/broadcast/message-service.cjs +13 -0
  15. package/broadcast/message-service.d.ts +1 -1
  16. package/broadcast/message-service.js +4 -2
  17. package/broadcast/message-service.js.map +1 -0
  18. package/chrome/default-connection-name.cjs +4 -0
  19. package/chrome/default-connection-name.js +2 -0
  20. package/chrome/default-connection-name.js.map +1 -0
  21. package/chrome/index.cjs +11 -0
  22. package/chrome/index.js +2 -0
  23. package/chrome/index.js.map +1 -0
  24. package/chrome/message-client.cjs +41 -0
  25. package/chrome/message-client.js +2 -0
  26. package/chrome/message-client.js.map +1 -0
  27. package/chrome/message-host.cjs +42 -0
  28. package/chrome/message-host.d.ts +1 -5
  29. package/chrome/message-host.js +11 -11
  30. package/chrome/message-host.js.map +1 -0
  31. package/iframe/channel-path-splitter.cjs +4 -0
  32. package/iframe/channel-path-splitter.js +2 -0
  33. package/iframe/channel-path-splitter.js.map +1 -0
  34. package/iframe/default-channel-name.cjs +4 -0
  35. package/iframe/default-channel-name.js +2 -0
  36. package/iframe/default-channel-name.js.map +1 -0
  37. package/iframe/iframe.type.cjs +2 -0
  38. package/iframe/iframe.type.js +2 -0
  39. package/iframe/iframe.type.js.map +1 -0
  40. package/iframe/index.cjs +13 -0
  41. package/iframe/index.js +2 -0
  42. package/iframe/index.js.map +1 -0
  43. package/iframe/message-client.cjs +50 -0
  44. package/iframe/message-client.d.ts +1 -5
  45. package/iframe/message-client.js +10 -10
  46. package/iframe/message-client.js.map +1 -0
  47. package/iframe/message-host.cjs +62 -0
  48. package/iframe/message-host.d.ts +1 -11
  49. package/iframe/message-host.js +20 -23
  50. package/iframe/message-host.js.map +1 -0
  51. package/iframe/message-service.cjs +13 -0
  52. package/iframe/message-service.d.ts +1 -1
  53. package/iframe/message-service.js +4 -2
  54. package/iframe/message-service.js.map +1 -0
  55. package/iframe/source-id-splitter.cjs +4 -0
  56. package/iframe/source-id-splitter.js +2 -0
  57. package/iframe/source-id-splitter.js.map +1 -0
  58. package/iframe/upcoming-message.cjs +2 -0
  59. package/iframe/upcoming-message.js +2 -0
  60. package/iframe/upcoming-message.js.map +1 -0
  61. package/index.cjs +13 -0
  62. package/index.js +2 -0
  63. package/index.js.map +1 -0
  64. package/listen.decorator.cjs +20 -0
  65. package/listen.decorator.js +4 -2
  66. package/listen.decorator.js.map +1 -0
  67. package/listener-storage.type.cjs +2 -0
  68. package/listener-storage.type.js +2 -0
  69. package/listener-storage.type.js.map +1 -0
  70. package/message-client.cjs +10 -0
  71. package/message-client.js +2 -0
  72. package/message-client.js.map +1 -0
  73. package/message-host.cjs +53 -0
  74. package/message-host.js +2 -0
  75. package/message-host.js.map +1 -0
  76. package/message-response.type.cjs +2 -0
  77. package/message-response.type.js +2 -0
  78. package/message-response.type.js.map +1 -0
  79. package/message.interface.cjs +2 -0
  80. package/message.interface.js +2 -0
  81. package/message.interface.js.map +1 -0
  82. package/package.json +32 -34
  83. package/request.decorator.cjs +20 -0
  84. package/request.decorator.js +3 -1
  85. package/request.decorator.js.map +1 -0
  86. package/selectors.cjs +8 -0
  87. package/selectors.js +2 -0
  88. package/selectors.js.map +1 -0
  89. package/worker/index.cjs +9 -0
  90. package/worker/index.js +2 -0
  91. package/worker/index.js.map +1 -0
  92. package/worker/message-client.cjs +40 -0
  93. package/worker/message-client.d.ts +1 -1
  94. package/worker/message-client.js +2 -0
  95. package/worker/message-client.js.map +1 -0
  96. package/worker/message-host.cjs +43 -0
  97. package/worker/message-host.js +2 -0
  98. package/worker/message-host.js.map +1 -0
  99. package/worker/message-service.cjs +12 -0
  100. package/worker/message-service.d.ts +1 -1
  101. package/worker/message-service.js +4 -2
  102. package/worker/message-service.js.map +1 -0
  103. package/.editorconfig +0 -9
  104. package/CODE_OF_CONDUCT.md +0 -76
  105. package/codecov.yml +0 -8
  106. package/jest.config.js +0 -22
  107. package/mixin.d.ts +0 -12
  108. package/mixin.js +0 -18
  109. package/setup-test.ts +0 -0
  110. package/tsconfig.lib.json +0 -12
  111. package/tsconfig.spec.json +0 -11
  112. package/tslint.json +0 -14
package/README.md CHANGED
@@ -1,121 +1,481 @@
1
- # hermes
2
- ![publish build](https://github.com/thalesrc/hermes/workflows/Npm%20Package/badge.svg)
1
+ # @thalesrc/hermes
2
+
3
3
  [![npm](https://img.shields.io/npm/v/@thalesrc/hermes.svg)](https://www.npmjs.com/package/@thalesrc/hermes)
4
4
  [![npm](https://img.shields.io/npm/dw/@thalesrc/hermes.svg)](https://www.npmjs.com/package/@thalesrc/hermes)
5
- [![codecov](https://codecov.io/gh/thalesrc/hermes/branch/master/graph/badge.svg)](https://codecov.io/gh/thalesrc/hermes)
6
5
  [![TypeScript](https://badges.frapsoft.com/typescript/version/typescript-next.svg?v=101)](https://www.typescriptlang.org/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ Javascript messaging library for cross-context communication
7
9
 
8
- Javascript messaging library
10
+ **Part of the [Thalesrc](https://github.com/thalesrc/thalesrc) monorepo**
9
11
 
10
12
  ## Installation
11
- `npm i @thalesrc/hermes` or `yarn add @thalesrc/hermes`
12
13
 
13
- ## Usage
14
+ ```bash
15
+ npm install @thalesrc/hermes
16
+ # or
17
+ yarn add @thalesrc/hermes
18
+ # or
19
+ pnpm add @thalesrc/hermes
20
+ ```
21
+
22
+ ## Overview
23
+
24
+ Hermes provides a unified, decorator-based API for cross-context messaging in JavaScript applications. Built on RxJS, it supports:
25
+
26
+ - 🖼️ **Iframe Communication** - Parent-child window messaging
27
+ - 🧩 **Chrome Extensions** - Background scripts, content scripts, and popups
28
+ - 👷 **Web Workers** - Main thread and worker communication
29
+ - 📡 **Broadcast Channel** - Tab-to-tab messaging
30
+
31
+ ## Core Concepts
32
+
33
+ ### MessageClient & MessageHost
34
+
35
+ The library uses two main abstractions:
14
36
 
15
- The main concept is sending messages via `MessageClient`'s and answering them via `MessageHost`'s.
37
+ - **`MessageClient`**: Sends requests and receives responses (uses `@Request` decorator)
38
+ - **`MessageHost`**: Listens for requests and sends responses (uses `@Listen` decorator)
39
+ - **`MessageService`**: Combines both client and host (bidirectional communication)
16
40
 
17
- ------------------------------------------------------------------
41
+ ### Decorators
18
42
 
19
- ### Iframe
43
+ - **`@Request(path)`**: Marks a method as a message sender
44
+ - **`@Listen(path)`**: Marks a method as a message listener
20
45
 
21
- Send and recieve messages accross iframes and parent windows
46
+ ## Usage
47
+
48
+ ### Iframe Communication
49
+
50
+ Send and receive messages between iframes and parent windows.
51
+
52
+ #### Client-Only (Iframe)
22
53
 
23
54
  ```typescript
24
- // inside iframe
25
55
  import { IframeMessageClient, Request } from '@thalesrc/hermes/iframe';
56
+ import { Observable } from 'rxjs';
26
57
 
27
- class MessageSenderService extends IframeMessageClient {
28
- @Request('hello')
29
- public sayHello(name: string): Observable<string> {
30
- return null;
58
+ class IframeClient extends IframeMessageClient {
59
+ @Request('greeting')
60
+ sayHello(name: string): Observable<string> {
61
+ return null; // Implementation handled by decorator
31
62
  }
32
63
  }
33
64
 
34
- const service = new MessageSenderService();
65
+ // Default: sends messages to parent window
66
+ const client = new IframeClient();
35
67
 
36
- service.sayHello('John').subscribe(message => {
37
- console.log(message);
38
- });
68
+ // Optional: specify channel name
69
+ const clientWithChannel = new IframeClient('my-channel');
70
+
71
+ // Optional: target specific iframe (from parent window)
72
+ const iframe = document.querySelector('iframe');
73
+ const clientToIframe = new IframeClient('my-channel', iframe);
39
74
 
40
- // 'Hi John, here are some data for you'
41
- // 'Thales Rocks!!'
75
+ // Optional: use a function to get iframe dynamically
76
+ const clientWithDynamicIframe = new IframeClient('my-channel', () =>
77
+ document.querySelector('iframe#dynamic')
78
+ );
42
79
 
80
+ client.sayHello('John').subscribe(response => {
81
+ console.log(response); // 'Hello John!'
82
+ });
43
83
  ```
44
84
 
85
+ #### Host-Only (Parent Window)
86
+
45
87
  ```typescript
46
- // inside parent window
47
88
  import { IframeMessageHost, Listen, UpcomingMessage } from '@thalesrc/hermes/iframe';
48
89
  import { of } from 'rxjs';
49
90
 
50
- class MessageListenerService extends IframeMessageHost {
51
- @Listen('hello')
52
- public listenHello({data, sender}: UpcomingMessage): Observable<string> {
53
- return of(
54
- 'Hi ' + data + ', here is some data for you',
55
- 'Thales Rocks!!'
56
- );
91
+ class ParentHost extends IframeMessageHost {
92
+ @Listen('greeting')
93
+ handleGreeting({ data }: UpcomingMessage<string>): Observable<string> {
94
+ return of(`Hello ${data}!`);
57
95
  }
58
96
  }
59
97
 
60
- const listener = new MessageListener();
98
+ // Default: listens to all iframes
99
+ const host = new ParentHost();
61
100
 
101
+ // Optional: specify channel name
102
+ const hostWithChannel = new ParentHost('my-channel');
103
+
104
+ // Optional: listen only to specific iframe
105
+ const iframe = document.querySelector('iframe');
106
+ const hostForSpecificIframe = new ParentHost('my-channel', iframe);
107
+
108
+ // Optional: use a function to get iframe dynamically
109
+ const hostWithDynamicIframe = new ParentHost('my-channel', () =>
110
+ document.querySelector('iframe#dynamic')
111
+ );
112
+ ```
113
+
114
+ #### Bidirectional Communication (MessageService)
115
+
116
+ ```typescript
117
+ import { IframeMessageService, Request, Listen } from '@thalesrc/hermes/iframe';
118
+ import { of, Observable } from 'rxjs';
119
+
120
+ class IframeBidirectional extends IframeMessageService {
121
+ // Send messages
122
+ @Request('getData')
123
+ requestData(): Observable<any> {
124
+ return null;
125
+ }
126
+
127
+ // Receive messages
128
+ @Listen('update')
129
+ handleUpdate(data: any): Observable<string> {
130
+ console.log('Received update:', data);
131
+ return of('Update processed');
132
+ }
133
+ }
134
+
135
+ // Default: communicates with parent window
136
+ const service = new IframeBidirectional();
137
+
138
+ // Optional: specify channel name and target frame
139
+ const iframe = document.querySelector('iframe');
140
+ const serviceWithTarget = new IframeBidirectional('my-channel', iframe);
141
+
142
+ // From within iframe (communicates with parent)
143
+ const iframeService = new IframeBidirectional('my-channel');
62
144
  ```
63
145
 
64
- ------------------------------------------------------------------
146
+ ---
65
147
 
66
148
  ### Chrome Extensions
67
149
 
68
- Send and recieve messages accross tabs, background-scripts, content-scripts etc.
150
+ Communicate across extension contexts (background, content scripts, popups).
151
+
152
+ #### Content Script
69
153
 
70
154
  ```typescript
71
- // content-script or a page etc.
72
155
  import { ChromeMessageClient, Request } from '@thalesrc/hermes/chrome';
156
+ import { Observable } from 'rxjs';
73
157
 
74
- class MessageSenderService extends ChromeMessageClient {
75
- @Request('hello')
76
- public sayHello(name: string): Observable<string> {
158
+ class ContentScript extends ChromeMessageClient {
159
+ @Request('fetchData')
160
+ getData(query: string): Observable<any> {
161
+ return null;
162
+ }
163
+
164
+ @Request('saveSettings')
165
+ saveSettings(settings: object): Observable<boolean> {
77
166
  return null;
78
167
  }
79
168
  }
80
169
 
81
- const service = new MessageSenderService();
170
+ const contentScript = new ContentScript();
82
171
 
83
- service.sayHello('John').subscribe(message => {
84
- console.log(message);
172
+ contentScript.getData('user').subscribe(data => {
173
+ console.log('Received:', data);
85
174
  });
175
+ ```
86
176
 
87
- // 'Hi John, here are some data for you'
88
- // 'Thales Rocks!!'
177
+ #### Background Script
89
178
 
179
+ ```typescript
180
+ import { ChromeMessageHost, Listen } from '@thalesrc/hermes/chrome';
181
+ import { of, Observable } from 'rxjs';
182
+
183
+ class BackgroundScript extends ChromeMessageHost {
184
+ @Listen('fetchData')
185
+ handleFetchData(query: string): Observable<any> {
186
+ // Fetch from API or storage
187
+ return of({ name: 'John', age: 30 });
188
+ }
189
+
190
+ @Listen('saveSettings')
191
+ handleSaveSettings(settings: object): Observable<boolean> {
192
+ // Save to chrome.storage
193
+ return of(true);
194
+ }
195
+ }
196
+
197
+ const background = new BackgroundScript();
90
198
  ```
91
199
 
200
+ ---
201
+
202
+ ### Web Workers
203
+
204
+ Communicate between main thread and web workers.
205
+
206
+ #### Main Thread
207
+
92
208
  ```typescript
93
- // background-script etc.
94
- import { ChromeMessageHost, Listen } from '@thalesrc/hermes/chrome';
95
- import { of } from 'rxjs';
209
+ import { WorkerMessageService, Request, Listen } from '@thalesrc/hermes/worker';
210
+ import { of, Observable } from 'rxjs';
211
+
212
+ class MainThread extends WorkerMessageService {
213
+ @Request('processData')
214
+ sendDataToWorker(data: number[]): Observable<number> {
215
+ return null;
216
+ }
217
+
218
+ @Listen('progress')
219
+ handleProgress(percent: number): Observable<void> {
220
+ console.log(`Progress: ${percent}%`);
221
+ return of(void 0);
222
+ }
223
+ }
224
+
225
+ // Must provide Worker instance in main thread
226
+ const worker = new Worker('./worker.js');
227
+ const mainService = new MainThread(worker);
228
+
229
+ mainService.sendDataToWorker([1, 2, 3, 4, 5]).subscribe(result => {
230
+ console.log('Worker result:', result);
231
+ });
232
+ ```
233
+
234
+ #### Worker Thread
235
+
236
+ ```typescript
237
+ import { WorkerMessageService, Request, Listen } from '@thalesrc/hermes/worker';
238
+ import { of, Observable } from 'rxjs';
239
+
240
+ class WorkerThread extends WorkerMessageService {
241
+ @Listen('processData')
242
+ handleProcessData(data: number[]): Observable<number> {
243
+ // Heavy computation
244
+ const result = data.reduce((sum, n) => sum + n, 0);
245
+ return of(result);
246
+ }
247
+
248
+ @Request('progress')
249
+ reportProgress(percent: number): Observable<void> {
250
+ return null;
251
+ }
252
+ }
253
+
254
+ // Inside worker: no argument needed (uses self)
255
+ const workerService = new WorkerThread();
256
+ ```
257
+
258
+ ---
259
+
260
+ ### Broadcast Channel
261
+
262
+ Communicate between different tabs/windows of the same origin.
263
+
264
+ #### Tab 1
265
+
266
+ ```typescript
267
+ import { BroadcastMessageService, Request, Listen } from '@thalesrc/hermes/broadcast';
268
+ import { of, Observable } from 'rxjs';
269
+
270
+ class Tab1 extends BroadcastMessageService {
271
+ @Request('sync')
272
+ requestSync(data: any): Observable<string> {
273
+ return null;
274
+ }
275
+
276
+ @Listen('notification')
277
+ handleNotification(message: string): Observable<void> {
278
+ console.log('Notification:', message);
279
+ return of(void 0);
280
+ }
281
+ }
282
+
283
+ const tab1 = new Tab1('my-app-channel');
284
+
285
+ tab1.requestSync({ user: 'John' }).subscribe(response => {
286
+ console.log(response); // 'Sync completed'
287
+ });
288
+ ```
289
+
290
+ #### Tab 2
291
+
292
+ ```typescript
293
+ import { BroadcastMessageService, Request, Listen } from '@thalesrc/hermes/broadcast';
294
+ import { of, Observable } from 'rxjs';
295
+
296
+ class Tab2 extends BroadcastMessageService {
297
+ @Listen('sync')
298
+ handleSync(data: any): Observable<string> {
299
+ console.log('Syncing data:', data);
300
+ return of('Sync completed');
301
+ }
302
+
303
+ @Request('notification')
304
+ sendNotification(message: string): Observable<void> {
305
+ return null;
306
+ }
307
+ }
308
+
309
+ const tab2 = new Tab2('my-app-channel');
310
+ ```
311
+
312
+ ---
313
+
314
+ ## Advanced Features
315
+
316
+ ### Streaming Responses
317
+
318
+ Return multiple values over time using RxJS operators:
96
319
 
97
- class MessageListenerService extends ChromeMessageHost {
98
- @Listen('hello')
99
- public listenHello(name: string): Observable<string> {
100
- return of(
101
- 'Hi ' + name + ', here is some data for you',
102
- 'Thales Rocks!!'
320
+ ```typescript
321
+ import { Listen } from '@thalesrc/hermes/iframe';
322
+ import { interval } from 'rxjs';
323
+ import { map, take } from 'rxjs/operators';
324
+
325
+ class StreamingHost extends IframeMessageHost {
326
+ @Listen('countdown')
327
+ handleCountdown(start: number): Observable<number> {
328
+ return interval(1000).pipe(
329
+ map(i => start - i),
330
+ take(start + 1)
103
331
  );
104
332
  }
105
333
  }
334
+ ```
335
+
336
+ The client receives each value as it's emitted:
337
+
338
+ ```typescript
339
+ client.countdown(5).subscribe(
340
+ value => console.log(value), // 5, 4, 3, 2, 1, 0
341
+ error => console.error(error),
342
+ () => console.log('Complete!')
343
+ );
344
+ ```
345
+
346
+ ### Error Handling
347
+
348
+ ```typescript
349
+ import { Listen } from '@thalesrc/hermes/iframe';
350
+ import { throwError } from 'rxjs';
351
+
352
+ class ErrorHost extends IframeMessageHost {
353
+ @Listen('riskyOperation')
354
+ handleRiskyOperation(data: any): Observable<any> {
355
+ if (!data.valid) {
356
+ return throwError(() => new Error('Invalid data'));
357
+ }
358
+ return of({ success: true });
359
+ }
360
+ }
361
+ ```
362
+
363
+ ### Constructor Parameters
106
364
 
107
- const listener = new MessageListener();
365
+ #### Iframe
108
366
 
367
+ **`IframeMessageClient` / `IframeMessageHost` / `IframeMessageService`**
368
+
369
+ ```typescript
370
+ constructor(channelName?: string, targetFrame?: HTMLIFrameElement | (() => HTMLIFrameElement))
109
371
  ```
110
372
 
111
- ------------------------------------------------------------------
373
+ - **`channelName`** (optional): Channel identifier for namespacing messages. Default: `'hermes-iframe-message'`
374
+ - **`targetFrame`** (optional): Specific iframe to communicate with. Can be:
375
+ - `HTMLIFrameElement`: Direct reference to iframe element
376
+ - `() => HTMLIFrameElement`: Function returning iframe (useful for dynamic iframes)
377
+ - Omit to communicate with parent window (from iframe) or all iframes (from parent)
378
+
379
+ **Examples:**
380
+ ```typescript
381
+ // From iframe: communicate with parent
382
+ const client = new IframeMessageClient();
383
+
384
+ // From parent: communicate with specific iframe
385
+ const iframe = document.querySelector('iframe');
386
+ const host = new IframeMessageHost('my-channel', iframe);
387
+
388
+ // Dynamic iframe reference
389
+ const service = new IframeMessageService('my-channel', () =>
390
+ document.querySelector('iframe[data-active="true"]')
391
+ );
392
+ ```
393
+
394
+ #### Worker
395
+
396
+ **`WorkerMessageClient` / `WorkerMessageHost` / `WorkerMessageService`**
397
+
398
+ ```typescript
399
+ constructor(worker?: Worker)
400
+ ```
401
+
402
+ - **`worker`** (optional): Worker instance for main thread communication
403
+ - **In main thread**: Must provide `Worker` instance
404
+ - **In worker thread**: Omit parameter (uses `self` automatically)
405
+
406
+ **Examples:**
407
+ ```typescript
408
+ // Main thread: must provide worker
409
+ const worker = new Worker('./worker.js');
410
+ const service = new WorkerMessageService(worker);
411
+
412
+ // Inside worker: no parameter needed
413
+ const service = new WorkerMessageService();
414
+ ```
415
+
416
+ #### Broadcast
417
+
418
+ **`BroadcastMessageClient` / `BroadcastMessageHost` / `BroadcastMessageService`**
419
+
420
+ ```typescript
421
+ constructor(channelName?: string)
422
+ ```
423
+
424
+ - **`channelName`** (optional): Broadcast channel name. Default: `'hermes-broadcast-message'`
425
+
426
+ **Example:**
427
+ ```typescript
428
+ const service = new BroadcastMessageService('app-sync-channel');
429
+ ```
430
+
431
+ #### Chrome
432
+
433
+ **`ChromeMessageClient` / `ChromeMessageHost`**
434
+
435
+ ```typescript
436
+ constructor(connectionName?: string)
437
+ ```
438
+
439
+ - **`connectionName`** (optional): Connection identifier. Default: `'hermes-chrome-message'`
440
+
441
+ **Example:**
442
+ ```typescript
443
+ const client = new ChromeMessageClient('extension-port');
444
+ ```
445
+
446
+ ## API Reference
447
+
448
+ ### Classes
449
+
450
+ - **`MessageClient`** - Base class for message senders
451
+ - **`MessageHost`** - Base class for message receivers
452
+ - **`IframeMessageClient`** - Iframe client implementation
453
+ - **`IframeMessageHost`** - Iframe host implementation
454
+ - **`IframeMessageService`** - Bidirectional iframe communication
455
+ - **`ChromeMessageClient`** - Chrome extension client
456
+ - **`ChromeMessageHost`** - Chrome extension host
457
+ - **`WorkerMessageService`** - Bidirectional worker communication
458
+ - **`BroadcastMessageClient`** - Broadcast channel client
459
+ - **`BroadcastMessageHost`** - Broadcast channel host
460
+ - **`BroadcastMessageService`** - Bidirectional broadcast communication
461
+
462
+ ### Decorators
463
+
464
+ - **`@Request(path: string)`** - Decorator for sending messages
465
+ - **`@Listen(path: string)`** - Decorator for receiving messages
466
+
467
+ ### Types
112
468
 
113
- ### Workers
469
+ - **`Message`** - Message payload structure
470
+ - **`MessageResponse`** - Response payload structure
471
+ - **`UpcomingMessage<T>`** - Incoming message with sender info (iframe)
114
472
 
115
- Implemented but not documented yet
473
+ ## Requirements
116
474
 
117
- ------------------------------------------------------------------
475
+ - RxJS 7.x or higher
476
+ - TypeScript 4.x or higher (for decorator support)
477
+ - Modern browser with ES2015+ support
118
478
 
119
- ### Broadcast
479
+ ## License
120
480
 
121
- Implemented but not documented yet
481
+ MIT © [Thalesrc](https://github.com/thalesrc)
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_CHANNEL_NAME = void 0;
4
+ exports.DEFAULT_CHANNEL_NAME = 'HERMES_DEFAULT_CHANNEL';
@@ -1 +1,3 @@
1
1
  export const DEFAULT_CHANNEL_NAME = 'HERMES_DEFAULT_CHANNEL';
2
+
3
+ //# sourceMappingURL=default-channel-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/hermes/src/broadcast/default-channel-name.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,wBAAwB,CAAC","file":"default-channel-name.js","sourcesContent":["export const DEFAULT_CHANNEL_NAME = 'HERMES_DEFAULT_CHANNEL';\n"]}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Listen = exports.Request = exports.BroadcastMessageService = exports.BroadcastMessageHost = exports.BroadcastMessageClient = void 0;
4
+ var message_client_1 = require("./message-client");
5
+ Object.defineProperty(exports, "BroadcastMessageClient", { enumerable: true, get: function () { return message_client_1.BroadcastMessageClient; } });
6
+ var message_host_1 = require("./message-host");
7
+ Object.defineProperty(exports, "BroadcastMessageHost", { enumerable: true, get: function () { return message_host_1.BroadcastMessageHost; } });
8
+ var message_service_1 = require("./message-service");
9
+ Object.defineProperty(exports, "BroadcastMessageService", { enumerable: true, get: function () { return message_service_1.BroadcastMessageService; } });
10
+ var request_decorator_1 = require("../request.decorator");
11
+ Object.defineProperty(exports, "Request", { enumerable: true, get: function () { return request_decorator_1.Request; } });
12
+ var listen_decorator_1 = require("../listen.decorator");
13
+ Object.defineProperty(exports, "Listen", { enumerable: true, get: function () { return listen_decorator_1.Listen; } });
@@ -3,3 +3,5 @@ export { BroadcastMessageHost } from './message-host';
3
3
  export { BroadcastMessageService } from './message-service';
4
4
  export { Request } from '../request.decorator';
5
5
  export { Listen } from '../listen.decorator';
6
+
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/hermes/src/broadcast/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC","file":"index.js","sourcesContent":["export { BroadcastMessageClient } from './message-client';\nexport { BroadcastMessageHost } from './message-host';\nexport { BroadcastMessageService } from './message-service';\nexport { Request } from '../request.decorator';\nexport { Listen } from '../listen.decorator';\n"]}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BroadcastMessageClient = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const message_client_1 = require("../message-client");
6
+ const selectors_1 = require("../selectors");
7
+ const default_channel_name_1 = require("./default-channel-name");
8
+ class BroadcastMessageClient extends message_client_1.MessageClient {
9
+ [selectors_1.RESPONSES$] = new rxjs_1.Subject();
10
+ #channel;
11
+ constructor(channelName = default_channel_name_1.DEFAULT_CHANNEL_NAME) {
12
+ super();
13
+ this.#channel = new BroadcastChannel(channelName);
14
+ this.#channel.addEventListener('message', this.#handler);
15
+ }
16
+ [selectors_1.SEND](message) {
17
+ this.#channel.postMessage(message);
18
+ }
19
+ #handler = (event) => {
20
+ this[selectors_1.RESPONSES$].next(event.data);
21
+ };
22
+ [selectors_1.GET_NEW_ID]() {
23
+ return crypto.randomUUID();
24
+ }
25
+ }
26
+ exports.BroadcastMessageClient = BroadcastMessageClient;
@@ -20,3 +20,5 @@ export class BroadcastMessageClient extends MessageClient {
20
20
  return crypto.randomUUID();
21
21
  }
22
22
  }
23
+
24
+ //# sourceMappingURL=message-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/hermes/src/broadcast/message-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAM9D,MAAM,OAAO,sBAAuB,SAAQ,aAAa;IAC7C,CAAC,UAAU,CAAC,GAAG,IAAI,OAAO,EAAmB,CAAC;IAExD,QAAQ,CAAmB;IAE3B,YAAY,WAAW,GAAG,oBAAoB;QAC5C,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAElD,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAES,CAAC,IAAI,CAAC,CAAI,OAAmB;QACrC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,QAAQ,GAAG,CAAC,KAAoC,EAAE,EAAE;QAClD,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAA;IAES,CAAC,UAAU,CAAC;QACpB,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;CACF","file":"message-client.js","sourcesContent":["import { Subject } from \"rxjs\";\nimport { MessageClient } from \"../message-client\";\nimport { MessageResponse } from \"../message-response.type\";\nimport { Message } from \"../message.interface\";\nimport { GET_NEW_ID, RESPONSES$, SEND } from \"../selectors\";\nimport { DEFAULT_CHANNEL_NAME } from \"./default-channel-name\";\n\ninterface MessageEvent<T> {\n data: T;\n}\n\nexport class BroadcastMessageClient extends MessageClient {\n protected [RESPONSES$] = new Subject<MessageResponse>();\n\n #channel: BroadcastChannel;\n\n constructor(channelName = DEFAULT_CHANNEL_NAME) {\n super();\n\n this.#channel = new BroadcastChannel(channelName);\n\n this.#channel.addEventListener('message', this.#handler);\n }\n\n protected [SEND]<T>(message: Message<T>) {\n this.#channel.postMessage(message);\n }\n\n #handler = (event: MessageEvent<MessageResponse>) => {\n this[RESPONSES$].next(event.data);\n }\n\n protected [GET_NEW_ID](): string {\n return crypto.randomUUID();\n }\n}"]}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BroadcastMessageHost = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const message_host_1 = require("../message-host");
6
+ const default_channel_name_1 = require("./default-channel-name");
7
+ class BroadcastMessageHost extends message_host_1.MessageHost {
8
+ #requests$ = new rxjs_1.Subject();
9
+ #channel;
10
+ constructor(channelName = default_channel_name_1.DEFAULT_CHANNEL_NAME) {
11
+ super();
12
+ this.#channel = new BroadcastChannel(channelName);
13
+ this.#channel.addEventListener('message', this.#handler);
14
+ this.listen(this.#requests$);
15
+ }
16
+ response(message) {
17
+ this.#channel.postMessage(message);
18
+ }
19
+ terminate() {
20
+ this.#channel.removeEventListener('message', this.#handler);
21
+ this.#channel.close();
22
+ }
23
+ #handler = (event) => {
24
+ this.#requests$.next(event.data);
25
+ };
26
+ }
27
+ exports.BroadcastMessageHost = BroadcastMessageHost;
@@ -21,3 +21,5 @@ export class BroadcastMessageHost extends MessageHost {
21
21
  this.#requests$.next(event.data);
22
22
  };
23
23
  }
24
+
25
+ //# sourceMappingURL=message-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/hermes/src/broadcast/message-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAM9D,MAAM,OAAO,oBAAqB,SAAQ,WAAW;IACnD,UAAU,GAAG,IAAI,OAAO,EAAW,CAAC;IACpC,QAAQ,CAAmB;IAE3B,YAAY,WAAW,GAAG,oBAAoB;QAC5C,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAElD,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;IAES,QAAQ,CAAC,OAAwB;QACzC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,SAAS;QACP,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,QAAQ,GAAG,CAAC,KAA4B,EAAE,EAAE;QAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC,CAAA;CACF","file":"message-host.js","sourcesContent":["import { Subject } from \"rxjs\";\nimport { MessageHost } from \"../message-host\";\nimport { MessageResponse } from \"../message-response.type\";\nimport { Message } from \"../message.interface\";\nimport { DEFAULT_CHANNEL_NAME } from \"./default-channel-name\";\n\ninterface MessageEvent<T> {\n data: T;\n}\n\nexport class BroadcastMessageHost extends MessageHost {\n #requests$ = new Subject<Message>();\n #channel: BroadcastChannel;\n\n constructor(channelName = DEFAULT_CHANNEL_NAME) {\n super();\n\n this.#channel = new BroadcastChannel(channelName);\n\n this.#channel.addEventListener('message', this.#handler);\n this.listen(this.#requests$);\n }\n\n protected response(message: MessageResponse) {\n this.#channel.postMessage(message);\n }\n\n terminate() {\n this.#channel.removeEventListener('message', this.#handler);\n this.#channel.close();\n }\n\n #handler = (event: MessageEvent<Message>) => {\n this.#requests$.next(event.data);\n }\n}"]}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BroadcastMessageService = void 0;
4
+ const mixin_1 = require("@thalesrc/js-utils/class/mixin");
5
+ const default_channel_name_1 = require("./default-channel-name");
6
+ const message_client_1 = require("./message-client");
7
+ const message_host_1 = require("./message-host");
8
+ class BroadcastMessageService extends (0, mixin_1.mixin)(message_host_1.BroadcastMessageHost, message_client_1.BroadcastMessageClient) {
9
+ constructor(channelName = default_channel_name_1.DEFAULT_CHANNEL_NAME) {
10
+ super([channelName], [channelName]);
11
+ }
12
+ }
13
+ exports.BroadcastMessageService = BroadcastMessageService;