@thalesrc/hermes 7.3.0 → 7.5.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 (50) hide show
  1. package/README.md +54 -8
  2. package/broadcast/message-client.js.map +1 -1
  3. package/broadcast/message-host.cjs +3 -2
  4. package/broadcast/message-host.d.ts +2 -1
  5. package/broadcast/message-host.js +3 -2
  6. package/broadcast/message-host.js.map +1 -1
  7. package/chrome/message-client.cjs +1 -1
  8. package/chrome/message-client.js +1 -1
  9. package/chrome/message-client.js.map +1 -1
  10. package/chrome/message-host.cjs +4 -3
  11. package/chrome/message-host.d.ts +2 -1
  12. package/chrome/message-host.js +4 -3
  13. package/chrome/message-host.js.map +1 -1
  14. package/iframe/message-client.js.map +1 -1
  15. package/iframe/message-host.cjs +3 -2
  16. package/iframe/message-host.d.ts +2 -1
  17. package/iframe/message-host.js +3 -2
  18. package/iframe/message-host.js.map +1 -1
  19. package/message-host.cjs +12 -7
  20. package/message-host.d.ts +4 -3
  21. package/message-host.js +13 -8
  22. package/message-host.js.map +1 -1
  23. package/message-response.type.d.ts +2 -0
  24. package/message-response.type.js.map +1 -1
  25. package/message.interface.d.ts +1 -0
  26. package/message.interface.js.map +1 -1
  27. package/package.json +1 -1
  28. package/request.decorator.cjs +2 -2
  29. package/request.decorator.js +2 -2
  30. package/request.decorator.js.map +1 -1
  31. package/selectors.cjs +4 -2
  32. package/selectors.d.ts +3 -1
  33. package/selectors.js +3 -1
  34. package/selectors.js.map +1 -1
  35. package/worker/initializer.cjs +39 -0
  36. package/worker/initializer.d.ts +12 -0
  37. package/worker/initializer.js +38 -0
  38. package/worker/initializer.js.map +1 -0
  39. package/worker/message-client.cjs +14 -30
  40. package/worker/message-client.d.ts +19 -5
  41. package/worker/message-client.js +14 -30
  42. package/worker/message-client.js.map +1 -1
  43. package/worker/message-host.cjs +146 -24
  44. package/worker/message-host.d.ts +120 -3
  45. package/worker/message-host.js +146 -24
  46. package/worker/message-host.js.map +1 -1
  47. package/worker/message-service.cjs +111 -0
  48. package/worker/message-service.d.ts +110 -1
  49. package/worker/message-service.js +111 -0
  50. package/worker/message-service.js.map +1 -1
@@ -3,39 +3,161 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WorkerMessageHost = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const message_host_1 = require("../message-host");
6
- const REQUESTS$ = Symbol('Requests');
7
- const HANDLER = Symbol('Handler');
8
- const WORKER = Symbol('Worker');
6
+ const selectors_1 = require("../selectors");
7
+ const initializer_1 = require("./initializer");
8
+ const noop_1 = require("@thalesrc/js-utils/function/noop");
9
+ const WORKER = Symbol('Host Worker');
10
+ const HANDLER = Symbol('Host Message Handler');
11
+ const REQUESTS$ = Symbol('Host Requests Stream');
12
+ /**
13
+ * WorkerMessageHost
14
+ *
15
+ * Host implementation for Web Worker communication. Receives messages from and sends
16
+ * responses to Web Workers using the Worker postMessage API.
17
+ *
18
+ * This class can be used in two contexts:
19
+ * - **Main thread**: Provide a Worker instance to receive messages from that specific worker
20
+ * - **Worker thread**: Omit the worker parameter to receive messages from the main thread via self
21
+ *
22
+ * The worker parameter supports multiple types for flexibility:
23
+ * - Direct Worker instance
24
+ * - Promise that resolves to a Worker (for async worker initialization)
25
+ * - Function that returns a Worker (for lazy initialization)
26
+ * - Function that returns a Promise<Worker> (for async lazy initialization)
27
+ *
28
+ * The `initialize()` method allows dynamic worker management, enabling you to switch
29
+ * workers at runtime or re-establish connections after errors.
30
+ *
31
+ * @example
32
+ * // In main thread - receive messages from a specific worker
33
+ * const worker = new Worker('./worker.js');
34
+ * const host = new WorkerMessageHost(worker);
35
+ *
36
+ * @example
37
+ * // In worker thread - receive messages from main thread
38
+ * const host = new WorkerMessageHost();
39
+ *
40
+ * @example
41
+ * // With async worker initialization
42
+ * const workerPromise = import('./worker.js').then(m => new m.MyWorker());
43
+ * const host = new WorkerMessageHost(workerPromise);
44
+ *
45
+ * @example
46
+ * // With lazy initialization
47
+ * const host = new WorkerMessageHost(() =>
48
+ * document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
49
+ * );
50
+ *
51
+ * @example
52
+ * // Re-initialize with a different worker
53
+ * const host = new WorkerMessageHost();
54
+ * // Later, switch to a different worker
55
+ * host.initialize(new Worker('./different-worker.js'));
56
+ */
9
57
  class WorkerMessageHost extends message_host_1.MessageHost {
58
+ /**
59
+ * Observable stream of incoming messages from the worker or main thread
60
+ * @private
61
+ */
10
62
  [REQUESTS$] = new rxjs_1.Subject();
11
- [WORKER];
63
+ /**
64
+ * Promise resolving to the Worker instance or undefined if running in worker context
65
+ * @private
66
+ */
67
+ [WORKER] = Promise.resolve(undefined);
68
+ /**
69
+ * Creates a new WorkerMessageHost instance
70
+ *
71
+ * @param worker - Optional worker configuration:
72
+ * - Worker: Direct worker instance (main thread)
73
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
74
+ * - () => Worker: Function returning worker (lazy initialization)
75
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
76
+ * - undefined: Omit for worker thread context (uses self)
77
+ */
12
78
  constructor(worker) {
13
79
  super();
14
- if (worker) {
15
- this[WORKER] = worker;
16
- worker.addEventListener('message', this[HANDLER]);
17
- }
18
- else {
19
- addEventListener('message', this[HANDLER]);
20
- }
21
- this.listen(this[REQUESTS$]);
80
+ this.initialize(worker);
81
+ this[selectors_1.LISTEN](this[REQUESTS$]);
22
82
  }
23
- response(message) {
24
- if (this[WORKER]) {
25
- this[WORKER].postMessage(message);
26
- }
27
- else {
28
- postMessage(message);
83
+ /**
84
+ * Initializes or re-initializes the worker connection.
85
+ *
86
+ * This method sets up message listeners for the provided worker. If a worker
87
+ * was previously initialized, it cleans up the old connection before establishing
88
+ * the new one. This allows for dynamic worker management, such as:
89
+ * - Switching between different workers at runtime
90
+ * - Re-establishing connections after worker errors
91
+ * - Lazy initialization when the worker is conditionally needed
92
+ *
93
+ * @param worker - Optional worker configuration:
94
+ * - Worker: Direct worker instance (main thread)
95
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
96
+ * - () => Worker: Function returning worker (lazy initialization)
97
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
98
+ * - undefined: Omit for worker thread context (uses self)
99
+ *
100
+ * @example
101
+ * // Switch to a different worker dynamically
102
+ * const host = new WorkerMessageHost(oldWorker);
103
+ * host.initialize(newWorker); // Cleans up old listener, sets up new one
104
+ *
105
+ * @example
106
+ * // Re-initialize after worker error
107
+ * worker.onerror = () => {
108
+ * host.initialize(new Worker('./worker.js'));
109
+ * };
110
+ */
111
+ initialize(worker) {
112
+ // Ensure WORKER is initialized if not already
113
+ if (!this[WORKER]) {
114
+ this[WORKER] = Promise.resolve(undefined);
29
115
  }
116
+ this[WORKER] = (0, initializer_1.initializer)(this[WORKER], worker, this[HANDLER]);
30
117
  }
118
+ /**
119
+ * Sends a response message back to the worker or main thread
120
+ *
121
+ * @param message - The response message to send
122
+ * @internal Used by the message handling system to send responses
123
+ */
124
+ [selectors_1.RESPONSE](message) {
125
+ this[WORKER].then(worker => {
126
+ if (worker) {
127
+ worker.postMessage(message);
128
+ }
129
+ else {
130
+ postMessage(message);
131
+ }
132
+ }).catch(noop_1.noop);
133
+ }
134
+ /**
135
+ * Terminates the worker connection and cleans up message listeners.
136
+ *
137
+ * This method should be called when you're done with the host to prevent memory leaks.
138
+ * It removes the message event listener from either the Worker instance (main thread)
139
+ * or the global scope (worker thread).
140
+ *
141
+ * @example
142
+ * // Clean up when done
143
+ * const host = new WorkerMessageHost(worker);
144
+ * // ... use the host ...
145
+ * host.terminate(); // Clean up listeners
146
+ */
31
147
  terminate() {
32
- if (this[WORKER]) {
33
- this[WORKER].removeEventListener('message', this[HANDLER]);
34
- }
35
- else {
36
- removeEventListener('message', this[HANDLER]);
37
- }
148
+ this[WORKER].then(worker => {
149
+ if (worker) {
150
+ worker.removeEventListener('message', this[HANDLER]);
151
+ }
152
+ else {
153
+ removeEventListener('message', this[HANDLER]);
154
+ }
155
+ }).catch(noop_1.noop);
38
156
  }
157
+ /**
158
+ * Handles incoming messages and forwards them to the requests stream
159
+ * @private
160
+ */
39
161
  [HANDLER] = (event) => {
40
162
  this[REQUESTS$].next(event.data);
41
163
  };
@@ -1,14 +1,131 @@
1
1
  import { MessageHost } from "../message-host";
2
2
  import { MessageResponse } from "../message-response.type";
3
- declare const REQUESTS$: unique symbol;
4
- declare const HANDLER: unique symbol;
3
+ import { RESPONSE } from "../selectors";
4
+ import { ClientWorkerArg } from "./initializer";
5
5
  declare const WORKER: unique symbol;
6
+ declare const HANDLER: unique symbol;
7
+ declare const REQUESTS$: unique symbol;
8
+ /**
9
+ * WorkerMessageHost
10
+ *
11
+ * Host implementation for Web Worker communication. Receives messages from and sends
12
+ * responses to Web Workers using the Worker postMessage API.
13
+ *
14
+ * This class can be used in two contexts:
15
+ * - **Main thread**: Provide a Worker instance to receive messages from that specific worker
16
+ * - **Worker thread**: Omit the worker parameter to receive messages from the main thread via self
17
+ *
18
+ * The worker parameter supports multiple types for flexibility:
19
+ * - Direct Worker instance
20
+ * - Promise that resolves to a Worker (for async worker initialization)
21
+ * - Function that returns a Worker (for lazy initialization)
22
+ * - Function that returns a Promise<Worker> (for async lazy initialization)
23
+ *
24
+ * The `initialize()` method allows dynamic worker management, enabling you to switch
25
+ * workers at runtime or re-establish connections after errors.
26
+ *
27
+ * @example
28
+ * // In main thread - receive messages from a specific worker
29
+ * const worker = new Worker('./worker.js');
30
+ * const host = new WorkerMessageHost(worker);
31
+ *
32
+ * @example
33
+ * // In worker thread - receive messages from main thread
34
+ * const host = new WorkerMessageHost();
35
+ *
36
+ * @example
37
+ * // With async worker initialization
38
+ * const workerPromise = import('./worker.js').then(m => new m.MyWorker());
39
+ * const host = new WorkerMessageHost(workerPromise);
40
+ *
41
+ * @example
42
+ * // With lazy initialization
43
+ * const host = new WorkerMessageHost(() =>
44
+ * document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
45
+ * );
46
+ *
47
+ * @example
48
+ * // Re-initialize with a different worker
49
+ * const host = new WorkerMessageHost();
50
+ * // Later, switch to a different worker
51
+ * host.initialize(new Worker('./different-worker.js'));
52
+ */
6
53
  export declare class WorkerMessageHost extends MessageHost {
54
+ /**
55
+ * Observable stream of incoming messages from the worker or main thread
56
+ * @private
57
+ */
7
58
  private [REQUESTS$];
59
+ /**
60
+ * Promise resolving to the Worker instance or undefined if running in worker context
61
+ * @private
62
+ */
8
63
  private [WORKER];
64
+ /**
65
+ * Creates a new WorkerMessageHost instance
66
+ *
67
+ * @param worker - Optional worker configuration:
68
+ * - Worker: Direct worker instance (main thread)
69
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
70
+ * - () => Worker: Function returning worker (lazy initialization)
71
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
72
+ * - undefined: Omit for worker thread context (uses self)
73
+ */
9
74
  constructor(worker?: Worker);
10
- protected response(message: MessageResponse): void;
75
+ /**
76
+ * Initializes or re-initializes the worker connection.
77
+ *
78
+ * This method sets up message listeners for the provided worker. If a worker
79
+ * was previously initialized, it cleans up the old connection before establishing
80
+ * the new one. This allows for dynamic worker management, such as:
81
+ * - Switching between different workers at runtime
82
+ * - Re-establishing connections after worker errors
83
+ * - Lazy initialization when the worker is conditionally needed
84
+ *
85
+ * @param worker - Optional worker configuration:
86
+ * - Worker: Direct worker instance (main thread)
87
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
88
+ * - () => Worker: Function returning worker (lazy initialization)
89
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
90
+ * - undefined: Omit for worker thread context (uses self)
91
+ *
92
+ * @example
93
+ * // Switch to a different worker dynamically
94
+ * const host = new WorkerMessageHost(oldWorker);
95
+ * host.initialize(newWorker); // Cleans up old listener, sets up new one
96
+ *
97
+ * @example
98
+ * // Re-initialize after worker error
99
+ * worker.onerror = () => {
100
+ * host.initialize(new Worker('./worker.js'));
101
+ * };
102
+ */
103
+ initialize(worker: ClientWorkerArg): void;
104
+ /**
105
+ * Sends a response message back to the worker or main thread
106
+ *
107
+ * @param message - The response message to send
108
+ * @internal Used by the message handling system to send responses
109
+ */
110
+ protected [RESPONSE](message: MessageResponse): void;
111
+ /**
112
+ * Terminates the worker connection and cleans up message listeners.
113
+ *
114
+ * This method should be called when you're done with the host to prevent memory leaks.
115
+ * It removes the message event listener from either the Worker instance (main thread)
116
+ * or the global scope (worker thread).
117
+ *
118
+ * @example
119
+ * // Clean up when done
120
+ * const host = new WorkerMessageHost(worker);
121
+ * // ... use the host ...
122
+ * host.terminate(); // Clean up listeners
123
+ */
11
124
  terminate(): void;
125
+ /**
126
+ * Handles incoming messages and forwards them to the requests stream
127
+ * @private
128
+ */
12
129
  private [HANDLER];
13
130
  }
14
131
  export {};
@@ -1,38 +1,160 @@
1
1
  import { Subject } from "rxjs";
2
2
  import { MessageHost } from "../message-host";
3
- const REQUESTS$ = Symbol('Requests');
4
- const HANDLER = Symbol('Handler');
5
- const WORKER = Symbol('Worker');
3
+ import { LISTEN, RESPONSE } from "../selectors";
4
+ import { initializer } from "./initializer";
5
+ import { noop } from "@thalesrc/js-utils/function/noop";
6
+ const WORKER = Symbol('Host Worker');
7
+ const HANDLER = Symbol('Host Message Handler');
8
+ const REQUESTS$ = Symbol('Host Requests Stream');
9
+ /**
10
+ * WorkerMessageHost
11
+ *
12
+ * Host implementation for Web Worker communication. Receives messages from and sends
13
+ * responses to Web Workers using the Worker postMessage API.
14
+ *
15
+ * This class can be used in two contexts:
16
+ * - **Main thread**: Provide a Worker instance to receive messages from that specific worker
17
+ * - **Worker thread**: Omit the worker parameter to receive messages from the main thread via self
18
+ *
19
+ * The worker parameter supports multiple types for flexibility:
20
+ * - Direct Worker instance
21
+ * - Promise that resolves to a Worker (for async worker initialization)
22
+ * - Function that returns a Worker (for lazy initialization)
23
+ * - Function that returns a Promise<Worker> (for async lazy initialization)
24
+ *
25
+ * The `initialize()` method allows dynamic worker management, enabling you to switch
26
+ * workers at runtime or re-establish connections after errors.
27
+ *
28
+ * @example
29
+ * // In main thread - receive messages from a specific worker
30
+ * const worker = new Worker('./worker.js');
31
+ * const host = new WorkerMessageHost(worker);
32
+ *
33
+ * @example
34
+ * // In worker thread - receive messages from main thread
35
+ * const host = new WorkerMessageHost();
36
+ *
37
+ * @example
38
+ * // With async worker initialization
39
+ * const workerPromise = import('./worker.js').then(m => new m.MyWorker());
40
+ * const host = new WorkerMessageHost(workerPromise);
41
+ *
42
+ * @example
43
+ * // With lazy initialization
44
+ * const host = new WorkerMessageHost(() =>
45
+ * document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
46
+ * );
47
+ *
48
+ * @example
49
+ * // Re-initialize with a different worker
50
+ * const host = new WorkerMessageHost();
51
+ * // Later, switch to a different worker
52
+ * host.initialize(new Worker('./different-worker.js'));
53
+ */
6
54
  export class WorkerMessageHost extends MessageHost {
55
+ /**
56
+ * Observable stream of incoming messages from the worker or main thread
57
+ * @private
58
+ */
7
59
  [REQUESTS$] = new Subject();
8
- [WORKER];
60
+ /**
61
+ * Promise resolving to the Worker instance or undefined if running in worker context
62
+ * @private
63
+ */
64
+ [WORKER] = Promise.resolve(undefined);
65
+ /**
66
+ * Creates a new WorkerMessageHost instance
67
+ *
68
+ * @param worker - Optional worker configuration:
69
+ * - Worker: Direct worker instance (main thread)
70
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
71
+ * - () => Worker: Function returning worker (lazy initialization)
72
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
73
+ * - undefined: Omit for worker thread context (uses self)
74
+ */
9
75
  constructor(worker) {
10
76
  super();
11
- if (worker) {
12
- this[WORKER] = worker;
13
- worker.addEventListener('message', this[HANDLER]);
14
- }
15
- else {
16
- addEventListener('message', this[HANDLER]);
17
- }
18
- this.listen(this[REQUESTS$]);
77
+ this.initialize(worker);
78
+ this[LISTEN](this[REQUESTS$]);
19
79
  }
20
- response(message) {
21
- if (this[WORKER]) {
22
- this[WORKER].postMessage(message);
23
- }
24
- else {
25
- postMessage(message);
80
+ /**
81
+ * Initializes or re-initializes the worker connection.
82
+ *
83
+ * This method sets up message listeners for the provided worker. If a worker
84
+ * was previously initialized, it cleans up the old connection before establishing
85
+ * the new one. This allows for dynamic worker management, such as:
86
+ * - Switching between different workers at runtime
87
+ * - Re-establishing connections after worker errors
88
+ * - Lazy initialization when the worker is conditionally needed
89
+ *
90
+ * @param worker - Optional worker configuration:
91
+ * - Worker: Direct worker instance (main thread)
92
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
93
+ * - () => Worker: Function returning worker (lazy initialization)
94
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
95
+ * - undefined: Omit for worker thread context (uses self)
96
+ *
97
+ * @example
98
+ * // Switch to a different worker dynamically
99
+ * const host = new WorkerMessageHost(oldWorker);
100
+ * host.initialize(newWorker); // Cleans up old listener, sets up new one
101
+ *
102
+ * @example
103
+ * // Re-initialize after worker error
104
+ * worker.onerror = () => {
105
+ * host.initialize(new Worker('./worker.js'));
106
+ * };
107
+ */
108
+ initialize(worker) {
109
+ // Ensure WORKER is initialized if not already
110
+ if (!this[WORKER]) {
111
+ this[WORKER] = Promise.resolve(undefined);
26
112
  }
113
+ this[WORKER] = initializer(this[WORKER], worker, this[HANDLER]);
27
114
  }
115
+ /**
116
+ * Sends a response message back to the worker or main thread
117
+ *
118
+ * @param message - The response message to send
119
+ * @internal Used by the message handling system to send responses
120
+ */
121
+ [RESPONSE](message) {
122
+ this[WORKER].then(worker => {
123
+ if (worker) {
124
+ worker.postMessage(message);
125
+ }
126
+ else {
127
+ postMessage(message);
128
+ }
129
+ }).catch(noop);
130
+ }
131
+ /**
132
+ * Terminates the worker connection and cleans up message listeners.
133
+ *
134
+ * This method should be called when you're done with the host to prevent memory leaks.
135
+ * It removes the message event listener from either the Worker instance (main thread)
136
+ * or the global scope (worker thread).
137
+ *
138
+ * @example
139
+ * // Clean up when done
140
+ * const host = new WorkerMessageHost(worker);
141
+ * // ... use the host ...
142
+ * host.terminate(); // Clean up listeners
143
+ */
28
144
  terminate() {
29
- if (this[WORKER]) {
30
- this[WORKER].removeEventListener('message', this[HANDLER]);
31
- }
32
- else {
33
- removeEventListener('message', this[HANDLER]);
34
- }
145
+ this[WORKER].then(worker => {
146
+ if (worker) {
147
+ worker.removeEventListener('message', this[HANDLER]);
148
+ }
149
+ else {
150
+ removeEventListener('message', this[HANDLER]);
151
+ }
152
+ }).catch(noop);
35
153
  }
154
+ /**
155
+ * Handles incoming messages and forwards them to the requests stream
156
+ * @private
157
+ */
36
158
  [HANDLER] = (event) => {
37
159
  this[REQUESTS$].next(event.data);
38
160
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../libs/hermes/src/worker/message-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAQ9C,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;AACrC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;AAClC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEhC,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IACxC,CAAC,SAAS,CAAC,GAAG,IAAI,OAAO,EAAW,CAAC;IACrC,CAAC,MAAM,CAAC,CAAqB;IAErC,YAAY,MAAe;QACzB,KAAK,EAAE,CAAC;QAER,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;YACtB,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/B,CAAC;IAES,QAAQ,CAAC,OAAwB;QACzC,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACL,WAAmB,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAEM,SAAS;QACd,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAEO,CAAC,OAAO,CAAC,GAAG,CAAC,KAA4B,EAAE,EAAE;QACnD,IAAI,CAAC,SAAS,CAAC,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\";\n\ninterface MessageEvent<T> {\n data: T;\n}\n\nconst REQUESTS$ = Symbol('Requests');\nconst HANDLER = Symbol('Handler');\nconst WORKER = Symbol('Worker');\n\nexport class WorkerMessageHost extends MessageHost {\n private [REQUESTS$] = new Subject<Message>();\n private [WORKER]: Worker | undefined;\n\n constructor(worker?: Worker) {\n super();\n\n if (worker) {\n this[WORKER] = worker;\n worker.addEventListener('message', this[HANDLER]);\n } else {\n addEventListener('message', this[HANDLER]);\n }\n\n this.listen(this[REQUESTS$]);\n }\n\n protected response(message: MessageResponse) {\n if (this[WORKER]) {\n this[WORKER].postMessage(message);\n } else {\n (postMessage as any)(message);\n }\n }\n\n public terminate() {\n if (this[WORKER]) {\n this[WORKER].removeEventListener('message', this[HANDLER]);\n } else {\n removeEventListener('message', this[HANDLER]);\n }\n }\n\n private [HANDLER] = (event: MessageEvent<Message>) => {\n this[REQUESTS$].next(event.data);\n }\n}\n"]}
1
+ {"version":3,"sources":["../../../../../libs/hermes/src/worker/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,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAwC,WAAW,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,IAAI,EAAE,MAAM,kCAAkC,CAAC;AAExD,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AACrC,MAAM,OAAO,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAChD;;;OAGG;IACK,CAAC,SAAS,CAAC,GAAG,IAAI,OAAO,EAAW,CAAC;IAE7C;;;OAGG;IACK,CAAC,MAAM,CAAC,GAAwB,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEnE;;;;;;;;;OASG;IACH,YAAY,MAAe;QACzB,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,UAAU,CAAC,MAAuB;QAChC,8CAA8C;QAC9C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,GAAG,WAAW,CACxB,IAAI,CAAC,MAAM,CAAC,EACZ,MAAM,EACN,IAAI,CAAC,OAAO,CAAC,CACd,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACO,CAAC,QAAQ,CAAC,CAAC,OAAwB;QAC3C,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;YACzB,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACL,WAAmB,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,SAAS;QACd,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;YACzB,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAChD,CAAC;QACH,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAED;;;OAGG;IACK,CAAC,OAAO,CAAC,GAAG,CAAC,KAA4B,EAAE,EAAE;QACnD,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC;CACH","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 { LISTEN, RESPONSE } from \"../selectors\";\nimport { ClientWorkerArg, ClientWorkerPromise, initializer } from \"./initializer\";\nimport { noop } from \"@thalesrc/js-utils/function/noop\";\n\nconst WORKER = Symbol('Host Worker');\nconst HANDLER = Symbol('Host Message Handler');\nconst REQUESTS$ = Symbol('Host Requests Stream');\n\n/**\n * WorkerMessageHost\n *\n * Host implementation for Web Worker communication. Receives messages from and sends\n * responses to Web Workers using the Worker postMessage API.\n *\n * This class can be used in two contexts:\n * - **Main thread**: Provide a Worker instance to receive messages from that specific worker\n * - **Worker thread**: Omit the worker parameter to receive messages from the main thread via self\n *\n * The worker parameter supports multiple types for flexibility:\n * - Direct Worker instance\n * - Promise that resolves to a Worker (for async worker initialization)\n * - Function that returns a Worker (for lazy initialization)\n * - Function that returns a Promise<Worker> (for async lazy initialization)\n *\n * The `initialize()` method allows dynamic worker management, enabling you to switch\n * workers at runtime or re-establish connections after errors.\n *\n * @example\n * // In main thread - receive messages from a specific worker\n * const worker = new Worker('./worker.js');\n * const host = new WorkerMessageHost(worker);\n *\n * @example\n * // In worker thread - receive messages from main thread\n * const host = new WorkerMessageHost();\n *\n * @example\n * // With async worker initialization\n * const workerPromise = import('./worker.js').then(m => new m.MyWorker());\n * const host = new WorkerMessageHost(workerPromise);\n *\n * @example\n * // With lazy initialization\n * const host = new WorkerMessageHost(() =>\n * document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined\n * );\n *\n * @example\n * // Re-initialize with a different worker\n * const host = new WorkerMessageHost();\n * // Later, switch to a different worker\n * host.initialize(new Worker('./different-worker.js'));\n */\nexport class WorkerMessageHost extends MessageHost {\n /**\n * Observable stream of incoming messages from the worker or main thread\n * @private\n */\n private [REQUESTS$] = new Subject<Message>();\n\n /**\n * Promise resolving to the Worker instance or undefined if running in worker context\n * @private\n */\n private [WORKER]: ClientWorkerPromise = Promise.resolve(undefined);\n\n /**\n * Creates a new WorkerMessageHost instance\n *\n * @param worker - Optional worker configuration:\n * - Worker: Direct worker instance (main thread)\n * - Promise<Worker>: Promise resolving to worker (async initialization)\n * - () => Worker: Function returning worker (lazy initialization)\n * - () => Promise<Worker>: Function returning promise (async lazy initialization)\n * - undefined: Omit for worker thread context (uses self)\n */\n constructor(worker?: Worker) {\n super();\n\n this.initialize(worker);\n this[LISTEN](this[REQUESTS$]);\n }\n\n /**\n * Initializes or re-initializes the worker connection.\n *\n * This method sets up message listeners for the provided worker. If a worker\n * was previously initialized, it cleans up the old connection before establishing\n * the new one. This allows for dynamic worker management, such as:\n * - Switching between different workers at runtime\n * - Re-establishing connections after worker errors\n * - Lazy initialization when the worker is conditionally needed\n *\n * @param worker - Optional worker configuration:\n * - Worker: Direct worker instance (main thread)\n * - Promise<Worker>: Promise resolving to worker (async initialization)\n * - () => Worker: Function returning worker (lazy initialization)\n * - () => Promise<Worker>: Function returning promise (async lazy initialization)\n * - undefined: Omit for worker thread context (uses self)\n *\n * @example\n * // Switch to a different worker dynamically\n * const host = new WorkerMessageHost(oldWorker);\n * host.initialize(newWorker); // Cleans up old listener, sets up new one\n *\n * @example\n * // Re-initialize after worker error\n * worker.onerror = () => {\n * host.initialize(new Worker('./worker.js'));\n * };\n */\n initialize(worker: ClientWorkerArg) {\n // Ensure WORKER is initialized if not already\n if (!this[WORKER]) {\n this[WORKER] = Promise.resolve(undefined);\n }\n\n this[WORKER] = initializer(\n this[WORKER],\n worker,\n this[HANDLER]\n );\n }\n\n /**\n * Sends a response message back to the worker or main thread\n *\n * @param message - The response message to send\n * @internal Used by the message handling system to send responses\n */\n protected [RESPONSE](message: MessageResponse) {\n this[WORKER].then(worker => {\n if (worker) {\n worker.postMessage(message);\n } else {\n (postMessage as any)(message);\n }\n }).catch(noop);\n }\n\n /**\n * Terminates the worker connection and cleans up message listeners.\n *\n * This method should be called when you're done with the host to prevent memory leaks.\n * It removes the message event listener from either the Worker instance (main thread)\n * or the global scope (worker thread).\n *\n * @example\n * // Clean up when done\n * const host = new WorkerMessageHost(worker);\n * // ... use the host ...\n * host.terminate(); // Clean up listeners\n */\n public terminate() {\n this[WORKER].then(worker => {\n if (worker) {\n worker.removeEventListener('message', this[HANDLER]);\n } else {\n removeEventListener('message', this[HANDLER]);\n }\n }).catch(noop);\n }\n\n /**\n * Handles incoming messages and forwards them to the requests stream\n * @private\n */\n private [HANDLER] = (event: MessageEvent<Message>) => {\n this[REQUESTS$].next(event.data);\n };\n}\n"]}
@@ -4,9 +4,120 @@ exports.WorkerMessageService = void 0;
4
4
  const mixin_1 = require("@thalesrc/js-utils/class/mixin");
5
5
  const message_client_1 = require("./message-client");
6
6
  const message_host_1 = require("./message-host");
7
+ /**
8
+ * WorkerMessageService
9
+ *
10
+ * Bidirectional communication service for Web Workers that combines both client and host
11
+ * capabilities. This class extends both WorkerMessageClient and WorkerMessageHost through
12
+ * mixin composition, enabling full duplex communication - it can both send messages and
13
+ * respond to incoming requests simultaneously.
14
+ *
15
+ * This class is useful when you need a single instance to handle both:
16
+ * - **Sending messages**: Using the @Request decorator to call methods on the other side
17
+ * - **Receiving messages**: Using the @Response decorator to handle incoming requests
18
+ *
19
+ * Like its parent classes, this can be used in two contexts:
20
+ * - **Main thread**: Provide a Worker instance for bidirectional communication with that worker
21
+ * - **Worker thread**: Omit the worker parameter for bidirectional communication with main thread
22
+ *
23
+ * The worker parameter supports multiple types for flexibility:
24
+ * - Direct Worker instance
25
+ * - Promise that resolves to a Worker (for async worker initialization)
26
+ * - Function that returns a Worker (for lazy initialization)
27
+ * - Function that returns a Promise<Worker> (for async lazy initialization)
28
+ *
29
+ * @example
30
+ * // In main thread - full duplex communication with worker
31
+ * const worker = new Worker('./worker.js');
32
+ * const service = new WorkerMessageService(worker);
33
+ *
34
+ * class MainAPI extends WorkerMessageService {
35
+ * // Send messages to worker
36
+ * @Request()
37
+ * fetchData(): Observable<Data> {
38
+ * return null!;
39
+ * }
40
+ *
41
+ * // Respond to worker requests
42
+ * @Listen()
43
+ * saveToLocalStorage(data: any) {
44
+ * localStorage.setItem('data', JSON.stringify(data));
45
+ * return [];
46
+ * }
47
+ * }
48
+ *
49
+ * @example
50
+ * // In worker thread - full duplex communication with main thread
51
+ * const service = new WorkerMessageService();
52
+ *
53
+ * class WorkerAPI extends WorkerMessageService {
54
+ * // Respond to main thread requests
55
+ * @Listen()
56
+ * fetchData() {
57
+ * return from(fetch('/api/data').then(r => r.json()));
58
+ * }
59
+ *
60
+ * // Send messages to main thread
61
+ * @Request()
62
+ * saveToLocalStorage(data: any): Observable<void> {
63
+ * return null!;
64
+ * }
65
+ * }
66
+ *
67
+ * @example
68
+ * // With async worker initialization
69
+ * const workerPromise = import('./worker.js').then(m => new m.MyWorker());
70
+ * const service = new WorkerMessageService(workerPromise);
71
+ *
72
+ * @example
73
+ * // Re-initialize with a different worker
74
+ * const service = new WorkerMessageService();
75
+ * // Later, switch to a different worker
76
+ * service.initialize(new Worker('./different-worker.js'));
77
+ */
7
78
  class WorkerMessageService extends (0, mixin_1.mixin)(message_host_1.WorkerMessageHost, message_client_1.WorkerMessageClient) {
79
+ /**
80
+ * Creates a new WorkerMessageService instance with bidirectional communication
81
+ *
82
+ * @param worker - Optional worker configuration:
83
+ * - Worker: Direct worker instance (main thread)
84
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
85
+ * - () => Worker: Function returning worker (lazy initialization)
86
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
87
+ * - undefined: Omit for worker thread context (uses self)
88
+ */
8
89
  constructor(worker) {
9
90
  super([worker], [worker]);
91
+ this.initialize(worker);
10
92
  }
93
+ /**
94
+ * Initializes or re-initializes the worker connection for both client and host.
95
+ *
96
+ * This method sets up message listeners for both sending and receiving messages.
97
+ * If a worker was previously initialized, it cleans up the old connections before
98
+ * establishing new ones. This allows for dynamic worker management.
99
+ *
100
+ * @param worker - Optional worker configuration:
101
+ * - Worker: Direct worker instance (main thread)
102
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
103
+ * - () => Worker: Function returning worker (lazy initialization)
104
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
105
+ * - undefined: Omit for worker thread context (uses self)
106
+ *
107
+ * @example
108
+ * // Switch to a different worker dynamically
109
+ * const service = new WorkerMessageService(oldWorker);
110
+ * service.initialize(newWorker); // Cleans up old listeners, sets up new ones
111
+ *
112
+ * @example
113
+ * // Re-initialize after worker error
114
+ * worker.onerror = () => {
115
+ * service.initialize(new Worker('./worker.js'));
116
+ * };
117
+ */
118
+ initialize = (worker) => {
119
+ message_host_1.WorkerMessageHost.prototype.initialize.call(this, worker);
120
+ message_client_1.WorkerMessageClient.prototype.initialize.call(this, worker);
121
+ };
11
122
  }
12
123
  exports.WorkerMessageService = WorkerMessageService;