@evolu/common 7.4.1 → 8.0.0-next.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.
- package/README.md +4 -61
- package/dist/src/Array.d.ts +343 -102
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +181 -85
- package/dist/src/Assert.d.ts +57 -11
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +47 -11
- package/dist/src/BigInt.d.ts +6 -1
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -0
- package/dist/src/Brand.d.ts +40 -12
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Brand.js +5 -0
- package/dist/src/Buffer.d.ts +6 -1
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Buffer.js +7 -2
- package/dist/src/Cache.d.ts +10 -2
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +6 -0
- package/dist/src/Callbacks.d.ts +10 -7
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Callbacks.js +23 -13
- package/dist/src/Console.d.ts +361 -69
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +217 -117
- package/dist/src/Crypto.d.ts +70 -21
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +72 -27
- package/dist/src/Eq.d.ts +22 -2
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +21 -1
- package/dist/src/Error.d.ts +23 -12
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +27 -11
- package/dist/src/Function.d.ts +128 -56
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +118 -14
- package/dist/src/Identicon.d.ts +5 -0
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +6 -1
- package/dist/src/Lookup.d.ts +162 -0
- package/dist/src/Lookup.d.ts.map +1 -0
- package/dist/src/Lookup.js +200 -0
- package/dist/src/Microtask.d.ts +21 -0
- package/dist/src/Microtask.d.ts.map +1 -0
- package/dist/src/Microtask.js +37 -0
- package/dist/src/Number.d.ts +18 -4
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +23 -1
- package/dist/src/Object.d.ts +110 -5
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +108 -5
- package/dist/src/Option.d.ts +58 -0
- package/dist/src/Option.d.ts.map +1 -0
- package/dist/src/Option.js +43 -0
- package/dist/src/Order.d.ts +5 -0
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +8 -3
- package/dist/src/Platform.d.ts +36 -2
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +10 -6
- package/dist/src/Polyfills.d.ts +29 -0
- package/dist/src/Polyfills.d.ts.map +1 -0
- package/dist/src/Polyfills.js +329 -0
- package/dist/src/Random.d.ts +18 -7
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +9 -7
- package/dist/src/Redacted.d.ts +7 -4
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +5 -0
- package/dist/src/Ref.d.ts +31 -16
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +35 -7
- package/dist/src/RefCount.d.ts +62 -0
- package/dist/src/RefCount.d.ts.map +1 -0
- package/dist/src/RefCount.js +83 -0
- package/dist/src/Relation.d.ts +84 -29
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +83 -105
- package/dist/src/Resource.d.ts +263 -0
- package/dist/src/Resource.d.ts.map +1 -0
- package/dist/src/Resource.js +389 -0
- package/dist/src/Result.d.ts +390 -374
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +142 -70
- package/dist/src/Schedule.d.ts +953 -0
- package/dist/src/Schedule.d.ts.map +1 -0
- package/dist/src/Schedule.js +1199 -0
- package/dist/src/Set.d.ts +181 -0
- package/dist/src/Set.d.ts.map +1 -0
- package/dist/src/Set.js +137 -0
- package/dist/src/Skiplist.d.ts +6 -1
- package/dist/src/Skiplist.d.ts.map +1 -1
- package/dist/src/Skiplist.js +5 -0
- package/dist/src/Sqlite.d.ts +160 -60
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +290 -190
- package/dist/src/Store.d.ts +36 -28
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +55 -15
- package/dist/src/String.d.ts +5 -0
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +5 -0
- package/dist/src/Task.d.ts +2274 -423
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1499 -348
- package/dist/src/Test.d.ts +150 -0
- package/dist/src/Test.d.ts.map +1 -0
- package/dist/src/Test.js +97 -0
- package/dist/src/Time.d.ts +202 -48
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +199 -88
- package/dist/src/Tracer.d.ts +48 -0
- package/dist/src/Tracer.d.ts.map +1 -0
- package/dist/src/Tracer.js +6 -0
- package/dist/src/Type.d.ts +587 -209
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +370 -240
- package/dist/src/Types.d.ts +160 -6
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +22 -2
- package/dist/src/WebSocket.d.ts +130 -58
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +274 -113
- package/dist/src/Worker.d.ts +245 -60
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +220 -64
- package/dist/src/index.d.ts +25 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +19 -3
- package/dist/src/local-first/Db.d.ts +24 -213
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +621 -293
- package/dist/src/local-first/Error.d.ts +12 -0
- package/dist/src/local-first/Error.d.ts.map +1 -0
- package/dist/src/local-first/Error.js +6 -0
- package/dist/src/local-first/Evolu.d.ts +330 -285
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +472 -402
- package/dist/src/local-first/LocalAuth.d.ts +10 -10
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/LocalAuth.js +6 -1
- package/dist/src/local-first/Owner.d.ts +70 -27
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +27 -14
- package/dist/src/local-first/Protocol.d.ts +58 -50
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +253 -155
- package/dist/src/local-first/Query.d.ts +133 -43
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +139 -90
- package/dist/src/local-first/Relay.d.ts +34 -49
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +59 -177
- package/dist/src/local-first/Schema.d.ts +139 -144
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +78 -163
- package/dist/src/local-first/Shared.d.ts +125 -0
- package/dist/src/local-first/Shared.d.ts.map +1 -0
- package/dist/src/local-first/Shared.js +569 -0
- package/dist/src/local-first/Storage.d.ts +54 -58
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +127 -179
- package/dist/src/local-first/Timestamp.d.ts +28 -35
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +24 -25
- package/dist/src/local-first/index.d.ts +2 -15
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +2 -15
- package/package.json +37 -24
- package/src/Array.ts +467 -106
- package/src/Assert.ts +87 -12
- package/src/BigInt.ts +7 -1
- package/src/Brand.ts +41 -12
- package/src/Buffer.ts +10 -4
- package/src/Cache.ts +11 -2
- package/src/Callbacks.ts +33 -23
- package/src/Console.ts +567 -178
- package/src/Crypto.ts +111 -62
- package/src/Eq.ts +30 -3
- package/src/Error.ts +50 -34
- package/src/Function.ts +140 -68
- package/src/Identicon.ts +7 -1
- package/src/Lookup.ts +429 -0
- package/src/Microtask.ts +58 -0
- package/src/Number.ts +40 -7
- package/src/Object.ts +155 -16
- package/src/Option.ts +74 -0
- package/src/Order.ts +11 -3
- package/src/Platform.ts +43 -7
- package/src/Polyfills.ts +520 -0
- package/src/Random.ts +25 -11
- package/src/Redacted.ts +8 -4
- package/src/Ref.ts +72 -21
- package/src/RefCount.ts +170 -0
- package/src/Relation.ts +188 -136
- package/src/Resource.ts +864 -0
- package/src/Result.ts +548 -381
- package/src/Schedule.ts +1471 -0
- package/src/Set.ts +247 -0
- package/src/Skiplist.ts +7 -1
- package/src/Sqlite.ts +409 -304
- package/src/Store.ts +94 -48
- package/src/String.ts +6 -0
- package/src/Task.ts +3696 -740
- package/src/Test.ts +202 -0
- package/src/Time.ts +357 -147
- package/src/Tracer.ts +54 -0
- package/src/Type.ts +866 -430
- package/src/Types.ts +202 -7
- package/src/WebSocket.ts +404 -167
- package/src/Worker.ts +527 -147
- package/src/index.ts +74 -3
- package/src/local-first/Db.ts +867 -597
- package/src/local-first/Error.ts +17 -0
- package/src/local-first/Evolu.ts +884 -824
- package/src/local-first/LocalAuth.ts +10 -10
- package/src/local-first/Owner.ts +94 -42
- package/src/local-first/Protocol.ts +441 -307
- package/src/local-first/Query.ts +243 -194
- package/src/local-first/Relay.ts +119 -273
- package/src/local-first/Schema.ts +284 -394
- package/src/local-first/Shared.ts +932 -0
- package/src/local-first/Storage.ts +211 -283
- package/src/local-first/Timestamp.ts +38 -45
- package/src/local-first/index.ts +2 -16
- package/dist/src/Instances.d.ts +0 -34
- package/dist/src/Instances.d.ts.map +0 -1
- package/dist/src/Instances.js +0 -44
- package/dist/src/Resources.d.ts +0 -118
- package/dist/src/Resources.d.ts.map +0 -1
- package/dist/src/Resources.js +0 -197
- package/dist/src/local-first/Platform.d.ts +0 -25
- package/dist/src/local-first/Platform.d.ts.map +0 -1
- package/dist/src/local-first/Platform.js +0 -1
- package/dist/src/local-first/Public.d.ts +0 -22
- package/dist/src/local-first/Public.d.ts.map +0 -1
- package/dist/src/local-first/Public.js +0 -15
- package/dist/src/local-first/PublicKysely.d.ts +0 -148
- package/dist/src/local-first/PublicKysely.d.ts.map +0 -1
- package/dist/src/local-first/PublicKysely.js +0 -184
- package/dist/src/local-first/Sync.d.ts +0 -112
- package/dist/src/local-first/Sync.d.ts.map +0 -1
- package/dist/src/local-first/Sync.js +0 -526
- package/src/Instances.ts +0 -92
- package/src/Resources.ts +0 -367
- package/src/local-first/Platform.ts +0 -27
- package/src/local-first/Public.ts +0 -42
- package/src/local-first/PublicKysely.ts +0 -239
- package/src/local-first/Sync.ts +0 -949
package/dist/src/WebSocket.js
CHANGED
|
@@ -1,131 +1,292 @@
|
|
|
1
|
-
import { err, ok } from "./Result.js";
|
|
2
|
-
import { retry } from "./Task.js";
|
|
3
|
-
import { maxPositiveInt } from "./Type.js";
|
|
4
1
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The default behavior is that WebSocket tries to reconnect repeatedly in case
|
|
8
|
-
* the application is offline, because online events (both web and native) are
|
|
9
|
-
* not reliable. Once it connects and the connection is closed, it tries to
|
|
10
|
-
* reconnect again. Retrying the connection can be controlled using the
|
|
11
|
-
* retryOptions retryable predicate.
|
|
12
|
-
*
|
|
13
|
-
* ### How Binary Messages Work in WebSockets
|
|
14
|
-
*
|
|
15
|
-
* The Server Chooses the Message Type:
|
|
16
|
-
*
|
|
17
|
-
* - Text (0x1) → Sent as UTF-8 encoded text (always received as a string in the
|
|
18
|
-
* browser).
|
|
19
|
-
* - Binary (0x2) → Sent as raw binary data (received as a Blob or ArrayBuffer,
|
|
20
|
-
* depending on binaryType).
|
|
2
|
+
* WebSocket with auto-reconnect.
|
|
21
3
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* - If the server sends a text frame (0x1), the browser always delivers
|
|
25
|
-
* event.data as a string, regardless of binaryType.
|
|
26
|
-
* - If the server sends a binary frame (0x2), the browser delivers event.data as:
|
|
27
|
-
*
|
|
28
|
-
* - A Blob (default: "blob")
|
|
29
|
-
* - An ArrayBuffer ("arraybuffer")
|
|
30
|
-
*
|
|
31
|
-
* ### Example
|
|
32
|
-
*
|
|
33
|
-
* TODO:
|
|
4
|
+
* @module
|
|
34
5
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
socket.onclose = null;
|
|
48
|
-
socket.onmessage = null;
|
|
49
|
-
socket.onerror = null;
|
|
50
|
-
if (socket.readyState !== socket.CLOSING &&
|
|
51
|
-
socket.readyState !== socket.CLOSED) {
|
|
52
|
-
socket.close();
|
|
6
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
7
|
+
if (value !== null && value !== void 0) {
|
|
8
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
9
|
+
var dispose, inner;
|
|
10
|
+
if (async) {
|
|
11
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
12
|
+
dispose = value[Symbol.asyncDispose];
|
|
13
|
+
}
|
|
14
|
+
if (dispose === void 0) {
|
|
15
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
16
|
+
dispose = value[Symbol.dispose];
|
|
17
|
+
if (async) inner = dispose;
|
|
53
18
|
}
|
|
54
|
-
|
|
19
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
20
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
21
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
22
|
+
}
|
|
23
|
+
else if (async) {
|
|
24
|
+
env.stack.push({ async: true });
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
};
|
|
28
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
29
|
+
return function (env) {
|
|
30
|
+
function fail(e) {
|
|
31
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
32
|
+
env.hasError = true;
|
|
33
|
+
}
|
|
34
|
+
var r, s = 0;
|
|
35
|
+
function next() {
|
|
36
|
+
while (r = env.stack.pop()) {
|
|
37
|
+
try {
|
|
38
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
39
|
+
if (r.dispose) {
|
|
40
|
+
var result = r.dispose.call(r.value);
|
|
41
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
42
|
+
}
|
|
43
|
+
else s |= 1;
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
fail(e);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
50
|
+
if (env.hasError) throw env.error;
|
|
51
|
+
}
|
|
52
|
+
return next();
|
|
55
53
|
};
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
socket.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
54
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
55
|
+
var e = new Error(message);
|
|
56
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
57
|
+
});
|
|
58
|
+
import { assert } from "./Assert.js";
|
|
59
|
+
import { lazyTrue } from "./Function.js";
|
|
60
|
+
import { err, ok } from "./Result.js";
|
|
61
|
+
import { exponential, jitter, maxDelay } from "./Schedule.js";
|
|
62
|
+
import { callback, retry } from "./Task.js";
|
|
63
|
+
import { ArrayBuffer, String, Uint8Array } from "./Type.js";
|
|
64
|
+
/** Create a new {@link WebSocket}. */
|
|
65
|
+
export const createWebSocket = (url, { protocols, binaryType, onOpen, onClose, shouldRetryOnClose = lazyTrue, onMessage, onError, schedule = jitter(1)(maxDelay("30s")(exponential("100ms"))), WebSocketConstructor = globalThis.WebSocket, } = {}) => async (run) => {
|
|
66
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
67
|
+
try {
|
|
68
|
+
const stack = __addDisposableResource(env_1, new AsyncDisposableStack(), true);
|
|
69
|
+
let socket = null;
|
|
70
|
+
const closeSocket = () => {
|
|
71
|
+
if (!socket)
|
|
72
|
+
return;
|
|
73
|
+
socket.onopen = null;
|
|
74
|
+
socket.onclose = null;
|
|
75
|
+
socket.onmessage = null;
|
|
76
|
+
socket.onerror = null;
|
|
77
|
+
if (socket.readyState !== socket.CLOSING &&
|
|
78
|
+
socket.readyState !== socket.CLOSED) {
|
|
79
|
+
socket.close();
|
|
80
|
+
}
|
|
81
|
+
socket = null;
|
|
82
82
|
};
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
/**
|
|
84
|
+
* A task that connects and stays connected until the connection closes or
|
|
85
|
+
* errors. Returns error to trigger retry.
|
|
86
|
+
*/
|
|
87
|
+
const connect = callback(({ err, ok }) => {
|
|
88
|
+
closeSocket();
|
|
89
|
+
socket = new WebSocketConstructor(url, String.is(protocols) ? protocols : protocols && [...protocols]);
|
|
90
|
+
if (binaryType)
|
|
91
|
+
socket.binaryType = binaryType;
|
|
92
|
+
let isOpen = false;
|
|
93
|
+
socket.onopen = () => {
|
|
94
|
+
isOpen = true;
|
|
95
|
+
onOpen?.();
|
|
96
|
+
};
|
|
97
|
+
socket.onclose = (event) => {
|
|
98
|
+
onClose?.(event);
|
|
99
|
+
if (shouldRetryOnClose(event)) {
|
|
100
|
+
err({ type: "WebSocketConnectionCloseError", event });
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
ok();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
socket.onmessage = (event) => {
|
|
107
|
+
onMessage?.(event.data);
|
|
108
|
+
};
|
|
109
|
+
socket.onerror = (event) => {
|
|
110
|
+
const error = isOpen
|
|
111
|
+
? { type: "WebSocketConnectionError", event }
|
|
112
|
+
: { type: "WebSocketConnectError", event };
|
|
113
|
+
onError?.(error);
|
|
114
|
+
if (error.type === "WebSocketConnectError")
|
|
115
|
+
err(error);
|
|
116
|
+
};
|
|
117
|
+
return closeSocket;
|
|
118
|
+
});
|
|
119
|
+
const retryFiber = stack.use(run.daemon(retry(connect, schedule)));
|
|
120
|
+
// Report RetryError (schedule exhausted) via onError callback
|
|
121
|
+
void retryFiber.then((result) => {
|
|
122
|
+
if (!result.ok && result.error.type === "RetryError") {
|
|
123
|
+
onError?.(result.error);
|
|
91
124
|
}
|
|
125
|
+
});
|
|
126
|
+
const moved = stack.move();
|
|
127
|
+
return ok({
|
|
128
|
+
send: (data) => {
|
|
129
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
|
|
130
|
+
if (!socket || socket.readyState === socket.CONNECTING) {
|
|
131
|
+
return err({ type: "WebSocketSendError" });
|
|
132
|
+
}
|
|
133
|
+
socket.send(ensureSendableData(data));
|
|
134
|
+
return ok();
|
|
135
|
+
},
|
|
136
|
+
getReadyState: () => {
|
|
137
|
+
if (moved.disposed)
|
|
138
|
+
return "closed";
|
|
139
|
+
return socket ? nativeToStringState[socket.readyState] : "connecting";
|
|
140
|
+
},
|
|
141
|
+
isOpen: () => !moved.disposed && socket?.readyState === globalThis.WebSocket.OPEN,
|
|
142
|
+
[Symbol.asyncDispose]: () => moved.disposeAsync(),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch (e_1) {
|
|
146
|
+
env_1.error = e_1;
|
|
147
|
+
env_1.hasError = true;
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
const result_1 = __disposeResources(env_1);
|
|
151
|
+
if (result_1)
|
|
152
|
+
await result_1;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
/** Clones SharedArrayBuffer-backed Uint8Array values before WebSocket.send. */
|
|
156
|
+
const ensureSendableData = (data) => {
|
|
157
|
+
if (!Uint8Array.is(data))
|
|
158
|
+
return data;
|
|
159
|
+
return ArrayBuffer.is(data.buffer)
|
|
160
|
+
? data
|
|
161
|
+
: new globalThis.Uint8Array(data);
|
|
162
|
+
};
|
|
163
|
+
const nativeToStringState = {
|
|
164
|
+
[globalThis.WebSocket.CONNECTING]: "connecting",
|
|
165
|
+
[globalThis.WebSocket.OPEN]: "open",
|
|
166
|
+
[globalThis.WebSocket.CLOSING]: "closing",
|
|
167
|
+
[globalThis.WebSocket.CLOSED]: "closed",
|
|
168
|
+
};
|
|
169
|
+
/** Creates {@link TestCreateWebSocket}. */
|
|
170
|
+
export const testCreateWebSocket = (options = {}) => {
|
|
171
|
+
const createdUrls = [];
|
|
172
|
+
const sentMessages = [];
|
|
173
|
+
const stateByUrl = new Map();
|
|
174
|
+
const getState = (url) => {
|
|
175
|
+
const state = stateByUrl.get(url);
|
|
176
|
+
assert(state, `Test WebSocket for ${url} does not exist.`);
|
|
177
|
+
return state;
|
|
178
|
+
};
|
|
179
|
+
const createWebSocket = (url, socketOptions) => () => {
|
|
180
|
+
if (options.throwOnCreate) {
|
|
181
|
+
throw new Error("testCreateWebSocket is configured to throw on create");
|
|
182
|
+
}
|
|
183
|
+
createdUrls.push(url);
|
|
184
|
+
stateByUrl.set(url, {
|
|
185
|
+
options: socketOptions,
|
|
186
|
+
isOpen: options.isOpen ?? true,
|
|
187
|
+
isDisposed: false,
|
|
188
|
+
});
|
|
189
|
+
return ok({
|
|
190
|
+
send: (data) => {
|
|
191
|
+
const state = getState(url);
|
|
192
|
+
if (state.isDisposed || !state.isOpen) {
|
|
193
|
+
return err({ type: "WebSocketSendError" });
|
|
194
|
+
}
|
|
195
|
+
sentMessages.push({
|
|
196
|
+
url,
|
|
197
|
+
data: ensureSendableData(data),
|
|
198
|
+
});
|
|
199
|
+
return ok();
|
|
200
|
+
},
|
|
201
|
+
getReadyState: () => {
|
|
202
|
+
const state = getState(url);
|
|
203
|
+
if (state.isDisposed)
|
|
204
|
+
return "closed";
|
|
205
|
+
return state.isOpen ? "open" : "closed";
|
|
206
|
+
},
|
|
207
|
+
isOpen: () => {
|
|
208
|
+
const state = getState(url);
|
|
209
|
+
return !state.isDisposed && state.isOpen;
|
|
210
|
+
},
|
|
211
|
+
[Symbol.asyncDispose]: () => {
|
|
212
|
+
const state = getState(url);
|
|
213
|
+
state.isDisposed = true;
|
|
214
|
+
state.isOpen = false;
|
|
215
|
+
return Promise.resolve();
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
return Object.assign(createWebSocket, {
|
|
220
|
+
createdUrls,
|
|
221
|
+
sentMessages,
|
|
222
|
+
message: (url, data) => {
|
|
223
|
+
getState(url).options?.onMessage?.(data);
|
|
224
|
+
},
|
|
225
|
+
open: (url) => {
|
|
226
|
+
const state = getState(url);
|
|
227
|
+
state.isOpen = true;
|
|
228
|
+
state.options?.onOpen?.();
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
};
|
|
232
|
+
/** Opens a native {@link WebSocket} and returns {@link TestSetupWebSocket}. */
|
|
233
|
+
export const testSetupWebSocket = async (url) => {
|
|
234
|
+
const socket = new globalThis.WebSocket(url);
|
|
235
|
+
socket.binaryType = "arraybuffer";
|
|
236
|
+
await new Promise((resolve, reject) => {
|
|
237
|
+
const onOpen = () => {
|
|
238
|
+
cleanup();
|
|
239
|
+
resolve();
|
|
92
240
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
241
|
+
const onError = () => {
|
|
242
|
+
cleanup();
|
|
243
|
+
socket.close();
|
|
244
|
+
reject(new Error("WebSocket connection failed"));
|
|
96
245
|
};
|
|
97
|
-
|
|
98
|
-
|
|
246
|
+
const cleanup = () => {
|
|
247
|
+
socket.removeEventListener("open", onOpen);
|
|
248
|
+
socket.removeEventListener("error", onError);
|
|
99
249
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return;
|
|
103
|
-
onError?.(result.error);
|
|
250
|
+
socket.addEventListener("open", onOpen, { once: true });
|
|
251
|
+
socket.addEventListener("error", onError, { once: true });
|
|
104
252
|
});
|
|
105
253
|
return {
|
|
254
|
+
socket,
|
|
106
255
|
send: (data) => {
|
|
107
|
-
|
|
108
|
-
if (!socket || socket.readyState === socket.CONNECTING) {
|
|
109
|
-
return err({ type: "WebSocketSendError" });
|
|
110
|
-
}
|
|
111
|
-
socket.send(data);
|
|
112
|
-
return ok();
|
|
256
|
+
socket.send(ensureSendableData(data));
|
|
113
257
|
},
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (isDisposed)
|
|
258
|
+
waitForMessage: () => new Promise((resolve, reject) => {
|
|
259
|
+
if (socket.readyState === globalThis.WebSocket.CLOSED) {
|
|
260
|
+
reject(new Error("WebSocket closed before message"));
|
|
118
261
|
return;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
262
|
+
}
|
|
263
|
+
const onMessage = (event) => {
|
|
264
|
+
cleanup();
|
|
265
|
+
if (typeof event.data === "string") {
|
|
266
|
+
resolve(event.data);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
resolve(new globalThis.Uint8Array(event.data));
|
|
270
|
+
};
|
|
271
|
+
const onClose = () => {
|
|
272
|
+
cleanup();
|
|
273
|
+
reject(new Error("WebSocket closed before message"));
|
|
274
|
+
};
|
|
275
|
+
const cleanup = () => {
|
|
276
|
+
socket.removeEventListener("message", onMessage);
|
|
277
|
+
socket.removeEventListener("close", onClose);
|
|
278
|
+
};
|
|
279
|
+
socket.addEventListener("message", onMessage, { once: true });
|
|
280
|
+
socket.addEventListener("close", onClose, { once: true });
|
|
281
|
+
}),
|
|
282
|
+
[Symbol.asyncDispose]: async () => {
|
|
283
|
+
if (socket.readyState === globalThis.WebSocket.CLOSED)
|
|
284
|
+
return;
|
|
285
|
+
const closed = new Promise((resolve) => {
|
|
286
|
+
socket.addEventListener("close", () => resolve(), { once: true });
|
|
287
|
+
});
|
|
288
|
+
socket.close();
|
|
289
|
+
await closed;
|
|
123
290
|
},
|
|
124
291
|
};
|
|
125
292
|
};
|
|
126
|
-
const nativeToStringState = {
|
|
127
|
-
[WebSocket.CONNECTING]: "connecting",
|
|
128
|
-
[WebSocket.OPEN]: "open",
|
|
129
|
-
[WebSocket.CLOSING]: "closing",
|
|
130
|
-
[WebSocket.CLOSED]: "closed",
|
|
131
|
-
};
|