@replit/river 0.200.0-rc.9 → 0.200.2
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 +8 -8
- package/dist/{chunk-42Z2FQIU.js → chunk-6BH2CXVE.js} +21 -13
- package/dist/chunk-6BH2CXVE.js.map +1 -0
- package/dist/{chunk-4HT6P2ZG.js → chunk-A4JKES5A.js} +22 -30
- package/dist/chunk-A4JKES5A.js.map +1 -0
- package/dist/{chunk-4PVU7J25.js → chunk-AJGIY2UB.js} +1 -1
- package/dist/chunk-AJGIY2UB.js.map +1 -0
- package/dist/{chunk-EETL2L77.js → chunk-GJUUVID2.js} +14 -32
- package/dist/chunk-GJUUVID2.js.map +1 -0
- package/dist/{chunk-GR3AQKHL.js → chunk-HRKM7BIE.js} +14 -4
- package/dist/chunk-HRKM7BIE.js.map +1 -0
- package/dist/{chunk-ZXZE253M.js → chunk-PJB2Y2AV.js} +24 -37
- package/dist/chunk-PJB2Y2AV.js.map +1 -0
- package/dist/{chunk-I75XYO5W.js → chunk-QIDEN5PP.js} +82 -20
- package/dist/chunk-QIDEN5PP.js.map +1 -0
- package/dist/{chunk-VXYHC666.js → chunk-YTMS7OP6.js} +1 -1
- package/dist/chunk-YTMS7OP6.js.map +1 -0
- package/dist/chunk-Z4PX66JO.js +307 -0
- package/dist/chunk-Z4PX66JO.js.map +1 -0
- package/dist/{client-22a47343.d.ts → client-9292552a.d.ts} +3 -4
- package/dist/codec/index.cjs.map +1 -1
- package/dist/codec/index.js +1 -1
- package/dist/connection-94dea547.d.ts +32 -0
- package/dist/{context-b4aff18f.d.ts → context-69f37ac1.d.ts} +48 -43
- package/dist/logging/index.cjs.map +1 -1
- package/dist/logging/index.d.cts +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +1 -1
- package/dist/{message-7d135e38.d.ts → message-57bb8187.d.ts} +5 -3
- package/dist/router/index.cjs +649 -709
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +22 -12
- package/dist/router/index.d.ts +22 -12
- package/dist/router/index.js +502 -404
- package/dist/router/index.js.map +1 -1
- package/dist/{server-dd6a9853.d.ts → server-8fdd7fb2.d.ts} +5 -5
- package/dist/{services-1b5ac5bc.d.ts → services-259f39a3.d.ts} +191 -194
- package/dist/transport/impls/ws/client.cjs +129 -62
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +4 -4
- package/dist/transport/impls/ws/client.d.ts +4 -4
- package/dist/transport/impls/ws/client.js +7 -7
- package/dist/transport/impls/ws/client.js.map +1 -1
- package/dist/transport/impls/ws/server.cjs +146 -70
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +6 -5
- package/dist/transport/impls/ws/server.d.ts +6 -5
- package/dist/transport/impls/ws/server.js +21 -9
- package/dist/transport/impls/ws/server.js.map +1 -1
- package/dist/transport/index.cjs +138 -92
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +4 -4
- package/dist/transport/index.d.ts +4 -4
- package/dist/transport/index.js +7 -7
- package/dist/util/testHelpers.cjs +265 -327
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +36 -31
- package/dist/util/testHelpers.d.ts +36 -31
- package/dist/util/testHelpers.js +82 -52
- package/dist/util/testHelpers.js.map +1 -1
- package/package.json +4 -3
- package/dist/chunk-42Z2FQIU.js.map +0 -1
- package/dist/chunk-4HT6P2ZG.js.map +0 -1
- package/dist/chunk-4PVU7J25.js.map +0 -1
- package/dist/chunk-EETL2L77.js.map +0 -1
- package/dist/chunk-GR3AQKHL.js.map +0 -1
- package/dist/chunk-I75XYO5W.js.map +0 -1
- package/dist/chunk-MQ6ANR3H.js +0 -451
- package/dist/chunk-MQ6ANR3H.js.map +0 -1
- package/dist/chunk-VXYHC666.js.map +0 -1
- package/dist/chunk-ZXZE253M.js.map +0 -1
- package/dist/connection-260e45a8.d.ts +0 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { C as ClientTransport } from '../../../client-
|
|
2
|
-
import { c as TransportClientId } from '../../../message-
|
|
3
|
-
import { b as ProvidedClientTransportOptions } from '../../../context-
|
|
4
|
-
import { W as WebSocketConnection } from '../../../connection-
|
|
1
|
+
import { C as ClientTransport } from '../../../client-9292552a.js';
|
|
2
|
+
import { c as TransportClientId } from '../../../message-57bb8187.js';
|
|
3
|
+
import { b as ProvidedClientTransportOptions } from '../../../context-69f37ac1.js';
|
|
4
|
+
import { W as WebSocketConnection } from '../../../connection-94dea547.js';
|
|
5
5
|
import { W as WsLike } from '../../../wslike-e0b32dd5.js';
|
|
6
6
|
import '@sinclair/typebox/value';
|
|
7
7
|
import '@sinclair/typebox';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { C as ClientTransport } from '../../../client-
|
|
2
|
-
import { c as TransportClientId } from '../../../message-
|
|
3
|
-
import { b as ProvidedClientTransportOptions } from '../../../context-
|
|
4
|
-
import { W as WebSocketConnection } from '../../../connection-
|
|
1
|
+
import { C as ClientTransport } from '../../../client-9292552a.js';
|
|
2
|
+
import { c as TransportClientId } from '../../../message-57bb8187.js';
|
|
3
|
+
import { b as ProvidedClientTransportOptions } from '../../../context-69f37ac1.js';
|
|
4
|
+
import { W as WebSocketConnection } from '../../../connection-94dea547.js';
|
|
5
5
|
import { W as WsLike } from '../../../wslike-e0b32dd5.js';
|
|
6
6
|
import '@sinclair/typebox/value';
|
|
7
7
|
import '@sinclair/typebox';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ClientTransport
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-A4JKES5A.js";
|
|
4
4
|
import {
|
|
5
5
|
WebSocketConnection
|
|
6
|
-
} from "../../../chunk-
|
|
7
|
-
import "../../../chunk-
|
|
8
|
-
import "../../../chunk-
|
|
9
|
-
import "../../../chunk-
|
|
10
|
-
import "../../../chunk-
|
|
11
|
-
import "../../../chunk-
|
|
6
|
+
} from "../../../chunk-HRKM7BIE.js";
|
|
7
|
+
import "../../../chunk-QIDEN5PP.js";
|
|
8
|
+
import "../../../chunk-YTMS7OP6.js";
|
|
9
|
+
import "../../../chunk-6BH2CXVE.js";
|
|
10
|
+
import "../../../chunk-GJUUVID2.js";
|
|
11
|
+
import "../../../chunk-AJGIY2UB.js";
|
|
12
12
|
|
|
13
13
|
// transport/impls/ws/client.ts
|
|
14
14
|
var WebSocketClientTransport = class extends ClientTransport {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../transport/impls/ws/client.ts"],"sourcesContent":["import { ClientTransport } from '../../client';\nimport { TransportClientId } from '../../message';\nimport { ProvidedClientTransportOptions } from '../../options';\nimport { WebSocketConnection } from './connection';\nimport { WsLike } from './wslike';\n\n/**\n * A transport implementation that uses a WebSocket connection with automatic reconnection.\n * @class\n * @extends Transport\n */\nexport class WebSocketClientTransport extends ClientTransport<WebSocketConnection> {\n /**\n * A function that returns a Promise that resolves to a websocket URL.\n */\n wsGetter: (to: TransportClientId) => Promise<WsLike> | WsLike;\n\n /**\n * Creates a new WebSocketClientTransport instance.\n * @param wsGetter A function that returns a Promise that resolves to a WebSocket instance.\n * @param clientId The ID of the client using the transport. This should be unique per session.\n * @param serverId The ID of the server this transport is connecting to.\n * @param providedOptions An optional object containing configuration options for the transport.\n */\n constructor(\n wsGetter: (to: TransportClientId) => Promise<WsLike> | WsLike,\n clientId: TransportClientId,\n providedOptions?: ProvidedClientTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.wsGetter = wsGetter;\n }\n\n async createNewOutgoingConnection(to: string) {\n this.log?.info(`establishing a new websocket to ${to}`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n\n const ws = await this.wsGetter(to);\n\n await new Promise<void>((resolve, reject) => {\n if (ws.readyState === ws.OPEN) {\n resolve();\n return;\n }\n\n if (ws.readyState === ws.CLOSING || ws.readyState === ws.CLOSED) {\n reject(new Error('ws is closing or closed'));\n return;\n }\n\n ws.onopen = () => {\n resolve();\n };\n\n ws.onclose = (evt) => {\n reject(new Error(evt.reason));\n };\n\n ws.onerror = (err) => {\n reject(new Error(err.message));\n };\n });\n\n const conn = new WebSocketConnection(ws);\n this.log?.info(`raw websocket to ${to} ok`, {\n clientId: this.clientId,\n connectedTo: to,\n ...conn.loggingMetadata,\n });\n\n return conn;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAWO,IAAM,2BAAN,cAAuC,gBAAqC;AAAA;AAAA;AAAA;AAAA,EAIjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACE,UACA,UACA,iBACA;AACA,UAAM,UAAU,eAAe;AAC/B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,MAAM,4BAA4B,IAAY;AAC5C,SAAK,KAAK,KAAK,mCAAmC,EAAE,IAAI;AAAA,MACtD,UAAU,KAAK;AAAA,MACf,aAAa;AAAA,IACf,CAAC;AAED,UAAM,KAAK,MAAM,KAAK,SAAS,EAAE;AAEjC,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,UAAI,GAAG,eAAe,GAAG,MAAM;AAC7B,gBAAQ;
|
|
1
|
+
{"version":3,"sources":["../../../../transport/impls/ws/client.ts"],"sourcesContent":["import { ClientTransport } from '../../client';\nimport { TransportClientId } from '../../message';\nimport { ProvidedClientTransportOptions } from '../../options';\nimport { WebSocketConnection } from './connection';\nimport { WsLike } from './wslike';\n\n/**\n * A transport implementation that uses a WebSocket connection with automatic reconnection.\n * @class\n * @extends Transport\n */\nexport class WebSocketClientTransport extends ClientTransport<WebSocketConnection> {\n /**\n * A function that returns a Promise that resolves to a websocket URL.\n */\n wsGetter: (to: TransportClientId) => Promise<WsLike> | WsLike;\n\n /**\n * Creates a new WebSocketClientTransport instance.\n * @param wsGetter A function that returns a Promise that resolves to a WebSocket instance.\n * @param clientId The ID of the client using the transport. This should be unique per session.\n * @param serverId The ID of the server this transport is connecting to.\n * @param providedOptions An optional object containing configuration options for the transport.\n */\n constructor(\n wsGetter: (to: TransportClientId) => Promise<WsLike> | WsLike,\n clientId: TransportClientId,\n providedOptions?: ProvidedClientTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.wsGetter = wsGetter;\n }\n\n async createNewOutgoingConnection(to: string) {\n this.log?.info(`establishing a new websocket to ${to}`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n\n const ws = await this.wsGetter(to);\n\n await new Promise<void>((resolve, reject) => {\n if (ws.readyState === ws.OPEN) {\n resolve();\n\n return;\n }\n\n if (ws.readyState === ws.CLOSING || ws.readyState === ws.CLOSED) {\n reject(new Error('ws is closing or closed'));\n\n return;\n }\n\n ws.onopen = () => {\n resolve();\n };\n\n ws.onclose = (evt) => {\n reject(new Error(evt.reason));\n };\n\n ws.onerror = (err) => {\n reject(new Error(err.message));\n };\n });\n\n const conn = new WebSocketConnection(ws);\n this.log?.info(`raw websocket to ${to} ok`, {\n clientId: this.clientId,\n connectedTo: to,\n ...conn.loggingMetadata,\n });\n\n return conn;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAWO,IAAM,2BAAN,cAAuC,gBAAqC;AAAA;AAAA;AAAA;AAAA,EAIjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACE,UACA,UACA,iBACA;AACA,UAAM,UAAU,eAAe;AAC/B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,MAAM,4BAA4B,IAAY;AAC5C,SAAK,KAAK,KAAK,mCAAmC,EAAE,IAAI;AAAA,MACtD,UAAU,KAAK;AAAA,MACf,aAAa;AAAA,IACf,CAAC;AAED,UAAM,KAAK,MAAM,KAAK,SAAS,EAAE;AAEjC,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,UAAI,GAAG,eAAe,GAAG,MAAM;AAC7B,gBAAQ;AAER;AAAA,MACF;AAEA,UAAI,GAAG,eAAe,GAAG,WAAW,GAAG,eAAe,GAAG,QAAQ;AAC/D,eAAO,IAAI,MAAM,yBAAyB,CAAC;AAE3C;AAAA,MACF;AAEA,SAAG,SAAS,MAAM;AAChB,gBAAQ;AAAA,MACV;AAEA,SAAG,UAAU,CAAC,QAAQ;AACpB,eAAO,IAAI,MAAM,IAAI,MAAM,CAAC;AAAA,MAC9B;AAEA,SAAG,UAAU,CAAC,QAAQ;AACpB,eAAO,IAAI,MAAM,IAAI,OAAO,CAAC;AAAA,MAC/B;AAAA,IACF,CAAC;AAED,UAAM,OAAO,IAAI,oBAAoB,EAAE;AACvC,SAAK,KAAK,KAAK,oBAAoB,EAAE,OAAO;AAAA,MAC1C,UAAU,KAAK;AAAA,MACf,aAAa;AAAA,MACb,GAAG,KAAK;AAAA,IACV,CAAC;AAED,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -103,11 +103,21 @@ var Connection = class {
|
|
|
103
103
|
};
|
|
104
104
|
|
|
105
105
|
// transport/impls/ws/connection.ts
|
|
106
|
+
var WS_HEALTHY_CLOSE_CODE = 1e3;
|
|
106
107
|
var WebSocketConnection = class extends Connection {
|
|
107
108
|
ws;
|
|
108
|
-
|
|
109
|
+
extras;
|
|
110
|
+
get loggingMetadata() {
|
|
111
|
+
const metadata = super.loggingMetadata;
|
|
112
|
+
if (this.extras) {
|
|
113
|
+
metadata.extras = this.extras;
|
|
114
|
+
}
|
|
115
|
+
return metadata;
|
|
116
|
+
}
|
|
117
|
+
constructor(ws, extras) {
|
|
109
118
|
super();
|
|
110
119
|
this.ws = ws;
|
|
120
|
+
this.extras = extras;
|
|
111
121
|
this.ws.binaryType = "arraybuffer";
|
|
112
122
|
let didError = false;
|
|
113
123
|
this.ws.onerror = () => {
|
|
@@ -140,7 +150,7 @@ var WebSocketConnection = class extends Connection {
|
|
|
140
150
|
return true;
|
|
141
151
|
}
|
|
142
152
|
close() {
|
|
143
|
-
this.ws.close();
|
|
153
|
+
this.ws.close(WS_HEALTHY_CLOSE_CODE);
|
|
144
154
|
}
|
|
145
155
|
};
|
|
146
156
|
|
|
@@ -175,6 +185,9 @@ var ControlMessageCloseSchema = import_typebox.Type.Object({
|
|
|
175
185
|
});
|
|
176
186
|
var currentProtocolVersion = "v2.0";
|
|
177
187
|
var acceptedProtocolVersions = ["v1.1", currentProtocolVersion];
|
|
188
|
+
function isAcceptedProtocolVersion(version2) {
|
|
189
|
+
return acceptedProtocolVersions.includes(version2);
|
|
190
|
+
}
|
|
178
191
|
var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
|
|
179
192
|
type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
|
|
180
193
|
protocolVersion: import_typebox.Type.String(),
|
|
@@ -187,10 +200,7 @@ var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
|
|
|
187
200
|
expectedSessionState: import_typebox.Type.Object({
|
|
188
201
|
// what the client expects the server to send next
|
|
189
202
|
nextExpectedSeq: import_typebox.Type.Integer(),
|
|
190
|
-
|
|
191
|
-
// are nextSentSeq here
|
|
192
|
-
// what the server expects the client to send next
|
|
193
|
-
nextSentSeq: import_typebox.Type.Optional(import_typebox.Type.Integer())
|
|
203
|
+
nextSentSeq: import_typebox.Type.Integer()
|
|
194
204
|
}),
|
|
195
205
|
metadata: import_typebox.Type.Optional(import_typebox.Type.Unknown())
|
|
196
206
|
});
|
|
@@ -226,9 +236,7 @@ var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
|
|
|
226
236
|
import_typebox.Type.Object({
|
|
227
237
|
ok: import_typebox.Type.Literal(false),
|
|
228
238
|
reason: import_typebox.Type.String(),
|
|
229
|
-
|
|
230
|
-
// are sending code here
|
|
231
|
-
code: import_typebox.Type.Optional(HandshakeErrorResponseCodes)
|
|
239
|
+
code: HandshakeErrorResponseCodes
|
|
232
240
|
})
|
|
233
241
|
])
|
|
234
242
|
});
|
|
@@ -398,7 +406,8 @@ var createLogProxy = (log) => ({
|
|
|
398
406
|
var ProtocolError = {
|
|
399
407
|
RetriesExceeded: "conn_retry_exceeded",
|
|
400
408
|
HandshakeFailed: "handshake_failed",
|
|
401
|
-
MessageOrderingViolated: "message_ordering_violated"
|
|
409
|
+
MessageOrderingViolated: "message_ordering_violated",
|
|
410
|
+
InvalidMessage: "invalid_message"
|
|
402
411
|
};
|
|
403
412
|
var EventDispatcher = class {
|
|
404
413
|
eventListeners = {};
|
|
@@ -676,7 +685,7 @@ var SessionNoConnection = class extends IdentifiedSessionWithGracePeriod {
|
|
|
676
685
|
var import_api = require("@opentelemetry/api");
|
|
677
686
|
|
|
678
687
|
// package.json
|
|
679
|
-
var version = "0.200.
|
|
688
|
+
var version = "0.200.2";
|
|
680
689
|
|
|
681
690
|
// tracing/index.ts
|
|
682
691
|
function createSessionTelemetryInfo(sessionId, to, from, propagationCtx) {
|
|
@@ -829,13 +838,13 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
829
838
|
this.conn.addCloseListener(this.listeners.onConnectionClosed);
|
|
830
839
|
this.conn.addErrorListener(this.listeners.onConnectionErrored);
|
|
831
840
|
if (this.sendBuffer.length > 0) {
|
|
832
|
-
this.log?.
|
|
833
|
-
`sending ${this.sendBuffer.length} buffered messages`,
|
|
841
|
+
this.log?.info(
|
|
842
|
+
`sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
|
|
834
843
|
this.loggingMetadata
|
|
835
844
|
);
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
845
|
+
for (const msg of this.sendBuffer) {
|
|
846
|
+
this.conn.send(this.options.codec.toBuffer(msg));
|
|
847
|
+
}
|
|
839
848
|
}
|
|
840
849
|
this.isActivelyHeartbeating = false;
|
|
841
850
|
this.heartbeatHandle = setInterval(() => {
|
|
@@ -877,6 +886,12 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
877
886
|
}
|
|
878
887
|
});
|
|
879
888
|
}
|
|
889
|
+
closeConnection() {
|
|
890
|
+
this.conn.removeDataListener(this.onMessageData);
|
|
891
|
+
this.conn.removeCloseListener(this.listeners.onConnectionClosed);
|
|
892
|
+
this.conn.removeErrorListener(this.listeners.onConnectionErrored);
|
|
893
|
+
this.conn.close();
|
|
894
|
+
}
|
|
880
895
|
onMessageData = (msg) => {
|
|
881
896
|
const parsedMsg = this.parseMsg(msg);
|
|
882
897
|
if (parsedMsg === null) {
|
|
@@ -893,8 +908,8 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
893
908
|
}
|
|
894
909
|
);
|
|
895
910
|
} else {
|
|
896
|
-
const reason = `received out-of-order msg (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack})`;
|
|
897
|
-
this.log?.
|
|
911
|
+
const reason = `received out-of-order msg, closing connection (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack})`;
|
|
912
|
+
this.log?.warn(reason, {
|
|
898
913
|
...this.loggingMetadata,
|
|
899
914
|
transportMessage: parsedMsg,
|
|
900
915
|
tags: ["invariant-violation"]
|
|
@@ -903,7 +918,7 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
903
918
|
code: import_api2.SpanStatusCode.ERROR,
|
|
904
919
|
message: reason
|
|
905
920
|
});
|
|
906
|
-
this.
|
|
921
|
+
this.closeConnection();
|
|
907
922
|
}
|
|
908
923
|
return;
|
|
909
924
|
}
|
|
@@ -929,8 +944,10 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
929
944
|
this.conn.removeDataListener(this.onMessageData);
|
|
930
945
|
this.conn.removeCloseListener(this.listeners.onConnectionClosed);
|
|
931
946
|
this.conn.removeErrorListener(this.listeners.onConnectionErrored);
|
|
932
|
-
|
|
933
|
-
|
|
947
|
+
if (this.heartbeatHandle) {
|
|
948
|
+
clearInterval(this.heartbeatHandle);
|
|
949
|
+
this.heartbeatHandle = void 0;
|
|
950
|
+
}
|
|
934
951
|
}
|
|
935
952
|
_handleClose() {
|
|
936
953
|
super._handleClose();
|
|
@@ -1297,12 +1314,12 @@ var Transport = class {
|
|
|
1297
1314
|
/**
|
|
1298
1315
|
* Called when a message is received by this transport.
|
|
1299
1316
|
* You generally shouldn't need to override this in downstream transport implementations.
|
|
1300
|
-
* @param
|
|
1317
|
+
* @param message The received message.
|
|
1301
1318
|
*/
|
|
1302
|
-
handleMsg(
|
|
1319
|
+
handleMsg(message) {
|
|
1303
1320
|
if (this.getStatus() !== "open")
|
|
1304
1321
|
return;
|
|
1305
|
-
this.eventDispatcher.dispatchEvent("message",
|
|
1322
|
+
this.eventDispatcher.dispatchEvent("message", message);
|
|
1306
1323
|
}
|
|
1307
1324
|
/**
|
|
1308
1325
|
* Adds a listener to this transport.
|
|
@@ -1342,28 +1359,59 @@ var Transport = class {
|
|
|
1342
1359
|
getStatus() {
|
|
1343
1360
|
return this.status;
|
|
1344
1361
|
}
|
|
1345
|
-
|
|
1362
|
+
// state transitions
|
|
1363
|
+
createSession(session) {
|
|
1346
1364
|
const activeSession = this.sessions.get(session.to);
|
|
1347
|
-
if (activeSession
|
|
1348
|
-
const msg = `attempt to
|
|
1365
|
+
if (activeSession) {
|
|
1366
|
+
const msg = `attempt to create session for ${session.to} but active session (${activeSession.id}) already exists`;
|
|
1367
|
+
this.log?.error(msg, {
|
|
1368
|
+
...session.loggingMetadata,
|
|
1369
|
+
tags: ["invariant-violation"]
|
|
1370
|
+
});
|
|
1349
1371
|
throw new Error(msg);
|
|
1350
1372
|
}
|
|
1351
1373
|
this.sessions.set(session.to, session);
|
|
1374
|
+
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
1375
|
+
status: "connect",
|
|
1376
|
+
session
|
|
1377
|
+
});
|
|
1378
|
+
this.eventDispatcher.dispatchEvent("sessionTransition", {
|
|
1379
|
+
state: session.state,
|
|
1380
|
+
session
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
updateSession(session) {
|
|
1384
|
+
const activeSession = this.sessions.get(session.to);
|
|
1352
1385
|
if (!activeSession) {
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
session
|
|
1386
|
+
const msg = `attempt to transition session for ${session.to} but no active session exists`;
|
|
1387
|
+
this.log?.error(msg, {
|
|
1388
|
+
...session.loggingMetadata,
|
|
1389
|
+
tags: ["invariant-violation"]
|
|
1390
|
+
});
|
|
1391
|
+
throw new Error(msg);
|
|
1392
|
+
}
|
|
1393
|
+
if (activeSession.id !== session.id) {
|
|
1394
|
+
const msg = `attempt to transition active session for ${session.to} but active session (${activeSession.id}) is different from handle (${session.id})`;
|
|
1395
|
+
this.log?.error(msg, {
|
|
1396
|
+
...session.loggingMetadata,
|
|
1397
|
+
tags: ["invariant-violation"]
|
|
1356
1398
|
});
|
|
1399
|
+
throw new Error(msg);
|
|
1357
1400
|
}
|
|
1401
|
+
this.sessions.set(session.to, session);
|
|
1358
1402
|
this.eventDispatcher.dispatchEvent("sessionTransition", {
|
|
1359
1403
|
state: session.state,
|
|
1360
1404
|
session
|
|
1361
1405
|
});
|
|
1362
|
-
return session;
|
|
1363
1406
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1407
|
+
deleteSession(session, options) {
|
|
1408
|
+
if (session._isConsumed)
|
|
1409
|
+
return;
|
|
1410
|
+
const loggingMetadata = session.loggingMetadata;
|
|
1411
|
+
if (loggingMetadata.tags && options?.unhealthy) {
|
|
1412
|
+
loggingMetadata.tags.push("unhealthy-session");
|
|
1413
|
+
}
|
|
1414
|
+
session.log?.info(`closing session ${session.id}`, loggingMetadata);
|
|
1367
1415
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
1368
1416
|
status: "disconnect",
|
|
1369
1417
|
session
|
|
@@ -1386,7 +1434,8 @@ var Transport = class {
|
|
|
1386
1434
|
this.onSessionGracePeriodElapsed(noConnectionSession);
|
|
1387
1435
|
}
|
|
1388
1436
|
});
|
|
1389
|
-
|
|
1437
|
+
this.updateSession(noConnectionSession);
|
|
1438
|
+
return noConnectionSession;
|
|
1390
1439
|
}
|
|
1391
1440
|
onConnClosed(session) {
|
|
1392
1441
|
let noConnectionSession;
|
|
@@ -1403,7 +1452,36 @@ var Transport = class {
|
|
|
1403
1452
|
}
|
|
1404
1453
|
});
|
|
1405
1454
|
}
|
|
1406
|
-
|
|
1455
|
+
this.updateSession(noConnectionSession);
|
|
1456
|
+
return noConnectionSession;
|
|
1457
|
+
}
|
|
1458
|
+
/**
|
|
1459
|
+
* Gets a send closure scoped to a specific session. Sending using the returned
|
|
1460
|
+
* closure after the session has transitioned to a different state will be a noop.
|
|
1461
|
+
*
|
|
1462
|
+
* Session objects themselves can become stale as they transition between
|
|
1463
|
+
* states. As stale sessions cannot be used again (and will throw), holding
|
|
1464
|
+
* onto a session object is not recommended.
|
|
1465
|
+
*/
|
|
1466
|
+
getSessionBoundSendFn(to, sessionId) {
|
|
1467
|
+
if (this.getStatus() !== "open") {
|
|
1468
|
+
throw new Error("cannot get a bound send function on a closed transport");
|
|
1469
|
+
}
|
|
1470
|
+
return (msg) => {
|
|
1471
|
+
const session = this.sessions.get(to);
|
|
1472
|
+
if (!session) {
|
|
1473
|
+
throw new Error(
|
|
1474
|
+
`session scope for ${sessionId} has ended (close), can't send`
|
|
1475
|
+
);
|
|
1476
|
+
}
|
|
1477
|
+
const sameSession = session.id === sessionId;
|
|
1478
|
+
if (!sameSession) {
|
|
1479
|
+
throw new Error(
|
|
1480
|
+
`session scope for ${sessionId} has ended (transition), can't send`
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1483
|
+
return session.send(msg);
|
|
1484
|
+
};
|
|
1407
1485
|
}
|
|
1408
1486
|
};
|
|
1409
1487
|
|
|
@@ -1447,35 +1525,13 @@ var ServerTransport = class extends Transport {
|
|
|
1447
1525
|
extendHandshake(options) {
|
|
1448
1526
|
this.handshakeExtensions = options;
|
|
1449
1527
|
}
|
|
1450
|
-
send(to, msg) {
|
|
1451
|
-
if (this.getStatus() === "closed") {
|
|
1452
|
-
const err = "transport is closed, cant send";
|
|
1453
|
-
this.log?.error(err, {
|
|
1454
|
-
clientId: this.clientId,
|
|
1455
|
-
transportMessage: msg,
|
|
1456
|
-
tags: ["invariant-violation"]
|
|
1457
|
-
});
|
|
1458
|
-
throw new Error(err);
|
|
1459
|
-
}
|
|
1460
|
-
const session = this.sessions.get(to);
|
|
1461
|
-
if (!session) {
|
|
1462
|
-
const err = `session to ${to} does not exist`;
|
|
1463
|
-
this.log?.error(err, {
|
|
1464
|
-
clientId: this.clientId,
|
|
1465
|
-
transportMessage: msg,
|
|
1466
|
-
tags: ["invariant-violation"]
|
|
1467
|
-
});
|
|
1468
|
-
throw new Error(err);
|
|
1469
|
-
}
|
|
1470
|
-
return session.send(msg);
|
|
1471
|
-
}
|
|
1472
1528
|
deletePendingSession(pendingSession) {
|
|
1473
1529
|
pendingSession.close();
|
|
1474
1530
|
this.pendingSessions.delete(pendingSession);
|
|
1475
1531
|
}
|
|
1476
|
-
deleteSession(session) {
|
|
1532
|
+
deleteSession(session, options) {
|
|
1477
1533
|
this.sessionHandshakeMetadata.delete(session.to);
|
|
1478
|
-
super.deleteSession(session);
|
|
1534
|
+
super.deleteSession(session, options);
|
|
1479
1535
|
}
|
|
1480
1536
|
handleConnection(conn) {
|
|
1481
1537
|
if (this.getStatus() !== "open")
|
|
@@ -1588,7 +1644,7 @@ var ServerTransport = class extends Transport {
|
|
|
1588
1644
|
return;
|
|
1589
1645
|
}
|
|
1590
1646
|
const gotVersion = msg.payload.protocolVersion;
|
|
1591
|
-
if (!
|
|
1647
|
+
if (!isAcceptedProtocolVersion(gotVersion)) {
|
|
1592
1648
|
this.rejectHandshakeRequest(
|
|
1593
1649
|
session,
|
|
1594
1650
|
msg.from,
|
|
@@ -1602,7 +1658,6 @@ var ServerTransport = class extends Transport {
|
|
|
1602
1658
|
);
|
|
1603
1659
|
return;
|
|
1604
1660
|
}
|
|
1605
|
-
let oldSession = this.sessions.get(msg.from);
|
|
1606
1661
|
let parsedMetadata = {};
|
|
1607
1662
|
if (this.handshakeExtensions) {
|
|
1608
1663
|
if (!import_value2.Value.Check(this.handshakeExtensions.schema, msg.payload.metadata)) {
|
|
@@ -1624,7 +1679,9 @@ var ServerTransport = class extends Transport {
|
|
|
1624
1679
|
);
|
|
1625
1680
|
return;
|
|
1626
1681
|
}
|
|
1627
|
-
const previousParsedMetadata =
|
|
1682
|
+
const previousParsedMetadata = this.sessionHandshakeMetadata.get(
|
|
1683
|
+
msg.from
|
|
1684
|
+
);
|
|
1628
1685
|
const parsedMetadataOrFailureCode = await this.handshakeExtensions.validate(
|
|
1629
1686
|
msg.payload.metadata,
|
|
1630
1687
|
previousParsedMetadata
|
|
@@ -1653,7 +1710,8 @@ var ServerTransport = class extends Transport {
|
|
|
1653
1710
|
}
|
|
1654
1711
|
let connectCase = "new session";
|
|
1655
1712
|
const clientNextExpectedSeq = msg.payload.expectedSessionState.nextExpectedSeq;
|
|
1656
|
-
const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq
|
|
1713
|
+
const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq;
|
|
1714
|
+
let oldSession = this.sessions.get(msg.from);
|
|
1657
1715
|
if (this.options.enableTransparentSessionReconnects && oldSession && oldSession.id === msg.payload.sessionId) {
|
|
1658
1716
|
connectCase = "transparent reconnection";
|
|
1659
1717
|
const ourNextSeq = oldSession.nextSeq();
|
|
@@ -1766,25 +1824,41 @@ var ServerTransport = class extends Transport {
|
|
|
1766
1824
|
);
|
|
1767
1825
|
this.onConnClosed(connectedSession);
|
|
1768
1826
|
},
|
|
1769
|
-
onMessage: (msg2) =>
|
|
1827
|
+
onMessage: (msg2) => {
|
|
1828
|
+
this.handleMsg(msg2);
|
|
1829
|
+
},
|
|
1770
1830
|
onInvalidMessage: (reason) => {
|
|
1771
1831
|
this.protocolError({
|
|
1772
|
-
type: ProtocolError.
|
|
1832
|
+
type: ProtocolError.InvalidMessage,
|
|
1773
1833
|
message: reason
|
|
1774
1834
|
});
|
|
1775
|
-
this.deleteSession(connectedSession);
|
|
1835
|
+
this.deleteSession(connectedSession, { unhealthy: true });
|
|
1776
1836
|
}
|
|
1777
1837
|
},
|
|
1778
1838
|
gotVersion
|
|
1779
1839
|
);
|
|
1780
1840
|
this.sessionHandshakeMetadata.set(connectedSession.to, parsedMetadata);
|
|
1781
|
-
|
|
1841
|
+
if (oldSession) {
|
|
1842
|
+
this.updateSession(connectedSession);
|
|
1843
|
+
} else {
|
|
1844
|
+
this.createSession(connectedSession);
|
|
1845
|
+
}
|
|
1782
1846
|
this.pendingSessions.delete(session);
|
|
1783
1847
|
connectedSession.startActiveHeartbeat();
|
|
1784
1848
|
}
|
|
1785
1849
|
};
|
|
1786
1850
|
|
|
1787
1851
|
// transport/impls/ws/server.ts
|
|
1852
|
+
function cleanHeaders(headers) {
|
|
1853
|
+
const cleanedHeaders = {};
|
|
1854
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1855
|
+
if (!key.startsWith("sec-") && value) {
|
|
1856
|
+
const cleanedValue = Array.isArray(value) ? value[0] : value;
|
|
1857
|
+
cleanedHeaders[key] = cleanedValue;
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
return cleanedHeaders;
|
|
1861
|
+
}
|
|
1788
1862
|
var WebSocketServerTransport = class extends ServerTransport {
|
|
1789
1863
|
wss;
|
|
1790
1864
|
constructor(wss, clientId, providedOptions) {
|
|
@@ -1792,8 +1866,10 @@ var WebSocketServerTransport = class extends ServerTransport {
|
|
|
1792
1866
|
this.wss = wss;
|
|
1793
1867
|
this.wss.on("connection", this.connectionHandler);
|
|
1794
1868
|
}
|
|
1795
|
-
connectionHandler = (ws) => {
|
|
1796
|
-
const conn = new WebSocketConnection(ws
|
|
1869
|
+
connectionHandler = (ws, req) => {
|
|
1870
|
+
const conn = new WebSocketConnection(ws, {
|
|
1871
|
+
headers: cleanHeaders(req.headersDistinct)
|
|
1872
|
+
});
|
|
1797
1873
|
this.handleConnection(conn);
|
|
1798
1874
|
};
|
|
1799
1875
|
close() {
|