@floegence/flowersec-core 0.27.0 → 2.0.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 +91 -22
- package/THIRD_PARTY_NOTICES.md +141 -0
- package/dist/browser/connectSession.d.ts +13 -0
- package/dist/browser/connectSession.js +40 -0
- package/dist/browser/index.d.ts +3 -10
- package/dist/browser/index.js +2 -5
- package/dist/browser/runtimeCapability.d.ts +13 -0
- package/dist/browser/runtimeCapability.js +27 -0
- package/dist/browser/sessionRuntime.d.ts +2 -0
- package/dist/browser/sessionRuntime.js +21 -0
- package/dist/browser/webTransportClient.d.ts +8 -0
- package/dist/browser/webTransportClient.js +55 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +126 -0
- package/dist/cliSpendMarker.d.ts +1 -0
- package/dist/cliSpendMarker.js +22 -0
- package/dist/connectionController.d.ts +54 -0
- package/dist/connectionController.js +438 -0
- package/dist/connector/adapters/webSocketCandidate.d.ts +7 -0
- package/dist/connector/adapters/webSocketCandidate.js +116 -0
- package/dist/connector/adapters/webTransportCandidate.d.ts +5 -0
- package/dist/connector/adapters/webTransportCandidate.js +73 -0
- package/dist/connector/admissionCommit.d.ts +31 -0
- package/dist/connector/admissionCommit.js +239 -0
- package/dist/connector/sessionAcceptor.d.ts +16 -0
- package/dist/connector/sessionAcceptor.js +114 -0
- package/dist/connector/sessionConfig.d.ts +3 -0
- package/dist/connector/sessionConfig.js +30 -0
- package/dist/connector/sessionConnector.d.ts +45 -0
- package/dist/connector/sessionConnector.js +603 -0
- package/dist/defaults.d.ts +7 -7
- package/dist/defaults.js +7 -7
- package/dist/facade.d.ts +12 -27
- package/dist/facade.js +6 -24
- package/dist/node/connectSession.d.ts +21 -0
- package/dist/node/connectSession.js +62 -0
- package/dist/node/index.d.ts +3 -11
- package/dist/node/index.js +2 -8
- package/dist/node/runtimeCapability.d.ts +7 -0
- package/dist/node/runtimeCapability.js +10 -0
- package/dist/node/sessionRuntime.d.ts +2 -0
- package/dist/node/sessionRuntime.js +13 -0
- package/dist/node/webTransportClient.d.ts +9 -0
- package/dist/node/webTransportClient.js +56 -0
- package/dist/node/webTransportServer.d.ts +22 -0
- package/dist/node/webTransportServer.js +100 -0
- package/dist/node/wsFactory.d.ts +3 -1
- package/dist/node/wsFactory.js +4 -3
- package/dist/proxy/controllerGuard.d.ts +4 -4
- package/dist/proxy/controllerGuard.js +83 -177
- package/dist/proxy/disableUpstreamServiceWorkerRegister.d.ts +3 -1
- package/dist/proxy/disableUpstreamServiceWorkerRegister.js +19 -17
- package/dist/proxy/index.d.ts +16 -15
- package/dist/proxy/index.js +8 -14
- package/dist/proxy/integration.d.ts +23 -71
- package/dist/proxy/integration.js +37 -340
- package/dist/proxy/registerServiceWorker.d.ts +1 -10
- package/dist/proxy/registerServiceWorker.js +43 -105
- package/dist/proxy/runtime.d.ts +3 -63
- package/dist/proxy/runtime.js +349 -462
- package/dist/proxy/scope.d.ts +6 -0
- package/dist/proxy/scope.js +131 -0
- package/dist/proxy/serviceWorker.d.ts +5 -16
- package/dist/proxy/serviceWorker.js +230 -617
- package/dist/proxy/stream.d.ts +9 -0
- package/dist/proxy/stream.js +40 -0
- package/dist/proxy/types.d.ts +78 -30
- package/dist/proxy/windowBridge.d.ts +61 -0
- package/dist/proxy/windowBridge.js +344 -0
- package/dist/proxy/wsPatch.d.ts +4 -14
- package/dist/proxy/wsPatch.js +173 -268
- package/dist/public/artifact.d.ts +11 -0
- package/dist/public/artifact.js +44 -0
- package/dist/public/artifactLease.d.ts +10 -0
- package/dist/public/artifactLease.js +48 -0
- package/dist/public/connectError.d.ts +6 -0
- package/dist/public/connectError.js +9 -0
- package/dist/public/contract.d.ts +83 -0
- package/dist/public/contract.js +17 -0
- package/dist/public/streamMetadata.d.ts +10 -0
- package/dist/public/streamMetadata.js +40 -0
- package/dist/rpc/caller.d.ts +1 -1
- package/dist/rpc/client.d.ts +1 -4
- package/dist/rpc/client.js +0 -21
- package/dist/rpc/rpcProxy.d.ts +1 -1
- package/dist/rpc/server.d.ts +1 -1
- package/dist/rpc/validate.d.ts +1 -1
- package/dist/rpc/wire.d.ts +15 -0
- package/dist/runtime/errors.d.ts +6 -0
- package/dist/runtime/errors.js +10 -0
- package/dist/transport/webSocketAdapter.d.ts +24 -0
- package/dist/transport/webSocketAdapter.js +234 -0
- package/dist/transport/webTransportAdapter.d.ts +27 -0
- package/dist/transport/webTransportAdapter.js +519 -0
- package/dist/utils/errors.d.ts +2 -20
- package/dist/utils/errors.js +73 -20
- package/dist/v2/admissionError.d.ts +4 -0
- package/dist/v2/admissionError.js +8 -0
- package/dist/v2/artifact.d.ts +128 -0
- package/dist/v2/artifact.js +1126 -0
- package/dist/v2/artifactLease.d.ts +1 -0
- package/dist/v2/artifactLease.js +7 -0
- package/dist/v2/capability.d.ts +29 -0
- package/dist/v2/capability.js +190 -0
- package/dist/v2/carrier.d.ts +79 -0
- package/dist/v2/carrier.js +405 -0
- package/dist/v2/contract.d.ts +37 -0
- package/dist/v2/contract.js +1 -0
- package/dist/v2/handshake.d.ts +80 -0
- package/dist/v2/handshake.js +470 -0
- package/dist/v2/opaqueArtifact.d.ts +1 -0
- package/dist/v2/opaqueArtifact.js +2 -0
- package/dist/v2/protocol.d.ts +99 -0
- package/dist/v2/protocol.js +739 -0
- package/dist/v2/publicSession.d.ts +1 -0
- package/dist/v2/publicSession.js +179 -0
- package/dist/v2/retryDisposition.d.ts +16 -0
- package/dist/v2/retryDisposition.js +30 -0
- package/dist/v2/session.d.ts +277 -0
- package/dist/v2/session.js +1879 -0
- package/dist/v2/streamLifetimeLedger.d.ts +31 -0
- package/dist/v2/streamLifetimeLedger.js +131 -0
- package/dist/v2/streamMetadata.d.ts +1 -0
- package/dist/v2/streamMetadata.js +7 -0
- package/dist/v2/unreliableMessage.d.ts +43 -0
- package/dist/v2/unreliableMessage.js +252 -0
- package/dist/vendor/tr46.d.ts +10 -0
- package/dist/vendor/tr46.js +501 -0
- package/dist/ws-client/binaryTransport.d.ts +0 -3
- package/dist/ws-client/binaryTransport.js +15 -39
- package/dist/yamux/errors.d.ts +0 -4
- package/dist/yamux/errors.js +0 -9
- package/dist/yamux/session.d.ts +0 -5
- package/dist/yamux/session.js +4 -70
- package/dist/yamux/stream.d.ts +1 -0
- package/dist/yamux/stream.js +4 -0
- package/package.json +29 -81
- package/sbom/cyclonedx.json +2764 -0
- package/sbom/spdx.json +1947 -0
- package/YAMUX_ALIGNMENT.md +0 -127
- package/dist/_examples/flowersec/demo/v1.facade.gen.d.ts +0 -12
- package/dist/_examples/flowersec/demo/v1.facade.gen.js +0 -15
- package/dist/_examples/flowersec/demo/v1.gen.d.ts +0 -16
- package/dist/_examples/flowersec/demo/v1.gen.js +0 -86
- package/dist/_examples/flowersec/demo/v1.rpc.gen.d.ts +0 -11
- package/dist/_examples/flowersec/demo/v1.rpc.gen.js +0 -22
- package/dist/browser/connect.d.ts +0 -13
- package/dist/browser/connect.js +0 -31
- package/dist/browser/reconnectConfig.d.ts +0 -15
- package/dist/browser/reconnectConfig.js +0 -20
- package/dist/client-connect/common.d.ts +0 -26
- package/dist/client-connect/common.js +0 -167
- package/dist/client-connect/connectCore.d.ts +0 -61
- package/dist/client-connect/connectCore.js +0 -572
- package/dist/client-connect/contract.d.ts +0 -8
- package/dist/client-connect/contract.js +0 -51
- package/dist/client-connect/termination.d.ts +0 -6
- package/dist/client-connect/termination.js +0 -7
- package/dist/client-connect/transportSecurity.d.ts +0 -27
- package/dist/client-connect/transportSecurity.js +0 -199
- package/dist/client-connect/tunnelAttachCloseReason.d.ts +0 -3
- package/dist/client-connect/tunnelAttachCloseReason.js +0 -23
- package/dist/client.d.ts +0 -23
- package/dist/connect/artifact.d.ts +0 -36
- package/dist/connect/artifact.js +0 -213
- package/dist/connect/resolveArtifact.d.ts +0 -22
- package/dist/connect/resolveArtifact.js +0 -87
- package/dist/controlplane/channelInit.d.ts +0 -27
- package/dist/controlplane/channelInit.js +0 -116
- package/dist/controlplane/http.d.ts +0 -16
- package/dist/controlplane/http.js +0 -59
- package/dist/controlplane/index.d.ts +0 -6
- package/dist/controlplane/index.js +0 -5
- package/dist/controlplane/issuer.d.ts +0 -18
- package/dist/controlplane/issuer.js +0 -113
- package/dist/controlplane/request.d.ts +0 -51
- package/dist/controlplane/request.js +0 -273
- package/dist/controlplane/token.d.ts +0 -33
- package/dist/controlplane/token.js +0 -119
- package/dist/direct-client/connect.d.ts +0 -9
- package/dist/direct-client/connect.js +0 -90
- package/dist/direct-client/index.d.ts +0 -1
- package/dist/direct-client/index.js +0 -1
- package/dist/e2ee/constants.d.ts +0 -9
- package/dist/e2ee/constants.js +0 -18
- package/dist/e2ee/errors.d.ts +0 -5
- package/dist/e2ee/errors.js +0 -8
- package/dist/e2ee/framing.d.ts +0 -12
- package/dist/e2ee/framing.js +0 -57
- package/dist/e2ee/handshake.d.ts +0 -88
- package/dist/e2ee/handshake.js +0 -353
- package/dist/e2ee/index.d.ts +0 -7
- package/dist/e2ee/index.js +0 -7
- package/dist/e2ee/kdf.d.ts +0 -15
- package/dist/e2ee/kdf.js +0 -39
- package/dist/e2ee/record.d.ts +0 -11
- package/dist/e2ee/record.js +0 -80
- package/dist/e2ee/secureChannel.d.ts +0 -93
- package/dist/e2ee/secureChannel.js +0 -342
- package/dist/e2ee/transcript.d.ts +0 -23
- package/dist/e2ee/transcript.js +0 -31
- package/dist/endpoint/index.d.ts +0 -84
- package/dist/endpoint/index.js +0 -557
- package/dist/endpoint/node.d.ts +0 -9
- package/dist/endpoint/node.js +0 -51
- package/dist/gen/flowersec/controlplane/v1.gen.d.ts +0 -36
- package/dist/gen/flowersec/controlplane/v1.gen.js +0 -135
- package/dist/gen/flowersec/direct/v1.gen.d.ts +0 -21
- package/dist/gen/flowersec/direct/v1.gen.js +0 -101
- package/dist/gen/flowersec/e2ee/v1.gen.d.ts +0 -68
- package/dist/gen/flowersec/e2ee/v1.gen.js +0 -194
- package/dist/gen/flowersec/rpc/v1.gen.d.ts +0 -30
- package/dist/gen/flowersec/rpc/v1.gen.js +0 -107
- package/dist/gen/flowersec/tunnel/v1.gen.d.ts +0 -23
- package/dist/gen/flowersec/tunnel/v1.gen.js +0 -104
- package/dist/index.d.ts +0 -22
- package/dist/index.js +0 -22
- package/dist/node/connect.d.ts +0 -10
- package/dist/node/connect.js +0 -29
- package/dist/node/reconnectConfig.d.ts +0 -16
- package/dist/node/reconnectConfig.js +0 -20
- package/dist/observability/index.d.ts +0 -1
- package/dist/observability/index.js +0 -1
- package/dist/observability/observer.d.ts +0 -52
- package/dist/observability/observer.js +0 -314
- package/dist/proxy/appWindow.d.ts +0 -37
- package/dist/proxy/appWindow.js +0 -273
- package/dist/proxy/bootstrap.d.ts +0 -35
- package/dist/proxy/bootstrap.js +0 -119
- package/dist/proxy/constants.d.ts +0 -7
- package/dist/proxy/constants.js +0 -8
- package/dist/proxy/controllerWindow.d.ts +0 -12
- package/dist/proxy/controllerWindow.js +0 -384
- package/dist/proxy/cookieJar.d.ts +0 -7
- package/dist/proxy/cookieJar.js +0 -136
- package/dist/proxy/headerPolicy.d.ts +0 -14
- package/dist/proxy/headerPolicy.js +0 -134
- package/dist/proxy/portStream.d.ts +0 -5
- package/dist/proxy/portStream.js +0 -256
- package/dist/proxy/preset.d.ts +0 -29
- package/dist/proxy/preset.js +0 -111
- package/dist/proxy/runtimeScope.d.ts +0 -57
- package/dist/proxy/runtimeScope.js +0 -218
- package/dist/proxy/server.d.ts +0 -28
- package/dist/proxy/server.js +0 -833
- package/dist/proxy/windowBridgeProtocol.d.ts +0 -65
- package/dist/proxy/windowBridgeProtocol.js +0 -11
- package/dist/reconnect/artifactControlplane.d.ts +0 -16
- package/dist/reconnect/artifactControlplane.js +0 -35
- package/dist/reconnect/index.d.ts +0 -36
- package/dist/reconnect/index.js +0 -388
- package/dist/rpc-proxy/index.d.ts +0 -1
- package/dist/rpc-proxy/index.js +0 -1
- package/dist/rpc-proxy/rpcProxy.d.ts +0 -1
- package/dist/rpc-proxy/rpcProxy.js +0 -1
- package/dist/streamhello/index.d.ts +0 -1
- package/dist/streamhello/index.js +0 -1
- package/dist/streamhello/streamHello.d.ts +0 -3
- package/dist/streamhello/streamHello.js +0 -13
- package/dist/streamio/index.d.ts +0 -32
- package/dist/streamio/index.js +0 -87
- package/dist/tunnel-client/connect.d.ts +0 -9
- package/dist/tunnel-client/connect.js +0 -147
- package/dist/tunnel-client/index.d.ts +0 -1
- package/dist/tunnel-client/index.js +0 -1
- package/dist/ws/index.d.ts +0 -1
- package/dist/ws/index.js +0 -1
- /package/dist/{client.js → rpc/wire.js} +0 -0
package/dist/proxy/wsPatch.js
CHANGED
|
@@ -1,113 +1,88 @@
|
|
|
1
|
-
import { createByteReader } from "../streamio/index.js";
|
|
2
1
|
import { readU32be, u16be, u32be } from "../utils/bin.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const te = new TextEncoder();
|
|
8
|
-
const td = new TextDecoder();
|
|
9
|
-
function defaultPortForProtocol(protocol) {
|
|
10
|
-
// Protocol strings include the trailing ':' in URL (e.g. 'http:', 'ws:').
|
|
2
|
+
import { ProxyByteReader, writeAll } from "./stream.js";
|
|
3
|
+
const encoder = new TextEncoder();
|
|
4
|
+
const decoder = new TextDecoder();
|
|
5
|
+
function defaultPort(protocol) {
|
|
11
6
|
if (protocol === "http:" || protocol === "ws:")
|
|
12
7
|
return "80";
|
|
13
8
|
if (protocol === "https:" || protocol === "wss:")
|
|
14
9
|
return "443";
|
|
15
10
|
return "";
|
|
16
11
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
12
|
+
function readU16(input) {
|
|
13
|
+
return ((input[0] << 8) | input[1]) >>> 0;
|
|
14
|
+
}
|
|
15
|
+
async function writeFrame(stream, opcode, payload, maximum) {
|
|
16
|
+
if (payload.length > maximum)
|
|
17
|
+
throw new Error("WebSocket frame exceeds the proxy limit");
|
|
18
|
+
const header = new Uint8Array(5);
|
|
19
|
+
header[0] = opcode;
|
|
20
|
+
header.set(u32be(payload.length), 1);
|
|
21
|
+
await writeAll(stream, header);
|
|
22
|
+
await writeAll(stream, payload);
|
|
23
|
+
}
|
|
24
|
+
async function readFrame(reader, maximum) {
|
|
25
|
+
const header = await reader.readExactly(5);
|
|
26
|
+
const length = readU32be(header, 1);
|
|
27
|
+
if (length > maximum)
|
|
28
|
+
throw new Error("WebSocket frame exceeds the proxy limit");
|
|
29
|
+
return { opcode: header[0], payload: await reader.readExactly(length) };
|
|
30
|
+
}
|
|
31
|
+
class EventListeners {
|
|
32
|
+
values = new Map();
|
|
33
|
+
add(type, listener) {
|
|
34
|
+
const entries = this.values.get(type) ?? new Set();
|
|
35
|
+
entries.add(listener);
|
|
36
|
+
this.values.set(type, entries);
|
|
29
37
|
}
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
remove(type, listener) { this.values.get(type)?.delete(listener); }
|
|
39
|
+
dispatch(type, event, target) {
|
|
40
|
+
for (const listener of this.values.get(type) ?? []) {
|
|
32
41
|
try {
|
|
33
|
-
|
|
42
|
+
if (typeof listener === "function")
|
|
43
|
+
listener.call(target, event);
|
|
44
|
+
else
|
|
45
|
+
listener.handleEvent(event);
|
|
34
46
|
}
|
|
35
47
|
catch {
|
|
36
|
-
//
|
|
48
|
+
// Event listener failures do not corrupt the transport state.
|
|
37
49
|
}
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
52
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
hdr.set(u32be(payload.length), 1);
|
|
47
|
-
await stream.write(hdr);
|
|
48
|
-
if (payload.length > 0)
|
|
49
|
-
await stream.write(payload);
|
|
53
|
+
function limit(name, input, fallback) {
|
|
54
|
+
const value = input ?? fallback;
|
|
55
|
+
if (!Number.isSafeInteger(value) || value <= 0)
|
|
56
|
+
throw new TypeError(`${name} must be a positive safe integer`);
|
|
57
|
+
return value;
|
|
50
58
|
}
|
|
51
|
-
|
|
52
|
-
const hdr = await reader.readExactly(5);
|
|
53
|
-
const op = hdr[0];
|
|
54
|
-
const n = readU32be(hdr, 1);
|
|
55
|
-
if (maxPayload > 0 && n > maxPayload)
|
|
56
|
-
throw new Error("ws payload too large");
|
|
57
|
-
const payload = n === 0 ? new Uint8Array() : await reader.readExactly(n);
|
|
58
|
-
return { op, payload };
|
|
59
|
-
}
|
|
60
|
-
export function installWebSocketPatch(opts) {
|
|
59
|
+
export function installWebSocketPatch(options) {
|
|
61
60
|
const Original = globalThis.WebSocket;
|
|
62
|
-
if (Original
|
|
63
|
-
return { uninstall: () =>
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const runtime = opts.runtime;
|
|
78
|
-
const runtimeMaxWsFrameBytes = typeof runtime.limits?.maxWsFrameBytes === "number" && Number.isFinite(runtime.limits.maxWsFrameBytes)
|
|
79
|
-
? runtime.limits.maxWsFrameBytes
|
|
80
|
-
: DEFAULT_MAX_WS_FRAME_BYTES;
|
|
81
|
-
const maxWsFrameBytesRaw = opts.maxWsFrameBytes ?? runtimeMaxWsFrameBytes;
|
|
82
|
-
if (!Number.isFinite(maxWsFrameBytesRaw))
|
|
83
|
-
throw new Error("maxWsFrameBytes must be a finite number");
|
|
84
|
-
const maxWsFrameBytesFloor = Math.floor(maxWsFrameBytesRaw);
|
|
85
|
-
if (maxWsFrameBytesFloor < 0)
|
|
86
|
-
throw new Error("maxWsFrameBytes must be >= 0");
|
|
87
|
-
const maxWsFrameBytes = maxWsFrameBytesFloor === 0 ? runtimeMaxWsFrameBytes : maxWsFrameBytesFloor;
|
|
88
|
-
const defaultMaxWsBufferedAmountBytes = 4 * (1 << 20);
|
|
89
|
-
const runtimeMaxWsBufferedAmountBytesRaw = runtime.limits?.maxWsBufferedAmountBytes;
|
|
90
|
-
if (runtimeMaxWsBufferedAmountBytesRaw !== undefined &&
|
|
91
|
-
(!Number.isSafeInteger(runtimeMaxWsBufferedAmountBytesRaw) || runtimeMaxWsBufferedAmountBytesRaw < 0)) {
|
|
92
|
-
throw new Error("runtime maxWsBufferedAmountBytes must be a non-negative safe integer");
|
|
93
|
-
}
|
|
94
|
-
const runtimeMaxWsBufferedAmountBytes = runtimeMaxWsBufferedAmountBytesRaw == null || runtimeMaxWsBufferedAmountBytesRaw === 0
|
|
95
|
-
? defaultMaxWsBufferedAmountBytes
|
|
96
|
-
: runtimeMaxWsBufferedAmountBytesRaw;
|
|
97
|
-
const maxWsBufferedAmountBytesRaw = opts.maxWsBufferedAmountBytes ?? runtimeMaxWsBufferedAmountBytes;
|
|
98
|
-
if (!Number.isSafeInteger(maxWsBufferedAmountBytesRaw) || maxWsBufferedAmountBytesRaw < 0) {
|
|
99
|
-
throw new Error("maxWsBufferedAmountBytes must be a non-negative safe integer");
|
|
100
|
-
}
|
|
101
|
-
const maxWsBufferedAmountBytes = maxWsBufferedAmountBytesRaw === 0
|
|
102
|
-
? runtimeMaxWsBufferedAmountBytes
|
|
103
|
-
: maxWsBufferedAmountBytesRaw;
|
|
104
|
-
class PatchedWebSocket {
|
|
61
|
+
if (Original === undefined)
|
|
62
|
+
return Object.freeze({ uninstall: () => undefined });
|
|
63
|
+
const NativeWebSocket = Original;
|
|
64
|
+
const runtimeLimits = options.runtime.limits;
|
|
65
|
+
const maxFrameBytes = limit("maxWsFrameBytes", options.maxWsFrameBytes, runtimeLimits.maxWsFrameBytes ?? 1024 * 1024);
|
|
66
|
+
const maxBufferedBytes = limit("maxWsBufferedAmountBytes", options.maxWsBufferedAmountBytes, runtimeLimits.maxWsBufferedAmountBytes ?? 4 * 1024 * 1024);
|
|
67
|
+
const shouldProxy = options.shouldProxy ?? ((url) => {
|
|
68
|
+
const location = globalThis.location;
|
|
69
|
+
if (location?.hostname === undefined || location.hostname === "")
|
|
70
|
+
return false;
|
|
71
|
+
const localPort = location.port || defaultPort(location.protocol);
|
|
72
|
+
const remotePort = url.port || defaultPort(url.protocol);
|
|
73
|
+
return url.hostname === location.hostname && remotePort === localPort;
|
|
74
|
+
});
|
|
75
|
+
class ProxyWebSocket {
|
|
105
76
|
static CONNECTING = 0;
|
|
106
77
|
static OPEN = 1;
|
|
107
78
|
static CLOSING = 2;
|
|
108
79
|
static CLOSED = 3;
|
|
80
|
+
CONNECTING = 0;
|
|
81
|
+
OPEN = 1;
|
|
82
|
+
CLOSING = 2;
|
|
83
|
+
CLOSED = 3;
|
|
109
84
|
url = "";
|
|
110
|
-
readyState =
|
|
85
|
+
readyState = ProxyWebSocket.CONNECTING;
|
|
111
86
|
bufferedAmount = 0;
|
|
112
87
|
extensions = "";
|
|
113
88
|
protocol = "";
|
|
@@ -116,206 +91,136 @@ export function installWebSocketPatch(opts) {
|
|
|
116
91
|
onmessage = null;
|
|
117
92
|
onerror = null;
|
|
118
93
|
onclose = null;
|
|
119
|
-
listeners = new
|
|
120
|
-
|
|
121
|
-
stream
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
this.url = u.toString();
|
|
130
|
-
void this.init(u, protocols);
|
|
131
|
-
}
|
|
132
|
-
addEventListener(type, listener) {
|
|
133
|
-
this.listeners.on(type, listener);
|
|
134
|
-
}
|
|
135
|
-
removeEventListener(type, listener) {
|
|
136
|
-
this.listeners.off(type, listener);
|
|
137
|
-
}
|
|
138
|
-
queueWriteFrame(stream, op, payload, bufferedBytes = 0) {
|
|
139
|
-
this.writeChain = this.writeChain
|
|
140
|
-
.then(async () => {
|
|
141
|
-
if (this.readyState === PatchedWebSocket.CLOSED)
|
|
142
|
-
return;
|
|
143
|
-
const resolved = typeof payload === "function" ? await payload() : payload;
|
|
144
|
-
await writeWSFrame(stream, op, resolved, maxWsFrameBytes);
|
|
145
|
-
})
|
|
146
|
-
.catch((e) => this.fail(e))
|
|
147
|
-
.finally(() => {
|
|
148
|
-
this.bufferedAmount = Math.max(0, this.bufferedAmount - bufferedBytes);
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
reserveBufferedAmount(bytes) {
|
|
152
|
-
if (this.bufferedAmount + bytes > maxWsBufferedAmountBytes) {
|
|
153
|
-
this.fail(new Error("WebSocket bufferedAmount limit exceeded"));
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
this.bufferedAmount += bytes;
|
|
157
|
-
return true;
|
|
94
|
+
listeners = new EventListeners();
|
|
95
|
+
abort = new AbortController();
|
|
96
|
+
stream;
|
|
97
|
+
writes = Promise.resolve();
|
|
98
|
+
constructor(input, protocols) {
|
|
99
|
+
const url = new URL(String(input), globalThis.location?.href);
|
|
100
|
+
if (!shouldProxy(url))
|
|
101
|
+
return new NativeWebSocket(input, protocols);
|
|
102
|
+
this.url = url.toString();
|
|
103
|
+
void this.connect(url, protocols);
|
|
158
104
|
}
|
|
105
|
+
addEventListener(type, listener) { this.listeners.add(type, listener); }
|
|
106
|
+
removeEventListener(type, listener) { this.listeners.remove(type, listener); }
|
|
107
|
+
dispatchEvent(event) { this.listeners.dispatch(event.type, event, this); return !event.defaultPrevented; }
|
|
159
108
|
send(data) {
|
|
160
|
-
if (this.readyState !==
|
|
161
|
-
throw new
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (!this.reserveBufferedAmount(byteLength))
|
|
166
|
-
return;
|
|
167
|
-
try {
|
|
168
|
-
this.queueWriteFrame(s, op, copyPayload(), byteLength);
|
|
169
|
-
}
|
|
170
|
-
catch (error) {
|
|
171
|
-
this.bufferedAmount = Math.max(0, this.bufferedAmount - byteLength);
|
|
172
|
-
throw error;
|
|
173
|
-
}
|
|
174
|
-
};
|
|
109
|
+
if (this.readyState !== ProxyWebSocket.OPEN || this.stream === undefined)
|
|
110
|
+
throw new DOMException("WebSocket is not open", "InvalidStateError");
|
|
111
|
+
let opcode;
|
|
112
|
+
let bytes;
|
|
113
|
+
let load;
|
|
175
114
|
if (typeof data === "string") {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
115
|
+
const encoded = encoder.encode(data);
|
|
116
|
+
opcode = 1;
|
|
117
|
+
bytes = encoded.length;
|
|
118
|
+
load = async () => encoded;
|
|
119
|
+
}
|
|
120
|
+
else if (typeof Blob !== "undefined" && data instanceof Blob) {
|
|
121
|
+
opcode = 2;
|
|
122
|
+
bytes = data.size;
|
|
123
|
+
load = async () => new Uint8Array(await data.arrayBuffer());
|
|
124
|
+
}
|
|
125
|
+
else if (ArrayBuffer.isView(data)) {
|
|
126
|
+
opcode = 2;
|
|
127
|
+
bytes = data.byteLength;
|
|
128
|
+
load = async () => new Uint8Array(data.buffer, data.byteOffset, data.byteLength).slice();
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const buffer = data;
|
|
132
|
+
opcode = 2;
|
|
133
|
+
bytes = buffer.byteLength;
|
|
134
|
+
load = async () => new Uint8Array(buffer).slice();
|
|
135
|
+
}
|
|
136
|
+
if (bytes > maxFrameBytes || this.bufferedAmount + bytes > maxBufferedBytes) {
|
|
137
|
+
this.fail();
|
|
182
138
|
return;
|
|
183
139
|
}
|
|
184
|
-
|
|
185
|
-
|
|
140
|
+
this.bufferedAmount += bytes;
|
|
141
|
+
const stream = this.stream;
|
|
142
|
+
this.writes = this.writes.then(async () => await writeFrame(stream, opcode, await load(), maxFrameBytes))
|
|
143
|
+
.catch(() => this.fail())
|
|
144
|
+
.finally(() => { this.bufferedAmount = Math.max(0, this.bufferedAmount - bytes); });
|
|
145
|
+
}
|
|
146
|
+
close(code, reason = "") {
|
|
147
|
+
if (this.readyState === ProxyWebSocket.CLOSED || this.readyState === ProxyWebSocket.CLOSING)
|
|
186
148
|
return;
|
|
149
|
+
if (code !== undefined && (code < 1000 || code > 4999 || code === 1005 || code === 1006 || code === 1015)) {
|
|
150
|
+
throw new DOMException("Invalid WebSocket close code", "InvalidAccessError");
|
|
151
|
+
}
|
|
152
|
+
const reasonBytes = encoder.encode(reason);
|
|
153
|
+
if (reasonBytes.length > 123)
|
|
154
|
+
throw new DOMException("WebSocket close reason is too long", "SyntaxError");
|
|
155
|
+
this.readyState = ProxyWebSocket.CLOSING;
|
|
156
|
+
const payload = code === undefined ? new Uint8Array() : new Uint8Array([...u16be(code), ...reasonBytes]);
|
|
157
|
+
this.writes = this.writes.then(async () => {
|
|
158
|
+
if (this.stream !== undefined)
|
|
159
|
+
await writeFrame(this.stream, 8, payload, maxFrameBytes);
|
|
160
|
+
}).catch(() => undefined).finally(() => this.abort.abort());
|
|
161
|
+
}
|
|
162
|
+
async connect(url, protocols) {
|
|
163
|
+
try {
|
|
164
|
+
const opened = await options.runtime.openWebSocketStream(url.pathname + url.search, {
|
|
165
|
+
protocols: typeof protocols === "string" ? [protocols] : protocols ?? [],
|
|
166
|
+
signal: this.abort.signal,
|
|
167
|
+
});
|
|
168
|
+
this.stream = opened.stream;
|
|
169
|
+
this.protocol = opened.protocol;
|
|
170
|
+
this.readyState = ProxyWebSocket.OPEN;
|
|
171
|
+
this.emit("open", new Event("open"));
|
|
172
|
+
await this.readLoop(opened.stream);
|
|
187
173
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return;
|
|
191
|
-
this.queueWriteFrame(s, 2, async () => new Uint8Array(await data.arrayBuffer()), data.size);
|
|
192
|
-
return;
|
|
174
|
+
catch {
|
|
175
|
+
this.fail();
|
|
193
176
|
}
|
|
194
|
-
throw new Error("unsupported WebSocket send payload");
|
|
195
177
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
payloadParts.push(u16be(code));
|
|
203
|
-
if (reason != null && reason !== "")
|
|
204
|
-
payloadParts.push(te.encode(reason));
|
|
205
|
-
const payload = payloadParts.length === 0 ? new Uint8Array() : payloadParts.reduce((a, b) => {
|
|
206
|
-
const out = new Uint8Array(a.length + b.length);
|
|
207
|
-
out.set(a, 0);
|
|
208
|
-
out.set(b, a.length);
|
|
209
|
-
return out;
|
|
210
|
-
});
|
|
211
|
-
this.writeChain = this.writeChain
|
|
212
|
-
.then(() => (this.stream ? writeWSFrame(this.stream, 8, payload, maxWsFrameBytes) : undefined))
|
|
213
|
-
.catch(() => undefined)
|
|
214
|
-
.finally(() => {
|
|
215
|
-
try {
|
|
216
|
-
this.ac.abort("closed");
|
|
178
|
+
async readLoop(stream) {
|
|
179
|
+
const reader = new ProxyByteReader(stream, { signal: this.abort.signal });
|
|
180
|
+
while (this.readyState !== ProxyWebSocket.CLOSED) {
|
|
181
|
+
const frame = await readFrame(reader, maxFrameBytes);
|
|
182
|
+
if (frame.opcode === 9) {
|
|
183
|
+
this.writes = this.writes.then(async () => await writeFrame(stream, 10, frame.payload, maxFrameBytes)).catch(() => this.fail());
|
|
217
184
|
}
|
|
218
|
-
|
|
219
|
-
|
|
185
|
+
else if (frame.opcode === 8) {
|
|
186
|
+
const code = frame.payload.length >= 2 ? readU16(frame.payload) : 1000;
|
|
187
|
+
const reason = frame.payload.length > 2 ? decoder.decode(frame.payload.subarray(2)) : "";
|
|
188
|
+
this.readyState = ProxyWebSocket.CLOSED;
|
|
189
|
+
this.emit("close", new CloseEvent("close", { code, reason, wasClean: true }));
|
|
190
|
+
return;
|
|
220
191
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
emit(type, ev) {
|
|
224
|
-
const prop = this["on" + type];
|
|
225
|
-
if (typeof prop === "function") {
|
|
226
|
-
try {
|
|
227
|
-
prop.call(this, ev);
|
|
192
|
+
else if (frame.opcode === 1) {
|
|
193
|
+
this.emit("message", new MessageEvent("message", { data: decoder.decode(frame.payload) }));
|
|
228
194
|
}
|
|
229
|
-
|
|
230
|
-
|
|
195
|
+
else if (frame.opcode === 2) {
|
|
196
|
+
const data = this.binaryType === "arraybuffer"
|
|
197
|
+
? frame.payload.slice().buffer
|
|
198
|
+
: new Blob([frame.payload.slice()]);
|
|
199
|
+
this.emit("message", new MessageEvent("message", { data }));
|
|
231
200
|
}
|
|
232
201
|
}
|
|
233
|
-
this.listeners.emit(type, ev);
|
|
234
202
|
}
|
|
235
|
-
|
|
203
|
+
emit(type, event) {
|
|
204
|
+
const callback = this[`on${type}`];
|
|
236
205
|
try {
|
|
237
|
-
|
|
238
|
-
? [protocols]
|
|
239
|
-
: Array.isArray(protocols)
|
|
240
|
-
? protocols
|
|
241
|
-
: [];
|
|
242
|
-
const { stream, protocol } = await runtime.openWebSocketStream(u.pathname + u.search, {
|
|
243
|
-
protocols: list,
|
|
244
|
-
signal: this.ac.signal
|
|
245
|
-
});
|
|
246
|
-
this.stream = stream;
|
|
247
|
-
this.protocol = protocol;
|
|
248
|
-
this.readyState = PatchedWebSocket.OPEN;
|
|
249
|
-
this.emit("open", { type: "open" });
|
|
250
|
-
this.readLoopPromise = this.readLoop(stream, this.ac.signal);
|
|
251
|
-
}
|
|
252
|
-
catch (e) {
|
|
253
|
-
this.fail(e);
|
|
206
|
+
callback?.call(this, event);
|
|
254
207
|
}
|
|
208
|
+
catch { /* User event handlers are isolated. */ }
|
|
209
|
+
this.listeners.dispatch(type, event, this);
|
|
255
210
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
try {
|
|
259
|
-
while (true) {
|
|
260
|
-
const { op, payload } = await readWSFrame(reader, maxWsFrameBytes);
|
|
261
|
-
if (op === 9) {
|
|
262
|
-
// Ping -> Pong (not exposed to WebSocket JS API).
|
|
263
|
-
// Must be serialized with user writes, otherwise concurrent writes can corrupt framing.
|
|
264
|
-
this.queueWriteFrame(stream, 10, payload);
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
if (op === 10)
|
|
268
|
-
continue;
|
|
269
|
-
if (op === 8) {
|
|
270
|
-
this.readyState = PatchedWebSocket.CLOSED;
|
|
271
|
-
const code = payload.length >= 2 ? readU16be(payload, 0) : 1000;
|
|
272
|
-
const reason = payload.length > 2 ? td.decode(payload.subarray(2)) : "";
|
|
273
|
-
this.emit("close", { type: "close", code, reason, wasClean: true });
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
if (op === 1) {
|
|
277
|
-
this.emit("message", { type: "message", data: td.decode(payload) });
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
if (op === 2) {
|
|
281
|
-
if (this.binaryType === "arraybuffer") {
|
|
282
|
-
const ab = payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength);
|
|
283
|
-
this.emit("message", { type: "message", data: ab });
|
|
284
|
-
continue;
|
|
285
|
-
}
|
|
286
|
-
if (typeof Blob !== "undefined") {
|
|
287
|
-
this.emit("message", { type: "message", data: new Blob([new Uint8Array(payload)]) });
|
|
288
|
-
continue;
|
|
289
|
-
}
|
|
290
|
-
// Fallback for non-browser contexts.
|
|
291
|
-
const ab = payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength);
|
|
292
|
-
this.emit("message", { type: "message", data: ab });
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
catch (e) {
|
|
298
|
-
if (this.readyState !== PatchedWebSocket.CLOSED)
|
|
299
|
-
this.fail(e);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
fail(e) {
|
|
303
|
-
if (this.readyState === PatchedWebSocket.CLOSED)
|
|
211
|
+
fail() {
|
|
212
|
+
if (this.readyState === ProxyWebSocket.CLOSED)
|
|
304
213
|
return;
|
|
305
|
-
this.readyState =
|
|
306
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
214
|
+
this.readyState = ProxyWebSocket.CLOSED;
|
|
307
215
|
this.bufferedAmount = 0;
|
|
308
|
-
this.emit("error",
|
|
309
|
-
this.emit("close",
|
|
310
|
-
this.stream =
|
|
311
|
-
|
|
312
|
-
this.ac.abort(msg);
|
|
313
|
-
}
|
|
314
|
-
catch {
|
|
315
|
-
// Best-effort.
|
|
316
|
-
}
|
|
216
|
+
this.emit("error", new Event("error"));
|
|
217
|
+
this.emit("close", new CloseEvent("close", { code: 1006, reason: "proxy WebSocket failed", wasClean: false }));
|
|
218
|
+
this.stream = undefined;
|
|
219
|
+
this.abort.abort();
|
|
317
220
|
}
|
|
318
221
|
}
|
|
319
|
-
globalThis.WebSocket =
|
|
320
|
-
return {
|
|
222
|
+
globalThis.WebSocket = ProxyWebSocket;
|
|
223
|
+
return Object.freeze({
|
|
224
|
+
uninstall: () => { globalThis.WebSocket = NativeWebSocket; },
|
|
225
|
+
});
|
|
321
226
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class Artifact {
|
|
2
|
+
private readonly artifactBrand;
|
|
3
|
+
private constructor();
|
|
4
|
+
}
|
|
5
|
+
export type ArtifactErrorCode = "artifact_too_large" | "invalid_artifact" | "invalid_candidate";
|
|
6
|
+
/** A stable, redacted failure returned while parsing an opaque artifact. */
|
|
7
|
+
export declare class ArtifactError extends Error {
|
|
8
|
+
readonly code: ArtifactErrorCode;
|
|
9
|
+
constructor(code: ArtifactErrorCode);
|
|
10
|
+
}
|
|
11
|
+
export declare function parseArtifact(input: string | Uint8Array): Artifact;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ArtifactV2Error, decodeArtifactV2JSON } from "../v2/artifact.js";
|
|
2
|
+
const artifactValues = new WeakMap();
|
|
3
|
+
export class Artifact {
|
|
4
|
+
constructor() { }
|
|
5
|
+
}
|
|
6
|
+
/** A stable, redacted failure returned while parsing an opaque artifact. */
|
|
7
|
+
export class ArtifactError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
constructor(code) {
|
|
10
|
+
super(`Flowersec artifact parsing failed (code=${code})`);
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.name = "ArtifactError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function parseArtifact(input) {
|
|
16
|
+
try {
|
|
17
|
+
return wrapArtifact(decodeArtifactV2JSON(input));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error instanceof ArtifactV2Error) {
|
|
21
|
+
switch (error.code) {
|
|
22
|
+
case "artifact_too_large":
|
|
23
|
+
case "invalid_candidate":
|
|
24
|
+
throw new ArtifactError(error.code);
|
|
25
|
+
default:
|
|
26
|
+
throw new ArtifactError("invalid_artifact");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
throw new ArtifactError("invalid_artifact");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** @internal */
|
|
33
|
+
export function wrapArtifact(value) {
|
|
34
|
+
const artifact = new Artifact();
|
|
35
|
+
artifactValues.set(artifact, value);
|
|
36
|
+
return Object.freeze(artifact);
|
|
37
|
+
}
|
|
38
|
+
/** @internal */
|
|
39
|
+
export function unwrapArtifact(artifact) {
|
|
40
|
+
const value = artifactValues.get(artifact);
|
|
41
|
+
if (value === undefined)
|
|
42
|
+
throw new TypeError("invalid Flowersec artifact handle");
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Artifact } from "./artifact.js";
|
|
2
|
+
export declare class ArtifactLeaseError extends Error {
|
|
3
|
+
readonly code = "already_consumed";
|
|
4
|
+
constructor();
|
|
5
|
+
}
|
|
6
|
+
export declare class ArtifactLease {
|
|
7
|
+
#private;
|
|
8
|
+
private constructor();
|
|
9
|
+
}
|
|
10
|
+
export declare function createArtifactLease(artifact: Artifact, commitSpend: (signal?: AbortSignal) => Promise<void>): ArtifactLease;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { validateArtifactV2 } from "../v2/artifact.js";
|
|
2
|
+
import { unwrapArtifact } from "./artifact.js";
|
|
3
|
+
export class ArtifactLeaseError extends Error {
|
|
4
|
+
code = "already_consumed";
|
|
5
|
+
constructor() {
|
|
6
|
+
super("Flowersec artifact lease has already been consumed");
|
|
7
|
+
this.name = "ArtifactLeaseError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class ArtifactLease {
|
|
11
|
+
#artifactLeaseBrand = undefined;
|
|
12
|
+
constructor() {
|
|
13
|
+
Object.freeze(this);
|
|
14
|
+
}
|
|
15
|
+
/** @internal */
|
|
16
|
+
static create() {
|
|
17
|
+
return new ArtifactLease();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const artifactLeaseStates = new WeakMap();
|
|
21
|
+
export function createArtifactLease(artifact, commitSpend) {
|
|
22
|
+
validateArtifactV2(unwrapArtifact(artifact));
|
|
23
|
+
const lease = ArtifactLease.create();
|
|
24
|
+
artifactLeaseStates.set(lease, { artifact, state: "idle", commitSpend });
|
|
25
|
+
return lease;
|
|
26
|
+
}
|
|
27
|
+
/** @internal Connector-owned access to validated lease material. */
|
|
28
|
+
export function artifactLeaseArtifact(lease) {
|
|
29
|
+
const leaseState = artifactLeaseStates.get(lease);
|
|
30
|
+
if (leaseState === undefined)
|
|
31
|
+
throw new ArtifactLeaseError();
|
|
32
|
+
return leaseState.artifact;
|
|
33
|
+
}
|
|
34
|
+
/** @internal Connector-owned durable spend transition. */
|
|
35
|
+
export async function commitArtifactLeaseSpend(lease, signal) {
|
|
36
|
+
const leaseState = artifactLeaseStates.get(lease);
|
|
37
|
+
if (leaseState === undefined || leaseState.state !== "idle")
|
|
38
|
+
throw new ArtifactLeaseError();
|
|
39
|
+
leaseState.state = "spending";
|
|
40
|
+
try {
|
|
41
|
+
await leaseState.commitSpend(signal);
|
|
42
|
+
leaseState.state = "consumed";
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
leaseState.state = "idle";
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type ConnectErrorCode = "invalid_input" | "invalid_options" | "expired_artifact" | "resolve_failed" | "credential_spend_failed" | "connection_failed" | "timeout" | "canceled" | "handshake_failed" | "rpc_failed" | "resource_exhausted" | "not_connected";
|
|
2
|
+
/** A stable connection failure that retains no carrier or credential details. */
|
|
3
|
+
export declare class ConnectError extends Error {
|
|
4
|
+
readonly code: ConnectErrorCode;
|
|
5
|
+
constructor(code: ConnectErrorCode);
|
|
6
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** A stable connection failure that retains no carrier or credential details. */
|
|
2
|
+
export class ConnectError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code) {
|
|
5
|
+
super(`Flowersec connection failed (code=${code})`);
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.name = "ConnectError";
|
|
8
|
+
}
|
|
9
|
+
}
|