@thalesrc/hermes 7.2.0 → 7.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -2
- package/broadcast/message-host.cjs +3 -2
- package/broadcast/message-host.d.ts +2 -1
- package/broadcast/message-host.js +3 -2
- package/broadcast/message-host.js.map +1 -1
- package/chrome/message-host.cjs +4 -3
- package/chrome/message-host.d.ts +2 -1
- package/chrome/message-host.js +4 -3
- package/chrome/message-host.js.map +1 -1
- package/iframe/message-host.cjs +3 -2
- package/iframe/message-host.d.ts +2 -1
- package/iframe/message-host.js +3 -2
- package/iframe/message-host.js.map +1 -1
- package/message-host.cjs +12 -7
- package/message-host.d.ts +4 -3
- package/message-host.js +13 -8
- package/message-host.js.map +1 -1
- package/message.interface.d.ts +1 -0
- package/message.interface.js.map +1 -1
- package/package.json +1 -1
- package/selectors.cjs +4 -2
- package/selectors.d.ts +3 -1
- package/selectors.js +3 -1
- package/selectors.js.map +1 -1
- package/worker/message-client.cjs +50 -1
- package/worker/message-client.d.ts +44 -1
- package/worker/message-client.js +50 -1
- package/worker/message-client.js.map +1 -1
- package/worker/message-host.cjs +15 -17
- package/worker/message-host.d.ts +3 -8
- package/worker/message-host.js +15 -17
- package/worker/message-host.js.map +1 -1
- package/worker/message-service.d.ts +1 -1
package/README.md
CHANGED
|
@@ -231,9 +231,9 @@ mainService.sendDataToWorker([1, 2, 3, 4, 5]).subscribe(result => {
|
|
|
231
231
|
});
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
-
#####
|
|
234
|
+
##### Flexible Worker Initialization
|
|
235
235
|
|
|
236
|
-
The worker parameter supports
|
|
236
|
+
The worker parameter supports multiple initialization patterns for different use cases:
|
|
237
237
|
|
|
238
238
|
```typescript
|
|
239
239
|
// Direct Worker instance
|
|
@@ -253,6 +253,41 @@ const service4 = new MainThread(async () => {
|
|
|
253
253
|
});
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
##### Dynamic Worker Management with `initialize()`
|
|
257
|
+
|
|
258
|
+
The `initialize()` method allows you to switch workers at runtime or re-establish connections:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
class MainThread extends WorkerMessageService {
|
|
262
|
+
// ... decorators and methods
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Start without a worker
|
|
266
|
+
const service = new MainThread();
|
|
267
|
+
|
|
268
|
+
// Later, connect to a worker dynamically
|
|
269
|
+
service.initialize(new Worker('./worker.js'));
|
|
270
|
+
|
|
271
|
+
// Switch to a different worker
|
|
272
|
+
service.initialize(new Worker('./different-worker.js'));
|
|
273
|
+
|
|
274
|
+
// Re-establish connection after worker error
|
|
275
|
+
const worker = new Worker('./worker.js');
|
|
276
|
+
worker.onerror = (error) => {
|
|
277
|
+
console.error('Worker error, reinitializing...', error);
|
|
278
|
+
service.initialize(new Worker('./worker.js'));
|
|
279
|
+
};
|
|
280
|
+
service.initialize(worker);
|
|
281
|
+
|
|
282
|
+
// Conditional worker initialization
|
|
283
|
+
function getWorker() {
|
|
284
|
+
return navigator.hardwareConcurrency > 2
|
|
285
|
+
? new Worker('./heavy-worker.js')
|
|
286
|
+
: new Worker('./light-worker.js');
|
|
287
|
+
}
|
|
288
|
+
service.initialize(getWorker);
|
|
289
|
+
```
|
|
290
|
+
|
|
256
291
|
#### Worker Thread
|
|
257
292
|
|
|
258
293
|
```typescript
|
|
@@ -4,6 +4,7 @@ exports.BroadcastMessageHost = void 0;
|
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const message_host_1 = require("../message-host");
|
|
6
6
|
const default_channel_name_1 = require("./default-channel-name");
|
|
7
|
+
const selectors_1 = require("../selectors");
|
|
7
8
|
class BroadcastMessageHost extends message_host_1.MessageHost {
|
|
8
9
|
#requests$ = new rxjs_1.Subject();
|
|
9
10
|
#channel;
|
|
@@ -11,9 +12,9 @@ class BroadcastMessageHost extends message_host_1.MessageHost {
|
|
|
11
12
|
super();
|
|
12
13
|
this.#channel = new BroadcastChannel(channelName);
|
|
13
14
|
this.#channel.addEventListener('message', this.#handler);
|
|
14
|
-
this.
|
|
15
|
+
this[selectors_1.LISTEN](this.#requests$);
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
+
[selectors_1.RESPONSE](message) {
|
|
17
18
|
this.#channel.postMessage(message);
|
|
18
19
|
}
|
|
19
20
|
terminate() {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { MessageHost } from "../message-host";
|
|
2
2
|
import { MessageResponse } from "../message-response.type";
|
|
3
|
+
import { RESPONSE } from "../selectors";
|
|
3
4
|
export declare class BroadcastMessageHost extends MessageHost {
|
|
4
5
|
#private;
|
|
5
6
|
constructor(channelName?: string);
|
|
6
|
-
protected
|
|
7
|
+
protected [RESPONSE](message: MessageResponse): void;
|
|
7
8
|
terminate(): void;
|
|
8
9
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Subject } from "rxjs";
|
|
2
2
|
import { MessageHost } from "../message-host";
|
|
3
3
|
import { DEFAULT_CHANNEL_NAME } from "./default-channel-name";
|
|
4
|
+
import { LISTEN, RESPONSE } from "../selectors";
|
|
4
5
|
export class BroadcastMessageHost extends MessageHost {
|
|
5
6
|
#requests$ = new Subject();
|
|
6
7
|
#channel;
|
|
@@ -8,9 +9,9 @@ export class BroadcastMessageHost extends MessageHost {
|
|
|
8
9
|
super();
|
|
9
10
|
this.#channel = new BroadcastChannel(channelName);
|
|
10
11
|
this.#channel.addEventListener('message', this.#handler);
|
|
11
|
-
this
|
|
12
|
+
this[LISTEN](this.#requests$);
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
+
[RESPONSE](message) {
|
|
14
15
|
this.#channel.postMessage(message);
|
|
15
16
|
}
|
|
16
17
|
terminate() {
|
|
@@ -1 +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;
|
|
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;AAC9D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAMhD,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,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAES,CAAC,QAAQ,CAAC,CAAC,OAAwB;QAC3C,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\";\nimport { LISTEN, RESPONSE } from \"../selectors\";\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}\n"]}
|
package/chrome/message-host.cjs
CHANGED
|
@@ -4,6 +4,7 @@ exports.ChromeMessageHost = void 0;
|
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const message_host_1 = require("../message-host");
|
|
6
6
|
const default_connection_name_1 = require("./default-connection-name");
|
|
7
|
+
const selectors_1 = require("../selectors");
|
|
7
8
|
class ChromeMessageHost extends message_host_1.MessageHost {
|
|
8
9
|
static PORT_IDENTIFIER = 'portIdentifier';
|
|
9
10
|
#ports = {};
|
|
@@ -19,7 +20,7 @@ class ChromeMessageHost extends message_host_1.MessageHost {
|
|
|
19
20
|
this.#ports[incomingMessagePort.sender.tab.id] = incomingMessagePort;
|
|
20
21
|
incomingMessagePort.onDisconnect.addListener(disconnectedPort => {
|
|
21
22
|
delete this.#ports[disconnectedPort.sender.tab.id];
|
|
22
|
-
this.
|
|
23
|
+
this[selectors_1.TERMINATE_MESSAGE$].next(message.id);
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
26
|
const newMessage = {
|
|
@@ -29,9 +30,9 @@ class ChromeMessageHost extends message_host_1.MessageHost {
|
|
|
29
30
|
this.#requests.next(newMessage);
|
|
30
31
|
});
|
|
31
32
|
});
|
|
32
|
-
this.
|
|
33
|
+
this[selectors_1.LISTEN](this.#requests);
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
[selectors_1.RESPONSE](message) {
|
|
35
36
|
const [messageId, portId] = message.id.split(`&${ChromeMessageHost.PORT_IDENTIFIER}=`);
|
|
36
37
|
message.id = messageId;
|
|
37
38
|
if (this.#ports[portId]) {
|
package/chrome/message-host.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { MessageHost } from '../message-host';
|
|
2
2
|
import { SuccessfulMessageResponse } from '../message-response.type';
|
|
3
|
+
import { RESPONSE } from '../selectors';
|
|
3
4
|
export declare class ChromeMessageHost extends MessageHost {
|
|
4
5
|
#private;
|
|
5
6
|
private static readonly PORT_IDENTIFIER;
|
|
6
7
|
constructor(name?: string);
|
|
7
|
-
protected
|
|
8
|
+
protected [RESPONSE](message: SuccessfulMessageResponse): void;
|
|
8
9
|
}
|
package/chrome/message-host.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Subject } from 'rxjs';
|
|
2
2
|
import { MessageHost } from '../message-host';
|
|
3
3
|
import { DEFAULT_CONNECTION_NAME } from './default-connection-name';
|
|
4
|
+
import { LISTEN, RESPONSE, TERMINATE_MESSAGE$ } from '../selectors';
|
|
4
5
|
export class ChromeMessageHost extends MessageHost {
|
|
5
6
|
static PORT_IDENTIFIER = 'portIdentifier';
|
|
6
7
|
#ports = {};
|
|
@@ -16,7 +17,7 @@ export class ChromeMessageHost extends MessageHost {
|
|
|
16
17
|
this.#ports[incomingMessagePort.sender.tab.id] = incomingMessagePort;
|
|
17
18
|
incomingMessagePort.onDisconnect.addListener(disconnectedPort => {
|
|
18
19
|
delete this.#ports[disconnectedPort.sender.tab.id];
|
|
19
|
-
this.
|
|
20
|
+
this[TERMINATE_MESSAGE$].next(message.id);
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
const newMessage = {
|
|
@@ -26,9 +27,9 @@ export class ChromeMessageHost extends MessageHost {
|
|
|
26
27
|
this.#requests.next(newMessage);
|
|
27
28
|
});
|
|
28
29
|
});
|
|
29
|
-
this
|
|
30
|
+
this[LISTEN](this.#requests);
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
+
[RESPONSE](message) {
|
|
32
33
|
const [messageId, portId] = message.id.split(`&${ChromeMessageHost.PORT_IDENTIFIER}=`);
|
|
33
34
|
message.id = messageId;
|
|
34
35
|
if (this.#ports[portId]) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../libs/hermes/src/chrome/message-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IACxC,MAAM,CAAU,eAAe,GAAG,gBAAgB,CAAC;IAE3D,MAAM,GAAyC,EAAE,CAAC;IAClD,SAAS,GAAG,IAAI,OAAO,EAAW,CAAC;IAEnC,YAAY,IAAI,GAAG,uBAAuB;QACxC,KAAK,EAAE,CAAC;QAER,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE;YAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBACvB,OAAO;YACT,CAAC;YAED,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,OAAgB,EAAE,mBAAwC,EAAE,EAAE;gBACxF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAO,CAAC,GAAI,CAAC,EAAG,CAAC,EAAE,CAAC;oBACvD,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAO,CAAC,GAAI,CAAC,EAAG,CAAC,GAAG,mBAAmB,CAAC;oBAExE,mBAAmB,CAAC,YAAY,CAAC,WAAW,CAAC,gBAAgB,CAAC,EAAE;wBAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAO,CAAC,GAAI,CAAC,EAAG,CAAC,CAAC;wBACtD,IAAI,CAAC,
|
|
1
|
+
{"version":3,"sources":["../../../../../libs/hermes/src/chrome/message-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IACxC,MAAM,CAAU,eAAe,GAAG,gBAAgB,CAAC;IAE3D,MAAM,GAAyC,EAAE,CAAC;IAClD,SAAS,GAAG,IAAI,OAAO,EAAW,CAAC;IAEnC,YAAY,IAAI,GAAG,uBAAuB;QACxC,KAAK,EAAE,CAAC;QAER,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE;YAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBACvB,OAAO;YACT,CAAC;YAED,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,OAAgB,EAAE,mBAAwC,EAAE,EAAE;gBACxF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAO,CAAC,GAAI,CAAC,EAAG,CAAC,EAAE,CAAC;oBACvD,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAO,CAAC,GAAI,CAAC,EAAG,CAAC,GAAG,mBAAmB,CAAC;oBAExE,mBAAmB,CAAC,YAAY,CAAC,WAAW,CAAC,gBAAgB,CAAC,EAAE;wBAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAO,CAAC,GAAI,CAAC,EAAG,CAAC,CAAC;wBACtD,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBAC5C,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,MAAM,UAAU,GAAG;oBACjB,GAAG,OAAO;oBACV,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,iBAAiB,CAAC,eAAe,IAAI,mBAAmB,CAAC,MAAO,CAAC,GAAI,CAAC,EAAG,EAAE;iBACjG,CAAC;gBAEF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAES,CAAC,QAAQ,CAAC,CAAC,OAAkC;QACrD,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,iBAAiB,CAAC,eAAe,GAAG,CAAC,CAAC;QAEvF,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC;QAEvB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC","file":"message-host.js","sourcesContent":["import { Subject } from 'rxjs';\n\nimport { MessageHost } from '../message-host';\nimport { SuccessfulMessageResponse } from '../message-response.type';\nimport { Message } from '../message.interface';\nimport { DEFAULT_CONNECTION_NAME } from './default-connection-name';\nimport { LISTEN, RESPONSE, TERMINATE_MESSAGE$ } from '../selectors';\n\nexport class ChromeMessageHost extends MessageHost {\n private static readonly PORT_IDENTIFIER = 'portIdentifier';\n\n #ports: {[key: string]: chrome.runtime.Port} = {};\n #requests = new Subject<Message>();\n\n constructor(name = DEFAULT_CONNECTION_NAME) {\n super();\n\n chrome.runtime.onConnect.addListener((port) => {\n if (port.name !== name) {\n return;\n }\n\n port.onMessage.addListener((message: Message, incomingMessagePort: chrome.runtime.Port) => {\n if (!this.#ports[incomingMessagePort.sender!.tab!.id!]) {\n this.#ports[incomingMessagePort.sender!.tab!.id!] = incomingMessagePort;\n\n incomingMessagePort.onDisconnect.addListener(disconnectedPort => {\n delete this.#ports[disconnectedPort.sender!.tab!.id!];\n this[TERMINATE_MESSAGE$].next(message.id);\n });\n }\n\n const newMessage = {\n ...message,\n id: `${message.id}&${ChromeMessageHost.PORT_IDENTIFIER}=${incomingMessagePort.sender!.tab!.id!}`,\n };\n\n this.#requests.next(newMessage);\n });\n });\n\n this[LISTEN](this.#requests);\n }\n\n protected [RESPONSE](message: SuccessfulMessageResponse): void {\n const [messageId, portId] = message.id.split(`&${ChromeMessageHost.PORT_IDENTIFIER}=`);\n\n message.id = messageId;\n\n if (this.#ports[portId]) {\n this.#ports[portId].postMessage(message);\n }\n }\n}\n"]}
|
package/iframe/message-host.cjs
CHANGED
|
@@ -7,6 +7,7 @@ const message_host_1 = require("../message-host");
|
|
|
7
7
|
const channel_path_splitter_1 = require("./channel-path-splitter");
|
|
8
8
|
const default_channel_name_1 = require("./default-channel-name");
|
|
9
9
|
const source_id_splitter_1 = require("./source-id-splitter");
|
|
10
|
+
const selectors_1 = require("../selectors");
|
|
10
11
|
class IframeMessageHost extends message_host_1.MessageHost {
|
|
11
12
|
channelName;
|
|
12
13
|
#requests = new rxjs_1.Subject();
|
|
@@ -22,12 +23,12 @@ class IframeMessageHost extends message_host_1.MessageHost {
|
|
|
22
23
|
this.channelName = channelName;
|
|
23
24
|
this.#_targetFrame = targetFrame;
|
|
24
25
|
window.addEventListener('message', this.#handler);
|
|
25
|
-
this.
|
|
26
|
+
this[selectors_1.LISTEN](this.#requests);
|
|
26
27
|
}
|
|
27
28
|
terminate() {
|
|
28
29
|
window.removeEventListener('message', this.#handler);
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
+
[selectors_1.RESPONSE](message) {
|
|
31
32
|
const [sourceId, messageId] = message.id.split(source_id_splitter_1.SOURCE_ID_SPLITTER);
|
|
32
33
|
const [, source] = this.#sources.find(([sId]) => sId === sourceId);
|
|
33
34
|
message = {
|
package/iframe/message-host.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { MessageHost } from '../message-host';
|
|
2
2
|
import { SuccessfulMessageResponse } from '../message-response.type';
|
|
3
3
|
import { IFrame } from './iframe.type';
|
|
4
|
+
import { RESPONSE } from '../selectors';
|
|
4
5
|
export declare class IframeMessageHost extends MessageHost {
|
|
5
6
|
#private;
|
|
6
7
|
private channelName;
|
|
7
8
|
constructor(channelName?: string, targetFrame?: IFrame);
|
|
8
9
|
terminate(): void;
|
|
9
|
-
protected
|
|
10
|
+
protected [RESPONSE](message: SuccessfulMessageResponse): void;
|
|
10
11
|
}
|
package/iframe/message-host.js
CHANGED
|
@@ -4,6 +4,7 @@ import { MessageHost } from '../message-host';
|
|
|
4
4
|
import { CHANNEL_PATH_SPLITTER } from './channel-path-splitter';
|
|
5
5
|
import { DEFAULT_CHANNEL_NAME } from './default-channel-name';
|
|
6
6
|
import { SOURCE_ID_SPLITTER } from './source-id-splitter';
|
|
7
|
+
import { LISTEN, RESPONSE } from '../selectors';
|
|
7
8
|
export class IframeMessageHost extends MessageHost {
|
|
8
9
|
channelName;
|
|
9
10
|
#requests = new Subject();
|
|
@@ -19,12 +20,12 @@ export class IframeMessageHost extends MessageHost {
|
|
|
19
20
|
this.channelName = channelName;
|
|
20
21
|
this.#_targetFrame = targetFrame;
|
|
21
22
|
window.addEventListener('message', this.#handler);
|
|
22
|
-
this
|
|
23
|
+
this[LISTEN](this.#requests);
|
|
23
24
|
}
|
|
24
25
|
terminate() {
|
|
25
26
|
window.removeEventListener('message', this.#handler);
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
+
[RESPONSE](message) {
|
|
28
29
|
const [sourceId, messageId] = message.id.split(SOURCE_ID_SPLITTER);
|
|
29
30
|
const [, source] = this.#sources.find(([sId]) => sId === sourceId);
|
|
30
31
|
message = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../libs/hermes/src/iframe/message-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"sources":["../../../../../libs/hermes/src/iframe/message-host.ts"],"names":[],"mappings":"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","file":"message-host.js","sourcesContent":["import { uniqueId } from '@thalesrc/js-utils';\nimport { Subject } from 'rxjs';\nimport { MessageHost } from '../message-host';\nimport { SuccessfulMessageResponse } from '../message-response.type';\nimport { Message } from '../message.interface';\nimport { CHANNEL_PATH_SPLITTER } from './channel-path-splitter';\nimport { DEFAULT_CHANNEL_NAME } from './default-channel-name';\nimport { SOURCE_ID_SPLITTER } from './source-id-splitter';\nimport { IFrame } from './iframe.type';\nimport { LISTEN, RESPONSE } from '../selectors';\n\nexport class IframeMessageHost extends MessageHost {\n #requests = new Subject<Message>();\n #sources: Array<[string, MessageEventSource]> = [];\n #_targetFrame: IFrame | undefined;\n\n get #targetFrame(): null | HTMLIFrameElement {\n return typeof this.#_targetFrame === 'function'\n ? (this.#_targetFrame as () => HTMLIFrameElement)() || null\n : this.#_targetFrame as HTMLIFrameElement || null;\n }\n\n constructor(\n private channelName = DEFAULT_CHANNEL_NAME,\n targetFrame?: IFrame\n ) {\n super();\n\n this.#_targetFrame = targetFrame;\n\n window.addEventListener('message', this.#handler);\n\n this[LISTEN](this.#requests);\n }\n\n public terminate(): void {\n window.removeEventListener('message', this.#handler);\n }\n\n protected [RESPONSE](message: SuccessfulMessageResponse): void {\n const [sourceId, messageId] = message.id.split(SOURCE_ID_SPLITTER);\n const [, source] = this.#sources.find(([sId]) => sId === sourceId)!;\n\n message = {\n ...message,\n id: messageId,\n };\n\n (source as any).postMessage(message);\n }\n\n #handler = ({data, source}: MessageEvent<Message>) => {\n if (!data || typeof data !== 'object' || !data.path || typeof data.id === 'undefined') {\n return;\n }\n\n const targetFrame = this.#targetFrame;\n\n if (targetFrame && targetFrame.contentWindow !== source) {\n return;\n }\n\n const [channel, path] = data.path.split(CHANNEL_PATH_SPLITTER);\n\n if (channel !== this.channelName) {\n return;\n }\n\n if (!this.#sources.some(([, s]) => s === source)) {\n this.#sources.push([uniqueId('hermes-iframe-source') as string, source!]);\n }\n\n const [sourceId] = this.#sources.find(([, s]) => s === source)!;\n this.#requests.next({\n body: targetFrame ? data.body : {data: data.body, sender: source},\n id: `${sourceId}${SOURCE_ID_SPLITTER}${data.id}`,\n path,\n });\n }\n}\n"]}
|
package/message-host.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MessageHost = void 0;
|
|
4
|
-
const js_utils_1 = require("@thalesrc/js-utils");
|
|
5
4
|
const rxjs_1 = require("rxjs");
|
|
6
5
|
const operators_1 = require("rxjs/operators");
|
|
7
6
|
const selectors_1 = require("./selectors");
|
|
@@ -14,20 +13,26 @@ class MessageHost {
|
|
|
14
13
|
*
|
|
15
14
|
* Use `next(messageId)` method to terminate a message connection
|
|
16
15
|
*/
|
|
17
|
-
|
|
16
|
+
[selectors_1.TERMINATE_MESSAGE$] = new rxjs_1.Subject();
|
|
18
17
|
/**
|
|
19
18
|
* Run this method to start listening the requests
|
|
20
19
|
*/
|
|
21
|
-
|
|
20
|
+
[selectors_1.LISTEN] = (messages$) => {
|
|
22
21
|
for (const [path, listeners] of this.#getListeners()) {
|
|
23
22
|
messages$
|
|
24
23
|
.pipe((0, operators_1.filter)(({ path: messagePath }) => path === messagePath))
|
|
25
24
|
.subscribe(({ body, id }) => {
|
|
26
25
|
for (const listener of listeners) {
|
|
27
|
-
listener.call(this, body).pipe((0, operators_1.takeUntil)(this.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
listener.call(this, body).pipe((0, operators_1.takeUntil)(this[selectors_1.TERMINATE_MESSAGE$].pipe((0, operators_1.filter)(terminatedMessageId => terminatedMessageId === id)))).subscribe({
|
|
27
|
+
next: result => {
|
|
28
|
+
this[selectors_1.RESPONSE]({ completed: false, id, body: result });
|
|
29
|
+
},
|
|
30
|
+
error: error => {
|
|
31
|
+
this[selectors_1.RESPONSE]({ completed: true, id, error });
|
|
32
|
+
},
|
|
33
|
+
complete: () => {
|
|
34
|
+
this[selectors_1.RESPONSE]({ completed: true, id });
|
|
35
|
+
}
|
|
31
36
|
});
|
|
32
37
|
}
|
|
33
38
|
});
|
package/message-host.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Observable, Subject } from 'rxjs';
|
|
2
2
|
import { SuccessfulMessageResponse } from './message-response.type';
|
|
3
3
|
import { Message } from './message.interface';
|
|
4
|
+
import { LISTEN, RESPONSE, TERMINATE_MESSAGE$ } from './selectors';
|
|
4
5
|
/**
|
|
5
6
|
* Message Host
|
|
6
7
|
*/
|
|
@@ -11,15 +12,15 @@ export declare abstract class MessageHost {
|
|
|
11
12
|
*
|
|
12
13
|
* Use `next(messageId)` method to terminate a message connection
|
|
13
14
|
*/
|
|
14
|
-
protected readonly
|
|
15
|
+
protected readonly [TERMINATE_MESSAGE$]: Subject<string>;
|
|
15
16
|
/**
|
|
16
17
|
* Run this method to start listening the requests
|
|
17
18
|
*/
|
|
18
|
-
protected readonly
|
|
19
|
+
protected readonly [LISTEN]: (messages$: Observable<Message>) => void;
|
|
19
20
|
/**
|
|
20
21
|
* Build a reponse method to send the responses to the requests by using the communication methods of the platform
|
|
21
22
|
*
|
|
22
23
|
* @param message Incoming response message
|
|
23
24
|
*/
|
|
24
|
-
protected abstract
|
|
25
|
+
protected abstract [RESPONSE]<T = any>(message: SuccessfulMessageResponse<T>): void;
|
|
25
26
|
}
|
package/message-host.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { noop } from '@thalesrc/js-utils';
|
|
2
1
|
import { Subject } from 'rxjs';
|
|
3
2
|
import { filter, takeUntil } from 'rxjs/operators';
|
|
4
|
-
import { MESSAGE_LISTENERS } from './selectors';
|
|
3
|
+
import { LISTEN, MESSAGE_LISTENERS, RESPONSE, TERMINATE_MESSAGE$ } from './selectors';
|
|
5
4
|
/**
|
|
6
5
|
* Message Host
|
|
7
6
|
*/
|
|
@@ -11,20 +10,26 @@ export class MessageHost {
|
|
|
11
10
|
*
|
|
12
11
|
* Use `next(messageId)` method to terminate a message connection
|
|
13
12
|
*/
|
|
14
|
-
|
|
13
|
+
[TERMINATE_MESSAGE$] = new Subject();
|
|
15
14
|
/**
|
|
16
15
|
* Run this method to start listening the requests
|
|
17
16
|
*/
|
|
18
|
-
|
|
17
|
+
[LISTEN] = (messages$) => {
|
|
19
18
|
for (const [path, listeners] of this.#getListeners()) {
|
|
20
19
|
messages$
|
|
21
20
|
.pipe(filter(({ path: messagePath }) => path === messagePath))
|
|
22
21
|
.subscribe(({ body, id }) => {
|
|
23
22
|
for (const listener of listeners) {
|
|
24
|
-
listener.call(this, body).pipe(takeUntil(this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
listener.call(this, body).pipe(takeUntil(this[TERMINATE_MESSAGE$].pipe(filter(terminatedMessageId => terminatedMessageId === id)))).subscribe({
|
|
24
|
+
next: result => {
|
|
25
|
+
this[RESPONSE]({ completed: false, id, body: result });
|
|
26
|
+
},
|
|
27
|
+
error: error => {
|
|
28
|
+
this[RESPONSE]({ completed: true, id, error });
|
|
29
|
+
},
|
|
30
|
+
complete: () => {
|
|
31
|
+
this[RESPONSE]({ completed: true, id });
|
|
32
|
+
}
|
|
28
33
|
});
|
|
29
34
|
}
|
|
30
35
|
});
|
package/message-host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../libs/hermes/src/message-host.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"sources":["../../../../../libs/hermes/src/message-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,OAAO,EAAE,MAAM,MAAM,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAKnD,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtF;;GAEG;AACH,MAAM,OAAgB,WAAW;IAC/B;;;;OAIG;IACgB,CAAC,kBAAkB,CAAC,GAAG,IAAI,OAAO,EAAU,CAAC;IAEhE;;OAEG;IACgB,CAAC,MAAM,CAAC,GAAG,CAAC,SAA8B,EAAQ,EAAE;QACrE,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;YACrD,SAAS;iBACN,IAAI,CAAC,MAAM,CAAC,CAAC,EAAC,IAAI,EAAE,WAAW,EAAC,EAAE,EAAE,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;iBAC3D,SAAS,CAAC,CAAC,EAAC,IAAI,EAAE,EAAE,EAAC,EAAE,EAAE;gBACxB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;oBAChC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAqB,CAAC,IAAI,CACjD,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC,mBAAmB,KAAK,EAAE,CAAC,CAAC,CAAC,CACpG,CAAC,SAAS,CAAC;wBACV,IAAI,EAAE,MAAM,CAAC,EAAE;4BACb,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAC,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;wBACvD,CAAC;wBACD,KAAK,EAAE,KAAK,CAAC,EAAE;4BACb,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAC,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAC,CAAC,CAAC;wBAC/C,CAAC;wBACD,QAAQ,EAAE,GAAG,EAAE;4BACb,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAC,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;wBACzC,CAAC;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;QACP,CAAC;IACH,CAAC,CAAA;IASD;;OAEG;IACH,aAAa;QACX,MAAM,GAAG,GAAoB,IAAI,GAAG,EAAE,CAAC;QAEvC,IAAI,YAAY,GAAI,IAAY,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;QAEnD,OAAO,YAAY,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC;YAC3C,IAAI,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBAC1E,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,YAAY,CAAC,WAAW,CAAC,iBAAiB,CAAoB,EAAE,CAAC;oBAC7F,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;YAED,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC;QACxC,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;CACF","file":"message-host.js","sourcesContent":["import { Observable, Subject } from 'rxjs';\nimport { filter, takeUntil } from 'rxjs/operators';\n\nimport { ListenerStorage } from './listener-storage.type';\nimport { SuccessfulMessageResponse } from './message-response.type';\nimport { Message } from './message.interface';\nimport { LISTEN, MESSAGE_LISTENERS, RESPONSE, TERMINATE_MESSAGE$ } from './selectors';\n\n/**\n * Message Host\n */\nexport abstract class MessageHost {\n /**\n * Message Terminator Subject\n *\n * Use `next(messageId)` method to terminate a message connection\n */\n protected readonly [TERMINATE_MESSAGE$] = new Subject<string>();\n\n /**\n * Run this method to start listening the requests\n */\n protected readonly [LISTEN] = (messages$: Observable<Message>): void => {\n for (const [path, listeners] of this.#getListeners()) {\n messages$\n .pipe(filter(({path: messagePath}) => path === messagePath))\n .subscribe(({body, id}) => {\n for (const listener of listeners) {\n (listener.call(this, body) as Observable<any>).pipe(\n takeUntil(this[TERMINATE_MESSAGE$].pipe(filter(terminatedMessageId => terminatedMessageId === id))),\n ).subscribe({\n next: result => {\n this[RESPONSE]({completed: false, id, body: result});\n },\n error: error => {\n this[RESPONSE]({completed: true, id, error});\n },\n complete: () => {\n this[RESPONSE]({completed: true, id });\n }\n });\n }\n });\n }\n }\n\n /**\n * Build a reponse method to send the responses to the requests by using the communication methods of the platform\n *\n * @param message Incoming response message\n */\n protected abstract [RESPONSE]<T = any>(message: SuccessfulMessageResponse<T>): void;\n\n /**\n * All inherited listeners\n */\n #getListeners(): ListenerStorage {\n const map: ListenerStorage = new Map();\n\n let currentProto = (this as any)['__proto__' + ''];\n\n while (currentProto.constructor !== Object) {\n if (Reflect.ownKeys(currentProto.constructor).includes(MESSAGE_LISTENERS)) {\n for (const [key, handlers] of currentProto.constructor[MESSAGE_LISTENERS] as ListenerStorage) {\n map.set(key, [...(map.get(key) || []), ...handlers]);\n }\n }\n\n currentProto = currentProto.__proto__;\n }\n\n return map;\n }\n}\n"]}
|
package/message.interface.d.ts
CHANGED
package/message.interface.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../libs/hermes/src/message.interface.ts"],"names":[],"mappings":"","file":"message.interface.js","sourcesContent":["export interface Message<T = any> {\n path: string;\n body: T;\n id: string;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../libs/hermes/src/message.interface.ts"],"names":[],"mappings":"","file":"message.interface.js","sourcesContent":["export interface Message<T = any> {\n path: string;\n body: T;\n id: string;\n error?: any;\n}\n"]}
|
package/package.json
CHANGED
package/selectors.cjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.RESPONSE = exports.TERMINATE_MESSAGE$ = exports.LISTEN = exports.GET_NEW_ID = exports.SEND = exports.RESPONSES$ = exports.MESSAGE_LISTENERS = void 0;
|
|
4
4
|
exports.MESSAGE_LISTENERS = Symbol('Message Listeners');
|
|
5
|
-
exports.SENDING_SERVICE = Symbol('Sending Service');
|
|
6
5
|
exports.RESPONSES$ = Symbol('Responses');
|
|
7
6
|
exports.SEND = Symbol('Send');
|
|
8
7
|
exports.GET_NEW_ID = Symbol('Get New Id');
|
|
8
|
+
exports.LISTEN = Symbol('Listen');
|
|
9
|
+
exports.TERMINATE_MESSAGE$ = Symbol('Terminate Message');
|
|
10
|
+
exports.RESPONSE = Symbol('Response');
|
package/selectors.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare const MESSAGE_LISTENERS: unique symbol;
|
|
2
|
-
export declare const SENDING_SERVICE: unique symbol;
|
|
3
2
|
export declare const RESPONSES$: unique symbol;
|
|
4
3
|
export declare const SEND: unique symbol;
|
|
5
4
|
export declare const GET_NEW_ID: unique symbol;
|
|
5
|
+
export declare const LISTEN: unique symbol;
|
|
6
|
+
export declare const TERMINATE_MESSAGE$: unique symbol;
|
|
7
|
+
export declare const RESPONSE: unique symbol;
|
package/selectors.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export const MESSAGE_LISTENERS = Symbol('Message Listeners');
|
|
2
|
-
export const SENDING_SERVICE = Symbol('Sending Service');
|
|
3
2
|
export const RESPONSES$ = Symbol('Responses');
|
|
4
3
|
export const SEND = Symbol('Send');
|
|
5
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');
|
|
6
8
|
|
|
7
9
|
//# sourceMappingURL=selectors.js.map
|
package/selectors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../libs/hermes/src/selectors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAC7D,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"sources":["../../../../../libs/hermes/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"]}
|
|
@@ -23,6 +23,9 @@ const selectors_1 = require("../selectors");
|
|
|
23
23
|
* - Function that returns a Worker (for lazy initialization)
|
|
24
24
|
* - Function that returns a Promise<Worker> (for async lazy initialization)
|
|
25
25
|
*
|
|
26
|
+
* The `initialize()` method allows dynamic worker management, enabling you to switch
|
|
27
|
+
* workers at runtime or re-establish connections after errors.
|
|
28
|
+
*
|
|
26
29
|
* @example
|
|
27
30
|
* // In main thread - communicate with a specific worker
|
|
28
31
|
* const worker = new Worker('./worker.js');
|
|
@@ -42,13 +45,19 @@ const selectors_1 = require("../selectors");
|
|
|
42
45
|
* const client = new WorkerMessageClient(() =>
|
|
43
46
|
* document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
|
|
44
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'));
|
|
45
54
|
*/
|
|
46
55
|
class WorkerMessageClient extends message_client_1.MessageClient {
|
|
47
56
|
/**
|
|
48
57
|
* Promise resolving to the Worker instance or undefined if running in worker context
|
|
49
58
|
* @private
|
|
50
59
|
*/
|
|
51
|
-
#worker =
|
|
60
|
+
#worker = Promise.resolve(undefined);
|
|
52
61
|
/**
|
|
53
62
|
* Unique identifier for this client instance to prevent ID collisions
|
|
54
63
|
* @private
|
|
@@ -70,6 +79,46 @@ class WorkerMessageClient extends message_client_1.MessageClient {
|
|
|
70
79
|
*/
|
|
71
80
|
constructor(worker) {
|
|
72
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
|
+
// Deinitialize previous worker if any
|
|
114
|
+
this.#worker.then(prevWorker => {
|
|
115
|
+
if (prevWorker) {
|
|
116
|
+
prevWorker.removeEventListener('message', this.#handler);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
removeEventListener('message', this.#handler);
|
|
120
|
+
}
|
|
121
|
+
}).catch(noop_1.noop);
|
|
73
122
|
// Resolve worker parameter: execute function if provided, otherwise use value directly
|
|
74
123
|
const _worker = typeof worker === 'function' ? worker() : worker;
|
|
75
124
|
// Ensure worker is wrapped in a promise for consistent async handling
|
|
@@ -3,6 +3,10 @@ import { MessageClient } from "../message-client";
|
|
|
3
3
|
import { MessageResponse } from "../message-response.type";
|
|
4
4
|
import { Message } from "../message.interface";
|
|
5
5
|
import { GET_NEW_ID, RESPONSES$, SEND } from "../selectors";
|
|
6
|
+
type ClientWorkerType = Worker | undefined;
|
|
7
|
+
type ClientWorkerPromise = Promise<ClientWorkerType>;
|
|
8
|
+
type ClientWorkerFactory = () => ClientWorkerType | ClientWorkerPromise;
|
|
9
|
+
type ClientWorkerArg = ClientWorkerType | ClientWorkerPromise | ClientWorkerFactory;
|
|
6
10
|
/**
|
|
7
11
|
* WorkerMessageClient
|
|
8
12
|
*
|
|
@@ -19,6 +23,9 @@ import { GET_NEW_ID, RESPONSES$, SEND } from "../selectors";
|
|
|
19
23
|
* - Function that returns a Worker (for lazy initialization)
|
|
20
24
|
* - Function that returns a Promise<Worker> (for async lazy initialization)
|
|
21
25
|
*
|
|
26
|
+
* The `initialize()` method allows dynamic worker management, enabling you to switch
|
|
27
|
+
* workers at runtime or re-establish connections after errors.
|
|
28
|
+
*
|
|
22
29
|
* @example
|
|
23
30
|
* // In main thread - communicate with a specific worker
|
|
24
31
|
* const worker = new Worker('./worker.js');
|
|
@@ -38,6 +45,12 @@ import { GET_NEW_ID, RESPONSES$, SEND } from "../selectors";
|
|
|
38
45
|
* const client = new WorkerMessageClient(() =>
|
|
39
46
|
* document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
|
|
40
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'));
|
|
41
54
|
*/
|
|
42
55
|
export declare class WorkerMessageClient extends MessageClient {
|
|
43
56
|
#private;
|
|
@@ -55,7 +68,36 @@ export declare class WorkerMessageClient extends MessageClient {
|
|
|
55
68
|
* - () => Promise<Worker>: Function returning promise (async lazy initialization)
|
|
56
69
|
* - undefined: Omit for worker thread context (uses self)
|
|
57
70
|
*/
|
|
58
|
-
constructor(worker?:
|
|
71
|
+
constructor(worker?: ClientWorkerArg);
|
|
72
|
+
/**
|
|
73
|
+
* Initializes or re-initializes the worker connection.
|
|
74
|
+
*
|
|
75
|
+
* This method sets up message listeners for the provided worker. If a worker
|
|
76
|
+
* was previously initialized, it cleans up the old connection before establishing
|
|
77
|
+
* the new one. This allows for dynamic worker management, such as:
|
|
78
|
+
* - Switching between different workers at runtime
|
|
79
|
+
* - Re-establishing connections after worker errors
|
|
80
|
+
* - Lazy initialization when the worker is conditionally needed
|
|
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
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* // Switch to a different worker dynamically
|
|
91
|
+
* const client = new WorkerMessageClient(oldWorker);
|
|
92
|
+
* client.initialize(newWorker); // Cleans up old listener, sets up new one
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // Re-initialize after worker error
|
|
96
|
+
* worker.onerror = () => {
|
|
97
|
+
* client.initialize(new Worker('./worker.js'));
|
|
98
|
+
* };
|
|
99
|
+
*/
|
|
100
|
+
initialize(worker?: ClientWorkerArg): void;
|
|
59
101
|
/**
|
|
60
102
|
* Sends a message to the worker or main thread
|
|
61
103
|
*
|
|
@@ -72,3 +114,4 @@ export declare class WorkerMessageClient extends MessageClient {
|
|
|
72
114
|
*/
|
|
73
115
|
protected [GET_NEW_ID](): string;
|
|
74
116
|
}
|
|
117
|
+
export {};
|
package/worker/message-client.js
CHANGED
|
@@ -20,6 +20,9 @@ import { GET_NEW_ID, RESPONSES$, SEND } from "../selectors";
|
|
|
20
20
|
* - Function that returns a Worker (for lazy initialization)
|
|
21
21
|
* - Function that returns a Promise<Worker> (for async lazy initialization)
|
|
22
22
|
*
|
|
23
|
+
* The `initialize()` method allows dynamic worker management, enabling you to switch
|
|
24
|
+
* workers at runtime or re-establish connections after errors.
|
|
25
|
+
*
|
|
23
26
|
* @example
|
|
24
27
|
* // In main thread - communicate with a specific worker
|
|
25
28
|
* const worker = new Worker('./worker.js');
|
|
@@ -39,13 +42,19 @@ import { GET_NEW_ID, RESPONSES$, SEND } from "../selectors";
|
|
|
39
42
|
* const client = new WorkerMessageClient(() =>
|
|
40
43
|
* document.querySelector('[data-worker]') ? new Worker('./worker.js') : undefined
|
|
41
44
|
* );
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // Re-initialize with a different worker
|
|
48
|
+
* const client = new WorkerMessageClient();
|
|
49
|
+
* // Later, switch to a different worker
|
|
50
|
+
* client.initialize(new Worker('./different-worker.js'));
|
|
42
51
|
*/
|
|
43
52
|
export class WorkerMessageClient extends MessageClient {
|
|
44
53
|
/**
|
|
45
54
|
* Promise resolving to the Worker instance or undefined if running in worker context
|
|
46
55
|
* @private
|
|
47
56
|
*/
|
|
48
|
-
#worker =
|
|
57
|
+
#worker = Promise.resolve(undefined);
|
|
49
58
|
/**
|
|
50
59
|
* Unique identifier for this client instance to prevent ID collisions
|
|
51
60
|
* @private
|
|
@@ -67,6 +76,46 @@ export class WorkerMessageClient extends MessageClient {
|
|
|
67
76
|
*/
|
|
68
77
|
constructor(worker) {
|
|
69
78
|
super();
|
|
79
|
+
this.initialize(worker);
|
|
80
|
+
}
|
|
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) {
|
|
110
|
+
// Deinitialize previous worker if any
|
|
111
|
+
this.#worker.then(prevWorker => {
|
|
112
|
+
if (prevWorker) {
|
|
113
|
+
prevWorker.removeEventListener('message', this.#handler);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
removeEventListener('message', this.#handler);
|
|
117
|
+
}
|
|
118
|
+
}).catch(noop);
|
|
70
119
|
// Resolve worker parameter: execute function if provided, otherwise use value directly
|
|
71
120
|
const _worker = typeof worker === 'function' ? worker() : worker;
|
|
72
121
|
// Ensure worker is wrapped in a promise for consistent async handling
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../libs/hermes/src/worker/message-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,kCAAkC,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACjE,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;
|
|
1
|
+
{"version":3,"sources":["../../../../../libs/hermes/src/worker/message-client.ts"],"names":[],"mappings":"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","file":"message-client.js","sourcesContent":["import { uniqueId } from \"@thalesrc/js-utils/unique-id\";\nimport { noop } from \"@thalesrc/js-utils/function/noop\";\nimport { promisify } from '@thalesrc/js-utils/promise/promisify';\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\";\n\ntype ClientWorkerType = Worker | undefined;\ntype ClientWorkerPromise = Promise<ClientWorkerType>;\ntype ClientWorkerFactory = () => ClientWorkerType | ClientWorkerPromise;\ntype ClientWorkerArg = ClientWorkerType | ClientWorkerPromise | ClientWorkerFactory;\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 #worker: ClientWorkerPromise = Promise.resolve(undefined);\n\n /**\n * Unique identifier for this client instance to prevent ID collisions\n * @private\n */\n #instanceId = Date.now();\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 // Deinitialize previous worker if any\n this.#worker.then(prevWorker => {\n if (prevWorker) {\n prevWorker.removeEventListener('message', this.#handler);\n } else {\n removeEventListener('message', this.#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 this.#worker = promisify(_worker);\n\n // Set up message listener once worker is resolved\n this.#worker.then(worker => {\n if (worker) {\n // Main thread context: listen to specific worker\n worker.addEventListener('message', this.#handler);\n } else {\n // Worker thread context: listen to messages from main thread\n addEventListener('message', this.#handler);\n }\n }).catch(noop);\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 #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('hermes-worker-message-' + this.#instanceId) as string;\n }\n}\n"]}
|
package/worker/message-host.cjs
CHANGED
|
@@ -3,41 +3,39 @@ 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
|
|
7
|
-
const HANDLER = Symbol('Handler');
|
|
8
|
-
const WORKER = Symbol('Worker');
|
|
6
|
+
const selectors_1 = require("../selectors");
|
|
9
7
|
class WorkerMessageHost extends message_host_1.MessageHost {
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
#requests$ = new rxjs_1.Subject();
|
|
9
|
+
#worker;
|
|
12
10
|
constructor(worker) {
|
|
13
11
|
super();
|
|
14
12
|
if (worker) {
|
|
15
|
-
this
|
|
16
|
-
worker.addEventListener('message', this
|
|
13
|
+
this.#worker = worker;
|
|
14
|
+
worker.addEventListener('message', this.#handler);
|
|
17
15
|
}
|
|
18
16
|
else {
|
|
19
|
-
addEventListener('message', this
|
|
17
|
+
addEventListener('message', this.#handler);
|
|
20
18
|
}
|
|
21
|
-
this.
|
|
19
|
+
this[selectors_1.LISTEN](this.#requests$);
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
if (this
|
|
25
|
-
this
|
|
21
|
+
[selectors_1.RESPONSE](message) {
|
|
22
|
+
if (this.#worker) {
|
|
23
|
+
this.#worker.postMessage(message);
|
|
26
24
|
}
|
|
27
25
|
else {
|
|
28
26
|
postMessage(message);
|
|
29
27
|
}
|
|
30
28
|
}
|
|
31
29
|
terminate() {
|
|
32
|
-
if (this
|
|
33
|
-
this
|
|
30
|
+
if (this.#worker) {
|
|
31
|
+
this.#worker.removeEventListener('message', this.#handler);
|
|
34
32
|
}
|
|
35
33
|
else {
|
|
36
|
-
removeEventListener('message', this
|
|
34
|
+
removeEventListener('message', this.#handler);
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
|
-
|
|
40
|
-
this
|
|
37
|
+
#handler = (event) => {
|
|
38
|
+
this.#requests$.next(event.data);
|
|
41
39
|
};
|
|
42
40
|
}
|
|
43
41
|
exports.WorkerMessageHost = WorkerMessageHost;
|
package/worker/message-host.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { MessageHost } from "../message-host";
|
|
2
2
|
import { MessageResponse } from "../message-response.type";
|
|
3
|
-
|
|
4
|
-
declare const HANDLER: unique symbol;
|
|
5
|
-
declare const WORKER: unique symbol;
|
|
3
|
+
import { RESPONSE } from "../selectors";
|
|
6
4
|
export declare class WorkerMessageHost extends MessageHost {
|
|
7
|
-
private
|
|
8
|
-
private [WORKER];
|
|
5
|
+
#private;
|
|
9
6
|
constructor(worker?: Worker);
|
|
10
|
-
protected
|
|
7
|
+
protected [RESPONSE](message: MessageResponse): void;
|
|
11
8
|
terminate(): void;
|
|
12
|
-
private [HANDLER];
|
|
13
9
|
}
|
|
14
|
-
export {};
|
package/worker/message-host.js
CHANGED
|
@@ -1,40 +1,38 @@
|
|
|
1
1
|
import { Subject } from "rxjs";
|
|
2
2
|
import { MessageHost } from "../message-host";
|
|
3
|
-
|
|
4
|
-
const HANDLER = Symbol('Handler');
|
|
5
|
-
const WORKER = Symbol('Worker');
|
|
3
|
+
import { LISTEN, RESPONSE } from "../selectors";
|
|
6
4
|
export class WorkerMessageHost extends MessageHost {
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
#requests$ = new Subject();
|
|
6
|
+
#worker;
|
|
9
7
|
constructor(worker) {
|
|
10
8
|
super();
|
|
11
9
|
if (worker) {
|
|
12
|
-
this
|
|
13
|
-
worker.addEventListener('message', this
|
|
10
|
+
this.#worker = worker;
|
|
11
|
+
worker.addEventListener('message', this.#handler);
|
|
14
12
|
}
|
|
15
13
|
else {
|
|
16
|
-
addEventListener('message', this
|
|
14
|
+
addEventListener('message', this.#handler);
|
|
17
15
|
}
|
|
18
|
-
this
|
|
16
|
+
this[LISTEN](this.#requests$);
|
|
19
17
|
}
|
|
20
|
-
|
|
21
|
-
if (this
|
|
22
|
-
this
|
|
18
|
+
[RESPONSE](message) {
|
|
19
|
+
if (this.#worker) {
|
|
20
|
+
this.#worker.postMessage(message);
|
|
23
21
|
}
|
|
24
22
|
else {
|
|
25
23
|
postMessage(message);
|
|
26
24
|
}
|
|
27
25
|
}
|
|
28
26
|
terminate() {
|
|
29
|
-
if (this
|
|
30
|
-
this
|
|
27
|
+
if (this.#worker) {
|
|
28
|
+
this.#worker.removeEventListener('message', this.#handler);
|
|
31
29
|
}
|
|
32
30
|
else {
|
|
33
|
-
removeEventListener('message', this
|
|
31
|
+
removeEventListener('message', this.#handler);
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
this
|
|
34
|
+
#handler = (event) => {
|
|
35
|
+
this.#requests$.next(event.data);
|
|
38
36
|
};
|
|
39
37
|
}
|
|
40
38
|
|
|
@@ -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;
|
|
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;AAMhD,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAChD,UAAU,GAAG,IAAI,OAAO,EAAW,CAAC;IACpC,OAAO,CAAqB;IAE5B,YAAY,MAAe;QACzB,KAAK,EAAE,CAAC;QAER,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;YACtB,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAES,CAAC,QAAQ,CAAC,CAAC,OAAwB;QAC3C,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,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,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC;IACH,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 { LISTEN, RESPONSE } from \"../selectors\";\n\ninterface MessageEvent<T> {\n data: T;\n}\n\nexport class WorkerMessageHost extends MessageHost {\n #requests$ = new Subject<Message>();\n #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 #handler = (event: MessageEvent<Message>) => {\n this.#requests$.next(event.data);\n }\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WorkerMessageClient } from "./message-client";
|
|
2
|
-
declare const WorkerMessageService_base: new (args_0: [worker?: Worker | undefined], args_1: [worker?: Worker | Promise<Worker | undefined> | (() => Worker | undefined) |
|
|
2
|
+
declare const WorkerMessageService_base: new (args_0: [worker?: Worker | undefined], args_1: [worker?: (Worker | undefined) | Promise<Worker | undefined> | (() => (Worker | undefined) | Promise<Worker | undefined>)]) => {
|
|
3
3
|
terminate: () => void;
|
|
4
4
|
} & WorkerMessageClient;
|
|
5
5
|
export declare class WorkerMessageService extends WorkerMessageService_base {
|