@replit/river 0.203.1 → 0.205.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 +7 -3
- package/dist/{chunk-TMOCPK63.js → chunk-AXZPYUY6.js} +50 -11
- package/dist/chunk-AXZPYUY6.js.map +1 -0
- package/dist/{chunk-2FHJVQBE.js → chunk-EU2H4J7U.js} +5 -11
- package/dist/chunk-EU2H4J7U.js.map +1 -0
- package/dist/chunk-GG3GL7CW.js +1955 -0
- package/dist/chunk-GG3GL7CW.js.map +1 -0
- package/dist/{chunk-T4WWG42M.js → chunk-RAO6UI45.js} +21 -17
- package/dist/chunk-RAO6UI45.js.map +1 -0
- package/dist/{chunk-7MKTFUJO.js → chunk-VN7QS6OS.js} +4 -3
- package/dist/chunk-VN7QS6OS.js.map +1 -0
- package/dist/{client-5d2e41a3.d.ts → client-3adfb12a.d.ts} +1 -1
- package/dist/{connection-11a4af0f.d.ts → connection-9ca3e7ed.d.ts} +1 -1
- package/dist/{context-d6dd8a1a.d.ts → context-1a332293.d.ts} +12 -3
- package/dist/router/index.cjs +25 -14
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +7 -7
- package/dist/router/index.d.ts +7 -7
- package/dist/router/index.js +18 -1611
- package/dist/router/index.js.map +1 -1
- package/dist/{server-e46399f9.d.ts → server-8ac5c6bf.d.ts} +1 -1
- package/dist/{services-56cbea0d.d.ts → services-4213d92e.d.ts} +2 -2
- package/dist/testUtil/index.cjs +82 -36
- package/dist/testUtil/index.cjs.map +1 -1
- package/dist/testUtil/index.d.cts +4 -4
- package/dist/testUtil/index.d.ts +4 -4
- package/dist/testUtil/index.js +8 -6
- package/dist/testUtil/index.js.map +1 -1
- package/dist/transport/impls/ws/client.cjs +82 -44
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +3 -3
- package/dist/transport/impls/ws/client.d.ts +3 -3
- package/dist/transport/impls/ws/client.js +4 -4
- package/dist/transport/impls/ws/server.cjs +66 -31
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +3 -3
- package/dist/transport/impls/ws/server.d.ts +3 -3
- package/dist/transport/impls/ws/server.js +4 -4
- package/dist/transport/index.cjs +80 -35
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +3 -3
- package/dist/transport/index.d.ts +3 -3
- package/dist/transport/index.js +4 -4
- package/package.json +2 -2
- package/dist/chunk-2FHJVQBE.js.map +0 -1
- package/dist/chunk-7MKTFUJO.js.map +0 -1
- package/dist/chunk-AK7NTFAM.js +0 -331
- package/dist/chunk-AK7NTFAM.js.map +0 -1
- package/dist/chunk-T4WWG42M.js.map +0 -1
- package/dist/chunk-TMOCPK63.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { b as ProvidedClientTransportOptions, c as ProvidedServerTransportOptions, n as ClientHandshakeOptions, C as Connection, r as ServerHandshakeOptions, T as Transport, A as SessionOptions, m as ClientTransportOptions, e as SessionNoConnection, B as SessionBoundSendFn } from '../context-
|
|
2
|
-
import { C as ClientTransport } from '../client-
|
|
3
|
-
import { S as ServerTransport } from '../server-
|
|
1
|
+
import { b as ProvidedClientTransportOptions, c as ProvidedServerTransportOptions, n as ClientHandshakeOptions, C as Connection, r as ServerHandshakeOptions, T as Transport, A as SessionOptions, m as ClientTransportOptions, e as SessionNoConnection, B as SessionBoundSendFn } from '../context-1a332293.js';
|
|
2
|
+
import { C as ClientTransport } from '../client-3adfb12a.js';
|
|
3
|
+
import { S as ServerTransport } from '../server-8ac5c6bf.js';
|
|
4
4
|
import { c as TransportClientId, f as PartialTransportMessage, b as OpaqueTransportMessage } from '../message-3def9ded.js';
|
|
5
5
|
import { Static } from '@sinclair/typebox';
|
|
6
|
-
import { E as BaseErrorSchemaType, u as Readable, X as ReadableIterator, Y as ReadableResult } from '../services-
|
|
6
|
+
import { E as BaseErrorSchemaType, u as Readable, X as ReadableIterator, Y as ReadableResult } from '../services-4213d92e.js';
|
|
7
7
|
import NodeWs from 'ws';
|
|
8
8
|
import http from 'node:http';
|
|
9
9
|
import { W as WsLike } from '../wslike-e0b32dd5.js';
|
package/dist/testUtil/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { b as ProvidedClientTransportOptions, c as ProvidedServerTransportOptions, n as ClientHandshakeOptions, C as Connection, r as ServerHandshakeOptions, T as Transport, A as SessionOptions, m as ClientTransportOptions, e as SessionNoConnection, B as SessionBoundSendFn } from '../context-
|
|
2
|
-
import { C as ClientTransport } from '../client-
|
|
3
|
-
import { S as ServerTransport } from '../server-
|
|
1
|
+
import { b as ProvidedClientTransportOptions, c as ProvidedServerTransportOptions, n as ClientHandshakeOptions, C as Connection, r as ServerHandshakeOptions, T as Transport, A as SessionOptions, m as ClientTransportOptions, e as SessionNoConnection, B as SessionBoundSendFn } from '../context-1a332293.js';
|
|
2
|
+
import { C as ClientTransport } from '../client-3adfb12a.js';
|
|
3
|
+
import { S as ServerTransport } from '../server-8ac5c6bf.js';
|
|
4
4
|
import { c as TransportClientId, f as PartialTransportMessage, b as OpaqueTransportMessage } from '../message-3def9ded.js';
|
|
5
5
|
import { Static } from '@sinclair/typebox';
|
|
6
|
-
import { E as BaseErrorSchemaType, u as Readable, X as ReadableIterator, Y as ReadableResult } from '../services-
|
|
6
|
+
import { E as BaseErrorSchemaType, u as Readable, X as ReadableIterator, Y as ReadableResult } from '../services-4213d92e.js';
|
|
7
7
|
import NodeWs from 'ws';
|
|
8
8
|
import http from 'node:http';
|
|
9
9
|
import { W as WsLike } from '../wslike-e0b32dd5.js';
|
package/dist/testUtil/index.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ClientTransport
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-RAO6UI45.js";
|
|
4
4
|
import {
|
|
5
5
|
ServerTransport
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-VN7QS6OS.js";
|
|
7
7
|
import {
|
|
8
8
|
Connection,
|
|
9
9
|
SessionStateGraph,
|
|
10
10
|
defaultClientTransportOptions,
|
|
11
11
|
defaultTransportOptions
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-AXZPYUY6.js";
|
|
13
13
|
import {
|
|
14
|
-
currentProtocolVersion
|
|
15
|
-
|
|
14
|
+
currentProtocolVersion,
|
|
15
|
+
getTracer
|
|
16
|
+
} from "../chunk-GG3GL7CW.js";
|
|
16
17
|
import "../chunk-WBGKPIFS.js";
|
|
17
18
|
import "../chunk-AJGIY2UB.js";
|
|
18
19
|
|
|
@@ -309,7 +310,8 @@ function dummySession() {
|
|
|
309
310
|
}
|
|
310
311
|
},
|
|
311
312
|
testingSessionOptions,
|
|
312
|
-
currentProtocolVersion
|
|
313
|
+
currentProtocolVersion,
|
|
314
|
+
getTracer()
|
|
313
315
|
);
|
|
314
316
|
}
|
|
315
317
|
function getClientSendFn(clientTransport, serverTransport) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../testUtil/index.ts","../../testUtil/observable/observable.ts","../../testUtil/duplex/duplexPair.ts","../../testUtil/fixtures/mockTransport.ts"],"sourcesContent":["import NodeWs, { WebSocketServer } from 'ws';\nimport http from 'node:http';\nimport { Static } from '@sinclair/typebox';\nimport {\n OpaqueTransportMessage,\n PartialTransportMessage,\n currentProtocolVersion,\n} from '../transport/message';\nimport { Transport } from '../transport/transport';\nimport { Readable, ReadableResult, ReadableIterator } from '../router/streams';\nimport { WsLike } from '../transport/impls/ws/wslike';\nimport {\n defaultClientTransportOptions,\n defaultTransportOptions,\n} from '../transport/options';\nimport { Connection } from '../transport/connection';\nimport { SessionState } from '../transport/sessionStateMachine/common';\nimport { SessionStateGraph } from '../transport/sessionStateMachine/transitions';\nimport { BaseErrorSchemaType } from '../router/errors';\nimport { ClientTransport } from '../transport/client';\nimport { ServerTransport } from '../transport/server';\n\nexport {\n createMockTransportNetwork,\n InMemoryConnection,\n} from './fixtures/mockTransport';\n\n/**\n * Creates a WebSocket client that connects to a local server at the specified port.\n * This should only be used for testing.\n * @param port - The port number to connect to.\n * @returns A Promise that resolves to a WebSocket instance.\n */\nexport function createLocalWebSocketClient(port: number): WsLike {\n const sock = new NodeWs(`ws://localhost:${port}`);\n sock.binaryType = 'arraybuffer';\n\n return sock;\n}\n\n/**\n * Creates a WebSocket server instance using the provided HTTP server.\n * Only used as helper for testing.\n * @param server - The HTTP server instance to use for the WebSocket server.\n * @returns A Promise that resolves to the created WebSocket server instance.\n */\nexport function createWebSocketServer(server: http.Server) {\n return new WebSocketServer({ server });\n}\n\n/**\n * Starts listening on the given server and returns the automatically allocated port number.\n * This should only be used for testing.\n * @param server - The http server to listen on.\n * @returns A promise that resolves with the allocated port number.\n * @throws An error if a port cannot be allocated.\n */\nexport function onWsServerReady(server: http.Server): Promise<number> {\n return new Promise((resolve, reject) => {\n server.listen(() => {\n const addr = server.address();\n if (typeof addr === 'object' && addr) {\n resolve(addr.port);\n } else {\n reject(new Error(\"couldn't find a port to allocate\"));\n }\n });\n });\n}\n\nconst readableIterators = new WeakMap<\n Readable<unknown, Static<BaseErrorSchemaType>>,\n ReadableIterator<unknown, Static<BaseErrorSchemaType>>\n>();\n\n/**\n * A safe way to access {@link Readble}'s iterator multiple times in test helpers.\n *\n * If there are other iteration attempts outside of the test helpers\n * (this function, {@link readNextResult}, and {@link isReadableDone})\n * it will throw an error.\n */\nexport function getReadableIterator<T, E extends Static<BaseErrorSchemaType>>(\n readable: Readable<T, E>,\n): ReadableIterator<T, E> {\n let iter = readableIterators.get(readable) as\n | ReadableIterator<T, E>\n | undefined;\n\n if (!iter) {\n iter = readable[Symbol.asyncIterator]();\n readableIterators.set(readable, iter);\n }\n\n return iter;\n}\n\n/**\n * Retrieves the next value from {@link Readable}, or throws an error if the Readable is done.\n *\n * Calling semantics are similar to {@link getReadableIterator}\n */\nexport async function readNextResult<T, E extends Static<BaseErrorSchemaType>>(\n readable: Readable<T, E>,\n): Promise<ReadableResult<T, E>> {\n const res = await getReadableIterator(readable).next();\n\n if (res.done) {\n throw new Error('readNext from a done Readable');\n }\n\n return res.value;\n}\n\n/**\n * Checks if the readable is done iterating, it consumes an iteration in the process.\n *\n * Calling semantics are similar to {@link getReadableIterator}\n */\nexport async function isReadableDone<T, E extends Static<BaseErrorSchemaType>>(\n readable: Readable<T, E>,\n) {\n const res = await getReadableIterator(readable).next();\n\n return res.done;\n}\n\nexport function payloadToTransportMessage<Payload>(\n payload: Payload,\n): PartialTransportMessage<Payload> {\n return {\n streamId: 'stream',\n controlFlags: 0,\n payload,\n };\n}\n\nexport function createDummyTransportMessage() {\n return payloadToTransportMessage({\n msg: 'cool',\n test: Math.random(),\n });\n}\n\n/**\n * Waits for a message on the transport.\n * @param {Transport} t - The transport to listen to.\n * @param filter - An optional filter function to apply to the received messages.\n * @returns A promise that resolves with the payload of the first message that passes the filter.\n */\nexport async function waitForMessage(\n t: Transport<Connection>,\n filter?: (msg: OpaqueTransportMessage) => boolean,\n rejectMismatch?: boolean,\n) {\n return new Promise((resolve, reject) => {\n function cleanup() {\n t.removeEventListener('message', onMessage);\n }\n\n function onMessage(msg: OpaqueTransportMessage) {\n if (!filter || filter(msg)) {\n cleanup();\n resolve(msg.payload);\n } else if (rejectMismatch) {\n cleanup();\n reject(new Error('message didnt match the filter'));\n }\n }\n\n t.addEventListener('message', onMessage);\n });\n}\n\nexport const testingSessionOptions = defaultTransportOptions;\nexport const testingClientSessionOptions = defaultClientTransportOptions;\n\nexport function dummySession() {\n return SessionStateGraph.entrypoints.NoConnection(\n 'client',\n 'server',\n {\n onSessionGracePeriodElapsed: () => {\n /* noop */\n },\n },\n testingSessionOptions,\n currentProtocolVersion,\n );\n}\n\nexport function getClientSendFn(\n clientTransport: ClientTransport<Connection>,\n serverTransport: ServerTransport<Connection>,\n) {\n const session =\n clientTransport.sessions.get(serverTransport.clientId) ??\n clientTransport.createUnconnectedSession(serverTransport.clientId);\n\n return clientTransport.getSessionBoundSendFn(\n serverTransport.clientId,\n session.id,\n );\n}\n\nexport function getServerSendFn(\n serverTransport: ServerTransport<Connection>,\n clientTransport: ClientTransport<Connection>,\n) {\n const session = serverTransport.sessions.get(clientTransport.clientId);\n if (!session) {\n throw new Error('session not found');\n }\n\n return serverTransport.getSessionBoundSendFn(\n clientTransport.clientId,\n session.id,\n );\n}\n\nexport function getTransportConnections<ConnType extends Connection>(\n transport: Transport<ConnType>,\n): Array<ConnType> {\n const connections = [];\n for (const session of transport.sessions.values()) {\n if (session.state === SessionState.Connected) {\n connections.push(session.conn);\n }\n }\n\n return connections;\n}\n\nexport function numberOfConnections<ConnType extends Connection>(\n transport: Transport<ConnType>,\n): number {\n return getTransportConnections(transport).length;\n}\n\nexport function closeAllConnections<ConnType extends Connection>(\n transport: Transport<ConnType>,\n) {\n for (const conn of getTransportConnections(transport)) {\n conn.close();\n }\n}\n","/**\n * Represents an observable value that can be subscribed to for changes.\n * This should only be used in tests\n * @template T - The type of the value being observed.\n */\nexport class Observable<T> {\n value: T;\n private listeners: Set<(val: T) => void>;\n\n constructor(initialValue: T) {\n this.value = initialValue;\n this.listeners = new Set();\n }\n\n /**\n * Gets the current value of the observable.\n */\n get() {\n return this.value;\n }\n\n /**\n * Sets the current value of the observable. All listeners will get an update with this value.\n * @param newValue - The new value to set.\n */\n set(tx: (preValue: T) => T) {\n const newValue = tx(this.value);\n this.value = newValue;\n this.listeners.forEach((listener) => listener(newValue));\n }\n\n /**\n * Subscribes to changes in the observable value.\n * @param listener - A callback function that will be called when the value changes.\n * @returns A function that can be called to unsubscribe from further notifications.\n */\n observe(listener: (val: T) => void) {\n this.listeners.add(listener);\n listener(this.get());\n\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Returns the number of listeners currently observing the observable\n */\n get listenerCount(): number {\n return this.listeners.size;\n }\n}\n","import { Duplex } from 'node:stream';\nimport assert from 'assert';\n\nconst kCallback = Symbol('Callback');\nconst kInitOtherSide = Symbol('InitOtherSide');\n\n// yoinked from https://github.com/nodejs/node/blob/c3a7b29e56a5ada6327ebb622ba746d022685742/lib/internal/streams/duplexpair.js#L55\n// but with types\nclass DuplexSide extends Duplex {\n private otherSide: DuplexSide | null;\n private [kCallback]: (() => void) | null;\n\n constructor() {\n super();\n this[kCallback] = null;\n this.otherSide = null;\n }\n\n [kInitOtherSide](otherSide: DuplexSide) {\n if (this.otherSide === null) {\n this.otherSide = otherSide;\n }\n }\n\n _read() {\n const callback = this[kCallback];\n if (callback) {\n this[kCallback] = null;\n callback();\n }\n }\n\n _write(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: (error?: Error | null) => void,\n ) {\n assert(this.otherSide !== null);\n assert(this.otherSide[kCallback] === null);\n if (chunk.length === 0) {\n process.nextTick(callback);\n } else {\n this.otherSide.push(chunk);\n this.otherSide[kCallback] = callback;\n }\n }\n\n _final(callback: (error?: Error | null) => void) {\n this.otherSide?.on('end', callback);\n this.otherSide?.push(null);\n }\n}\n\nexport function duplexPair(): [DuplexSide, DuplexSide] {\n const side0 = new DuplexSide();\n const side1 = new DuplexSide();\n side0[kInitOtherSide](side1);\n side1[kInitOtherSide](side0);\n\n return [side0, side1];\n}\n","import { TransportClientId } from '../../transport';\nimport { ClientTransport } from '../../transport/client';\nimport { Connection } from '../../transport/connection';\nimport { ServerTransport } from '../../transport/server';\nimport { Observable } from '../observable/observable';\nimport { ProvidedServerTransportOptions } from '../../transport/options';\nimport { TestSetupHelpers, TestTransportOptions } from './transports';\nimport { Duplex } from 'node:stream';\nimport { duplexPair } from '../duplex/duplexPair';\nimport { nanoid } from 'nanoid';\n\nexport class InMemoryConnection extends Connection {\n conn: Duplex;\n\n constructor(pipe: Duplex) {\n super();\n this.conn = pipe;\n\n this.conn.on('data', (data: Uint8Array) => {\n for (const cb of this.dataListeners) {\n cb(data);\n }\n });\n\n this.conn.on('end', () => {\n for (const cb of this.closeListeners) {\n cb();\n }\n });\n\n this.conn.on('error', (err) => {\n for (const cb of this.errorListeners) {\n cb(err);\n }\n });\n }\n\n send(payload: Uint8Array): boolean {\n setImmediate(() => {\n this.conn.write(payload);\n });\n\n return true;\n }\n\n close(): void {\n setImmediate(() => {\n this.conn.end();\n });\n }\n}\n\ninterface BidiConnection {\n id: string;\n clientToServer: Duplex;\n serverToClient: Duplex;\n clientId: TransportClientId;\n serverId: TransportClientId;\n handled: boolean;\n}\n\n// we construct a network of transports connected by node streams here\n// so that we can test the transport layer without needing to actually\n// use real network/websocket connections\n// this is useful for testing the transport layer in isolation\n// and allows us to control network conditions in a way that would be\n// difficult with real network connections (e.g. simulating a phantom\n// disconnect, .pause() vs .removeAllListeners('data'), congestion,\n// latency, differences in ws implementations between node and browsers, etc.)\nexport function createMockTransportNetwork(\n opts?: TestTransportOptions,\n): TestSetupHelpers {\n // conn id -> [client->server, server->client]\n const connections = new Observable<Record<string, BidiConnection>>({});\n\n const transports: Array<MockClientTransport | MockServerTransport> = [];\n class MockClientTransport extends ClientTransport<InMemoryConnection> {\n async createNewOutgoingConnection(\n to: TransportClientId,\n ): Promise<InMemoryConnection> {\n const [clientToServer, serverToClient] = duplexPair();\n await new Promise((resolve) => setImmediate(resolve));\n\n const connId = nanoid();\n connections.set((prev) => ({\n ...prev,\n [connId]: {\n id: connId,\n clientToServer,\n serverToClient,\n clientId: this.clientId,\n serverId: to,\n handled: false,\n },\n }));\n\n return new InMemoryConnection(clientToServer);\n }\n }\n\n class MockServerTransport extends ServerTransport<InMemoryConnection> {\n subscribeCleanup: () => void;\n\n constructor(\n clientId: TransportClientId,\n options?: ProvidedServerTransportOptions,\n ) {\n super(clientId, options);\n\n this.subscribeCleanup = connections.observe((conns) => {\n // look for any unhandled connections\n for (const conn of Object.values(conns)) {\n // if we've already handled this connection, skip it\n // or if it's not for us, skip it\n if (conn.handled || conn.serverId !== this.clientId) {\n continue;\n }\n\n conn.handled = true;\n const connection = new InMemoryConnection(conn.serverToClient);\n this.handleConnection(connection);\n }\n });\n }\n\n close() {\n this.subscribeCleanup();\n super.close();\n }\n }\n\n return {\n getClientTransport: (id, handshakeOptions) => {\n const clientTransport = new MockClientTransport(id, opts?.client);\n if (handshakeOptions) {\n clientTransport.extendHandshake(handshakeOptions);\n }\n\n transports.push(clientTransport);\n\n return clientTransport;\n },\n getServerTransport: (id = 'SERVER', handshakeOptions) => {\n const serverTransport = new MockServerTransport(id, opts?.server);\n if (handshakeOptions) {\n serverTransport.extendHandshake(handshakeOptions);\n }\n\n transports.push(serverTransport);\n\n return serverTransport;\n },\n simulatePhantomDisconnect() {\n for (const conn of Object.values(connections.get())) {\n conn.serverToClient.pause();\n }\n },\n async restartServer() {\n for (const transport of transports) {\n if (transport.clientId !== 'SERVER') continue;\n transport.close();\n }\n\n // kill all connections while we're at it\n for (const conn of Object.values(connections.get())) {\n conn.serverToClient.end();\n conn.clientToServer.end();\n }\n },\n cleanup() {\n for (const conn of Object.values(connections.get())) {\n conn.serverToClient.end();\n conn.clientToServer.end();\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../testUtil/index.ts","../../testUtil/observable/observable.ts","../../testUtil/duplex/duplexPair.ts","../../testUtil/fixtures/mockTransport.ts"],"sourcesContent":["import NodeWs, { WebSocketServer } from 'ws';\nimport http from 'node:http';\nimport { Static } from '@sinclair/typebox';\nimport {\n OpaqueTransportMessage,\n PartialTransportMessage,\n currentProtocolVersion,\n} from '../transport/message';\nimport { Transport } from '../transport/transport';\nimport { Readable, ReadableResult, ReadableIterator } from '../router/streams';\nimport { WsLike } from '../transport/impls/ws/wslike';\nimport {\n defaultClientTransportOptions,\n defaultTransportOptions,\n} from '../transport/options';\nimport { Connection } from '../transport/connection';\nimport { SessionState } from '../transport/sessionStateMachine/common';\nimport { SessionStateGraph } from '../transport/sessionStateMachine/transitions';\nimport { BaseErrorSchemaType } from '../router/errors';\nimport { ClientTransport } from '../transport/client';\nimport { ServerTransport } from '../transport/server';\nimport { getTracer } from '../tracing';\n\nexport {\n createMockTransportNetwork,\n InMemoryConnection,\n} from './fixtures/mockTransport';\n\n/**\n * Creates a WebSocket client that connects to a local server at the specified port.\n * This should only be used for testing.\n * @param port - The port number to connect to.\n * @returns A Promise that resolves to a WebSocket instance.\n */\nexport function createLocalWebSocketClient(port: number): WsLike {\n const sock = new NodeWs(`ws://localhost:${port}`);\n sock.binaryType = 'arraybuffer';\n\n return sock;\n}\n\n/**\n * Creates a WebSocket server instance using the provided HTTP server.\n * Only used as helper for testing.\n * @param server - The HTTP server instance to use for the WebSocket server.\n * @returns A Promise that resolves to the created WebSocket server instance.\n */\nexport function createWebSocketServer(server: http.Server) {\n return new WebSocketServer({ server });\n}\n\n/**\n * Starts listening on the given server and returns the automatically allocated port number.\n * This should only be used for testing.\n * @param server - The http server to listen on.\n * @returns A promise that resolves with the allocated port number.\n * @throws An error if a port cannot be allocated.\n */\nexport function onWsServerReady(server: http.Server): Promise<number> {\n return new Promise((resolve, reject) => {\n server.listen(() => {\n const addr = server.address();\n if (typeof addr === 'object' && addr) {\n resolve(addr.port);\n } else {\n reject(new Error(\"couldn't find a port to allocate\"));\n }\n });\n });\n}\n\nconst readableIterators = new WeakMap<\n Readable<unknown, Static<BaseErrorSchemaType>>,\n ReadableIterator<unknown, Static<BaseErrorSchemaType>>\n>();\n\n/**\n * A safe way to access {@link Readble}'s iterator multiple times in test helpers.\n *\n * If there are other iteration attempts outside of the test helpers\n * (this function, {@link readNextResult}, and {@link isReadableDone})\n * it will throw an error.\n */\nexport function getReadableIterator<T, E extends Static<BaseErrorSchemaType>>(\n readable: Readable<T, E>,\n): ReadableIterator<T, E> {\n let iter = readableIterators.get(readable) as\n | ReadableIterator<T, E>\n | undefined;\n\n if (!iter) {\n iter = readable[Symbol.asyncIterator]();\n readableIterators.set(readable, iter);\n }\n\n return iter;\n}\n\n/**\n * Retrieves the next value from {@link Readable}, or throws an error if the Readable is done.\n *\n * Calling semantics are similar to {@link getReadableIterator}\n */\nexport async function readNextResult<T, E extends Static<BaseErrorSchemaType>>(\n readable: Readable<T, E>,\n): Promise<ReadableResult<T, E>> {\n const res = await getReadableIterator(readable).next();\n\n if (res.done) {\n throw new Error('readNext from a done Readable');\n }\n\n return res.value;\n}\n\n/**\n * Checks if the readable is done iterating, it consumes an iteration in the process.\n *\n * Calling semantics are similar to {@link getReadableIterator}\n */\nexport async function isReadableDone<T, E extends Static<BaseErrorSchemaType>>(\n readable: Readable<T, E>,\n) {\n const res = await getReadableIterator(readable).next();\n\n return res.done;\n}\n\nexport function payloadToTransportMessage<Payload>(\n payload: Payload,\n): PartialTransportMessage<Payload> {\n return {\n streamId: 'stream',\n controlFlags: 0,\n payload,\n };\n}\n\nexport function createDummyTransportMessage() {\n return payloadToTransportMessage({\n msg: 'cool',\n test: Math.random(),\n });\n}\n\n/**\n * Waits for a message on the transport.\n * @param {Transport} t - The transport to listen to.\n * @param filter - An optional filter function to apply to the received messages.\n * @returns A promise that resolves with the payload of the first message that passes the filter.\n */\nexport async function waitForMessage(\n t: Transport<Connection>,\n filter?: (msg: OpaqueTransportMessage) => boolean,\n rejectMismatch?: boolean,\n) {\n return new Promise((resolve, reject) => {\n function cleanup() {\n t.removeEventListener('message', onMessage);\n }\n\n function onMessage(msg: OpaqueTransportMessage) {\n if (!filter || filter(msg)) {\n cleanup();\n resolve(msg.payload);\n } else if (rejectMismatch) {\n cleanup();\n reject(new Error('message didnt match the filter'));\n }\n }\n\n t.addEventListener('message', onMessage);\n });\n}\n\nexport const testingSessionOptions = defaultTransportOptions;\nexport const testingClientSessionOptions = defaultClientTransportOptions;\n\nexport function dummySession() {\n return SessionStateGraph.entrypoints.NoConnection(\n 'client',\n 'server',\n {\n onSessionGracePeriodElapsed: () => {\n /* noop */\n },\n },\n testingSessionOptions,\n currentProtocolVersion,\n getTracer(),\n );\n}\n\nexport function getClientSendFn(\n clientTransport: ClientTransport<Connection>,\n serverTransport: ServerTransport<Connection>,\n) {\n const session =\n clientTransport.sessions.get(serverTransport.clientId) ??\n clientTransport.createUnconnectedSession(serverTransport.clientId);\n\n return clientTransport.getSessionBoundSendFn(\n serverTransport.clientId,\n session.id,\n );\n}\n\nexport function getServerSendFn(\n serverTransport: ServerTransport<Connection>,\n clientTransport: ClientTransport<Connection>,\n) {\n const session = serverTransport.sessions.get(clientTransport.clientId);\n if (!session) {\n throw new Error('session not found');\n }\n\n return serverTransport.getSessionBoundSendFn(\n clientTransport.clientId,\n session.id,\n );\n}\n\nexport function getTransportConnections<ConnType extends Connection>(\n transport: Transport<ConnType>,\n): Array<ConnType> {\n const connections = [];\n for (const session of transport.sessions.values()) {\n if (session.state === SessionState.Connected) {\n connections.push(session.conn);\n }\n }\n\n return connections;\n}\n\nexport function numberOfConnections<ConnType extends Connection>(\n transport: Transport<ConnType>,\n): number {\n return getTransportConnections(transport).length;\n}\n\nexport function closeAllConnections<ConnType extends Connection>(\n transport: Transport<ConnType>,\n) {\n for (const conn of getTransportConnections(transport)) {\n conn.close();\n }\n}\n","/**\n * Represents an observable value that can be subscribed to for changes.\n * This should only be used in tests\n * @template T - The type of the value being observed.\n */\nexport class Observable<T> {\n value: T;\n private listeners: Set<(val: T) => void>;\n\n constructor(initialValue: T) {\n this.value = initialValue;\n this.listeners = new Set();\n }\n\n /**\n * Gets the current value of the observable.\n */\n get() {\n return this.value;\n }\n\n /**\n * Sets the current value of the observable. All listeners will get an update with this value.\n * @param newValue - The new value to set.\n */\n set(tx: (preValue: T) => T) {\n const newValue = tx(this.value);\n this.value = newValue;\n this.listeners.forEach((listener) => listener(newValue));\n }\n\n /**\n * Subscribes to changes in the observable value.\n * @param listener - A callback function that will be called when the value changes.\n * @returns A function that can be called to unsubscribe from further notifications.\n */\n observe(listener: (val: T) => void) {\n this.listeners.add(listener);\n listener(this.get());\n\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Returns the number of listeners currently observing the observable\n */\n get listenerCount(): number {\n return this.listeners.size;\n }\n}\n","import { Duplex } from 'node:stream';\nimport assert from 'assert';\n\nconst kCallback = Symbol('Callback');\nconst kInitOtherSide = Symbol('InitOtherSide');\n\n// yoinked from https://github.com/nodejs/node/blob/c3a7b29e56a5ada6327ebb622ba746d022685742/lib/internal/streams/duplexpair.js#L55\n// but with types\nclass DuplexSide extends Duplex {\n private otherSide: DuplexSide | null;\n private [kCallback]: (() => void) | null;\n\n constructor() {\n super();\n this[kCallback] = null;\n this.otherSide = null;\n }\n\n [kInitOtherSide](otherSide: DuplexSide) {\n if (this.otherSide === null) {\n this.otherSide = otherSide;\n }\n }\n\n _read() {\n const callback = this[kCallback];\n if (callback) {\n this[kCallback] = null;\n callback();\n }\n }\n\n _write(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: (error?: Error | null) => void,\n ) {\n assert(this.otherSide !== null);\n assert(this.otherSide[kCallback] === null);\n if (chunk.length === 0) {\n process.nextTick(callback);\n } else {\n this.otherSide.push(chunk);\n this.otherSide[kCallback] = callback;\n }\n }\n\n _final(callback: (error?: Error | null) => void) {\n this.otherSide?.on('end', callback);\n this.otherSide?.push(null);\n }\n}\n\nexport function duplexPair(): [DuplexSide, DuplexSide] {\n const side0 = new DuplexSide();\n const side1 = new DuplexSide();\n side0[kInitOtherSide](side1);\n side1[kInitOtherSide](side0);\n\n return [side0, side1];\n}\n","import { TransportClientId } from '../../transport';\nimport { ClientTransport } from '../../transport/client';\nimport { Connection } from '../../transport/connection';\nimport { ServerTransport } from '../../transport/server';\nimport { Observable } from '../observable/observable';\nimport { ProvidedServerTransportOptions } from '../../transport/options';\nimport { TestSetupHelpers, TestTransportOptions } from './transports';\nimport { Duplex } from 'node:stream';\nimport { duplexPair } from '../duplex/duplexPair';\nimport { nanoid } from 'nanoid';\n\nexport class InMemoryConnection extends Connection {\n conn: Duplex;\n\n constructor(pipe: Duplex) {\n super();\n this.conn = pipe;\n\n this.conn.on('data', (data: Uint8Array) => {\n for (const cb of this.dataListeners) {\n cb(data);\n }\n });\n\n this.conn.on('end', () => {\n for (const cb of this.closeListeners) {\n cb();\n }\n });\n\n this.conn.on('error', (err) => {\n for (const cb of this.errorListeners) {\n cb(err);\n }\n });\n }\n\n send(payload: Uint8Array): boolean {\n setImmediate(() => {\n this.conn.write(payload);\n });\n\n return true;\n }\n\n close(): void {\n setImmediate(() => {\n this.conn.end();\n });\n }\n}\n\ninterface BidiConnection {\n id: string;\n clientToServer: Duplex;\n serverToClient: Duplex;\n clientId: TransportClientId;\n serverId: TransportClientId;\n handled: boolean;\n}\n\n// we construct a network of transports connected by node streams here\n// so that we can test the transport layer without needing to actually\n// use real network/websocket connections\n// this is useful for testing the transport layer in isolation\n// and allows us to control network conditions in a way that would be\n// difficult with real network connections (e.g. simulating a phantom\n// disconnect, .pause() vs .removeAllListeners('data'), congestion,\n// latency, differences in ws implementations between node and browsers, etc.)\nexport function createMockTransportNetwork(\n opts?: TestTransportOptions,\n): TestSetupHelpers {\n // conn id -> [client->server, server->client]\n const connections = new Observable<Record<string, BidiConnection>>({});\n\n const transports: Array<MockClientTransport | MockServerTransport> = [];\n class MockClientTransport extends ClientTransport<InMemoryConnection> {\n async createNewOutgoingConnection(\n to: TransportClientId,\n ): Promise<InMemoryConnection> {\n const [clientToServer, serverToClient] = duplexPair();\n await new Promise((resolve) => setImmediate(resolve));\n\n const connId = nanoid();\n connections.set((prev) => ({\n ...prev,\n [connId]: {\n id: connId,\n clientToServer,\n serverToClient,\n clientId: this.clientId,\n serverId: to,\n handled: false,\n },\n }));\n\n return new InMemoryConnection(clientToServer);\n }\n }\n\n class MockServerTransport extends ServerTransport<InMemoryConnection> {\n subscribeCleanup: () => void;\n\n constructor(\n clientId: TransportClientId,\n options?: ProvidedServerTransportOptions,\n ) {\n super(clientId, options);\n\n this.subscribeCleanup = connections.observe((conns) => {\n // look for any unhandled connections\n for (const conn of Object.values(conns)) {\n // if we've already handled this connection, skip it\n // or if it's not for us, skip it\n if (conn.handled || conn.serverId !== this.clientId) {\n continue;\n }\n\n conn.handled = true;\n const connection = new InMemoryConnection(conn.serverToClient);\n this.handleConnection(connection);\n }\n });\n }\n\n close() {\n this.subscribeCleanup();\n super.close();\n }\n }\n\n return {\n getClientTransport: (id, handshakeOptions) => {\n const clientTransport = new MockClientTransport(id, opts?.client);\n if (handshakeOptions) {\n clientTransport.extendHandshake(handshakeOptions);\n }\n\n transports.push(clientTransport);\n\n return clientTransport;\n },\n getServerTransport: (id = 'SERVER', handshakeOptions) => {\n const serverTransport = new MockServerTransport(id, opts?.server);\n if (handshakeOptions) {\n serverTransport.extendHandshake(handshakeOptions);\n }\n\n transports.push(serverTransport);\n\n return serverTransport;\n },\n simulatePhantomDisconnect() {\n for (const conn of Object.values(connections.get())) {\n conn.serverToClient.pause();\n }\n },\n async restartServer() {\n for (const transport of transports) {\n if (transport.clientId !== 'SERVER') continue;\n transport.close();\n }\n\n // kill all connections while we're at it\n for (const conn of Object.values(connections.get())) {\n conn.serverToClient.end();\n conn.clientToServer.end();\n }\n },\n cleanup() {\n for (const conn of Object.values(connections.get())) {\n conn.serverToClient.end();\n conn.clientToServer.end();\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -460,12 +460,14 @@ var StateMachineState = class {
|
|
|
460
460
|
var CommonSession = class extends StateMachineState {
|
|
461
461
|
from;
|
|
462
462
|
options;
|
|
463
|
+
tracer;
|
|
463
464
|
log;
|
|
464
|
-
constructor({ from, options, log }) {
|
|
465
|
+
constructor({ from, options, log, tracer }) {
|
|
465
466
|
super();
|
|
466
467
|
this.from = from;
|
|
467
468
|
this.options = options;
|
|
468
469
|
this.log = log;
|
|
470
|
+
this.tracer = tracer;
|
|
469
471
|
}
|
|
470
472
|
parseMsg(msg) {
|
|
471
473
|
const parsedMsg = this.options.codec.fromBuffer(msg);
|
|
@@ -650,8 +652,16 @@ var SessionNoConnection = class extends IdentifiedSessionWithGracePeriod {
|
|
|
650
652
|
// tracing/index.ts
|
|
651
653
|
var import_api2 = require("@opentelemetry/api");
|
|
652
654
|
|
|
655
|
+
// transport/stringifyError.ts
|
|
656
|
+
function coerceErrorString(err) {
|
|
657
|
+
if (err instanceof Error) {
|
|
658
|
+
return err.message || "unknown reason";
|
|
659
|
+
}
|
|
660
|
+
return `[coerced to error] ${String(err)}`;
|
|
661
|
+
}
|
|
662
|
+
|
|
653
663
|
// package.json
|
|
654
|
-
var version = "0.
|
|
664
|
+
var version = "0.205.0";
|
|
655
665
|
|
|
656
666
|
// tracing/index.ts
|
|
657
667
|
function getPropagationContext(ctx) {
|
|
@@ -662,10 +672,10 @@ function getPropagationContext(ctx) {
|
|
|
662
672
|
import_api2.propagation.inject(ctx, tracing);
|
|
663
673
|
return tracing;
|
|
664
674
|
}
|
|
665
|
-
function createSessionTelemetryInfo(sessionId, to, from, propagationCtx) {
|
|
675
|
+
function createSessionTelemetryInfo(tracer, sessionId, to, from, propagationCtx) {
|
|
666
676
|
const parentCtx = propagationCtx ? import_api2.propagation.extract(import_api2.context.active(), propagationCtx) : import_api2.context.active();
|
|
667
677
|
const span = tracer.startSpan(
|
|
668
|
-
`session
|
|
678
|
+
`river.session.${sessionId}`,
|
|
669
679
|
{
|
|
670
680
|
attributes: {
|
|
671
681
|
component: "river",
|
|
@@ -679,7 +689,7 @@ function createSessionTelemetryInfo(sessionId, to, from, propagationCtx) {
|
|
|
679
689
|
const ctx = import_api2.trace.setSpan(parentCtx, span);
|
|
680
690
|
return { span, ctx };
|
|
681
691
|
}
|
|
682
|
-
function createConnectionTelemetryInfo(connection, info) {
|
|
692
|
+
function createConnectionTelemetryInfo(tracer, connection, info) {
|
|
683
693
|
const span = tracer.startSpan(
|
|
684
694
|
`connection ${connection.id}`,
|
|
685
695
|
{
|
|
@@ -694,8 +704,9 @@ function createConnectionTelemetryInfo(connection, info) {
|
|
|
694
704
|
const ctx = import_api2.trace.setSpan(info.ctx, span);
|
|
695
705
|
return { span, ctx };
|
|
696
706
|
}
|
|
697
|
-
|
|
698
|
-
|
|
707
|
+
function getTracer() {
|
|
708
|
+
return import_api2.trace.getTracer("river", version);
|
|
709
|
+
}
|
|
699
710
|
|
|
700
711
|
// transport/sessionStateMachine/SessionWaitingForHandshake.ts
|
|
701
712
|
var SessionWaitingForHandshake = class extends CommonSession {
|
|
@@ -981,6 +992,7 @@ function inheritSharedSession(session) {
|
|
|
981
992
|
telemetry: session.telemetry,
|
|
982
993
|
options: session.options,
|
|
983
994
|
log: session.log,
|
|
995
|
+
tracer: session.tracer,
|
|
984
996
|
protocolVersion: session.protocolVersion
|
|
985
997
|
};
|
|
986
998
|
}
|
|
@@ -992,9 +1004,9 @@ function inheritSharedSessionWithGrace(session) {
|
|
|
992
1004
|
}
|
|
993
1005
|
var SessionStateGraph = {
|
|
994
1006
|
entrypoints: {
|
|
995
|
-
NoConnection: (to, from, listeners, options, protocolVersion, log) => {
|
|
1007
|
+
NoConnection: (to, from, listeners, options, protocolVersion, tracer, log) => {
|
|
996
1008
|
const id = `session-${generateId()}`;
|
|
997
|
-
const telemetry = createSessionTelemetryInfo(id, to, from);
|
|
1009
|
+
const telemetry = createSessionTelemetryInfo(tracer, id, to, from);
|
|
998
1010
|
const sendBuffer = [];
|
|
999
1011
|
const session = new SessionNoConnection({
|
|
1000
1012
|
listeners,
|
|
@@ -1008,6 +1020,7 @@ var SessionStateGraph = {
|
|
|
1008
1020
|
telemetry,
|
|
1009
1021
|
options,
|
|
1010
1022
|
protocolVersion,
|
|
1023
|
+
tracer,
|
|
1011
1024
|
log
|
|
1012
1025
|
});
|
|
1013
1026
|
session.log?.info(`session ${session.id} created in NoConnection state`, {
|
|
@@ -1016,12 +1029,13 @@ var SessionStateGraph = {
|
|
|
1016
1029
|
});
|
|
1017
1030
|
return session;
|
|
1018
1031
|
},
|
|
1019
|
-
WaitingForHandshake: (from, conn, listeners, options, log) => {
|
|
1032
|
+
WaitingForHandshake: (from, conn, listeners, options, tracer, log) => {
|
|
1020
1033
|
const session = new SessionWaitingForHandshake({
|
|
1021
1034
|
conn,
|
|
1022
1035
|
listeners,
|
|
1023
1036
|
from,
|
|
1024
1037
|
options,
|
|
1038
|
+
tracer,
|
|
1025
1039
|
log
|
|
1026
1040
|
});
|
|
1027
1041
|
session.log?.info(`session created in WaitingForHandshake state`, {
|
|
@@ -1077,7 +1091,11 @@ var SessionStateGraph = {
|
|
|
1077
1091
|
listeners,
|
|
1078
1092
|
...carriedState
|
|
1079
1093
|
});
|
|
1080
|
-
conn.telemetry = createConnectionTelemetryInfo(
|
|
1094
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
1095
|
+
session.tracer,
|
|
1096
|
+
conn,
|
|
1097
|
+
session.telemetry
|
|
1098
|
+
);
|
|
1081
1099
|
session.log?.info(
|
|
1082
1100
|
`session ${session.id} transition from Connecting to Handshaking`,
|
|
1083
1101
|
{
|
|
@@ -1121,12 +1139,14 @@ var SessionStateGraph = {
|
|
|
1121
1139
|
ack: 0,
|
|
1122
1140
|
sendBuffer: [],
|
|
1123
1141
|
telemetry: createSessionTelemetryInfo(
|
|
1142
|
+
pendingSession.tracer,
|
|
1124
1143
|
sessionId,
|
|
1125
1144
|
to,
|
|
1126
1145
|
from,
|
|
1127
1146
|
propagationCtx
|
|
1128
1147
|
),
|
|
1129
1148
|
options,
|
|
1149
|
+
tracer: pendingSession.tracer,
|
|
1130
1150
|
log: pendingSession.log,
|
|
1131
1151
|
protocolVersion
|
|
1132
1152
|
}
|
|
@@ -1138,7 +1158,11 @@ var SessionStateGraph = {
|
|
|
1138
1158
|
listeners,
|
|
1139
1159
|
...carriedState
|
|
1140
1160
|
});
|
|
1141
|
-
conn.telemetry = createConnectionTelemetryInfo(
|
|
1161
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
1162
|
+
session.tracer,
|
|
1163
|
+
conn,
|
|
1164
|
+
session.telemetry
|
|
1165
|
+
);
|
|
1142
1166
|
session.log?.info(
|
|
1143
1167
|
`session ${session.id} transition from WaitingForHandshake to Connected`,
|
|
1144
1168
|
{
|
|
@@ -1283,6 +1307,7 @@ var Transport = class {
|
|
|
1283
1307
|
*/
|
|
1284
1308
|
options;
|
|
1285
1309
|
log;
|
|
1310
|
+
tracer;
|
|
1286
1311
|
sessions;
|
|
1287
1312
|
/**
|
|
1288
1313
|
* Creates a new Transport instance.
|
|
@@ -1295,6 +1320,7 @@ var Transport = class {
|
|
|
1295
1320
|
this.clientId = clientId;
|
|
1296
1321
|
this.status = "open";
|
|
1297
1322
|
this.sessions = /* @__PURE__ */ new Map();
|
|
1323
|
+
this.tracer = getTracer();
|
|
1298
1324
|
}
|
|
1299
1325
|
bindLogger(fn, level) {
|
|
1300
1326
|
if (typeof fn === "function") {
|
|
@@ -1339,7 +1365,8 @@ var Transport = class {
|
|
|
1339
1365
|
*/
|
|
1340
1366
|
close() {
|
|
1341
1367
|
this.status = "closed";
|
|
1342
|
-
|
|
1368
|
+
const sessions = Array.from(this.sessions.values());
|
|
1369
|
+
for (const session of sessions) {
|
|
1343
1370
|
this.deleteSession(session);
|
|
1344
1371
|
}
|
|
1345
1372
|
this.eventDispatcher.dispatchEvent("transportStatus", {
|
|
@@ -1364,7 +1391,7 @@ var Transport = class {
|
|
|
1364
1391
|
}
|
|
1365
1392
|
this.sessions.set(session.to, session);
|
|
1366
1393
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
1367
|
-
status: "
|
|
1394
|
+
status: "created",
|
|
1368
1395
|
session
|
|
1369
1396
|
});
|
|
1370
1397
|
this.eventDispatcher.dispatchEvent("sessionTransition", {
|
|
@@ -1405,12 +1432,16 @@ var Transport = class {
|
|
|
1405
1432
|
}
|
|
1406
1433
|
session.log?.info(`closing session ${session.id}`, loggingMetadata);
|
|
1407
1434
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
1408
|
-
status: "
|
|
1435
|
+
status: "closing",
|
|
1409
1436
|
session
|
|
1410
1437
|
});
|
|
1411
1438
|
const to = session.to;
|
|
1412
1439
|
session.close();
|
|
1413
1440
|
this.sessions.delete(to);
|
|
1441
|
+
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
1442
|
+
status: "closed",
|
|
1443
|
+
session: { id: session.id, to }
|
|
1444
|
+
});
|
|
1414
1445
|
}
|
|
1415
1446
|
// common listeners
|
|
1416
1447
|
onSessionGracePeriodElapsed(session) {
|
|
@@ -1477,14 +1508,6 @@ var Transport = class {
|
|
|
1477
1508
|
}
|
|
1478
1509
|
};
|
|
1479
1510
|
|
|
1480
|
-
// transport/stringifyError.ts
|
|
1481
|
-
function coerceErrorString(err) {
|
|
1482
|
-
if (err instanceof Error) {
|
|
1483
|
-
return err.message || "unknown reason";
|
|
1484
|
-
}
|
|
1485
|
-
return `[coerced to error] ${String(err)}`;
|
|
1486
|
-
}
|
|
1487
|
-
|
|
1488
1511
|
// transport/client.ts
|
|
1489
1512
|
var import_value2 = require("@sinclair/typebox/value");
|
|
1490
1513
|
var ClientTransport = class extends Transport {
|
|
@@ -1541,6 +1564,7 @@ var ClientTransport = class extends Transport {
|
|
|
1541
1564
|
},
|
|
1542
1565
|
this.options,
|
|
1543
1566
|
currentProtocolVersion,
|
|
1567
|
+
this.tracer,
|
|
1544
1568
|
this.log
|
|
1545
1569
|
);
|
|
1546
1570
|
this.createSession(session);
|
|
@@ -1745,23 +1769,27 @@ var ClientTransport = class extends Transport {
|
|
|
1745
1769
|
* and don't want to wait for the grace period to elapse.
|
|
1746
1770
|
*/
|
|
1747
1771
|
hardDisconnect() {
|
|
1748
|
-
|
|
1772
|
+
const sessions = Array.from(this.sessions.values());
|
|
1773
|
+
for (const session of sessions) {
|
|
1749
1774
|
this.deleteSession(session);
|
|
1750
1775
|
}
|
|
1751
1776
|
}
|
|
1752
1777
|
onBackoffFinished(session) {
|
|
1753
|
-
const connPromise =
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1778
|
+
const connPromise = session.tracer.startActiveSpan(
|
|
1779
|
+
"connect",
|
|
1780
|
+
async (span) => {
|
|
1781
|
+
try {
|
|
1782
|
+
return await this.createNewOutgoingConnection(session.to);
|
|
1783
|
+
} catch (err) {
|
|
1784
|
+
const errStr = coerceErrorString(err);
|
|
1785
|
+
span.recordException(errStr);
|
|
1786
|
+
span.setStatus({ code: import_api4.SpanStatusCode.ERROR });
|
|
1787
|
+
throw err;
|
|
1788
|
+
} finally {
|
|
1789
|
+
span.end();
|
|
1790
|
+
}
|
|
1763
1791
|
}
|
|
1764
|
-
|
|
1792
|
+
);
|
|
1765
1793
|
const connectingSession = ClientSessionStateGraph.transition.BackingOffToConnecting(
|
|
1766
1794
|
session,
|
|
1767
1795
|
connPromise,
|
|
@@ -1860,6 +1888,22 @@ var Connection = class {
|
|
|
1860
1888
|
get errorListeners() {
|
|
1861
1889
|
return [...this._errorListeners];
|
|
1862
1890
|
}
|
|
1891
|
+
onData(msg) {
|
|
1892
|
+
for (const cb of this.dataListeners) {
|
|
1893
|
+
cb(msg);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
onError(err) {
|
|
1897
|
+
for (const cb of this.errorListeners) {
|
|
1898
|
+
cb(err);
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
onClose() {
|
|
1902
|
+
for (const cb of this.closeListeners) {
|
|
1903
|
+
cb();
|
|
1904
|
+
}
|
|
1905
|
+
this.telemetry?.span.end();
|
|
1906
|
+
}
|
|
1863
1907
|
/**
|
|
1864
1908
|
* Handle adding a callback for when a message is received.
|
|
1865
1909
|
* @param msg The message that was received.
|
|
@@ -1926,18 +1970,12 @@ var WebSocketConnection = class extends Connection {
|
|
|
1926
1970
|
const err = new Error(
|
|
1927
1971
|
`websocket closed with code and reason: ${code} - ${reason}`
|
|
1928
1972
|
);
|
|
1929
|
-
|
|
1930
|
-
cb(err);
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
for (const cb of this.closeListeners) {
|
|
1934
|
-
cb();
|
|
1973
|
+
this.onError(err);
|
|
1935
1974
|
}
|
|
1975
|
+
this.onClose();
|
|
1936
1976
|
};
|
|
1937
1977
|
this.ws.onmessage = (msg) => {
|
|
1938
|
-
|
|
1939
|
-
cb(msg.data);
|
|
1940
|
-
}
|
|
1978
|
+
this.onData(msg.data);
|
|
1941
1979
|
};
|
|
1942
1980
|
}
|
|
1943
1981
|
send(payload) {
|