@mtcute/web 0.28.2 → 0.29.0
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 +6 -4
- package/package.json +5 -4
- package/worker.cjs +75 -60
- package/worker.js +75 -60
- package/worker.shared.fixture.d.cts +1 -0
- package/worker.shared.fixture.d.ts +1 -0
- package/worker.test.d.cts +1 -0
- package/worker.test.d.ts +1 -0
package/README.md
CHANGED
|
@@ -31,16 +31,16 @@ You can also use this package with web workers to offload most of the heavy lift
|
|
|
31
31
|
// worker.ts
|
|
32
32
|
import { BaseTelegramClient, TelegramWorker } from '@mtcute/web'
|
|
33
33
|
|
|
34
|
-
// main.ts
|
|
35
|
-
import { TelegramClient, TelegramWorkerPort } from '@mtcute/web'
|
|
36
|
-
|
|
37
34
|
const client = new BaseTelegramClient({
|
|
38
35
|
apiId: 12345,
|
|
39
36
|
apiHash: 'abcdef',
|
|
40
37
|
storage: 'my-account'
|
|
41
38
|
})
|
|
42
39
|
|
|
43
|
-
new TelegramWorker({ client })
|
|
40
|
+
new TelegramWorker({ client }).mount()
|
|
41
|
+
|
|
42
|
+
// main.ts
|
|
43
|
+
import { TelegramClient, TelegramWorkerPort } from '@mtcute/web'
|
|
44
44
|
|
|
45
45
|
const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' }) // or SharedWorker
|
|
46
46
|
const port = new TelegramWorkerPort({ worker })
|
|
@@ -49,3 +49,5 @@ const tg = new TelegramClient({ client: port })
|
|
|
49
49
|
const self = await tg.start()
|
|
50
50
|
console.log(`✨ logged in as ${user.displayName}`)
|
|
51
51
|
```
|
|
52
|
+
|
|
53
|
+
`port.destroy()` only releases that port. Use `port.unsafeForceDestroy()` if you need to tear down the shared worker-side client.
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mtcute/web",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.29.0",
|
|
5
5
|
"description": "Meta-package for the web platform",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@mtcute/core": "^0.
|
|
9
|
-
"@mtcute/wasm": "^0.
|
|
10
|
-
"@fuman/net": "0.0.19"
|
|
8
|
+
"@mtcute/core": "^0.29.0",
|
|
9
|
+
"@mtcute/wasm": "^0.29.0",
|
|
10
|
+
"@fuman/net": "0.0.19",
|
|
11
|
+
"@fuman/utils": "0.0.19"
|
|
11
12
|
},
|
|
12
13
|
"exports": {
|
|
13
14
|
".": {
|
package/worker.cjs
CHANGED
|
@@ -5,57 +5,86 @@ if (typeof globalThis !== "undefined" && !globalThis._MTCUTE_CJS_DEPRECATION_WAR
|
|
|
5
5
|
}
|
|
6
6
|
"use strict";
|
|
7
7
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
8
|
+
const utils = require("@fuman/utils");
|
|
8
9
|
const worker_js = require("@mtcute/core/worker.js");
|
|
9
10
|
const platform$1 = require("./platform.cjs");
|
|
10
11
|
let _broadcast;
|
|
11
12
|
const _sharedHandlers = /* @__PURE__ */ new Set();
|
|
13
|
+
function isWorkerInboundMessage(message) {
|
|
14
|
+
if (!message || typeof message !== "object") return false;
|
|
15
|
+
const data = message;
|
|
16
|
+
if (typeof data._mtcuteWorkerId !== "string") return false;
|
|
17
|
+
if (typeof data.connectionId !== "string") return false;
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
function setupSharedWorker() {
|
|
21
|
+
if (_broadcast) return _broadcast;
|
|
22
|
+
utils.unsafeCastType(self);
|
|
23
|
+
const ports = /* @__PURE__ */ new Map();
|
|
24
|
+
const knownConnectionIds = /* @__PURE__ */ new WeakMap();
|
|
25
|
+
const addConnection = (port, connectionId) => {
|
|
26
|
+
ports.set(connectionId, port);
|
|
27
|
+
const known = knownConnectionIds.get(port);
|
|
28
|
+
if (known) {
|
|
29
|
+
known.add(connectionId);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
knownConnectionIds.set(port, /* @__PURE__ */ new Set([connectionId]));
|
|
33
|
+
};
|
|
34
|
+
const cleanupConnection = (port, connectionId) => {
|
|
35
|
+
ports.delete(connectionId);
|
|
36
|
+
const known = knownConnectionIds.get(port);
|
|
37
|
+
if (!known) return;
|
|
38
|
+
known.delete(connectionId);
|
|
39
|
+
if (!known.size) {
|
|
40
|
+
knownConnectionIds.delete(port);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const broadcast = (message) => {
|
|
44
|
+
if ("connectionId" in message) {
|
|
45
|
+
const port = ports.get(message.connectionId);
|
|
46
|
+
if (!port) return;
|
|
47
|
+
port.postMessage(message);
|
|
48
|
+
if (message.type === "connection_expired") {
|
|
49
|
+
cleanupConnection(port, message.connectionId);
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
for (const port of ports.values()) {
|
|
54
|
+
port.postMessage(message);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
self.onconnect = (event) => {
|
|
58
|
+
const port = event.ports[0];
|
|
59
|
+
const respond = (message) => {
|
|
60
|
+
port.postMessage(message);
|
|
61
|
+
if ("connectionId" in message && message.type === "connection_expired") {
|
|
62
|
+
cleanupConnection(port, message.connectionId);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
port.addEventListener("message", (message) => {
|
|
66
|
+
const data = message.data;
|
|
67
|
+
if (!isWorkerInboundMessage(data)) return;
|
|
68
|
+
if (data.type === "connect") {
|
|
69
|
+
addConnection(port, data.connectionId);
|
|
70
|
+
} else if (data.type === "release") {
|
|
71
|
+
cleanupConnection(port, data.connectionId);
|
|
72
|
+
}
|
|
73
|
+
for (const handler of _sharedHandlers) {
|
|
74
|
+
handler(data, respond);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
port.start();
|
|
78
|
+
};
|
|
79
|
+
_broadcast = broadcast;
|
|
80
|
+
return broadcast;
|
|
81
|
+
}
|
|
12
82
|
class TelegramWorker extends worker_js.TelegramWorker {
|
|
13
83
|
registerWorker(handler) {
|
|
14
84
|
if (typeof SharedWorkerGlobalScope !== "undefined" && self instanceof SharedWorkerGlobalScope) {
|
|
15
|
-
|
|
16
|
-
const connections = [];
|
|
17
|
-
const broadcast = (message) => {
|
|
18
|
-
for (const port of connections) {
|
|
19
|
-
port.postMessage(message);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
self.onconnect = (event) => {
|
|
23
|
-
const port = event.ports[0];
|
|
24
|
-
connections.push(port);
|
|
25
|
-
const respond = port.postMessage.bind(port);
|
|
26
|
-
const onClose = () => {
|
|
27
|
-
port.close();
|
|
28
|
-
const idx = connections.indexOf(port);
|
|
29
|
-
if (idx >= 0) {
|
|
30
|
-
connections.splice(connections.indexOf(port), 1);
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
const onTimeout = () => {
|
|
34
|
-
console.warn("some connection timed out!");
|
|
35
|
-
respond({ __type__: "timeout" });
|
|
36
|
-
onClose();
|
|
37
|
-
};
|
|
38
|
-
let timeout = setTimeout(onTimeout, 6e4);
|
|
39
|
-
port.addEventListener("message", (message) => {
|
|
40
|
-
if (message.data.__type__ === "close") {
|
|
41
|
-
onClose();
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (message.data.__type__ === "ping") {
|
|
45
|
-
clearTimeout(timeout);
|
|
46
|
-
timeout = setTimeout(onTimeout, 6e4);
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
for (const handler2 of _sharedHandlers) {
|
|
50
|
-
handler2(message.data, respond);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
port.start();
|
|
54
|
-
};
|
|
55
|
-
_broadcast = broadcast;
|
|
56
|
-
}
|
|
85
|
+
const broadcast = setupSharedWorker();
|
|
57
86
|
_sharedHandlers.add(handler);
|
|
58
|
-
return [
|
|
87
|
+
return [broadcast, () => _sharedHandlers.delete(handler)];
|
|
59
88
|
}
|
|
60
89
|
if (typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope) {
|
|
61
90
|
const respond = self.postMessage.bind(self);
|
|
@@ -76,12 +105,11 @@ class TelegramWorkerPort extends worker_js.TelegramWorkerPort {
|
|
|
76
105
|
});
|
|
77
106
|
}
|
|
78
107
|
connectToWorker(worker, handler) {
|
|
79
|
-
if (worker instanceof Worker) {
|
|
108
|
+
if (worker instanceof Worker || worker instanceof MessagePort) {
|
|
80
109
|
const send = worker.postMessage.bind(worker);
|
|
81
|
-
const messageHandler = (ev) =>
|
|
82
|
-
handler(ev.data);
|
|
83
|
-
};
|
|
110
|
+
const messageHandler = (ev) => handler(ev.data);
|
|
84
111
|
worker.addEventListener("message", messageHandler);
|
|
112
|
+
if (worker instanceof MessagePort) worker.start();
|
|
85
113
|
return [
|
|
86
114
|
send,
|
|
87
115
|
() => {
|
|
@@ -91,27 +119,14 @@ class TelegramWorkerPort extends worker_js.TelegramWorkerPort {
|
|
|
91
119
|
}
|
|
92
120
|
if (worker instanceof SharedWorker) {
|
|
93
121
|
const send = worker.port.postMessage.bind(worker.port);
|
|
94
|
-
const pingInterval = setInterval(() => {
|
|
95
|
-
worker.port.postMessage({ __type__: "ping" });
|
|
96
|
-
}, 1e4);
|
|
97
122
|
const messageHandler = (ev) => {
|
|
98
|
-
if (ev.data.__type__ === "timeout") {
|
|
99
|
-
location.reload();
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
123
|
handler(ev.data);
|
|
103
124
|
};
|
|
104
125
|
worker.port.addEventListener("message", messageHandler);
|
|
105
126
|
worker.port.start();
|
|
106
|
-
let cancelBeforeExit;
|
|
107
127
|
const close = () => {
|
|
108
|
-
clearInterval(pingInterval);
|
|
109
|
-
worker.port.postMessage({ __type__: "close" });
|
|
110
128
|
worker.port.removeEventListener("message", messageHandler);
|
|
111
|
-
worker.port.close();
|
|
112
|
-
cancelBeforeExit();
|
|
113
129
|
};
|
|
114
|
-
cancelBeforeExit = platform.beforeExit(close);
|
|
115
130
|
return [send, close];
|
|
116
131
|
}
|
|
117
132
|
throw new Error("Only workers and shared workers are supported");
|
package/worker.js
CHANGED
|
@@ -1,54 +1,83 @@
|
|
|
1
|
+
import { unsafeCastType } from "@fuman/utils";
|
|
1
2
|
import { TelegramWorker as TelegramWorker$1, TelegramWorkerPort as TelegramWorkerPort$1 } from "@mtcute/core/worker.js";
|
|
2
3
|
import { WebPlatform } from "./platform.js";
|
|
3
4
|
let _broadcast;
|
|
4
5
|
const _sharedHandlers = /* @__PURE__ */ new Set();
|
|
6
|
+
function isWorkerInboundMessage(message) {
|
|
7
|
+
if (!message || typeof message !== "object") return false;
|
|
8
|
+
const data = message;
|
|
9
|
+
if (typeof data._mtcuteWorkerId !== "string") return false;
|
|
10
|
+
if (typeof data.connectionId !== "string") return false;
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
function setupSharedWorker() {
|
|
14
|
+
if (_broadcast) return _broadcast;
|
|
15
|
+
unsafeCastType(self);
|
|
16
|
+
const ports = /* @__PURE__ */ new Map();
|
|
17
|
+
const knownConnectionIds = /* @__PURE__ */ new WeakMap();
|
|
18
|
+
const addConnection = (port, connectionId) => {
|
|
19
|
+
ports.set(connectionId, port);
|
|
20
|
+
const known = knownConnectionIds.get(port);
|
|
21
|
+
if (known) {
|
|
22
|
+
known.add(connectionId);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
knownConnectionIds.set(port, /* @__PURE__ */ new Set([connectionId]));
|
|
26
|
+
};
|
|
27
|
+
const cleanupConnection = (port, connectionId) => {
|
|
28
|
+
ports.delete(connectionId);
|
|
29
|
+
const known = knownConnectionIds.get(port);
|
|
30
|
+
if (!known) return;
|
|
31
|
+
known.delete(connectionId);
|
|
32
|
+
if (!known.size) {
|
|
33
|
+
knownConnectionIds.delete(port);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const broadcast = (message) => {
|
|
37
|
+
if ("connectionId" in message) {
|
|
38
|
+
const port = ports.get(message.connectionId);
|
|
39
|
+
if (!port) return;
|
|
40
|
+
port.postMessage(message);
|
|
41
|
+
if (message.type === "connection_expired") {
|
|
42
|
+
cleanupConnection(port, message.connectionId);
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
for (const port of ports.values()) {
|
|
47
|
+
port.postMessage(message);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
self.onconnect = (event) => {
|
|
51
|
+
const port = event.ports[0];
|
|
52
|
+
const respond = (message) => {
|
|
53
|
+
port.postMessage(message);
|
|
54
|
+
if ("connectionId" in message && message.type === "connection_expired") {
|
|
55
|
+
cleanupConnection(port, message.connectionId);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
port.addEventListener("message", (message) => {
|
|
59
|
+
const data = message.data;
|
|
60
|
+
if (!isWorkerInboundMessage(data)) return;
|
|
61
|
+
if (data.type === "connect") {
|
|
62
|
+
addConnection(port, data.connectionId);
|
|
63
|
+
} else if (data.type === "release") {
|
|
64
|
+
cleanupConnection(port, data.connectionId);
|
|
65
|
+
}
|
|
66
|
+
for (const handler of _sharedHandlers) {
|
|
67
|
+
handler(data, respond);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
port.start();
|
|
71
|
+
};
|
|
72
|
+
_broadcast = broadcast;
|
|
73
|
+
return broadcast;
|
|
74
|
+
}
|
|
5
75
|
class TelegramWorker extends TelegramWorker$1 {
|
|
6
76
|
registerWorker(handler) {
|
|
7
77
|
if (typeof SharedWorkerGlobalScope !== "undefined" && self instanceof SharedWorkerGlobalScope) {
|
|
8
|
-
|
|
9
|
-
const connections = [];
|
|
10
|
-
const broadcast = (message) => {
|
|
11
|
-
for (const port of connections) {
|
|
12
|
-
port.postMessage(message);
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
self.onconnect = (event) => {
|
|
16
|
-
const port = event.ports[0];
|
|
17
|
-
connections.push(port);
|
|
18
|
-
const respond = port.postMessage.bind(port);
|
|
19
|
-
const onClose = () => {
|
|
20
|
-
port.close();
|
|
21
|
-
const idx = connections.indexOf(port);
|
|
22
|
-
if (idx >= 0) {
|
|
23
|
-
connections.splice(connections.indexOf(port), 1);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
const onTimeout = () => {
|
|
27
|
-
console.warn("some connection timed out!");
|
|
28
|
-
respond({ __type__: "timeout" });
|
|
29
|
-
onClose();
|
|
30
|
-
};
|
|
31
|
-
let timeout = setTimeout(onTimeout, 6e4);
|
|
32
|
-
port.addEventListener("message", (message) => {
|
|
33
|
-
if (message.data.__type__ === "close") {
|
|
34
|
-
onClose();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
if (message.data.__type__ === "ping") {
|
|
38
|
-
clearTimeout(timeout);
|
|
39
|
-
timeout = setTimeout(onTimeout, 6e4);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
for (const handler2 of _sharedHandlers) {
|
|
43
|
-
handler2(message.data, respond);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
port.start();
|
|
47
|
-
};
|
|
48
|
-
_broadcast = broadcast;
|
|
49
|
-
}
|
|
78
|
+
const broadcast = setupSharedWorker();
|
|
50
79
|
_sharedHandlers.add(handler);
|
|
51
|
-
return [
|
|
80
|
+
return [broadcast, () => _sharedHandlers.delete(handler)];
|
|
52
81
|
}
|
|
53
82
|
if (typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope) {
|
|
54
83
|
const respond = self.postMessage.bind(self);
|
|
@@ -69,12 +98,11 @@ class TelegramWorkerPort extends TelegramWorkerPort$1 {
|
|
|
69
98
|
});
|
|
70
99
|
}
|
|
71
100
|
connectToWorker(worker, handler) {
|
|
72
|
-
if (worker instanceof Worker) {
|
|
101
|
+
if (worker instanceof Worker || worker instanceof MessagePort) {
|
|
73
102
|
const send = worker.postMessage.bind(worker);
|
|
74
|
-
const messageHandler = (ev) =>
|
|
75
|
-
handler(ev.data);
|
|
76
|
-
};
|
|
103
|
+
const messageHandler = (ev) => handler(ev.data);
|
|
77
104
|
worker.addEventListener("message", messageHandler);
|
|
105
|
+
if (worker instanceof MessagePort) worker.start();
|
|
78
106
|
return [
|
|
79
107
|
send,
|
|
80
108
|
() => {
|
|
@@ -84,27 +112,14 @@ class TelegramWorkerPort extends TelegramWorkerPort$1 {
|
|
|
84
112
|
}
|
|
85
113
|
if (worker instanceof SharedWorker) {
|
|
86
114
|
const send = worker.port.postMessage.bind(worker.port);
|
|
87
|
-
const pingInterval = setInterval(() => {
|
|
88
|
-
worker.port.postMessage({ __type__: "ping" });
|
|
89
|
-
}, 1e4);
|
|
90
115
|
const messageHandler = (ev) => {
|
|
91
|
-
if (ev.data.__type__ === "timeout") {
|
|
92
|
-
location.reload();
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
116
|
handler(ev.data);
|
|
96
117
|
};
|
|
97
118
|
worker.port.addEventListener("message", messageHandler);
|
|
98
119
|
worker.port.start();
|
|
99
|
-
let cancelBeforeExit;
|
|
100
120
|
const close = () => {
|
|
101
|
-
clearInterval(pingInterval);
|
|
102
|
-
worker.port.postMessage({ __type__: "close" });
|
|
103
121
|
worker.port.removeEventListener("message", messageHandler);
|
|
104
|
-
worker.port.close();
|
|
105
|
-
cancelBeforeExit();
|
|
106
122
|
};
|
|
107
|
-
cancelBeforeExit = platform.beforeExit(close);
|
|
108
123
|
return [send, close];
|
|
109
124
|
}
|
|
110
125
|
throw new Error("Only workers and shared workers are supported");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/worker.test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|