@telperion/messenger 7.6.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 (136) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +600 -0
  3. package/broadcast/default-channel-name.cjs +4 -0
  4. package/broadcast/default-channel-name.d.ts +1 -0
  5. package/broadcast/default-channel-name.js +3 -0
  6. package/broadcast/default-channel-name.js.map +1 -0
  7. package/broadcast/index.cjs +13 -0
  8. package/broadcast/index.d.ts +5 -0
  9. package/broadcast/index.js +7 -0
  10. package/broadcast/index.js.map +1 -0
  11. package/broadcast/message-client.cjs +26 -0
  12. package/broadcast/message-client.d.ts +12 -0
  13. package/broadcast/message-client.js +24 -0
  14. package/broadcast/message-client.js.map +1 -0
  15. package/broadcast/message-host.cjs +28 -0
  16. package/broadcast/message-host.d.ts +9 -0
  17. package/broadcast/message-host.js +26 -0
  18. package/broadcast/message-host.js.map +1 -0
  19. package/broadcast/message-service.cjs +13 -0
  20. package/broadcast/message-service.d.ts +8 -0
  21. package/broadcast/message-service.js +11 -0
  22. package/broadcast/message-service.js.map +1 -0
  23. package/chrome/default-connection-name.cjs +4 -0
  24. package/chrome/default-connection-name.d.ts +1 -0
  25. package/chrome/default-connection-name.js +3 -0
  26. package/chrome/default-connection-name.js.map +1 -0
  27. package/chrome/index.cjs +11 -0
  28. package/chrome/index.d.ts +4 -0
  29. package/chrome/index.js +6 -0
  30. package/chrome/index.js.map +1 -0
  31. package/chrome/message-client.cjs +41 -0
  32. package/chrome/message-client.d.ts +15 -0
  33. package/chrome/message-client.js +39 -0
  34. package/chrome/message-client.js.map +1 -0
  35. package/chrome/message-host.cjs +43 -0
  36. package/chrome/message-host.d.ts +9 -0
  37. package/chrome/message-host.js +41 -0
  38. package/chrome/message-host.js.map +1 -0
  39. package/docs/images/broadcast-communication.svg +87 -0
  40. package/docs/images/chrome-extension-communication.svg +110 -0
  41. package/docs/images/core-architecture.svg +59 -0
  42. package/docs/images/iframe-communication.svg +74 -0
  43. package/docs/images/worker-communication.svg +75 -0
  44. package/iframe/channel-path-splitter.cjs +4 -0
  45. package/iframe/channel-path-splitter.d.ts +1 -0
  46. package/iframe/channel-path-splitter.js +3 -0
  47. package/iframe/channel-path-splitter.js.map +1 -0
  48. package/iframe/default-channel-name.cjs +4 -0
  49. package/iframe/default-channel-name.d.ts +1 -0
  50. package/iframe/default-channel-name.js +3 -0
  51. package/iframe/default-channel-name.js.map +1 -0
  52. package/iframe/iframe.type.cjs +2 -0
  53. package/iframe/iframe.type.d.ts +1 -0
  54. package/iframe/iframe.type.js +3 -0
  55. package/iframe/iframe.type.js.map +1 -0
  56. package/iframe/index.cjs +13 -0
  57. package/iframe/index.d.ts +6 -0
  58. package/iframe/index.js +7 -0
  59. package/iframe/index.js.map +1 -0
  60. package/iframe/message-client.cjs +50 -0
  61. package/iframe/message-client.d.ts +14 -0
  62. package/iframe/message-client.js +48 -0
  63. package/iframe/message-client.js.map +1 -0
  64. package/iframe/message-host.cjs +63 -0
  65. package/iframe/message-host.d.ts +11 -0
  66. package/iframe/message-host.js +61 -0
  67. package/iframe/message-host.js.map +1 -0
  68. package/iframe/message-service.cjs +13 -0
  69. package/iframe/message-service.d.ts +9 -0
  70. package/iframe/message-service.js +11 -0
  71. package/iframe/message-service.js.map +1 -0
  72. package/iframe/source-id-splitter.cjs +4 -0
  73. package/iframe/source-id-splitter.d.ts +1 -0
  74. package/iframe/source-id-splitter.js +3 -0
  75. package/iframe/source-id-splitter.js.map +1 -0
  76. package/iframe/upcoming-message.cjs +2 -0
  77. package/iframe/upcoming-message.d.ts +4 -0
  78. package/iframe/upcoming-message.js +3 -0
  79. package/iframe/upcoming-message.js.map +1 -0
  80. package/index.cjs +13 -0
  81. package/index.d.ts +7 -0
  82. package/index.js +7 -0
  83. package/index.js.map +1 -0
  84. package/listen.decorator.cjs +20 -0
  85. package/listen.decorator.d.ts +6 -0
  86. package/listen.decorator.js +19 -0
  87. package/listen.decorator.js.map +1 -0
  88. package/listener-storage.type.cjs +2 -0
  89. package/listener-storage.type.d.ts +2 -0
  90. package/listener-storage.type.js +3 -0
  91. package/listener-storage.type.js.map +1 -0
  92. package/message-client.cjs +10 -0
  93. package/message-client.d.ts +23 -0
  94. package/message-client.js +8 -0
  95. package/message-client.js.map +1 -0
  96. package/message-host.cjs +58 -0
  97. package/message-host.d.ts +26 -0
  98. package/message-host.js +56 -0
  99. package/message-host.js.map +1 -0
  100. package/message-response.type.cjs +2 -0
  101. package/message-response.type.d.ts +16 -0
  102. package/message-response.type.js +3 -0
  103. package/message-response.type.js.map +1 -0
  104. package/message.interface.cjs +2 -0
  105. package/message.interface.d.ts +6 -0
  106. package/message.interface.js +3 -0
  107. package/message.interface.js.map +1 -0
  108. package/package.json +158 -0
  109. package/request.decorator.cjs +20 -0
  110. package/request.decorator.d.ts +1 -0
  111. package/request.decorator.js +19 -0
  112. package/request.decorator.js.map +1 -0
  113. package/selectors.cjs +10 -0
  114. package/selectors.d.ts +7 -0
  115. package/selectors.js +9 -0
  116. package/selectors.js.map +1 -0
  117. package/worker/index.cjs +13 -0
  118. package/worker/index.d.ts +5 -0
  119. package/worker/index.js +7 -0
  120. package/worker/index.js.map +1 -0
  121. package/worker/initializer.cjs +39 -0
  122. package/worker/initializer.d.ts +12 -0
  123. package/worker/initializer.js +38 -0
  124. package/worker/initializer.js.map +1 -0
  125. package/worker/message-client.cjs +158 -0
  126. package/worker/message-client.d.ts +131 -0
  127. package/worker/message-client.js +156 -0
  128. package/worker/message-client.js.map +1 -0
  129. package/worker/message-host.cjs +165 -0
  130. package/worker/message-host.d.ts +131 -0
  131. package/worker/message-host.js +163 -0
  132. package/worker/message-host.js.map +1 -0
  133. package/worker/message-service.cjs +123 -0
  134. package/worker/message-service.d.ts +117 -0
  135. package/worker/message-service.js +121 -0
  136. package/worker/message-service.js.map +1 -0
package/selectors.js ADDED
@@ -0,0 +1,9 @@
1
+ export const MESSAGE_LISTENERS = Symbol('Message Listeners');
2
+ export const RESPONSES$ = Symbol('Responses');
3
+ export const SEND = Symbol('Send');
4
+ export const GET_NEW_ID = Symbol('Get New Id');
5
+ export const LISTEN = Symbol('Listen');
6
+ export const TERMINATE_MESSAGE$ = Symbol('Terminate Message');
7
+ export const RESPONSE = Symbol('Response');
8
+
9
+ //# sourceMappingURL=selectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/messenger/src/selectors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAC7D,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAC/C,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAC9D,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC","file":"selectors.js","sourcesContent":["export const MESSAGE_LISTENERS = Symbol('Message Listeners');\nexport const RESPONSES$ = Symbol('Responses');\nexport const SEND = Symbol('Send');\nexport const GET_NEW_ID = Symbol('Get New Id');\nexport const LISTEN = Symbol('Listen');\nexport const TERMINATE_MESSAGE$ = Symbol('Terminate Message');\nexport const RESPONSE = Symbol('Response');\n"]}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Listen = exports.Request = exports.WorkerMessageHost = exports.WorkerMessageClient = exports.WorkerMessageService = void 0;
4
+ var message_service_1 = require("./message-service");
5
+ Object.defineProperty(exports, "WorkerMessageService", { enumerable: true, get: function () { return message_service_1.WorkerMessageService; } });
6
+ var message_client_1 = require("./message-client");
7
+ Object.defineProperty(exports, "WorkerMessageClient", { enumerable: true, get: function () { return message_client_1.WorkerMessageClient; } });
8
+ var message_host_1 = require("./message-host");
9
+ Object.defineProperty(exports, "WorkerMessageHost", { enumerable: true, get: function () { return message_host_1.WorkerMessageHost; } });
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; } });
@@ -0,0 +1,5 @@
1
+ export { WorkerMessageService } from './message-service';
2
+ export { WorkerMessageClient } from './message-client';
3
+ export { WorkerMessageHost } from './message-host';
4
+ export { Request } from '../request.decorator';
5
+ export { Listen } from '../listen.decorator';
@@ -0,0 +1,7 @@
1
+ export { WorkerMessageService } from './message-service';
2
+ export { WorkerMessageClient } from './message-client';
3
+ export { WorkerMessageHost } from './message-host';
4
+ export { Request } from '../request.decorator';
5
+ export { Listen } from '../listen.decorator';
6
+
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/messenger/src/worker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC","file":"index.js","sourcesContent":["export { WorkerMessageService } from './message-service';\nexport { WorkerMessageClient } from './message-client';\nexport { WorkerMessageHost } from './message-host';\nexport { Request } from '../request.decorator';\nexport { Listen } from '../listen.decorator';\n"]}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initializer = initializer;
4
+ const noop_1 = require("@telperion/js-utils/function/noop");
5
+ const promisify_1 = require("@telperion/js-utils/promise/promisify");
6
+ /**
7
+ * Initializes a Web Worker or the worker context for message communication.
8
+ * @param prevWorker The previous worker promise to deinitialize
9
+ * @param worker The new worker argument (Worker instance, promise, or factory function)
10
+ * @param handler The message event handler to attach
11
+ * @returns A promise resolving to the initialized Worker or undefined if in worker context
12
+ */
13
+ function initializer(prevWorker, worker, handler) {
14
+ // Deinitialize previous worker if any
15
+ prevWorker.then(pw => {
16
+ if (pw) {
17
+ pw.removeEventListener('message', handler);
18
+ }
19
+ else {
20
+ removeEventListener('message', handler);
21
+ }
22
+ }).catch(noop_1.noop);
23
+ // Resolve worker parameter: execute function if provided, otherwise use value directly
24
+ const _worker = typeof worker === 'function' ? worker() : worker;
25
+ // Ensure worker is wrapped in a promise for consistent async handling
26
+ const newWorker = (0, promisify_1.promisify)(_worker);
27
+ // Set up message listener once worker is resolved
28
+ newWorker.then(worker => {
29
+ if (worker) {
30
+ // Main thread context: listen to specific worker
31
+ worker.addEventListener('message', handler);
32
+ }
33
+ else {
34
+ // Worker thread context: listen to messages from main thread
35
+ addEventListener('message', handler);
36
+ }
37
+ }).catch(noop_1.noop);
38
+ return newWorker;
39
+ }
@@ -0,0 +1,12 @@
1
+ export type ClientWorkerType = Worker | undefined;
2
+ export type ClientWorkerPromise = Promise<ClientWorkerType>;
3
+ export type ClientWorkerFactory = () => ClientWorkerType | ClientWorkerPromise;
4
+ export type ClientWorkerArg = ClientWorkerType | ClientWorkerPromise | ClientWorkerFactory;
5
+ /**
6
+ * Initializes a Web Worker or the worker context for message communication.
7
+ * @param prevWorker The previous worker promise to deinitialize
8
+ * @param worker The new worker argument (Worker instance, promise, or factory function)
9
+ * @param handler The message event handler to attach
10
+ * @returns A promise resolving to the initialized Worker or undefined if in worker context
11
+ */
12
+ export declare function initializer(prevWorker: ClientWorkerPromise, worker: ClientWorkerArg, handler: (event: MessageEvent) => void): Promise<Worker | undefined>;
@@ -0,0 +1,38 @@
1
+ import { noop } from "@telperion/js-utils/function/noop";
2
+ import { promisify } from "@telperion/js-utils/promise/promisify";
3
+ /**
4
+ * Initializes a Web Worker or the worker context for message communication.
5
+ * @param prevWorker The previous worker promise to deinitialize
6
+ * @param worker The new worker argument (Worker instance, promise, or factory function)
7
+ * @param handler The message event handler to attach
8
+ * @returns A promise resolving to the initialized Worker or undefined if in worker context
9
+ */
10
+ export function initializer(prevWorker, worker, handler) {
11
+ // Deinitialize previous worker if any
12
+ prevWorker.then(pw => {
13
+ if (pw) {
14
+ pw.removeEventListener('message', handler);
15
+ }
16
+ else {
17
+ removeEventListener('message', handler);
18
+ }
19
+ }).catch(noop);
20
+ // Resolve worker parameter: execute function if provided, otherwise use value directly
21
+ const _worker = typeof worker === 'function' ? worker() : worker;
22
+ // Ensure worker is wrapped in a promise for consistent async handling
23
+ const newWorker = promisify(_worker);
24
+ // Set up message listener once worker is resolved
25
+ newWorker.then(worker => {
26
+ if (worker) {
27
+ // Main thread context: listen to specific worker
28
+ worker.addEventListener('message', handler);
29
+ }
30
+ else {
31
+ // Worker thread context: listen to messages from main thread
32
+ addEventListener('message', handler);
33
+ }
34
+ }).catch(noop);
35
+ return newWorker;
36
+ }
37
+
38
+ //# sourceMappingURL=initializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/messenger/src/worker/initializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mCAAmC,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AAOlE;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,UAA+B,EAC/B,MAAuB,EACvB,OAAsC;IAEtC,sCAAsC;IACtC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QACnB,IAAI,EAAE,EAAE,CAAC;YACP,EAAE,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEf,uFAAuF;IACvF,MAAM,OAAO,GAAuD,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACrH,sEAAsE;IACtE,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAErC,kDAAkD;IAClD,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;QACtB,IAAI,MAAM,EAAE,CAAC;YACX,iDAAiD;YACjD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,6DAA6D;YAC7D,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEf,OAAO,SAAS,CAAC;AACnB,CAAC","file":"initializer.js","sourcesContent":["import { noop } from \"@telperion/js-utils/function/noop\";\nimport { promisify } from \"@telperion/js-utils/promise/promisify\";\n\nexport type ClientWorkerType = Worker | undefined;\nexport type ClientWorkerPromise = Promise<ClientWorkerType>;\nexport type ClientWorkerFactory = () => ClientWorkerType | ClientWorkerPromise;\nexport type ClientWorkerArg = ClientWorkerType | ClientWorkerPromise | ClientWorkerFactory;\n\n/**\n * Initializes a Web Worker or the worker context for message communication.\n * @param prevWorker The previous worker promise to deinitialize\n * @param worker The new worker argument (Worker instance, promise, or factory function)\n * @param handler The message event handler to attach\n * @returns A promise resolving to the initialized Worker or undefined if in worker context\n */\nexport function initializer(\n prevWorker: ClientWorkerPromise,\n worker: ClientWorkerArg,\n handler: (event: MessageEvent) => void\n) {\n // Deinitialize previous worker if any\n prevWorker.then(pw => {\n if (pw) {\n pw.removeEventListener('message', handler);\n } else {\n removeEventListener('message', handler);\n }\n }).catch(noop);\n\n // Resolve worker parameter: execute function if provided, otherwise use value directly\n const _worker: ClientWorkerType | ClientWorkerPromise | undefined = typeof worker === 'function' ? worker() : worker;\n // Ensure worker is wrapped in a promise for consistent async handling\n const newWorker = promisify(_worker);\n\n // Set up message listener once worker is resolved\n newWorker.then(worker => {\n if (worker) {\n // Main thread context: listen to specific worker\n worker.addEventListener('message', handler);\n } else {\n // Worker thread context: listen to messages from main thread\n addEventListener('message', handler);\n }\n }).catch(noop);\n\n return newWorker;\n}\n"]}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkerMessageClient = void 0;
4
+ const unique_id_1 = require("@telperion/js-utils/unique-id");
5
+ const noop_1 = require("@telperion/js-utils/function/noop");
6
+ const rxjs_1 = require("rxjs");
7
+ const message_client_1 = require("../message-client");
8
+ const selectors_1 = require("../selectors");
9
+ const initializer_1 = require("./initializer");
10
+ const WORKER = Symbol('Client Worker');
11
+ const HANDLER = Symbol('Client Message Handler');
12
+ const INSTANCE_ID = Symbol('Client Instance ID');
13
+ /**
14
+ * WorkerMessageClient
15
+ *
16
+ * Client implementation for Web Worker communication. Sends messages to and receives
17
+ * responses from Web Workers using the Worker postMessage API.
18
+ *
19
+ * This class can be used in two contexts:
20
+ * - **Main thread**: Provide a Worker instance to communicate with that specific worker
21
+ * - **Worker thread**: Omit the worker parameter to communicate with the main thread via self
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
+ * The `initialize()` method allows dynamic worker management, enabling you to switch
30
+ * workers at runtime or re-establish connections after errors.
31
+ *
32
+ * @example
33
+ * // In main thread - communicate with a specific worker
34
+ * const worker = new Worker('./worker.js');
35
+ * const client = new WorkerMessageClient(worker);
36
+ *
37
+ * @example
38
+ * // In worker thread - communicate with main thread
39
+ * const client = new WorkerMessageClient();
40
+ *
41
+ * @example
42
+ * // With async worker initialization
43
+ * const workerPromise = import('./worker.js').then(m => new m.MyWorker());
44
+ * const client = new WorkerMessageClient(workerPromise);
45
+ *
46
+ * @example
47
+ * // With lazy initialization
48
+ * const client = new WorkerMessageClient(() =>
49
+ * document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
50
+ * );
51
+ *
52
+ * @example
53
+ * // Re-initialize with a different worker
54
+ * const client = new WorkerMessageClient();
55
+ * // Later, switch to a different worker
56
+ * client.initialize(new Worker('./different-worker.js'));
57
+ */
58
+ class WorkerMessageClient extends message_client_1.MessageClient {
59
+ /**
60
+ * Promise resolving to the Worker instance or undefined if running in worker context
61
+ * @private
62
+ */
63
+ [WORKER] = Promise.resolve(undefined);
64
+ /**
65
+ * Unique identifier for this client instance to prevent ID collisions
66
+ * @private
67
+ */
68
+ [INSTANCE_ID] = '' + Math.floor(Math.random() * 10000);
69
+ /**
70
+ * Observable stream of message responses from the worker or main thread
71
+ */
72
+ [selectors_1.RESPONSES$] = new rxjs_1.Subject();
73
+ /**
74
+ * Creates a new WorkerMessageClient instance
75
+ *
76
+ * @param worker - Optional worker configuration:
77
+ * - Worker: Direct worker instance (main thread)
78
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
79
+ * - () => Worker: Function returning worker (lazy initialization)
80
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
81
+ * - undefined: Omit for worker thread context (uses self)
82
+ */
83
+ constructor(worker) {
84
+ super();
85
+ this.initialize(worker);
86
+ }
87
+ /**
88
+ * Initializes or re-initializes the worker connection.
89
+ *
90
+ * This method sets up message listeners for the provided worker. If a worker
91
+ * was previously initialized, it cleans up the old connection before establishing
92
+ * the new one. This allows for dynamic worker management, such as:
93
+ * - Switching between different workers at runtime
94
+ * - Re-establishing connections after worker errors
95
+ * - Lazy initialization when the worker is conditionally needed
96
+ *
97
+ * @param worker - Optional worker configuration:
98
+ * - Worker: Direct worker instance (main thread)
99
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
100
+ * - () => Worker: Function returning worker (lazy initialization)
101
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
102
+ * - undefined: Omit for worker thread context (uses self)
103
+ *
104
+ * @example
105
+ * // Switch to a different worker dynamically
106
+ * const client = new WorkerMessageClient(oldWorker);
107
+ * client.initialize(newWorker); // Cleans up old listener, sets up new one
108
+ *
109
+ * @example
110
+ * // Re-initialize after worker error
111
+ * worker.onerror = () => {
112
+ * client.initialize(new Worker('./worker.js'));
113
+ * };
114
+ */
115
+ initialize(worker) {
116
+ // Ensure WORKER is initialized if not already
117
+ if (!this[WORKER]) {
118
+ this[WORKER] = Promise.resolve(undefined);
119
+ }
120
+ this[WORKER] = (0, initializer_1.initializer)(this[WORKER], worker, this[HANDLER]);
121
+ }
122
+ /**
123
+ * Sends a message to the worker or main thread
124
+ *
125
+ * @param message - The message to send
126
+ * @template T - Type of the message body
127
+ * @internal Used by @Request decorator
128
+ */
129
+ [selectors_1.SEND](message) {
130
+ this[WORKER].then(worker => {
131
+ if (worker) {
132
+ // Main thread: send to worker
133
+ worker.postMessage(message);
134
+ }
135
+ else {
136
+ // Worker thread: send to main thread
137
+ postMessage(message);
138
+ }
139
+ }).catch(noop_1.noop);
140
+ }
141
+ /**
142
+ * Handles incoming messages and forwards them to the responses stream
143
+ * @private
144
+ */
145
+ [HANDLER] = (event) => {
146
+ this[selectors_1.RESPONSES$].next(event.data);
147
+ };
148
+ /**
149
+ * Generates a unique message ID for tracking request-response pairs
150
+ *
151
+ * @returns Unique message identifier
152
+ * @internal Used by @Request decorator
153
+ */
154
+ [selectors_1.GET_NEW_ID]() {
155
+ return (0, unique_id_1.uniqueId)('messenger-worker-message-' + this[INSTANCE_ID]);
156
+ }
157
+ }
158
+ exports.WorkerMessageClient = WorkerMessageClient;
@@ -0,0 +1,131 @@
1
+ import { Subject } from "rxjs";
2
+ import { MessageClient } from "../message-client";
3
+ import { MessageResponse } from "../message-response.type";
4
+ import { Message } from "../message.interface";
5
+ import { GET_NEW_ID, RESPONSES$, SEND } from "../selectors";
6
+ import { ClientWorkerArg } from "./initializer";
7
+ declare const WORKER: unique symbol;
8
+ declare const HANDLER: unique symbol;
9
+ declare const INSTANCE_ID: unique symbol;
10
+ /**
11
+ * WorkerMessageClient
12
+ *
13
+ * Client implementation for Web Worker communication. Sends messages to and receives
14
+ * responses from Web Workers using the Worker postMessage API.
15
+ *
16
+ * This class can be used in two contexts:
17
+ * - **Main thread**: Provide a Worker instance to communicate with that specific worker
18
+ * - **Worker thread**: Omit the worker parameter to communicate with the main thread via self
19
+ *
20
+ * The worker parameter supports multiple types for flexibility:
21
+ * - Direct Worker instance
22
+ * - Promise that resolves to a Worker (for async worker initialization)
23
+ * - Function that returns a Worker (for lazy initialization)
24
+ * - Function that returns a Promise<Worker> (for async lazy initialization)
25
+ *
26
+ * The `initialize()` method allows dynamic worker management, enabling you to switch
27
+ * workers at runtime or re-establish connections after errors.
28
+ *
29
+ * @example
30
+ * // In main thread - communicate with a specific worker
31
+ * const worker = new Worker('./worker.js');
32
+ * const client = new WorkerMessageClient(worker);
33
+ *
34
+ * @example
35
+ * // In worker thread - communicate with main thread
36
+ * const client = new WorkerMessageClient();
37
+ *
38
+ * @example
39
+ * // With async worker initialization
40
+ * const workerPromise = import('./worker.js').then(m => new m.MyWorker());
41
+ * const client = new WorkerMessageClient(workerPromise);
42
+ *
43
+ * @example
44
+ * // With lazy initialization
45
+ * const client = new WorkerMessageClient(() =>
46
+ * document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
47
+ * );
48
+ *
49
+ * @example
50
+ * // Re-initialize with a different worker
51
+ * const client = new WorkerMessageClient();
52
+ * // Later, switch to a different worker
53
+ * client.initialize(new Worker('./different-worker.js'));
54
+ */
55
+ export declare class WorkerMessageClient extends MessageClient {
56
+ /**
57
+ * Promise resolving to the Worker instance or undefined if running in worker context
58
+ * @private
59
+ */
60
+ private [WORKER];
61
+ /**
62
+ * Unique identifier for this client instance to prevent ID collisions
63
+ * @private
64
+ */
65
+ private [INSTANCE_ID];
66
+ /**
67
+ * Observable stream of message responses from the worker or main thread
68
+ */
69
+ [RESPONSES$]: Subject<MessageResponse>;
70
+ /**
71
+ * Creates a new WorkerMessageClient instance
72
+ *
73
+ * @param worker - Optional worker configuration:
74
+ * - Worker: Direct worker instance (main thread)
75
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
76
+ * - () => Worker: Function returning worker (lazy initialization)
77
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
78
+ * - undefined: Omit for worker thread context (uses self)
79
+ */
80
+ constructor(worker?: ClientWorkerArg);
81
+ /**
82
+ * Initializes or re-initializes the worker connection.
83
+ *
84
+ * This method sets up message listeners for the provided worker. If a worker
85
+ * was previously initialized, it cleans up the old connection before establishing
86
+ * the new one. This allows for dynamic worker management, such as:
87
+ * - Switching between different workers at runtime
88
+ * - Re-establishing connections after worker errors
89
+ * - Lazy initialization when the worker is conditionally needed
90
+ *
91
+ * @param worker - Optional worker configuration:
92
+ * - Worker: Direct worker instance (main thread)
93
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
94
+ * - () => Worker: Function returning worker (lazy initialization)
95
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
96
+ * - undefined: Omit for worker thread context (uses self)
97
+ *
98
+ * @example
99
+ * // Switch to a different worker dynamically
100
+ * const client = new WorkerMessageClient(oldWorker);
101
+ * client.initialize(newWorker); // Cleans up old listener, sets up new one
102
+ *
103
+ * @example
104
+ * // Re-initialize after worker error
105
+ * worker.onerror = () => {
106
+ * client.initialize(new Worker('./worker.js'));
107
+ * };
108
+ */
109
+ initialize(worker?: ClientWorkerArg): void;
110
+ /**
111
+ * Sends a message to the worker or main thread
112
+ *
113
+ * @param message - The message to send
114
+ * @template T - Type of the message body
115
+ * @internal Used by @Request decorator
116
+ */
117
+ [SEND]<T>(message: Message<T>): void;
118
+ /**
119
+ * Handles incoming messages and forwards them to the responses stream
120
+ * @private
121
+ */
122
+ private [HANDLER];
123
+ /**
124
+ * Generates a unique message ID for tracking request-response pairs
125
+ *
126
+ * @returns Unique message identifier
127
+ * @internal Used by @Request decorator
128
+ */
129
+ protected [GET_NEW_ID](): string;
130
+ }
131
+ export {};
@@ -0,0 +1,156 @@
1
+ import { uniqueId } from "@telperion/js-utils/unique-id";
2
+ import { noop } from "@telperion/js-utils/function/noop";
3
+ import { Subject } from "rxjs";
4
+ import { MessageClient } from "../message-client";
5
+ import { GET_NEW_ID, RESPONSES$, SEND } from "../selectors";
6
+ import { initializer } from "./initializer";
7
+ const WORKER = Symbol('Client Worker');
8
+ const HANDLER = Symbol('Client Message Handler');
9
+ const INSTANCE_ID = Symbol('Client Instance ID');
10
+ /**
11
+ * WorkerMessageClient
12
+ *
13
+ * Client implementation for Web Worker communication. Sends messages to and receives
14
+ * responses from Web Workers using the Worker postMessage API.
15
+ *
16
+ * This class can be used in two contexts:
17
+ * - **Main thread**: Provide a Worker instance to communicate with that specific worker
18
+ * - **Worker thread**: Omit the worker parameter to communicate with the main thread via self
19
+ *
20
+ * The worker parameter supports multiple types for flexibility:
21
+ * - Direct Worker instance
22
+ * - Promise that resolves to a Worker (for async worker initialization)
23
+ * - Function that returns a Worker (for lazy initialization)
24
+ * - Function that returns a Promise<Worker> (for async lazy initialization)
25
+ *
26
+ * The `initialize()` method allows dynamic worker management, enabling you to switch
27
+ * workers at runtime or re-establish connections after errors.
28
+ *
29
+ * @example
30
+ * // In main thread - communicate with a specific worker
31
+ * const worker = new Worker('./worker.js');
32
+ * const client = new WorkerMessageClient(worker);
33
+ *
34
+ * @example
35
+ * // In worker thread - communicate with main thread
36
+ * const client = new WorkerMessageClient();
37
+ *
38
+ * @example
39
+ * // With async worker initialization
40
+ * const workerPromise = import('./worker.js').then(m => new m.MyWorker());
41
+ * const client = new WorkerMessageClient(workerPromise);
42
+ *
43
+ * @example
44
+ * // With lazy initialization
45
+ * const client = new WorkerMessageClient(() =>
46
+ * document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
47
+ * );
48
+ *
49
+ * @example
50
+ * // Re-initialize with a different worker
51
+ * const client = new WorkerMessageClient();
52
+ * // Later, switch to a different worker
53
+ * client.initialize(new Worker('./different-worker.js'));
54
+ */
55
+ export class WorkerMessageClient extends MessageClient {
56
+ /**
57
+ * Promise resolving to the Worker instance or undefined if running in worker context
58
+ * @private
59
+ */
60
+ [WORKER] = Promise.resolve(undefined);
61
+ /**
62
+ * Unique identifier for this client instance to prevent ID collisions
63
+ * @private
64
+ */
65
+ [INSTANCE_ID] = '' + Math.floor(Math.random() * 10000);
66
+ /**
67
+ * Observable stream of message responses from the worker or main thread
68
+ */
69
+ [RESPONSES$] = new Subject();
70
+ /**
71
+ * Creates a new WorkerMessageClient instance
72
+ *
73
+ * @param worker - Optional worker configuration:
74
+ * - Worker: Direct worker instance (main thread)
75
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
76
+ * - () => Worker: Function returning worker (lazy initialization)
77
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
78
+ * - undefined: Omit for worker thread context (uses self)
79
+ */
80
+ constructor(worker) {
81
+ super();
82
+ this.initialize(worker);
83
+ }
84
+ /**
85
+ * Initializes or re-initializes the worker connection.
86
+ *
87
+ * This method sets up message listeners for the provided worker. If a worker
88
+ * was previously initialized, it cleans up the old connection before establishing
89
+ * the new one. This allows for dynamic worker management, such as:
90
+ * - Switching between different workers at runtime
91
+ * - Re-establishing connections after worker errors
92
+ * - Lazy initialization when the worker is conditionally needed
93
+ *
94
+ * @param worker - Optional worker configuration:
95
+ * - Worker: Direct worker instance (main thread)
96
+ * - Promise<Worker>: Promise resolving to worker (async initialization)
97
+ * - () => Worker: Function returning worker (lazy initialization)
98
+ * - () => Promise<Worker>: Function returning promise (async lazy initialization)
99
+ * - undefined: Omit for worker thread context (uses self)
100
+ *
101
+ * @example
102
+ * // Switch to a different worker dynamically
103
+ * const client = new WorkerMessageClient(oldWorker);
104
+ * client.initialize(newWorker); // Cleans up old listener, sets up new one
105
+ *
106
+ * @example
107
+ * // Re-initialize after worker error
108
+ * worker.onerror = () => {
109
+ * client.initialize(new Worker('./worker.js'));
110
+ * };
111
+ */
112
+ initialize(worker) {
113
+ // Ensure WORKER is initialized if not already
114
+ if (!this[WORKER]) {
115
+ this[WORKER] = Promise.resolve(undefined);
116
+ }
117
+ this[WORKER] = initializer(this[WORKER], worker, this[HANDLER]);
118
+ }
119
+ /**
120
+ * Sends a message to the worker or main thread
121
+ *
122
+ * @param message - The message to send
123
+ * @template T - Type of the message body
124
+ * @internal Used by @Request decorator
125
+ */
126
+ [SEND](message) {
127
+ this[WORKER].then(worker => {
128
+ if (worker) {
129
+ // Main thread: send to worker
130
+ worker.postMessage(message);
131
+ }
132
+ else {
133
+ // Worker thread: send to main thread
134
+ postMessage(message);
135
+ }
136
+ }).catch(noop);
137
+ }
138
+ /**
139
+ * Handles incoming messages and forwards them to the responses stream
140
+ * @private
141
+ */
142
+ [HANDLER] = (event) => {
143
+ this[RESPONSES$].next(event.data);
144
+ };
145
+ /**
146
+ * Generates a unique message ID for tracking request-response pairs
147
+ *
148
+ * @returns Unique message identifier
149
+ * @internal Used by @Request decorator
150
+ */
151
+ [GET_NEW_ID]() {
152
+ return uniqueId('messenger-worker-message-' + this[INSTANCE_ID]);
153
+ }
154
+ }
155
+
156
+ //# sourceMappingURL=message-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/messenger/src/worker/message-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,mCAAmC,CAAC;AACzD,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,EAAwC,WAAW,EAAE,MAAM,eAAe,CAAC;AAElF,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AACvC,MAAM,OAAO,GAAG,MAAM,CAAC,wBAAwB,CAAC,CAAC;AACjD,MAAM,WAAW,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,OAAO,mBAAoB,SAAQ,aAAa;IACpD;;;OAGG;IACK,CAAC,MAAM,CAAC,GAAwB,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEnE;;;OAGG;IACK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC;IAE/D;;OAEG;IACI,CAAC,UAAU,CAAC,GAAG,IAAI,OAAO,EAAmB,CAAC;IAErD;;;;;;;;;OASG;IACH,YAAY,MAAwB;QAClC,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,UAAU,CAAC,MAAwB;QACjC,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;;;;;;OAMG;IACI,CAAC,IAAI,CAAC,CAAI,OAAmB;QAClC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;YACzB,IAAI,MAAM,EAAE,CAAC;gBACX,8BAA8B;gBAC9B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,qCAAqC;gBACpC,WAAmB,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAED;;;OAGG;IACK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAoC,EAAE,EAAE;QAC3D,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAA;IAED;;;;;OAKG;IACO,CAAC,UAAU,CAAC;QACpB,OAAO,QAAQ,CAAC,2BAA2B,GAAG,IAAI,CAAC,WAAW,CAAC,CAAW,CAAC;IAC7E,CAAC;CACF","file":"message-client.js","sourcesContent":["import { uniqueId } from \"@telperion/js-utils/unique-id\";\nimport { noop } from \"@telperion/js-utils/function/noop\";\nimport { 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 { ClientWorkerArg, ClientWorkerPromise, initializer } from \"./initializer\";\n\nconst WORKER = Symbol('Client Worker');\nconst HANDLER = Symbol('Client Message Handler');\nconst INSTANCE_ID = Symbol('Client Instance ID');\n\n/**\n * WorkerMessageClient\n *\n * Client implementation for Web Worker communication. Sends messages to and receives\n * responses from 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 communicate with that specific worker\n * - **Worker thread**: Omit the worker parameter to communicate with 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 - communicate with a specific worker\n * const worker = new Worker('./worker.js');\n * const client = new WorkerMessageClient(worker);\n *\n * @example\n * // In worker thread - communicate with main thread\n * const client = new WorkerMessageClient();\n *\n * @example\n * // With async worker initialization\n * const workerPromise = import('./worker.js').then(m => new m.MyWorker());\n * const client = new WorkerMessageClient(workerPromise);\n *\n * @example\n * // With lazy initialization\n * const client = new WorkerMessageClient(() =>\n * document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined\n * );\n *\n * @example\n * // Re-initialize with a different worker\n * const client = new WorkerMessageClient();\n * // Later, switch to a different worker\n * client.initialize(new Worker('./different-worker.js'));\n */\nexport class WorkerMessageClient extends MessageClient {\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 * Unique identifier for this client instance to prevent ID collisions\n * @private\n */\n private [INSTANCE_ID] = '' + Math.floor(Math.random() * 10000);\n\n /**\n * Observable stream of message responses from the worker or main thread\n */\n public [RESPONSES$] = new Subject<MessageResponse>();\n\n /**\n * Creates a new WorkerMessageClient 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?: ClientWorkerArg) {\n super();\n\n this.initialize(worker);\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 client = new WorkerMessageClient(oldWorker);\n * client.initialize(newWorker); // Cleans up old listener, sets up new one\n *\n * @example\n * // Re-initialize after worker error\n * worker.onerror = () => {\n * client.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 message to the worker or main thread\n *\n * @param message - The message to send\n * @template T - Type of the message body\n * @internal Used by @Request decorator\n */\n public [SEND]<T>(message: Message<T>) {\n this[WORKER].then(worker => {\n if (worker) {\n // Main thread: send to worker\n worker.postMessage(message);\n } else {\n // Worker thread: send to main thread\n (postMessage as any)(message);\n }\n }).catch(noop);\n }\n\n /**\n * Handles incoming messages and forwards them to the responses stream\n * @private\n */\n private [HANDLER] = (event: MessageEvent<MessageResponse>) => {\n this[RESPONSES$].next(event.data);\n }\n\n /**\n * Generates a unique message ID for tracking request-response pairs\n *\n * @returns Unique message identifier\n * @internal Used by @Request decorator\n */\n protected [GET_NEW_ID](): string {\n return uniqueId('messenger-worker-message-' + this[INSTANCE_ID]) as string;\n }\n}\n"]}