@replit/river 0.200.3 → 0.200.5
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/dist/{chunk-HYPTZTEZ.js → chunk-3FMY7VTM.js} +2 -2
- package/dist/{chunk-QHMZKXXG.js → chunk-64J442AK.js} +2 -2
- package/dist/{chunk-QHMZKXXG.js.map → chunk-64J442AK.js.map} +1 -1
- package/dist/{chunk-HFW27CAC.js → chunk-7Z5MSOKL.js} +4 -4
- package/dist/{chunk-YTMS7OP6.js → chunk-LHH5LQ7C.js} +1 -1
- package/dist/chunk-LHH5LQ7C.js.map +1 -0
- package/dist/{chunk-O2VICK2U.js → chunk-MSJGPQRT.js} +4 -4
- package/dist/{chunk-YOC4BXQ5.js → chunk-WN7GEBMX.js} +4 -4
- package/dist/{chunk-FX5DKRIK.js → chunk-Z7Q5CDXD.js} +2 -2
- package/dist/chunk-Z7Q5CDXD.js.map +1 -0
- package/dist/{client-9292552a.d.ts → client-ba6815ae.d.ts} +2 -2
- package/dist/{connection-94dea547.d.ts → connection-d217c989.d.ts} +4 -4
- package/dist/{context-69f37ac1.d.ts → context-8d1ed9a1.d.ts} +3 -3
- 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-57bb8187.d.ts → message-45658364.d.ts} +2 -2
- package/dist/router/index.cjs +10 -9
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +8 -8
- package/dist/router/index.d.ts +8 -8
- package/dist/router/index.js +10 -9
- package/dist/router/index.js.map +1 -1
- package/dist/{server-8fdd7fb2.d.ts → server-eb7d2cfd.d.ts} +3 -3
- package/dist/{services-c8fe49bf.d.ts → services-94e0afc3.d.ts} +3 -3
- package/dist/transport/impls/ws/client.cjs +1 -1
- 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 +6 -6
- package/dist/transport/impls/ws/server.cjs +1 -1
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +4 -4
- package/dist/transport/impls/ws/server.d.ts +4 -4
- package/dist/transport/impls/ws/server.js +6 -6
- package/dist/transport/index.cjs +1 -1
- 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 +6 -6
- package/dist/util/testHelpers.cjs +1 -1
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +5 -5
- package/dist/util/testHelpers.d.ts +5 -5
- package/dist/util/testHelpers.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-FX5DKRIK.js.map +0 -1
- package/dist/chunk-YTMS7OP6.js.map +0 -1
- /package/dist/{chunk-HYPTZTEZ.js.map → chunk-3FMY7VTM.js.map} +0 -0
- /package/dist/{chunk-HFW27CAC.js.map → chunk-7Z5MSOKL.js.map} +0 -0
- /package/dist/{chunk-O2VICK2U.js.map → chunk-MSJGPQRT.js.map} +0 -0
- /package/dist/{chunk-YOC4BXQ5.js.map → chunk-WN7GEBMX.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../util/testHelpers.ts","../../router/result.ts","../../transport/message.ts","../../transport/id.ts","../../util/stringify.ts","../../router/streams.ts","../../codec/json.ts","../../transport/options.ts","../../transport/sessionStateMachine/common.ts","../../transport/sessionStateMachine/SessionConnecting.ts","../../transport/sessionStateMachine/SessionNoConnection.ts","../../tracing/index.ts","../../package.json","../../transport/sessionStateMachine/SessionWaitingForHandshake.ts","../../transport/sessionStateMachine/SessionHandshaking.ts","../../transport/sessionStateMachine/SessionConnected.ts","../../transport/sessionStateMachine/SessionBackingOff.ts","../../transport/sessionStateMachine/transitions.ts","../../router/errors.ts"],"sourcesContent":["import NodeWs, { WebSocketServer } from 'ws';\nimport http from 'node:http';\nimport { Err, Ok, Result } from '../router/result';\nimport { PayloadType, Procedure } from '../router/procedures';\nimport { Static } from '@sinclair/typebox';\nimport {\n OpaqueTransportMessage,\n PartialTransportMessage,\n currentProtocolVersion,\n} from '../transport/message';\nimport { coerceErrorString } from './stringify';\nimport { Transport } from '../transport/transport';\nimport {\n Readable,\n ReadableImpl,\n ReadableResult,\n ReadableIterator,\n Writable,\n WritableImpl,\n} from '../router/streams';\nimport { ServiceContext, ProcedureHandlerContext } from '../router/context';\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 {\n Session,\n SessionStateGraph,\n} from '../transport/sessionStateMachine/transitions';\nimport {\n BaseErrorSchemaType,\n ProcedureErrorSchemaType,\n ReaderErrorSchema,\n UNCAUGHT_ERROR_CODE,\n} from '../router/errors';\nimport { ClientTransport } from '../transport/client';\nimport { ServerTransport } from '../transport/server';\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\nfunction catchProcError(err: unknown) {\n const errorMsg = coerceErrorString(err);\n\n return Err({ code: UNCAUGHT_ERROR_CODE, message: errorMsg });\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\nfunction dummyCtx<State>(\n state: State,\n session: Session<Connection>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n): ProcedureHandlerContext<State> {\n return {\n ...extendedContext,\n state,\n sessionId: session.id,\n from: session.from,\n metadata: {},\n // TODO might wanna hook these up!\n cancel: () => undefined,\n signal: new AbortController().signal,\n };\n}\n\nexport function asClientRpc<\n State extends object,\n Init extends PayloadType,\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(\n state: State,\n proc: Procedure<State, 'rpc', Init, null, Res, Err>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n session: Session<Connection> = dummySession(),\n) {\n return async (\n msg: Static<Init>,\n ): Promise<\n Result<Static<Res>, Static<Err> | Static<typeof ReaderErrorSchema>>\n > => {\n return proc\n .handler({\n ctx: dummyCtx(state, session, extendedContext),\n reqInit: msg,\n })\n .catch(catchProcError);\n };\n}\n\nfunction createResponsePipe<\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(): {\n readable: Readable<\n Static<Res>,\n Static<Err> | Static<typeof ReaderErrorSchema>\n >;\n writable: Writable<Result<Static<Res>, Static<Err>>>;\n} {\n const readable = new ReadableImpl<\n Static<Res>,\n Static<Err> | Static<typeof ReaderErrorSchema>\n >();\n const writable = new WritableImpl<Result<Static<Res>, Static<Err>>>({\n writeCb: (v) => {\n readable._pushValue(v);\n },\n closeCb: () => {\n // Make it async to simulate request going over the wire\n // using promises so that we don't get affected by fake timers.\n void Promise.resolve().then(() => {\n readable._triggerClose();\n });\n },\n });\n\n return { readable, writable };\n}\n\nfunction createRequestPipe<Req extends PayloadType>(): {\n readable: Readable<Static<Req>, Static<typeof ReaderErrorSchema>>;\n writable: Writable<Static<Req>>;\n} {\n const readable = new ReadableImpl<\n Static<Req>,\n Static<typeof ReaderErrorSchema>\n >();\n const writable = new WritableImpl<Static<Req>>({\n writeCb: (v) => {\n readable._pushValue(Ok(v));\n },\n closeCb: () => {\n // Make it async to simulate request going over the wire\n // using promises so that we don't get affected by fake timers.\n void Promise.resolve().then(() => {\n readable._triggerClose();\n });\n },\n });\n\n return { readable, writable };\n}\n\nexport function asClientStream<\n State extends object,\n Init extends PayloadType,\n Req extends PayloadType,\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(\n state: State,\n proc: Procedure<State, 'stream', Init, Req, Res, Err>,\n reqInit?: Static<Init>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n session: Session<Connection> = dummySession(),\n): {\n reqWritable: Writable<Static<Req>>;\n resReadable: Readable<Static<Res>, Static<Err>>;\n} {\n const requestPipe = createRequestPipe<Req>();\n const responsePipe = createResponsePipe<Res, Err>();\n\n void proc\n .handler({\n ctx: dummyCtx(state, session, extendedContext),\n reqInit: reqInit ?? {},\n reqReadable: requestPipe.readable,\n resWritable: responsePipe.writable,\n })\n .catch((err: unknown) => responsePipe.writable.write(catchProcError(err)));\n\n return {\n reqWritable: requestPipe.writable,\n resReadable: responsePipe.readable,\n };\n}\n\nexport function asClientSubscription<\n State extends object,\n Init extends PayloadType,\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(\n state: State,\n proc: Procedure<State, 'subscription', Init, null, Res, Err>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n session: Session<Connection> = dummySession(),\n): (msg: Static<Init>) => {\n resReadable: Readable<Static<Res>, Static<Err>>;\n} {\n const responsePipe = createResponsePipe<Res, Err>();\n\n return (msg: Static<Init>) => {\n void proc\n .handler({\n ctx: dummyCtx(state, session, extendedContext),\n reqInit: msg,\n resWritable: responsePipe.writable,\n })\n .catch((err: unknown) =>\n responsePipe.writable.write(catchProcError(err)),\n );\n\n return { resReadable: responsePipe.readable };\n };\n}\n\nexport function asClientUpload<\n State extends object,\n Init extends PayloadType,\n Req extends PayloadType,\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(\n state: State,\n proc: Procedure<State, 'upload', Init, Req, Res, Err>,\n reqInit?: Static<Init>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n session: Session<Connection> = dummySession(),\n): {\n reqWritable: Writable<Static<Req>>;\n finalize: () => Promise<Result<Static<Res>, Static<Err>>>;\n} {\n const requestPipe = createRequestPipe<Req>();\n const result = proc\n .handler({\n ctx: dummyCtx(state, session, extendedContext),\n reqInit: reqInit ?? {},\n reqReadable: requestPipe.readable,\n })\n .catch(catchProcError);\n\n return { reqWritable: requestPipe.writable, finalize: () => result };\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","import { Static, Type } from '@sinclair/typebox';\nimport { Client } from './client';\nimport { Readable } from './streams';\nimport { BaseErrorSchemaType } from './errors';\n\n/**\n * AnyResultSchema is a schema to validate any result.\n */\nexport const AnyResultSchema = Type.Union([\n Type.Object({\n ok: Type.Literal(false),\n payload: Type.Object({\n code: Type.String(),\n message: Type.String(),\n extras: Type.Optional(Type.Unknown()),\n }),\n }),\n\n Type.Object({\n ok: Type.Literal(true),\n payload: Type.Unknown(),\n }),\n]);\n\nexport interface OkResult<T> {\n ok: true;\n payload: T;\n}\nexport interface ErrResult<Err extends Static<BaseErrorSchemaType>> {\n ok: false;\n payload: Err;\n}\nexport type Result<T, Err extends Static<BaseErrorSchemaType>> =\n | OkResult<T>\n | ErrResult<Err>;\n\nexport function Ok<const T extends Array<unknown>>(p: T): OkResult<T>;\nexport function Ok<const T extends ReadonlyArray<unknown>>(p: T): OkResult<T>;\nexport function Ok<const T>(payload: T): OkResult<T>;\nexport function Ok<const T>(payload: T): OkResult<T> {\n return {\n ok: true,\n payload,\n };\n}\n\nexport function Err<const Err extends Static<BaseErrorSchemaType>>(\n error: Err,\n): ErrResult<Err> {\n return {\n ok: false,\n payload: error,\n };\n}\n\n/**\n * Refine a {@link Result} type to its returned payload.\n */\nexport type ResultUnwrapOk<R> = R extends Result<infer T, infer __E>\n ? T\n : never;\n\n/**\n * Unwrap a {@link Result} type and return the payload if successful,\n * otherwise throws an error.\n * @param result - The result to unwrap.\n * @throws Will throw an error if the result is not ok.\n */\nexport function unwrapOrThrow<T, Err extends Static<BaseErrorSchemaType>>(\n result: Result<T, Err>,\n): T {\n if (result.ok) {\n return result.payload;\n }\n\n throw new Error(\n `Cannot non-ok result, got: ${result.payload.code} - ${result.payload.message}`,\n );\n}\n\n/**\n * Refine a {@link Result} type to its error payload.\n */\nexport type ResultUnwrapErr<R> = R extends Result<infer __T, infer Err>\n ? Err\n : never;\n\n/**\n * Retrieve the response type for a procedure, represented as a {@link Result}\n * type.\n * Example:\n * ```\n * type Message = ResponseData<typeof client, 'serviceName', 'procedureName'>\n * ```\n */\nexport type ResponseData<\n RiverClient,\n ServiceName extends keyof RiverClient,\n ProcedureName extends keyof RiverClient[ServiceName],\n Procedure = RiverClient[ServiceName][ProcedureName],\n Fn extends (...args: never) => unknown = (...args: never) => unknown,\n> = RiverClient extends Client<infer __ServiceSchemaMap>\n ? Procedure extends object\n ? Procedure extends object & { rpc: infer RpcFn extends Fn }\n ? Awaited<ReturnType<RpcFn>>\n : Procedure extends object & { upload: infer UploadFn extends Fn }\n ? ReturnType<UploadFn> extends {\n finalize: (...args: never) => Promise<infer UploadOutputMessage>;\n }\n ? UploadOutputMessage\n : never\n : Procedure extends object & { stream: infer StreamFn extends Fn }\n ? ReturnType<StreamFn> extends {\n resReadable: Readable<\n infer StreamOutputMessage,\n Static<BaseErrorSchemaType>\n >;\n }\n ? StreamOutputMessage\n : never\n : Procedure extends object & {\n subscribe: infer SubscriptionFn extends Fn;\n }\n ? Awaited<ReturnType<SubscriptionFn>> extends {\n resReadable: Readable<\n infer SubscriptionOutputMessage,\n Static<BaseErrorSchemaType>\n >;\n }\n ? SubscriptionOutputMessage\n : never\n : never\n : never\n : never;\n","import { Type, TSchema, Static } from '@sinclair/typebox';\nimport { PropagationContext } from '../tracing';\nimport { generateId } from './id';\nimport { ErrResult, ReaderErrorSchema } from '../router';\n\n/**\n * Control flags for transport messages.\n */\nexport const enum ControlFlags {\n /**\n * Used in heartbeat messages.\n */\n AckBit = 0b00001,\n /**\n * Used in stream open requests.\n */\n StreamOpenBit = 0b00010,\n /**\n * Used when a stream is cancelled due errors or to explicit cancellation\n */\n StreamCancelBit = 0b00100,\n /**\n * Used when writer closes the stream.\n */\n StreamClosedBit = 0b01000,\n}\n\n/**\n * Generic Typebox schema for a transport message.\n * @template T The type of the payload.\n * @param {T} t The payload schema.\n * @returns The transport message schema.\n */\nexport const TransportMessageSchema = <T extends TSchema>(t: T) =>\n Type.Object({\n id: Type.String(),\n from: Type.String(),\n to: Type.String(),\n seq: Type.Integer(),\n ack: Type.Integer(),\n serviceName: Type.Optional(Type.String()),\n procedureName: Type.Optional(Type.String()),\n streamId: Type.String(),\n controlFlags: Type.Integer(),\n tracing: Type.Optional(\n Type.Object({\n traceparent: Type.String(),\n tracestate: Type.String(),\n }),\n ),\n payload: t,\n });\n\n/**\n * Defines the schema for a transport acknowledgement message. This is never constructed manually\n * and is only used internally by the library for tracking inflight messages.\n * @returns The transport message schema.\n */\nexport const ControlMessageAckSchema = Type.Object({\n type: Type.Literal('ACK'),\n});\n\n/**\n * Defines the schema for a transport close message. This is never constructed manually and is only\n * used internally by the library for closing and cleaning up streams.\n */\nexport const ControlMessageCloseSchema = Type.Object({\n type: Type.Literal('CLOSE'),\n});\n\nexport type ProtocolVersion = 'v1.1' | 'v2.0';\nexport const currentProtocolVersion = 'v2.0' satisfies ProtocolVersion;\nexport const acceptedProtocolVersions = ['v1.1', currentProtocolVersion];\nexport function isAcceptedProtocolVersion(\n version: string,\n): version is ProtocolVersion {\n return acceptedProtocolVersions.includes(version);\n}\n\nexport const ControlMessageHandshakeRequestSchema = Type.Object({\n type: Type.Literal('HANDSHAKE_REQ'),\n protocolVersion: Type.String(),\n sessionId: Type.String(),\n /**\n * Specifies what the server's expected session state (from the pov of the client). This can be\n * used by the server to know whether this is a new or a reestablished connection, and whether it\n * is compatible with what it already has.\n */\n expectedSessionState: Type.Object({\n // what the client expects the server to send next\n nextExpectedSeq: Type.Integer(),\n nextSentSeq: Type.Integer(),\n }),\n\n metadata: Type.Optional(Type.Unknown()),\n});\n\nexport const HandshakeErrorRetriableResponseCodes = Type.Union([\n Type.Literal('SESSION_STATE_MISMATCH'),\n]);\n\nexport const HandshakeErrorCustomHandlerFatalResponseCodes = Type.Union([\n // The custom validation handler rejected the handler because the client is unsupported.\n Type.Literal('REJECTED_UNSUPPORTED_CLIENT'),\n // The custom validation handler rejected the handshake.\n Type.Literal('REJECTED_BY_CUSTOM_HANDLER'),\n]);\n\nexport const HandshakeErrorFatalResponseCodes = Type.Union([\n HandshakeErrorCustomHandlerFatalResponseCodes,\n // The ciient sent a handshake that doesn't comply with the extended handshake metadata.\n Type.Literal('MALFORMED_HANDSHAKE_META'),\n // The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.\n Type.Literal('MALFORMED_HANDSHAKE'),\n // The client's protocol version does not match the server's.\n Type.Literal('PROTOCOL_VERSION_MISMATCH'),\n]);\n\nexport const HandshakeErrorResponseCodes = Type.Union([\n HandshakeErrorRetriableResponseCodes,\n HandshakeErrorFatalResponseCodes,\n]);\n\nexport const ControlMessageHandshakeResponseSchema = Type.Object({\n type: Type.Literal('HANDSHAKE_RESP'),\n status: Type.Union([\n Type.Object({\n ok: Type.Literal(true),\n sessionId: Type.String(),\n }),\n Type.Object({\n ok: Type.Literal(false),\n reason: Type.String(),\n code: HandshakeErrorResponseCodes,\n }),\n ]),\n});\n\nexport const ControlMessagePayloadSchema = Type.Union([\n ControlMessageCloseSchema,\n ControlMessageAckSchema,\n ControlMessageHandshakeRequestSchema,\n ControlMessageHandshakeResponseSchema,\n]);\n\n/**\n * Defines the schema for an opaque transport message that is agnostic to any\n * procedure/service.\n * @returns The transport message schema.\n */\nexport const OpaqueTransportMessageSchema = TransportMessageSchema(\n Type.Unknown(),\n);\n\n/**\n * Represents a transport message. This is the same type as {@link TransportMessageSchema} but\n * we can't statically infer generics from generic Typebox schemas so we have to define it again here.\n *\n * TypeScript can't enforce types when a bitmask is involved, so these are the semantics of\n * `controlFlags`:\n * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `streamId` must be set to a unique value\n * (suggestion: use `nanoid`).\n * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `serviceName` and `procedureName` must be set.\n * * If `controlFlags & StreamClosedBit == StreamClosedBit` and the kind is `stream` or `subscription`,\n * `payload` should be discarded (usually contains a control message).\n * * If `controlFlags & AckBit == AckBit`, the message is an explicit acknowledgement message and doesn't\n * contain any payload that is relevant to the application so should not be delivered.\n * @template Payload The type of the payload.\n */\nexport interface TransportMessage<Payload = unknown> {\n id: string;\n from: TransportClientId;\n to: TransportClientId;\n seq: number;\n ack: number;\n serviceName?: string;\n procedureName?: string;\n streamId: string;\n controlFlags: number;\n tracing?: PropagationContext;\n payload: Payload;\n}\n\nexport type PartialTransportMessage<Payload = unknown> = Omit<\n TransportMessage<Payload>,\n 'id' | 'from' | 'to' | 'seq' | 'ack'\n>;\n\nexport function handshakeRequestMessage({\n from,\n to,\n sessionId,\n expectedSessionState,\n metadata,\n tracing,\n}: {\n from: TransportClientId;\n to: TransportClientId;\n sessionId: string;\n expectedSessionState: Static<\n typeof ControlMessageHandshakeRequestSchema\n >['expectedSessionState'];\n metadata?: unknown;\n tracing?: PropagationContext;\n}): TransportMessage<Static<typeof ControlMessageHandshakeRequestSchema>> {\n return {\n id: generateId(),\n from,\n to,\n seq: 0,\n ack: 0,\n streamId: generateId(),\n controlFlags: 0,\n tracing,\n payload: {\n type: 'HANDSHAKE_REQ',\n protocolVersion: currentProtocolVersion,\n sessionId,\n expectedSessionState,\n metadata,\n } satisfies Static<typeof ControlMessageHandshakeRequestSchema>,\n };\n}\n\n/**\n * This is a reason that can be given during the handshake to indicate that the peer has the wrong\n * session state.\n */\nexport const SESSION_STATE_MISMATCH = 'session state mismatch';\n\nexport function handshakeResponseMessage({\n from,\n to,\n status,\n}: {\n from: TransportClientId;\n to: TransportClientId;\n status: Static<typeof ControlMessageHandshakeResponseSchema>['status'];\n}): TransportMessage<Static<typeof ControlMessageHandshakeResponseSchema>> {\n return {\n id: generateId(),\n from,\n to,\n seq: 0,\n ack: 0,\n streamId: generateId(),\n controlFlags: 0,\n payload: {\n type: 'HANDSHAKE_RESP',\n status,\n } satisfies Static<typeof ControlMessageHandshakeResponseSchema>,\n };\n}\n\nexport function closeStreamMessage(streamId: string): PartialTransportMessage {\n return {\n streamId,\n controlFlags: ControlFlags.StreamClosedBit,\n payload: {\n type: 'CLOSE' as const,\n } satisfies Static<typeof ControlMessagePayloadSchema>,\n };\n}\n\nexport function cancelMessage(\n streamId: string,\n payload: ErrResult<Static<typeof ReaderErrorSchema>>,\n) {\n return {\n streamId,\n controlFlags: ControlFlags.StreamCancelBit,\n payload,\n };\n}\n\n/**\n * A type alias for a transport message with an opaque payload.\n * @template T - The type of the opaque payload.\n */\nexport type OpaqueTransportMessage = TransportMessage;\nexport type TransportClientId = string;\n\n/**\n * Checks if the given control flag (usually found in msg.controlFlag) is an ack message.\n * @param controlFlag - The control flag to check.\n * @returns True if the control flag contains the AckBit, false otherwise.\n */\nexport function isAck(controlFlag: number): boolean {\n /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */\n return (controlFlag & ControlFlags.AckBit) === ControlFlags.AckBit;\n}\n\n/**\n * Checks if the given control flag (usually found in msg.controlFlag) is a stream open message.\n * @param controlFlag - The control flag to check.\n * @returns True if the control flag contains the StreamOpenBit, false otherwise.\n */\nexport function isStreamOpen(controlFlag: number): boolean {\n return (\n /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */\n (controlFlag & ControlFlags.StreamOpenBit) === ControlFlags.StreamOpenBit\n );\n}\n\n/**\n * Checks if the given control flag (usually found in msg.controlFlag) is a stream close message.\n * @param controlFlag - The control flag to check.\n * @returns True if the control flag contains the StreamCloseBit, false otherwise.\n */\nexport function isStreamClose(controlFlag: number): boolean {\n return (\n /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */\n (controlFlag & ControlFlags.StreamClosedBit) ===\n ControlFlags.StreamClosedBit\n );\n}\n\n/**\n * Checks if the given control flag (usually found in msg.controlFlag) is an cancel message.\n * @param controlFlag - The control flag to check.\n * @returns True if the control flag contains the CancelBit, false otherwise\n */\nexport function isStreamCancel(controlFlag: number): boolean {\n return (\n /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */\n (controlFlag & ControlFlags.StreamCancelBit) ===\n ControlFlags.StreamCancelBit\n );\n}\n","import { customAlphabet } from 'nanoid';\n\nconst alphabet = customAlphabet(\n '1234567890abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ',\n);\nexport const generateId = () => alphabet(12);\n","export function coerceErrorString(err: unknown): string {\n if (err instanceof Error) {\n return err.message || 'unknown reason';\n }\n\n return `[coerced to error] ${String(err)}`;\n}\n","import { Static } from '@sinclair/typebox';\nimport { Err, Result } from './result';\nimport { BaseErrorSchemaType } from './errors';\n\nexport const ReadableBrokenError = {\n code: 'READABLE_BROKEN',\n message: 'Readable was broken before it is fully consumed',\n} as const satisfies Static<BaseErrorSchemaType>;\n\n/**\n * Similar to {@link Result} but with an extra error to handle cases where {@link Readable.break} is called\n */\nexport type ReadableResult<T, E extends Static<BaseErrorSchemaType>> = Result<\n T,\n E | typeof ReadableBrokenError\n>;\n\n/**\n * A simple {@link AsyncIterator} used in {@link Readable}\n * that doesn't have a the extra \"return\" and \"throw\" methods, and\n * the doesn't have a \"done value\" (TReturn).\n */\nexport interface ReadableIterator<T, E extends Static<BaseErrorSchemaType>> {\n next(): Promise<\n | {\n done: false;\n value: ReadableResult<T, E>;\n }\n | {\n done: true;\n value: undefined;\n }\n >;\n}\n\n/**\n * A {@link Readable} is an abstraction from which data is consumed from {@link Writable} source.\n *\n * - On the server the argument passed the procedure handler for `upload` and `stream` implements a {@link Readable} interface\n * so you can read client's request data.\n * - On the client the returned value of `subscription` or `stream` invocation implements a {@link Readable} interface\n * so you can read server's response data.\n *\n * A {@link Readable} can only have one consumer (iterator or {@link collect}) for the {@link Readable}'s\n * lifetime, in essense, reading from a {@link Readable} locks it forever.\n */\nexport interface Readable<T, E extends Static<BaseErrorSchemaType>> {\n /**\n * {@link Readable} implements AsyncIterator API and can be consumed via\n * for-await-of loops. Iteration locks the Readable. Exiting the loop\n * will **not** release the lock and it'll be equivalent of calling\n * {@link break}.\n */\n [Symbol.asyncIterator](): ReadableIterator<T, E>;\n /**\n * {@link collect} locks the {@link Readable} and returns a promise that resolves\n * with an array of the content when the {@link Readable} is fully done. This could\n * be due to the {@link Writable} end of the pipe closing cleanly, the procedure invocation\n * is cancelled, or {@link break} is called.\n */\n collect(): Promise<Array<ReadableResult<T, E>>>;\n /**\n * {@link break} locks the {@link Readable} and discards any existing or future incoming data.\n *\n * If there is an existing reader waiting for the next value, {@link break} causes it to\n * resolve with a {@link ReadableBrokenError} error.\n */\n break(): undefined;\n /**\n * {@link isReadable} returns true if it's safe to read from the {@link Readable}, either\n * via iteration or {@link collect}. It returns false if the {@link Readable} is locked\n * by a consumer (iterator or {@link collect}) or readable was broken via {@link break}.\n */\n isReadable(): boolean;\n}\n\n/**\n * A {@link Writeable} is a an abstraction for a {@link Readable} destination to which data is written to.\n *\n * - On the server the argument passed the procedure handler for `subscription` and `stream` implements a {@link Writeable}\n * so you can write server's response data.\n * - On the client the returned value of `upload` or `stream` invocation implements a {@link Writeable}\n * so you can write client's request data.\n *\n * Once closed, a {@link Writeable} can't be re-opened.` `\n */\nexport interface Writable<T> {\n /**\n * {@link write} writes a value to the pipe. An error is thrown if writing to a closed {@link Writable}.\n */\n write(value: T): undefined;\n /**\n * {@link close} signals the closure of the {@link Writeable}, informing the {@link Readable} end that\n * all data has been transmitted and we've cleanly closed.\n *\n * Calling {@link close} multiple times is a no-op.\n */\n close(): undefined;\n /**\n * {@link isWritable} returns true if it's safe to call {@link write}, which\n * means that the {@link Writable} hasn't been closed due to {@link close} being called\n * on this {@link Writable} or the procedure invocation ending for any reason.\n */\n isWritable(): boolean;\n}\n\n/**\n * @internal\n *\n * @see {@link createPromiseWithResolvers}\n */\ninterface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T) => void;\n reject: (reason: unknown) => void;\n}\n\n/**\n * @internal\n *\n * Same as https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers\n * but we support versions where it doesn't exist\n */\nfunction createPromiseWithResolvers<T>(): PromiseWithResolvers<T> {\n let resolve: (value: T) => void;\n let reject: (reason: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return {\n promise,\n // @ts-expect-error promise callbacks are sync\n resolve,\n // @ts-expect-error promise callbacks are sync\n reject,\n };\n}\n\n/**\n * @internal\n *\n * Internal implementation of a {@link Readable}.\n * This won't be exposed as an interface to river\n * consumers directly.\n */\nexport class ReadableImpl<T, E extends Static<BaseErrorSchemaType>>\n implements Readable<T, E>\n{\n /**\n * Whether the {@link Readable} is closed.\n *\n * Closed {@link Readable}s are done receiving values, but that doesn't affect\n * any other aspect of the {@link Readable} such as it's consumability.\n */\n private closed = false;\n /**\n * Whether the {@link Readable} is locked.\n *\n * @see {@link Readable}'s typedoc to understand locking\n */\n private locked = false;\n /**\n * Whether {@link break} was called.\n *\n * @see {@link break} for more information\n */\n private broken = false;\n /**\n * This flag allows us to avoid emitting a {@link ReadableBrokenError} after {@link break} was called\n * in cases where the {@link queue} is fully consumed and {@link ReadableImpl} is {@link closed}. This is just an\n * ergonomic feature to avoid emitting an error in our iteration when we don't have to.\n */\n private brokenWithValuesLeftToRead = false;\n /**\n * A list of values that have been pushed to the {@link ReadableImpl} but not yet emitted to the user.\n */\n private queue: Array<ReadableResult<T, E>> = [];\n /**\n * Used by methods in the class to signal to the iterator that it\n * should check for the next value.\n */\n private next: PromiseWithResolvers<void> | null = null;\n\n public [Symbol.asyncIterator]() {\n if (this.locked) {\n throw new TypeError('Readable is already locked');\n }\n\n this.locked = true;\n\n /**\n * First iteration with {@link break} signals an error, the following one signals end of iteration.\n * This variable is used to signal the end of iteration.\n */\n let didSignalBreak = false;\n\n return {\n next: async () => {\n if (didSignalBreak) {\n return {\n done: true,\n value: undefined,\n } as const;\n }\n\n /**\n * In a normal iteration case the while loop can be structured as a couple of if statements,\n * in other words the loop will run at most a couple of times:\n * - it will run 0 times if we have something in the queue to consume\n * - it will run 1 time if we have nothing in the queue and then get something in the queue\n * - it will run 2 times if we have nothing in the queue and then the readable closes or breaks\n *\n * However, in a degenerate case where something has the handle to the iterator and is calling `next`\n * eagerly multiple times this loop will come in handy by queuing them up and looping as needed.\n */\n while (this.queue.length === 0) {\n if (this.closed && !this.brokenWithValuesLeftToRead) {\n return {\n done: true,\n value: undefined,\n } as const;\n }\n\n if (this.broken) {\n didSignalBreak = true;\n\n return {\n done: false,\n value: Err(ReadableBrokenError),\n } as const;\n }\n\n if (!this.next) {\n this.next = createPromiseWithResolvers();\n }\n\n await this.next.promise;\n this.next = null;\n }\n\n // Unfortunately we have to use non-null assertion here, because T can be undefined\n // we already check for array length above anyway\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const value = this.queue.shift()!;\n\n return { done: false, value } as const;\n },\n return: () => {\n this.break();\n\n return { done: true, value: undefined } as const;\n },\n };\n }\n\n public async collect(): Promise<Array<ReadableResult<T, E>>> {\n const array: Array<ReadableResult<T, E>> = [];\n for await (const value of this) {\n array.push(value);\n }\n\n return array;\n }\n\n public break(): undefined {\n if (this.broken) {\n return;\n }\n\n this.locked = true;\n this.broken = true;\n this.brokenWithValuesLeftToRead = this.queue.length > 0;\n this.queue.length = 0;\n\n // if we have any iterators waiting for the next value,\n this.next?.resolve();\n }\n\n public isReadable(): boolean {\n return !this.locked && !this.broken;\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n *\n * Pushes a value to be read.\n */\n public _pushValue(value: Result<T, E>): undefined {\n if (this.broken) {\n return;\n }\n\n if (this.closed) {\n throw new Error('Cannot push to closed Readable');\n }\n\n this.queue.push(value);\n this.next?.resolve();\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n *\n * Triggers the close of the {@link Readable}. Make sure to push all remaining\n * values before calling this method.\n */\n public _triggerClose(): undefined {\n if (this.closed) {\n throw new Error('Unexpected closing multiple times');\n }\n\n this.closed = true;\n this.next?.resolve();\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n */\n public _hasValuesInQueue(): boolean {\n return this.queue.length > 0;\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n */\n public isClosed(): boolean {\n return this.closed;\n }\n}\n\n/**\n * Internal implementation of a {@link Writable}.\n * This won't be exposed as an interface to river\n * consumers directly.\n */\nexport class WritableImpl<T> implements Writable<T> {\n /**\n * Passed via constructor to pass on calls to {@link write}\n */\n private writeCb: (value: T) => void;\n\n /**\n * Passed via constructor to pass on calls to {@link close}\n */\n private closeCb: () => void;\n /**\n * Whether {@link close} was called, and {@link Writable} is not writable anymore.\n */\n private closed = false;\n\n constructor(callbacks: { writeCb: (value: T) => void; closeCb: () => void }) {\n this.writeCb = callbacks.writeCb;\n this.closeCb = callbacks.closeCb;\n }\n\n public write(value: T): undefined {\n if (this.closed) {\n throw new Error('Cannot write to closed Writable');\n }\n\n this.writeCb(value);\n }\n\n public isWritable(): boolean {\n return !this.closed;\n }\n\n public close(): undefined {\n if (this.closed) {\n return;\n }\n\n this.closed = true;\n this.writeCb = () => undefined;\n this.closeCb();\n this.closeCb = () => undefined;\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n */\n public isClosed(): boolean {\n return this.closed;\n }\n}\n","import { Codec } from './types';\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\n// Convert Uint8Array to base64\nfunction uint8ArrayToBase64(uint8Array: Uint8Array) {\n let binary = '';\n uint8Array.forEach((byte) => {\n binary += String.fromCharCode(byte);\n });\n\n return btoa(binary);\n}\n\n// Convert base64 to Uint8Array\nfunction base64ToUint8Array(base64: string) {\n const binaryString = atob(base64);\n const uint8Array = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n uint8Array[i] = binaryString.charCodeAt(i);\n }\n\n return uint8Array;\n}\n\ninterface Base64EncodedValue {\n $t: string;\n}\n\n/**\n * Naive JSON codec implementation using JSON.stringify and JSON.parse.\n * @type {Codec}\n */\nexport const NaiveJsonCodec: Codec = {\n toBuffer: (obj: object) => {\n return encoder.encode(\n JSON.stringify(obj, function replacer<\n T extends object,\n >(this: T, key: keyof T) {\n const val = this[key];\n if (val instanceof Uint8Array) {\n return { $t: uint8ArrayToBase64(val) } satisfies Base64EncodedValue;\n } else {\n return val;\n }\n }),\n );\n },\n fromBuffer: (buff: Uint8Array) => {\n try {\n const parsed = JSON.parse(\n decoder.decode(buff),\n function reviver(_key, val: unknown) {\n if ((val as Base64EncodedValue | undefined)?.$t) {\n return base64ToUint8Array((val as Base64EncodedValue).$t);\n } else {\n return val;\n }\n },\n ) as unknown;\n\n if (typeof parsed === 'object') return parsed;\n\n return null;\n } catch {\n return null;\n }\n },\n};\n","import { NaiveJsonCodec } from '../codec/json';\nimport { ConnectionRetryOptions } from './rateLimit';\nimport { SessionOptions } from './sessionStateMachine/common';\n\nexport type TransportOptions = SessionOptions;\n\nexport type ProvidedTransportOptions = Partial<TransportOptions>;\n\nexport const defaultTransportOptions: TransportOptions = {\n heartbeatIntervalMs: 1_000,\n heartbeatsUntilDead: 2,\n sessionDisconnectGraceMs: 5_000,\n connectionTimeoutMs: 2_000,\n handshakeTimeoutMs: 1_000,\n enableTransparentSessionReconnects: true,\n codec: NaiveJsonCodec,\n};\n\nexport type ClientTransportOptions = TransportOptions & ConnectionRetryOptions;\n\nexport type ProvidedClientTransportOptions = Partial<ClientTransportOptions>;\n\nconst defaultConnectionRetryOptions: ConnectionRetryOptions = {\n baseIntervalMs: 150,\n maxJitterMs: 200,\n maxBackoffMs: 32_000,\n attemptBudgetCapacity: 5,\n budgetRestoreIntervalMs: 200,\n};\n\nexport const defaultClientTransportOptions: ClientTransportOptions = {\n ...defaultTransportOptions,\n ...defaultConnectionRetryOptions,\n};\n\nexport type ServerTransportOptions = TransportOptions;\n\nexport type ProvidedServerTransportOptions = Partial<ServerTransportOptions>;\n\nexport const defaultServerTransportOptions: ServerTransportOptions = {\n ...defaultTransportOptions,\n};\n","import { Logger, MessageMetadata } from '../../logging';\nimport { TelemetryInfo } from '../../tracing';\nimport {\n OpaqueTransportMessage,\n OpaqueTransportMessageSchema,\n PartialTransportMessage,\n ProtocolVersion,\n TransportClientId,\n TransportMessage,\n} from '../message';\nimport { Value } from '@sinclair/typebox/value';\nimport { Codec } from '../../codec';\nimport { generateId } from '../id';\n\nexport const enum SessionState {\n NoConnection = 'NoConnection',\n BackingOff = 'BackingOff',\n Connecting = 'Connecting',\n Handshaking = 'Handshaking',\n Connected = 'Connected',\n WaitingForHandshake = 'WaitingForHandshake',\n}\n\nexport const ERR_CONSUMED = `session state has been consumed and is no longer valid`;\n\nabstract class StateMachineState {\n abstract readonly state: SessionState;\n\n /*\n * Whether this state has been consumed\n * and we've moved on to another state\n */\n _isConsumed: boolean;\n\n // called when we're transitioning to another state\n // note that this is internal and should not be called directly\n // by consumers, the proxy will call this when the state is consumed\n // and we're transitioning to another state\n abstract _handleStateExit(): void;\n\n // called when we exit the state machine entirely\n // note that this is internal and should not be called directly\n // by consumers, the proxy will call this when .close is closed\n abstract _handleClose(): void;\n\n close(): void {\n this._handleClose();\n }\n\n constructor() {\n this._isConsumed = false;\n\n // proxy helps us prevent access to properties after the state has been consumed\n // e.g. if we hold a reference to a state and try to access it after it's been consumed\n // we intercept the access and throw an error to help catch bugs\n return new Proxy(this, {\n get(target, prop) {\n // always allow access to _isConsumed, id, and state\n if (prop === '_isConsumed' || prop === 'id' || prop === 'state') {\n return Reflect.get(target, prop);\n }\n\n // modify _handleStateExit\n if (prop === '_handleStateExit') {\n return () => {\n target._isConsumed = true;\n target._handleStateExit();\n };\n }\n\n // modify _handleClose\n if (prop === '_handleClose') {\n return () => {\n // target is the non-proxied object, we need to set _isConsumed again\n target._isConsumed = true;\n target._handleStateExit();\n target._handleClose();\n };\n }\n\n if (target._isConsumed) {\n throw new Error(\n `${ERR_CONSUMED}: getting ${prop.toString()} on consumed state`,\n );\n }\n\n return Reflect.get(target, prop);\n },\n set(target, prop, value) {\n if (target._isConsumed) {\n throw new Error(\n `${ERR_CONSUMED}: setting ${prop.toString()} on consumed state`,\n );\n }\n\n return Reflect.set(target, prop, value);\n },\n });\n }\n}\n\nexport interface SessionOptions {\n /**\n * Frequency at which to send heartbeat acknowledgements\n */\n heartbeatIntervalMs: number;\n /**\n * Number of elapsed heartbeats without a response message before we consider\n * the connection dead.\n */\n heartbeatsUntilDead: number;\n /**\n * Max duration that a session can be without a connection before we consider\n * it dead. This deadline is carried between states and is used to determine\n * when to consider the session a lost cause and delete it entirely.\n * Generally, this should be strictly greater than the sum of\n * {@link connectionTimeoutMs} and {@link handshakeTimeoutMs}.\n */\n sessionDisconnectGraceMs: number;\n /**\n * Connection timeout in milliseconds\n */\n connectionTimeoutMs: number;\n /**\n * Handshake timeout in milliseconds\n */\n handshakeTimeoutMs: number;\n /**\n * Whether to enable transparent session reconnects\n */\n enableTransparentSessionReconnects: boolean;\n /**\n * The codec to use for encoding/decoding messages over the wire\n */\n codec: Codec;\n}\n\n// all session states have a from and options\nexport interface CommonSessionProps {\n from: TransportClientId;\n options: SessionOptions;\n log: Logger | undefined;\n}\n\nexport abstract class CommonSession extends StateMachineState {\n readonly from: TransportClientId;\n readonly options: SessionOptions;\n\n log?: Logger;\n abstract get loggingMetadata(): MessageMetadata;\n\n constructor({ from, options, log }: CommonSessionProps) {\n super();\n this.from = from;\n this.options = options;\n this.log = log;\n }\n\n parseMsg(msg: Uint8Array): OpaqueTransportMessage | null {\n const parsedMsg = this.options.codec.fromBuffer(msg);\n\n if (parsedMsg === null) {\n const decodedBuffer = new TextDecoder().decode(Buffer.from(msg));\n this.log?.error(\n `received malformed msg: ${decodedBuffer}`,\n this.loggingMetadata,\n );\n\n return null;\n }\n\n if (!Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {\n this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {\n ...this.loggingMetadata,\n validationErrors: [\n ...Value.Errors(OpaqueTransportMessageSchema, parsedMsg),\n ],\n });\n\n return null;\n }\n\n return parsedMsg;\n }\n}\n\nexport type InheritedProperties = Pick<\n IdentifiedSession,\n 'id' | 'from' | 'to' | 'seq' | 'ack' | 'sendBuffer' | 'telemetry' | 'options'\n>;\n\nexport type SessionId = string;\n\n// all sessions where we know the other side's client id\nexport interface IdentifiedSessionProps extends CommonSessionProps {\n id: SessionId;\n to: TransportClientId;\n seq: number;\n ack: number;\n sendBuffer: Array<OpaqueTransportMessage>;\n telemetry: TelemetryInfo;\n protocolVersion: ProtocolVersion;\n}\n\nexport abstract class IdentifiedSession extends CommonSession {\n readonly id: SessionId;\n readonly telemetry: TelemetryInfo;\n readonly to: TransportClientId;\n readonly protocolVersion: ProtocolVersion;\n\n /**\n * Index of the message we will send next (excluding handshake)\n */\n seq: number;\n\n /**\n * Number of unique messages we've received this session (excluding handshake)\n */\n ack: number;\n sendBuffer: Array<OpaqueTransportMessage>;\n\n constructor(props: IdentifiedSessionProps) {\n const { id, to, seq, ack, sendBuffer, telemetry, log, protocolVersion } =\n props;\n super(props);\n this.id = id;\n this.to = to;\n this.seq = seq;\n this.ack = ack;\n this.sendBuffer = sendBuffer;\n this.telemetry = telemetry;\n this.log = log;\n this.protocolVersion = protocolVersion;\n }\n\n get loggingMetadata(): MessageMetadata {\n const spanContext = this.telemetry.span.spanContext();\n\n const metadata: MessageMetadata = {\n clientId: this.from,\n connectedTo: this.to,\n sessionId: this.id,\n };\n\n if (this.telemetry.span.isRecording()) {\n metadata.telemetry = {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n };\n }\n\n return metadata;\n }\n\n constructMsg<Payload>(\n partialMsg: PartialTransportMessage<Payload>,\n ): TransportMessage<Payload> {\n const msg = {\n ...partialMsg,\n id: generateId(),\n to: this.to,\n from: this.from,\n seq: this.seq,\n ack: this.ack,\n };\n\n this.seq++;\n\n return msg;\n }\n\n nextSeq(): number {\n return this.sendBuffer.length > 0 ? this.sendBuffer[0].seq : this.seq;\n }\n\n send(msg: PartialTransportMessage): string {\n const constructedMsg = this.constructMsg(msg);\n this.sendBuffer.push(constructedMsg);\n\n return constructedMsg.id;\n }\n\n _handleStateExit(): void {\n // noop\n }\n\n _handleClose(): void {\n // zero out the buffer\n this.sendBuffer.length = 0;\n this.telemetry.span.end();\n }\n}\n\nexport interface IdentifiedSessionWithGracePeriodListeners {\n onSessionGracePeriodElapsed: () => void;\n}\n\nexport interface IdentifiedSessionWithGracePeriodProps\n extends IdentifiedSessionProps {\n graceExpiryTime: number;\n listeners: IdentifiedSessionWithGracePeriodListeners;\n}\n\nexport abstract class IdentifiedSessionWithGracePeriod extends IdentifiedSession {\n graceExpiryTime: number;\n protected gracePeriodTimeout?: ReturnType<typeof setTimeout>;\n\n listeners: IdentifiedSessionWithGracePeriodListeners;\n\n constructor(props: IdentifiedSessionWithGracePeriodProps) {\n super(props);\n this.listeners = props.listeners;\n\n this.graceExpiryTime = props.graceExpiryTime;\n this.gracePeriodTimeout = setTimeout(() => {\n this.listeners.onSessionGracePeriodElapsed();\n }, this.graceExpiryTime - Date.now());\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.gracePeriodTimeout) {\n clearTimeout(this.gracePeriodTimeout);\n this.gracePeriodTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n super._handleClose();\n }\n}\n","import { Connection } from '../connection';\nimport {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionConnectingListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onConnectionEstablished: (conn: Connection) => void;\n onConnectionFailed: (err: unknown) => void;\n\n // timeout related\n onConnectionTimeout: () => void;\n}\n\nexport interface SessionConnectingProps<ConnType extends Connection>\n extends IdentifiedSessionWithGracePeriodProps {\n connPromise: Promise<ConnType>;\n listeners: SessionConnectingListeners;\n}\n\n/*\n * A session that is connecting but we don't have access to the raw connection yet.\n * See transitions.ts for valid transitions.\n */\nexport class SessionConnecting<\n ConnType extends Connection,\n> extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.Connecting as const;\n connPromise: Promise<ConnType>;\n listeners: SessionConnectingListeners;\n\n connectionTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionConnectingProps<ConnType>) {\n super(props);\n this.connPromise = props.connPromise;\n this.listeners = props.listeners;\n\n this.connPromise.then(\n (conn) => {\n if (this._isConsumed) return;\n this.listeners.onConnectionEstablished(conn);\n },\n (err) => {\n if (this._isConsumed) return;\n this.listeners.onConnectionFailed(err);\n },\n );\n\n this.connectionTimeout = setTimeout(() => {\n this.listeners.onConnectionTimeout();\n }, this.options.connectionTimeoutMs);\n }\n\n // close a pending connection if it resolves, ignore errors if the promise\n // ends up rejected anyways\n bestEffortClose() {\n // these can technically be stale if the connPromise resolves after the\n // state has transitioned, but that's fine, this is best effort anyways\n // we pull these out so even if the state has transitioned, we can still log\n // without erroring out\n const logger = this.log;\n const metadata = this.loggingMetadata;\n\n this.connPromise\n .then((conn) => {\n conn.close();\n logger?.info(\n 'connection eventually resolved but session has transitioned, closed connection',\n {\n ...metadata,\n ...conn.loggingMetadata,\n },\n );\n })\n .catch(() => {\n // ignore errors\n });\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.connectionTimeout) {\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n // close the pending connection if it resolves\n this.bestEffortClose();\n super._handleClose();\n }\n}\n","import {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport type SessionNoConnectionListeners =\n IdentifiedSessionWithGracePeriodListeners;\n\nexport type SessionNoConnectionProps = IdentifiedSessionWithGracePeriodProps;\n\n/*\n * A session that is not connected and cannot send or receive messages.\n * See transitions.ts for valid transitions.\n */\nexport class SessionNoConnection extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.NoConnection as const;\n\n _handleClose(): void {\n super._handleClose();\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n }\n}\n","import {\n Context,\n Span,\n SpanKind,\n context,\n propagation,\n trace,\n} from '@opentelemetry/api';\nimport { version as RIVER_VERSION } from '../package.json';\nimport { ValidProcType } from '../router';\nimport { ClientTransport, Connection } from '../transport';\n\nexport interface PropagationContext {\n traceparent: string;\n tracestate: string;\n}\n\nexport interface TelemetryInfo {\n span: Span;\n ctx: Context;\n}\n\nexport function getPropagationContext(\n ctx: Context,\n): PropagationContext | undefined {\n const tracing = {\n traceparent: '',\n tracestate: '',\n };\n propagation.inject(ctx, tracing);\n\n return tracing;\n}\n\nexport function createSessionTelemetryInfo(\n sessionId: string,\n to: string,\n from: string,\n propagationCtx?: PropagationContext,\n): TelemetryInfo {\n const parentCtx = propagationCtx\n ? propagation.extract(context.active(), propagationCtx)\n : context.active();\n\n const span = tracer.startSpan(\n `session ${sessionId}`,\n {\n attributes: {\n component: 'river',\n 'river.session.id': sessionId,\n 'river.session.to': to,\n 'river.session.from': from,\n },\n },\n parentCtx,\n );\n\n const ctx = trace.setSpan(parentCtx, span);\n\n return { span, ctx };\n}\n\nexport function createConnectionTelemetryInfo(\n connection: Connection,\n info: TelemetryInfo,\n): TelemetryInfo {\n const span = tracer.startSpan(\n `connection ${connection.id}`,\n {\n attributes: {\n component: 'river',\n 'river.connection.id': connection.id,\n },\n links: [{ context: info.span.spanContext() }],\n },\n info.ctx,\n );\n\n const ctx = trace.setSpan(info.ctx, span);\n\n return { span, ctx };\n}\n\nexport function createProcTelemetryInfo(\n transport: ClientTransport<Connection>,\n kind: ValidProcType,\n serviceName: string,\n procedureName: string,\n streamId: string,\n): TelemetryInfo {\n const baseCtx = context.active();\n const span = tracer.startSpan(\n `procedure call ${serviceName}.${procedureName}`,\n {\n attributes: {\n component: 'river',\n 'river.method.kind': kind,\n 'river.method.service': serviceName,\n 'river.method.name': procedureName,\n 'river.streamId': streamId,\n 'span.kind': 'client',\n },\n kind: SpanKind.CLIENT,\n },\n baseCtx,\n );\n\n const ctx = trace.setSpan(baseCtx, span);\n\n transport.log?.info(`invoked ${serviceName}.${procedureName}`, {\n clientId: transport.clientId,\n transportMessage: {\n procedureName,\n serviceName,\n },\n telemetry: {\n traceId: span.spanContext().traceId,\n spanId: span.spanContext().spanId,\n },\n });\n\n return { span, ctx };\n}\n\nexport function createHandlerSpan<Fn extends (span: Span) => unknown>(\n kind: ValidProcType,\n serviceName: string,\n procedureName: string,\n streamId: string,\n tracing: PropagationContext | undefined,\n fn: Fn,\n): ReturnType<Fn> {\n const ctx = tracing\n ? propagation.extract(context.active(), tracing)\n : context.active();\n\n return tracer.startActiveSpan<Fn>(\n `procedure handler ${serviceName}.${procedureName}`,\n {\n attributes: {\n component: 'river',\n 'river.method.kind': kind,\n 'river.method.service': serviceName,\n 'river.method.name': procedureName,\n 'river.streamId': streamId,\n 'span.kind': 'server',\n },\n kind: SpanKind.SERVER,\n },\n ctx,\n fn,\n );\n}\n\nconst tracer = trace.getTracer('river', RIVER_VERSION);\nexport default tracer;\n","{\n \"name\": \"@replit/river\",\n \"description\": \"It's like tRPC but... with JSON Schema Support, duplex streaming and support for service multiplexing. Transport agnostic!\",\n \"version\": \"0.200.3\",\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/router/index.js\",\n \"require\": \"./dist/router/index.cjs\"\n },\n \"./logging\": {\n \"import\": \"./dist/logging/index.js\",\n \"require\": \"./dist/logging/index.cjs\"\n },\n \"./codec\": {\n \"import\": \"./dist/codec/index.js\",\n \"require\": \"./dist/codec/index.cjs\"\n },\n \"./transport\": {\n \"import\": \"./dist/transport/index.js\",\n \"require\": \"./dist/transport/index.cjs\"\n },\n \"./transport/ws/client\": {\n \"import\": \"./dist/transport/impls/ws/client.js\",\n \"require\": \"./dist/transport/impls/ws/client.cjs\"\n },\n \"./transport/ws/server\": {\n \"import\": \"./dist/transport/impls/ws/server.js\",\n \"require\": \"./dist/transport/impls/ws/server.cjs\"\n },\n \"./transport/uds/client\": {\n \"import\": \"./dist/transport/impls/uds/client.js\",\n \"require\": \"./dist/transport/impls/uds/client.cjs\"\n },\n \"./transport/uds/server\": {\n \"import\": \"./dist/transport/impls/uds/server.js\",\n \"require\": \"./dist/transport/impls/uds/server.cjs\"\n },\n \"./test-util\": {\n \"import\": \"./dist/util/testHelpers.js\",\n \"require\": \"./dist/util/testHelpers.cjs\"\n }\n },\n \"sideEffects\": [\n \"./dist/logging/index.js\"\n ],\n \"files\": [\n \"dist\"\n ],\n \"dependencies\": {\n \"@msgpack/msgpack\": \"^3.0.0-beta2\",\n \"nanoid\": \"^4.0.2\",\n \"ws\": \"^8.17.0\"\n },\n \"peerDependencies\": {\n \"@opentelemetry/api\": \"^1.7.0\",\n \"@sinclair/typebox\": \"~0.32.8\"\n },\n \"devDependencies\": {\n \"@opentelemetry/core\": \"^1.7.0\",\n \"@opentelemetry/sdk-trace-base\": \"^1.24.1\",\n \"@opentelemetry/sdk-trace-web\": \"^1.24.1\",\n \"@stylistic/eslint-plugin\": \"^2.6.4\",\n \"@types/ws\": \"^8.5.5\",\n \"@typescript-eslint/eslint-plugin\": \"^7.8.0\",\n \"@typescript-eslint/parser\": \"^7.8.0\",\n \"@vitest/ui\": \"^2.0.5\",\n \"eslint\": \"^8.57.0\",\n \"eslint-config-prettier\": \"^9.1.0\",\n \"eslint-plugin-prettier\": \"^5.1.3\",\n \"prettier\": \"^3.0.0\",\n \"tsup\": \"^7.2.0\",\n \"typescript\": \"^5.4.5\",\n \"vitest\": \"^2.0.5\"\n },\n \"scripts\": {\n \"check\": \"tsc --noEmit && npm run format && npm run lint\",\n \"format\": \"npx prettier . --check\",\n \"format:fix\": \"npx prettier . --write\",\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"fix\": \"npm run format:fix && npm run lint:fix\",\n \"build\": \"rm -rf dist && tsup && du -sh dist\",\n \"prepack\": \"npm run build\",\n \"release\": \"npm publish --access public\",\n \"test:ui\": \"echo \\\"remember to go to /__vitest__ in the webview\\\" && vitest --ui --api.host 0.0.0.0 --api.port 3000\",\n \"test\": \"vitest\",\n \"test:single\": \"vitest run --reporter=dot\",\n \"test:flake\": \"./flake.sh\",\n \"bench\": \"vitest bench\"\n },\n \"engines\": {\n \"node\": \">=16\"\n },\n \"keywords\": [\n \"rpc\",\n \"websockets\",\n \"jsonschema\"\n ],\n \"author\": \"Jacky Zhao\",\n \"license\": \"MIT\"\n}\n","import { Static } from '@sinclair/typebox';\nimport { Connection } from '../connection';\nimport {\n HandshakeErrorResponseCodes,\n OpaqueTransportMessage,\n TransportMessage,\n} from '../message';\nimport { CommonSession, CommonSessionProps, SessionState } from './common';\n\nexport interface SessionWaitingForHandshakeListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onHandshake: (msg: OpaqueTransportMessage) => void;\n onInvalidHandshake: (\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n ) => void;\n\n // timeout related\n onHandshakeTimeout: () => void;\n}\n\nexport interface SessionWaitingForHandshakeProps<ConnType extends Connection>\n extends CommonSessionProps {\n conn: ConnType;\n listeners: SessionWaitingForHandshakeListeners;\n}\n\n/*\n * Server-side session that has a connection but is waiting for the client to identify itself.\n * See transitions.ts for valid transitions.\n */\nexport class SessionWaitingForHandshake<\n ConnType extends Connection,\n> extends CommonSession {\n readonly state = SessionState.WaitingForHandshake as const;\n conn: ConnType;\n listeners: SessionWaitingForHandshakeListeners;\n\n handshakeTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionWaitingForHandshakeProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.handshakeTimeout = setTimeout(() => {\n this.listeners.onHandshakeTimeout();\n }, this.options.handshakeTimeoutMs);\n\n this.conn.addDataListener(this.onHandshakeData);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n }\n\n get loggingMetadata() {\n return {\n clientId: this.from,\n connId: this.conn.id,\n ...this.conn.loggingMetadata,\n };\n }\n\n onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake(\n 'could not parse message',\n 'MALFORMED_HANDSHAKE',\n );\n\n return;\n }\n\n // after this fires, the listener is responsible for transitioning the session\n // and thus removing the handshake timeout\n this.listeners.onHandshake(parsedMsg);\n };\n\n sendHandshake(msg: TransportMessage): boolean {\n return this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n _handleStateExit(): void {\n this.conn.removeDataListener(this.onHandshakeData);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n clearTimeout(this.handshakeTimeout);\n this.handshakeTimeout = undefined;\n }\n\n _handleClose(): void {\n this.conn.close();\n }\n}\n","import { Static } from '@sinclair/typebox';\nimport { Connection } from '../connection';\nimport {\n OpaqueTransportMessage,\n TransportMessage,\n HandshakeErrorResponseCodes,\n} from '../message';\nimport {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionHandshakingListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onHandshake: (msg: OpaqueTransportMessage) => void;\n onInvalidHandshake: (\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n ) => void;\n\n // timeout related\n onHandshakeTimeout: () => void;\n}\n\nexport interface SessionHandshakingProps<ConnType extends Connection>\n extends IdentifiedSessionWithGracePeriodProps {\n conn: ConnType;\n listeners: SessionHandshakingListeners;\n}\n\n/*\n * A session that is handshaking and waiting for the other side to identify itself.\n * See transitions.ts for valid transitions.\n */\nexport class SessionHandshaking<\n ConnType extends Connection,\n> extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.Handshaking as const;\n conn: ConnType;\n listeners: SessionHandshakingListeners;\n\n handshakeTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionHandshakingProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.handshakeTimeout = setTimeout(() => {\n this.listeners.onHandshakeTimeout();\n }, this.options.handshakeTimeoutMs);\n\n this.conn.addDataListener(this.onHandshakeData);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n }\n\n get loggingMetadata() {\n return {\n ...super.loggingMetadata,\n ...this.conn.loggingMetadata,\n };\n }\n\n onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake(\n 'could not parse message',\n 'MALFORMED_HANDSHAKE',\n );\n\n return;\n }\n\n this.listeners.onHandshake(parsedMsg);\n };\n\n sendHandshake(msg: TransportMessage): boolean {\n return this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n this.conn.removeDataListener(this.onHandshakeData);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n\n if (this.handshakeTimeout) {\n clearTimeout(this.handshakeTimeout);\n this.handshakeTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import { Static } from '@sinclair/typebox';\nimport {\n ControlFlags,\n ControlMessageAckSchema,\n OpaqueTransportMessage,\n PartialTransportMessage,\n isAck,\n} from '../message';\nimport {\n IdentifiedSession,\n IdentifiedSessionProps,\n SessionState,\n} from './common';\nimport { Connection } from '../connection';\nimport { SpanStatusCode } from '@opentelemetry/api';\n\nexport interface SessionConnectedListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onMessage: (msg: OpaqueTransportMessage) => void;\n onInvalidMessage: (reason: string) => void;\n}\n\nexport interface SessionConnectedProps<ConnType extends Connection>\n extends IdentifiedSessionProps {\n conn: ConnType;\n listeners: SessionConnectedListeners;\n}\n\n/*\n * A session that is connected and can send and receive messages.\n * See transitions.ts for valid transitions.\n */\nexport class SessionConnected<\n ConnType extends Connection,\n> extends IdentifiedSession {\n readonly state = SessionState.Connected as const;\n conn: ConnType;\n listeners: SessionConnectedListeners;\n\n private heartbeatHandle?: ReturnType<typeof setInterval> | undefined;\n private heartbeatMisses = 0;\n isActivelyHeartbeating: boolean;\n\n updateBookkeeping(ack: number, seq: number) {\n this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);\n this.ack = seq + 1;\n this.heartbeatMisses = 0;\n }\n\n send(msg: PartialTransportMessage): string {\n const constructedMsg = this.constructMsg(msg);\n this.sendBuffer.push(constructedMsg);\n this.conn.send(this.options.codec.toBuffer(constructedMsg));\n\n return constructedMsg.id;\n }\n\n constructor(props: SessionConnectedProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.conn.addDataListener(this.onMessageData);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n\n // send any buffered messages\n if (this.sendBuffer.length > 0) {\n this.log?.info(\n `sending ${\n this.sendBuffer.length\n } buffered messages, starting at seq ${this.nextSeq()}`,\n this.loggingMetadata,\n );\n\n for (const msg of this.sendBuffer) {\n this.conn.send(this.options.codec.toBuffer(msg));\n }\n }\n\n // dont explicity clear the buffer, we'll just filter out old messages\n // when we receive an ack\n\n // setup heartbeat\n this.isActivelyHeartbeating = false;\n this.heartbeatHandle = setInterval(() => {\n const misses = this.heartbeatMisses;\n const missDuration = misses * this.options.heartbeatIntervalMs;\n if (misses >= this.options.heartbeatsUntilDead) {\n this.log?.info(\n `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,\n this.loggingMetadata,\n );\n this.telemetry.span.addEvent('closing connection due to inactivity');\n\n // it is OK to close this even on the client when we can't trust the client timer\n // due to browser throttling or hibernation\n // at worst, this interval will fire later than what the server expects and the server\n // will have already closed the connection\n // this just helps us in cases where we have a proxying setup where the server has closed\n // the connection but the proxy hasn't synchronized the server-side close to the client so\n // the client isn't stuck with a pseudo-dead connection forever\n this.conn.close();\n clearInterval(this.heartbeatHandle);\n this.heartbeatHandle = undefined;\n\n return;\n }\n\n if (this.isActivelyHeartbeating) {\n this.sendHeartbeat();\n }\n\n this.heartbeatMisses++;\n }, this.options.heartbeatIntervalMs);\n }\n\n get loggingMetadata() {\n return {\n ...super.loggingMetadata,\n ...this.conn.loggingMetadata,\n };\n }\n\n startActiveHeartbeat() {\n this.isActivelyHeartbeating = true;\n }\n\n private sendHeartbeat() {\n this.log?.debug('sending heartbeat', this.loggingMetadata);\n this.send({\n streamId: 'heartbeat',\n controlFlags: ControlFlags.AckBit,\n payload: {\n type: 'ACK',\n } satisfies Static<typeof ControlMessageAckSchema>,\n });\n }\n\n closeConnection() {\n this.conn.removeDataListener(this.onMessageData);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.close();\n }\n\n onMessageData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidMessage('could not parse message');\n\n return;\n }\n\n // check message ordering here\n if (parsedMsg.seq !== this.ack) {\n if (parsedMsg.seq < this.ack) {\n this.log?.debug(\n `received duplicate msg (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack}), discarding`,\n {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n },\n );\n } else {\n const reason = `received out-of-order msg, closing connection (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack})`;\n this.log?.warn(reason, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n tags: ['invariant-violation'],\n });\n\n this.telemetry.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: reason,\n });\n\n // try to recover by closing the connection and re-handshaking\n // with the session intact\n this.closeConnection();\n }\n\n return;\n }\n\n // message is ok to update bookkeeping with\n this.log?.debug(`received msg`, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n });\n\n this.updateBookkeeping(parsedMsg.ack, parsedMsg.seq);\n\n // dispatch directly if its not an explicit ack\n if (!isAck(parsedMsg.controlFlags)) {\n this.listeners.onMessage(parsedMsg);\n\n return;\n }\n\n // discard acks (unless we aren't heartbeating in which case just respond)\n this.log?.debug(`discarding msg (ack bit set)`, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n });\n\n // if we are not actively heartbeating, we are in passive\n // heartbeat mode and should send a response to the ack\n if (!this.isActivelyHeartbeating) {\n this.sendHeartbeat();\n }\n };\n\n _handleStateExit(): void {\n super._handleStateExit();\n this.conn.removeDataListener(this.onMessageData);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n\n if (this.heartbeatHandle) {\n clearInterval(this.heartbeatHandle);\n this.heartbeatHandle = undefined;\n }\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionBackingOffListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onBackoffFinished: () => void;\n}\n\nexport interface SessionBackingOffProps\n extends IdentifiedSessionWithGracePeriodProps {\n backoffMs: number;\n listeners: SessionBackingOffListeners;\n}\n\n/*\n * A session that is backing off before attempting to connect.\n * See transitions.ts for valid transitions.\n */\nexport class SessionBackingOff extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.BackingOff as const;\n listeners: SessionBackingOffListeners;\n\n backoffTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionBackingOffProps) {\n super(props);\n this.listeners = props.listeners;\n\n this.backoffTimeout = setTimeout(() => {\n this.listeners.onBackoffFinished();\n }, props.backoffMs);\n }\n\n _handleClose(): void {\n super._handleClose();\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.backoffTimeout) {\n clearTimeout(this.backoffTimeout);\n this.backoffTimeout = undefined;\n }\n }\n}\n","import { OpaqueTransportMessage, TransportClientId } from '..';\nimport {\n SessionConnecting,\n SessionConnectingListeners,\n} from './SessionConnecting';\nimport {\n SessionNoConnection,\n SessionNoConnectionListeners,\n} from './SessionNoConnection';\nimport {\n IdentifiedSession,\n IdentifiedSessionProps,\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodProps,\n SessionOptions,\n} from './common';\nimport { PropagationContext, createSessionTelemetryInfo } from '../../tracing';\nimport {\n SessionWaitingForHandshake,\n SessionWaitingForHandshakeListeners,\n} from './SessionWaitingForHandshake';\nimport {\n SessionHandshaking,\n SessionHandshakingListeners,\n} from './SessionHandshaking';\nimport {\n SessionConnected,\n SessionConnectedListeners,\n} from './SessionConnected';\nimport { generateId } from '../id';\nimport { Connection } from '../connection';\nimport { Logger } from '../../logging';\nimport {\n SessionBackingOff,\n SessionBackingOffListeners,\n} from './SessionBackingOff';\nimport { ProtocolVersion } from '../message';\n\nfunction inheritSharedSession(\n session: IdentifiedSession,\n): IdentifiedSessionProps {\n return {\n id: session.id,\n from: session.from,\n to: session.to,\n seq: session.seq,\n ack: session.ack,\n sendBuffer: session.sendBuffer,\n telemetry: session.telemetry,\n options: session.options,\n log: session.log,\n protocolVersion: session.protocolVersion,\n };\n}\n\nfunction inheritSharedSessionWithGrace(\n session: IdentifiedSessionWithGracePeriod,\n): Omit<IdentifiedSessionWithGracePeriodProps, 'listeners'> {\n return {\n ...inheritSharedSession(session),\n graceExpiryTime: session.graceExpiryTime,\n };\n}\n\nexport const SessionStateGraph = {\n entrypoints: {\n NoConnection: (\n to: TransportClientId,\n from: TransportClientId,\n listeners: SessionNoConnectionListeners,\n options: SessionOptions,\n protocolVersion: ProtocolVersion,\n log?: Logger,\n ) => {\n const id = `session-${generateId()}`;\n const telemetry = createSessionTelemetryInfo(id, to, from);\n const sendBuffer: Array<OpaqueTransportMessage> = [];\n\n const session = new SessionNoConnection({\n listeners,\n id,\n from,\n to,\n seq: 0,\n ack: 0,\n graceExpiryTime: Date.now() + options.sessionDisconnectGraceMs,\n sendBuffer,\n telemetry,\n options,\n protocolVersion,\n log,\n });\n\n session.log?.info(`session ${session.id} created in NoConnection state`, {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n });\n\n return session;\n },\n WaitingForHandshake: <ConnType extends Connection>(\n from: TransportClientId,\n conn: ConnType,\n listeners: SessionWaitingForHandshakeListeners,\n options: SessionOptions,\n log?: Logger,\n ): SessionWaitingForHandshake<ConnType> => {\n const session = new SessionWaitingForHandshake({\n conn,\n listeners,\n from,\n options,\n log,\n });\n\n session.log?.info(`session created in WaitingForHandshake state`, {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n });\n\n return session;\n },\n },\n // All of the transitions 'move'/'consume' the old session and return a new one.\n // After a session is transitioned, any usage of the old session will throw.\n transition: {\n // happy path transitions\n NoConnectionToBackingOff: (\n oldSession: SessionNoConnection,\n backoffMs: number,\n listeners: SessionBackingOffListeners,\n ): SessionBackingOff => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionBackingOff({\n backoffMs,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from NoConnection to BackingOff`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n BackingOffToConnecting: <ConnType extends Connection>(\n oldSession: SessionBackingOff,\n connPromise: Promise<ConnType>,\n listeners: SessionConnectingListeners,\n ): SessionConnecting<ConnType> => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionConnecting({\n connPromise,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from BackingOff to Connecting`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectingToHandshaking: <ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n conn: ConnType,\n listeners: SessionHandshakingListeners,\n ): SessionHandshaking<ConnType> => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionHandshaking({\n conn,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from Connecting to Handshaking`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n HandshakingToConnected: <ConnType extends Connection>(\n oldSession: SessionHandshaking<ConnType>,\n listeners: SessionConnectedListeners,\n ): SessionConnected<ConnType> => {\n const carriedState = inheritSharedSession(oldSession);\n const conn = oldSession.conn;\n oldSession._handleStateExit();\n\n const session = new SessionConnected({\n conn,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from Handshaking to Connected`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n WaitingForHandshakeToConnected: <ConnType extends Connection>(\n pendingSession: SessionWaitingForHandshake<ConnType>,\n oldSession: SessionNoConnection | undefined,\n sessionId: string,\n to: TransportClientId,\n propagationCtx: PropagationContext | undefined,\n listeners: SessionConnectedListeners,\n protocolVersion: ProtocolVersion,\n ): SessionConnected<ConnType> => {\n const conn = pendingSession.conn;\n const { from, options } = pendingSession;\n const carriedState: IdentifiedSessionProps = oldSession\n ? // old session exists, inherit state\n inheritSharedSession(oldSession)\n : // old session does not exist, create new state\n {\n id: sessionId,\n from,\n to,\n seq: 0,\n ack: 0,\n sendBuffer: [],\n telemetry: createSessionTelemetryInfo(\n sessionId,\n to,\n from,\n propagationCtx,\n ),\n options,\n log: pendingSession.log,\n protocolVersion,\n };\n\n pendingSession._handleStateExit();\n oldSession?._handleStateExit();\n\n const session = new SessionConnected({\n conn,\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from WaitingForHandshake to Connected`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n // disconnect paths\n BackingOffToNoConnection: (\n oldSession: SessionBackingOff,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from BackingOff to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectingToNoConnection: <ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession.bestEffortClose();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Connecting to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n HandshakingToNoConnection: <ConnType extends Connection>(\n oldSession: SessionHandshaking<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Handshaking to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectedToNoConnection: <ConnType extends Connection>(\n oldSession: SessionConnected<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSession(oldSession);\n const graceExpiryTime =\n Date.now() + oldSession.options.sessionDisconnectGraceMs;\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n graceExpiryTime,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Connected to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n },\n} as const;\n\nconst transitions = SessionStateGraph.transition;\n\nexport const ClientSessionStateGraph = {\n entrypoint: SessionStateGraph.entrypoints.NoConnection,\n transition: {\n // happy paths\n // NoConnection -> BackingOff: attempt to connect\n NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,\n // BackingOff -> Connecting: backoff period elapsed, start connection\n BackingOffToConnecting: transitions.BackingOffToConnecting,\n // Connecting -> Handshaking: connection established, start handshake\n ConnectingToHandshaking: transitions.ConnectingToHandshaking,\n // Handshaking -> Connected: handshake complete, session ready\n HandshakingToConnected: transitions.HandshakingToConnected,\n\n // disconnect paths\n // BackingOff -> NoConnection: unused\n BackingOffToNoConnection: transitions.BackingOffToNoConnection,\n // Connecting -> NoConnection: connection failed or connection timeout\n ConnectingToNoConnection: transitions.ConnectingToNoConnection,\n // Handshaking -> NoConnection: connection closed or handshake timeout\n HandshakingToNoConnection: transitions.HandshakingToNoConnection,\n // Connected -> NoConnection: connection closed\n ConnectedToNoConnection: transitions.ConnectedToNoConnection,\n\n // destroy/close paths\n // NoConnection -> x: grace period elapsed\n // BackingOff -> x: grace period elapsed\n // Connecting -> x: grace period elapsed\n // Handshaking -> x: grace period elapsed or invalid handshake message or handshake rejection\n // Connected -> x: grace period elapsed or invalid message\n },\n};\n\nexport type ClientSession<ConnType extends Connection> =\n | SessionNoConnection\n | SessionBackingOff\n | SessionConnecting<ConnType>\n | SessionHandshaking<ConnType>\n | SessionConnected<ConnType>;\n\nexport const ServerSessionStateGraph = {\n entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,\n transition: {\n // happy paths\n // WaitingForHandshake -> Connected: handshake complete, session ready\n WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,\n\n // disconnect paths\n // Connected -> NoConnection: connection closed\n ConnectedToNoConnection: transitions.ConnectedToNoConnection,\n\n // destroy/close paths\n // WaitingForHandshake -> x: handshake timeout elapsed or invalid handshake message or handshake rejection or connection closed\n },\n};\n\nexport type ServerSession<ConnType extends Connection> =\n // SessionWaitingForHandshake<ConnType> is stored separately in the server transport\n SessionConnected<ConnType> | SessionNoConnection;\n\nexport type Session<ConnType extends Connection> =\n | ClientSession<ConnType>\n | ServerSession<ConnType>;\n","import {\n Kind,\n TLiteral,\n TNever,\n TObject,\n TSchema,\n TString,\n TUnion,\n Type,\n} from '@sinclair/typebox';\n\n/**\n * {@link UNCAUGHT_ERROR_CODE} is the code that is used when an error is thrown\n * inside a procedure handler that's not required.\n */\nexport const UNCAUGHT_ERROR_CODE = 'UNCAUGHT_ERROR';\n/**\n * {@link UNEXPECTED_DISCONNECT_CODE} is the code used the stream's session\n * disconnect unexpetedly.\n */\nexport const UNEXPECTED_DISCONNECT_CODE = 'UNEXPECTED_DISCONNECT';\n/**\n * {@link INVALID_REQUEST_CODE} is the code used when a client's request is invalid.\n */\nexport const INVALID_REQUEST_CODE = 'INVALID_REQUEST';\n/**\n * {@link CANCEL_CODE} is the code used when either server or client cancels the stream.\n */\nexport const CANCEL_CODE = 'CANCEL';\n\ntype TLiteralString = TLiteral<string>;\n\nexport type BaseErrorSchemaType =\n | TObject<{\n code: TLiteralString;\n message: TLiteralString | TString;\n }>\n | TObject<{\n code: TLiteralString;\n message: TLiteralString | TString;\n extras: TSchema;\n }>;\n\n/**\n * Takes in a specific error schema and returns a result schema the error\n */\nexport const ErrResultSchema = <T extends ProcedureErrorSchemaType>(t: T) =>\n Type.Object({\n ok: Type.Literal(false),\n payload: t,\n });\n\n/**\n * {@link ReaderErrorSchema} is the schema for all the built-in river errors that\n * can be emitted to a reader (request reader on the server, and response reader\n * on the client).\n */\nexport const ReaderErrorSchema = Type.Union([\n Type.Object({\n code: Type.Literal(UNCAUGHT_ERROR_CODE),\n message: Type.String(),\n }),\n Type.Object({\n code: Type.Literal(UNEXPECTED_DISCONNECT_CODE),\n message: Type.String(),\n }),\n Type.Object({\n code: Type.Literal(INVALID_REQUEST_CODE),\n message: Type.String(),\n }),\n Type.Object({\n code: Type.Literal(CANCEL_CODE),\n message: Type.String(),\n }),\n]) satisfies ProcedureErrorSchemaType;\n\n/**\n * Represents an acceptable schema to pass to a procedure.\n * Just a type of a schema, not an actual schema.\n *\n */\nexport type ProcedureErrorSchemaType =\n | TNever\n | BaseErrorSchemaType\n | TUnion<Array<BaseErrorSchemaType>>;\n\n// arbitrarily nested unions\n// river doesn't accept this by default, use the `flattenErrorType` helper\ntype NestableProcedureErrorSchemaType =\n | BaseErrorSchemaType\n | TUnion<NestableProcedureErrorSchemaTypeArray>;\n\n// use an interface to defer the type definition to be evaluated lazily\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\ninterface NestableProcedureErrorSchemaTypeArray\n extends Array<NestableProcedureErrorSchemaType> {}\n\nfunction isUnion(schema: TSchema): schema is TUnion {\n return schema[Kind] === 'Union';\n}\n\ntype Flatten<T> = T extends BaseErrorSchemaType\n ? T\n : T extends TUnion<Array<infer U extends TSchema>>\n ? Flatten<U>\n : unknown;\n\n/**\n * In the case where API consumers for some god-forsaken reason want to use\n * arbitrarily nested unions, this helper flattens them to a single level.\n *\n * Note that loses some metadata information on the nested unions like\n * nested description fields, etc.\n *\n * @param errType - An arbitrarily union-nested error schema.\n * @returns The flattened error schema.\n */\nexport function flattenErrorType<T extends NestableProcedureErrorSchemaType>(\n errType: T,\n): Flatten<T>;\nexport function flattenErrorType(\n errType: NestableProcedureErrorSchemaType,\n): ProcedureErrorSchemaType {\n if (!isUnion(errType)) {\n return errType;\n }\n\n const flattenedTypes: Array<BaseErrorSchemaType> = [];\n function flatten(type: NestableProcedureErrorSchemaType) {\n if (isUnion(type)) {\n for (const t of type.anyOf) {\n flatten(t);\n }\n } else {\n flattenedTypes.push(type);\n }\n }\n\n flatten(errType);\n\n return Type.Union(flattenedTypes);\n}\n"],"mappings":"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","names":["import_typebox","import_api","import_typebox","NodeWs"]}
|
|
1
|
+
{"version":3,"sources":["../../util/testHelpers.ts","../../router/result.ts","../../transport/message.ts","../../transport/id.ts","../../util/stringify.ts","../../router/streams.ts","../../codec/json.ts","../../transport/options.ts","../../transport/sessionStateMachine/common.ts","../../transport/sessionStateMachine/SessionConnecting.ts","../../transport/sessionStateMachine/SessionNoConnection.ts","../../tracing/index.ts","../../package.json","../../transport/sessionStateMachine/SessionWaitingForHandshake.ts","../../transport/sessionStateMachine/SessionHandshaking.ts","../../transport/sessionStateMachine/SessionConnected.ts","../../transport/sessionStateMachine/SessionBackingOff.ts","../../transport/sessionStateMachine/transitions.ts","../../router/errors.ts"],"sourcesContent":["import NodeWs, { WebSocketServer } from 'ws';\nimport http from 'node:http';\nimport { Err, Ok, Result } from '../router/result';\nimport { PayloadType, Procedure } from '../router/procedures';\nimport { Static } from '@sinclair/typebox';\nimport {\n OpaqueTransportMessage,\n PartialTransportMessage,\n currentProtocolVersion,\n} from '../transport/message';\nimport { coerceErrorString } from './stringify';\nimport { Transport } from '../transport/transport';\nimport {\n Readable,\n ReadableImpl,\n ReadableResult,\n ReadableIterator,\n Writable,\n WritableImpl,\n} from '../router/streams';\nimport { ServiceContext, ProcedureHandlerContext } from '../router/context';\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 {\n Session,\n SessionStateGraph,\n} from '../transport/sessionStateMachine/transitions';\nimport {\n BaseErrorSchemaType,\n ProcedureErrorSchemaType,\n ReaderErrorSchema,\n UNCAUGHT_ERROR_CODE,\n} from '../router/errors';\nimport { ClientTransport } from '../transport/client';\nimport { ServerTransport } from '../transport/server';\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\nfunction catchProcError(err: unknown) {\n const errorMsg = coerceErrorString(err);\n\n return Err({ code: UNCAUGHT_ERROR_CODE, message: errorMsg });\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\nfunction dummyCtx<State>(\n state: State,\n session: Session<Connection>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n): ProcedureHandlerContext<State> {\n return {\n ...extendedContext,\n state,\n sessionId: session.id,\n from: session.from,\n metadata: {},\n // TODO might wanna hook these up!\n cancel: () => undefined,\n signal: new AbortController().signal,\n };\n}\n\nexport function asClientRpc<\n State extends object,\n Init extends PayloadType,\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(\n state: State,\n proc: Procedure<State, 'rpc', Init, null, Res, Err>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n session: Session<Connection> = dummySession(),\n) {\n return async (\n msg: Static<Init>,\n ): Promise<\n Result<Static<Res>, Static<Err> | Static<typeof ReaderErrorSchema>>\n > => {\n return proc\n .handler({\n ctx: dummyCtx(state, session, extendedContext),\n reqInit: msg,\n })\n .catch(catchProcError);\n };\n}\n\nfunction createResponsePipe<\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(): {\n readable: Readable<\n Static<Res>,\n Static<Err> | Static<typeof ReaderErrorSchema>\n >;\n writable: Writable<Result<Static<Res>, Static<Err>>>;\n} {\n const readable = new ReadableImpl<\n Static<Res>,\n Static<Err> | Static<typeof ReaderErrorSchema>\n >();\n const writable = new WritableImpl<Result<Static<Res>, Static<Err>>>({\n writeCb: (v) => {\n readable._pushValue(v);\n },\n closeCb: () => {\n // Make it async to simulate request going over the wire\n // using promises so that we don't get affected by fake timers.\n void Promise.resolve().then(() => {\n readable._triggerClose();\n });\n },\n });\n\n return { readable, writable };\n}\n\nfunction createRequestPipe<Req extends PayloadType>(): {\n readable: Readable<Static<Req>, Static<typeof ReaderErrorSchema>>;\n writable: Writable<Static<Req>>;\n} {\n const readable = new ReadableImpl<\n Static<Req>,\n Static<typeof ReaderErrorSchema>\n >();\n const writable = new WritableImpl<Static<Req>>({\n writeCb: (v) => {\n readable._pushValue(Ok(v));\n },\n closeCb: () => {\n // Make it async to simulate request going over the wire\n // using promises so that we don't get affected by fake timers.\n void Promise.resolve().then(() => {\n readable._triggerClose();\n });\n },\n });\n\n return { readable, writable };\n}\n\nexport function asClientStream<\n State extends object,\n Init extends PayloadType,\n Req extends PayloadType,\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(\n state: State,\n proc: Procedure<State, 'stream', Init, Req, Res, Err>,\n reqInit?: Static<Init>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n session: Session<Connection> = dummySession(),\n): {\n reqWritable: Writable<Static<Req>>;\n resReadable: Readable<Static<Res>, Static<Err>>;\n} {\n const requestPipe = createRequestPipe<Req>();\n const responsePipe = createResponsePipe<Res, Err>();\n\n void proc\n .handler({\n ctx: dummyCtx(state, session, extendedContext),\n reqInit: reqInit ?? {},\n reqReadable: requestPipe.readable,\n resWritable: responsePipe.writable,\n })\n .catch((err: unknown) => responsePipe.writable.write(catchProcError(err)));\n\n return {\n reqWritable: requestPipe.writable,\n resReadable: responsePipe.readable,\n };\n}\n\nexport function asClientSubscription<\n State extends object,\n Init extends PayloadType,\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(\n state: State,\n proc: Procedure<State, 'subscription', Init, null, Res, Err>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n session: Session<Connection> = dummySession(),\n): (msg: Static<Init>) => {\n resReadable: Readable<Static<Res>, Static<Err>>;\n} {\n const responsePipe = createResponsePipe<Res, Err>();\n\n return (msg: Static<Init>) => {\n void proc\n .handler({\n ctx: dummyCtx(state, session, extendedContext),\n reqInit: msg,\n resWritable: responsePipe.writable,\n })\n .catch((err: unknown) =>\n responsePipe.writable.write(catchProcError(err)),\n );\n\n return { resReadable: responsePipe.readable };\n };\n}\n\nexport function asClientUpload<\n State extends object,\n Init extends PayloadType,\n Req extends PayloadType,\n Res extends PayloadType,\n Err extends ProcedureErrorSchemaType,\n>(\n state: State,\n proc: Procedure<State, 'upload', Init, Req, Res, Err>,\n reqInit?: Static<Init>,\n extendedContext?: Omit<ServiceContext, 'state'>,\n session: Session<Connection> = dummySession(),\n): {\n reqWritable: Writable<Static<Req>>;\n finalize: () => Promise<Result<Static<Res>, Static<Err>>>;\n} {\n const requestPipe = createRequestPipe<Req>();\n const result = proc\n .handler({\n ctx: dummyCtx(state, session, extendedContext),\n reqInit: reqInit ?? {},\n reqReadable: requestPipe.readable,\n })\n .catch(catchProcError);\n\n return { reqWritable: requestPipe.writable, finalize: () => result };\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","import { Static, Type } from '@sinclair/typebox';\nimport { Client } from './client';\nimport { Readable } from './streams';\nimport { BaseErrorSchemaType } from './errors';\n\n/**\n * AnyResultSchema is a schema to validate any result.\n */\nexport const AnyResultSchema = Type.Union([\n Type.Object({\n ok: Type.Literal(false),\n payload: Type.Object({\n code: Type.String(),\n message: Type.String(),\n extras: Type.Optional(Type.Unknown()),\n }),\n }),\n\n Type.Object({\n ok: Type.Literal(true),\n payload: Type.Unknown(),\n }),\n]);\n\nexport interface OkResult<T> {\n ok: true;\n payload: T;\n}\nexport interface ErrResult<Err extends Static<BaseErrorSchemaType>> {\n ok: false;\n payload: Err;\n}\nexport type Result<T, Err extends Static<BaseErrorSchemaType>> =\n | OkResult<T>\n | ErrResult<Err>;\n\nexport function Ok<const T extends Array<unknown>>(p: T): OkResult<T>;\nexport function Ok<const T extends ReadonlyArray<unknown>>(p: T): OkResult<T>;\nexport function Ok<const T>(payload: T): OkResult<T>;\nexport function Ok<const T>(payload: T): OkResult<T> {\n return {\n ok: true,\n payload,\n };\n}\n\nexport function Err<const Err extends Static<BaseErrorSchemaType>>(\n error: Err,\n): ErrResult<Err> {\n return {\n ok: false,\n payload: error,\n };\n}\n\n/**\n * Refine a {@link Result} type to its returned payload.\n */\nexport type ResultUnwrapOk<R> = R extends Result<infer T, infer __E>\n ? T\n : never;\n\n/**\n * Unwrap a {@link Result} type and return the payload if successful,\n * otherwise throws an error.\n * @param result - The result to unwrap.\n * @throws Will throw an error if the result is not ok.\n */\nexport function unwrapOrThrow<T, Err extends Static<BaseErrorSchemaType>>(\n result: Result<T, Err>,\n): T {\n if (result.ok) {\n return result.payload;\n }\n\n throw new Error(\n `Cannot non-ok result, got: ${result.payload.code} - ${result.payload.message}`,\n );\n}\n\n/**\n * Refine a {@link Result} type to its error payload.\n */\nexport type ResultUnwrapErr<R> = R extends Result<infer __T, infer Err>\n ? Err\n : never;\n\n/**\n * Retrieve the response type for a procedure, represented as a {@link Result}\n * type.\n * Example:\n * ```\n * type Message = ResponseData<typeof client, 'serviceName', 'procedureName'>\n * ```\n */\nexport type ResponseData<\n RiverClient,\n ServiceName extends keyof RiverClient,\n ProcedureName extends keyof RiverClient[ServiceName],\n Procedure = RiverClient[ServiceName][ProcedureName],\n Fn extends (...args: never) => unknown = (...args: never) => unknown,\n> = RiverClient extends Client<infer __ServiceSchemaMap>\n ? Procedure extends object\n ? Procedure extends object & { rpc: infer RpcFn extends Fn }\n ? Awaited<ReturnType<RpcFn>>\n : Procedure extends object & { upload: infer UploadFn extends Fn }\n ? ReturnType<UploadFn> extends {\n finalize: (...args: never) => Promise<infer UploadOutputMessage>;\n }\n ? UploadOutputMessage\n : never\n : Procedure extends object & { stream: infer StreamFn extends Fn }\n ? ReturnType<StreamFn> extends {\n resReadable: Readable<\n infer StreamOutputMessage,\n Static<BaseErrorSchemaType>\n >;\n }\n ? StreamOutputMessage\n : never\n : Procedure extends object & {\n subscribe: infer SubscriptionFn extends Fn;\n }\n ? Awaited<ReturnType<SubscriptionFn>> extends {\n resReadable: Readable<\n infer SubscriptionOutputMessage,\n Static<BaseErrorSchemaType>\n >;\n }\n ? SubscriptionOutputMessage\n : never\n : never\n : never\n : never;\n","import { Type, TSchema, Static } from '@sinclair/typebox';\nimport { PropagationContext } from '../tracing';\nimport { generateId } from './id';\nimport { ErrResult, ReaderErrorSchema } from '../router';\n\n/**\n * Control flags for transport messages.\n */\nexport const enum ControlFlags {\n /**\n * Used in heartbeat messages.\n */\n AckBit = 0b00001,\n /**\n * Used in stream open requests.\n */\n StreamOpenBit = 0b00010,\n /**\n * Used when a stream is cancelled due errors or to explicit cancellation\n */\n StreamCancelBit = 0b00100,\n /**\n * Used when writer closes the stream.\n */\n StreamClosedBit = 0b01000,\n}\n\n/**\n * Generic Typebox schema for a transport message.\n * @template T The type of the payload.\n * @param {T} t The payload schema.\n * @returns The transport message schema.\n */\nexport const TransportMessageSchema = <T extends TSchema>(t: T) =>\n Type.Object({\n id: Type.String(),\n from: Type.String(),\n to: Type.String(),\n seq: Type.Integer(),\n ack: Type.Integer(),\n serviceName: Type.Optional(Type.String()),\n procedureName: Type.Optional(Type.String()),\n streamId: Type.String(),\n controlFlags: Type.Integer(),\n tracing: Type.Optional(\n Type.Object({\n traceparent: Type.String(),\n tracestate: Type.String(),\n }),\n ),\n payload: t,\n });\n\n/**\n * Defines the schema for a transport acknowledgement message. This is never constructed manually\n * and is only used internally by the library for tracking inflight messages.\n * @returns The transport message schema.\n */\nexport const ControlMessageAckSchema = Type.Object({\n type: Type.Literal('ACK'),\n});\n\n/**\n * Defines the schema for a transport close message. This is never constructed manually and is only\n * used internally by the library for closing and cleaning up streams.\n */\nexport const ControlMessageCloseSchema = Type.Object({\n type: Type.Literal('CLOSE'),\n});\n\nexport type ProtocolVersion = 'v1.1' | 'v2.0';\nexport const currentProtocolVersion = 'v2.0' satisfies ProtocolVersion;\nexport const acceptedProtocolVersions = ['v1.1', currentProtocolVersion];\nexport function isAcceptedProtocolVersion(\n version: string,\n): version is ProtocolVersion {\n return acceptedProtocolVersions.includes(version);\n}\n\nexport const ControlMessageHandshakeRequestSchema = Type.Object({\n type: Type.Literal('HANDSHAKE_REQ'),\n protocolVersion: Type.String(),\n sessionId: Type.String(),\n /**\n * Specifies what the server's expected session state (from the pov of the client). This can be\n * used by the server to know whether this is a new or a reestablished connection, and whether it\n * is compatible with what it already has.\n */\n expectedSessionState: Type.Object({\n // what the client expects the server to send next\n nextExpectedSeq: Type.Integer(),\n nextSentSeq: Type.Integer(),\n }),\n\n metadata: Type.Optional(Type.Unknown()),\n});\n\nexport const HandshakeErrorRetriableResponseCodes = Type.Union([\n Type.Literal('SESSION_STATE_MISMATCH'),\n]);\n\nexport const HandshakeErrorCustomHandlerFatalResponseCodes = Type.Union([\n // The custom validation handler rejected the handler because the client is unsupported.\n Type.Literal('REJECTED_UNSUPPORTED_CLIENT'),\n // The custom validation handler rejected the handshake.\n Type.Literal('REJECTED_BY_CUSTOM_HANDLER'),\n]);\n\nexport const HandshakeErrorFatalResponseCodes = Type.Union([\n HandshakeErrorCustomHandlerFatalResponseCodes,\n // The ciient sent a handshake that doesn't comply with the extended handshake metadata.\n Type.Literal('MALFORMED_HANDSHAKE_META'),\n // The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.\n Type.Literal('MALFORMED_HANDSHAKE'),\n // The client's protocol version does not match the server's.\n Type.Literal('PROTOCOL_VERSION_MISMATCH'),\n]);\n\nexport const HandshakeErrorResponseCodes = Type.Union([\n HandshakeErrorRetriableResponseCodes,\n HandshakeErrorFatalResponseCodes,\n]);\n\nexport const ControlMessageHandshakeResponseSchema = Type.Object({\n type: Type.Literal('HANDSHAKE_RESP'),\n status: Type.Union([\n Type.Object({\n ok: Type.Literal(true),\n sessionId: Type.String(),\n }),\n Type.Object({\n ok: Type.Literal(false),\n reason: Type.String(),\n code: HandshakeErrorResponseCodes,\n }),\n ]),\n});\n\nexport const ControlMessagePayloadSchema = Type.Union([\n ControlMessageCloseSchema,\n ControlMessageAckSchema,\n ControlMessageHandshakeRequestSchema,\n ControlMessageHandshakeResponseSchema,\n]);\n\n/**\n * Defines the schema for an opaque transport message that is agnostic to any\n * procedure/service.\n * @returns The transport message schema.\n */\nexport const OpaqueTransportMessageSchema = TransportMessageSchema(\n Type.Unknown(),\n);\n\n/**\n * Represents a transport message. This is the same type as {@link TransportMessageSchema} but\n * we can't statically infer generics from generic Typebox schemas so we have to define it again here.\n *\n * TypeScript can't enforce types when a bitmask is involved, so these are the semantics of\n * `controlFlags`:\n * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `streamId` must be set to a unique value\n * (suggestion: use `nanoid`).\n * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `serviceName` and `procedureName` must be set.\n * * If `controlFlags & StreamClosedBit == StreamClosedBit` and the kind is `stream` or `subscription`,\n * `payload` should be discarded (usually contains a control message).\n * * If `controlFlags & AckBit == AckBit`, the message is an explicit acknowledgement message and doesn't\n * contain any payload that is relevant to the application so should not be delivered.\n * @template Payload The type of the payload.\n */\nexport interface TransportMessage<Payload = unknown> {\n id: string;\n from: TransportClientId;\n to: TransportClientId;\n seq: number;\n ack: number;\n serviceName?: string;\n procedureName?: string;\n streamId: string;\n controlFlags: number;\n tracing?: PropagationContext;\n payload: Payload;\n}\n\nexport type PartialTransportMessage<Payload = unknown> = Omit<\n TransportMessage<Payload>,\n 'id' | 'from' | 'to' | 'seq' | 'ack'\n>;\n\nexport function handshakeRequestMessage({\n from,\n to,\n sessionId,\n expectedSessionState,\n metadata,\n tracing,\n}: {\n from: TransportClientId;\n to: TransportClientId;\n sessionId: string;\n expectedSessionState: Static<\n typeof ControlMessageHandshakeRequestSchema\n >['expectedSessionState'];\n metadata?: unknown;\n tracing?: PropagationContext;\n}): TransportMessage<Static<typeof ControlMessageHandshakeRequestSchema>> {\n return {\n id: generateId(),\n from,\n to,\n seq: 0,\n ack: 0,\n streamId: generateId(),\n controlFlags: 0,\n tracing,\n payload: {\n type: 'HANDSHAKE_REQ',\n protocolVersion: currentProtocolVersion,\n sessionId,\n expectedSessionState,\n metadata,\n } satisfies Static<typeof ControlMessageHandshakeRequestSchema>,\n };\n}\n\n/**\n * This is a reason that can be given during the handshake to indicate that the peer has the wrong\n * session state.\n */\nexport const SESSION_STATE_MISMATCH = 'session state mismatch';\n\nexport function handshakeResponseMessage({\n from,\n to,\n status,\n}: {\n from: TransportClientId;\n to: TransportClientId;\n status: Static<typeof ControlMessageHandshakeResponseSchema>['status'];\n}): TransportMessage<Static<typeof ControlMessageHandshakeResponseSchema>> {\n return {\n id: generateId(),\n from,\n to,\n seq: 0,\n ack: 0,\n streamId: generateId(),\n controlFlags: 0,\n payload: {\n type: 'HANDSHAKE_RESP',\n status,\n } satisfies Static<typeof ControlMessageHandshakeResponseSchema>,\n };\n}\n\nexport function closeStreamMessage(streamId: string): PartialTransportMessage {\n return {\n streamId,\n controlFlags: ControlFlags.StreamClosedBit,\n payload: {\n type: 'CLOSE' as const,\n } satisfies Static<typeof ControlMessagePayloadSchema>,\n };\n}\n\nexport function cancelMessage(\n streamId: string,\n payload: ErrResult<Static<typeof ReaderErrorSchema>>,\n) {\n return {\n streamId,\n controlFlags: ControlFlags.StreamCancelBit,\n payload,\n };\n}\n\n/**\n * A type alias for a transport message with an opaque payload.\n * @template T - The type of the opaque payload.\n */\nexport type OpaqueTransportMessage = TransportMessage;\nexport type TransportClientId = string;\n\n/**\n * Checks if the given control flag (usually found in msg.controlFlag) is an ack message.\n * @param controlFlag - The control flag to check.\n * @returns True if the control flag contains the AckBit, false otherwise.\n */\nexport function isAck(controlFlag: number): boolean {\n /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */\n return (controlFlag & ControlFlags.AckBit) === ControlFlags.AckBit;\n}\n\n/**\n * Checks if the given control flag (usually found in msg.controlFlag) is a stream open message.\n * @param controlFlag - The control flag to check.\n * @returns True if the control flag contains the StreamOpenBit, false otherwise.\n */\nexport function isStreamOpen(controlFlag: number): boolean {\n return (\n /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */\n (controlFlag & ControlFlags.StreamOpenBit) === ControlFlags.StreamOpenBit\n );\n}\n\n/**\n * Checks if the given control flag (usually found in msg.controlFlag) is a stream close message.\n * @param controlFlag - The control flag to check.\n * @returns True if the control flag contains the StreamCloseBit, false otherwise.\n */\nexport function isStreamClose(controlFlag: number): boolean {\n return (\n /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */\n (controlFlag & ControlFlags.StreamClosedBit) ===\n ControlFlags.StreamClosedBit\n );\n}\n\n/**\n * Checks if the given control flag (usually found in msg.controlFlag) is an cancel message.\n * @param controlFlag - The control flag to check.\n * @returns True if the control flag contains the CancelBit, false otherwise\n */\nexport function isStreamCancel(controlFlag: number): boolean {\n return (\n /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */\n (controlFlag & ControlFlags.StreamCancelBit) ===\n ControlFlags.StreamCancelBit\n );\n}\n","import { customAlphabet } from 'nanoid';\n\nconst alphabet = customAlphabet(\n '1234567890abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ',\n);\nexport const generateId = () => alphabet(12);\n","export function coerceErrorString(err: unknown): string {\n if (err instanceof Error) {\n return err.message || 'unknown reason';\n }\n\n return `[coerced to error] ${String(err)}`;\n}\n","import { Static } from '@sinclair/typebox';\nimport { Err, Result } from './result';\nimport { BaseErrorSchemaType } from './errors';\n\nexport const ReadableBrokenError = {\n code: 'READABLE_BROKEN',\n message: 'Readable was broken before it is fully consumed',\n} as const satisfies Static<BaseErrorSchemaType>;\n\n/**\n * Similar to {@link Result} but with an extra error to handle cases where {@link Readable.break} is called\n */\nexport type ReadableResult<T, E extends Static<BaseErrorSchemaType>> = Result<\n T,\n E | typeof ReadableBrokenError\n>;\n\n/**\n * A simple {@link AsyncIterator} used in {@link Readable}\n * that doesn't have a the extra \"return\" and \"throw\" methods, and\n * the doesn't have a \"done value\" (TReturn).\n */\nexport interface ReadableIterator<T, E extends Static<BaseErrorSchemaType>> {\n next(): Promise<\n | {\n done: false;\n value: ReadableResult<T, E>;\n }\n | {\n done: true;\n value: undefined;\n }\n >;\n}\n\n/**\n * A {@link Readable} is an abstraction from which data is consumed from {@link Writable} source.\n *\n * - On the server the argument passed the procedure handler for `upload` and `stream` implements a {@link Readable} interface\n * so you can read client's request data.\n * - On the client the returned value of `subscription` or `stream` invocation implements a {@link Readable} interface\n * so you can read server's response data.\n *\n * A {@link Readable} can only have one consumer (iterator or {@link collect}) for the {@link Readable}'s\n * lifetime, in essense, reading from a {@link Readable} locks it forever.\n */\nexport interface Readable<T, E extends Static<BaseErrorSchemaType>> {\n /**\n * {@link Readable} implements AsyncIterator API and can be consumed via\n * for-await-of loops. Iteration locks the Readable. Exiting the loop\n * will **not** release the lock and it'll be equivalent of calling\n * {@link break}.\n */\n [Symbol.asyncIterator](): ReadableIterator<T, E>;\n /**\n * {@link collect} locks the {@link Readable} and returns a promise that resolves\n * with an array of the content when the {@link Readable} is fully done. This could\n * be due to the {@link Writable} end of the pipe closing cleanly, the procedure invocation\n * is cancelled, or {@link break} is called.\n */\n collect(): Promise<Array<ReadableResult<T, E>>>;\n /**\n * {@link break} locks the {@link Readable} and discards any existing or future incoming data.\n *\n * If there is an existing reader waiting for the next value, {@link break} causes it to\n * resolve with a {@link ReadableBrokenError} error.\n */\n break(): undefined;\n /**\n * {@link isReadable} returns true if it's safe to read from the {@link Readable}, either\n * via iteration or {@link collect}. It returns false if the {@link Readable} is locked\n * by a consumer (iterator or {@link collect}) or readable was broken via {@link break}.\n */\n isReadable(): boolean;\n}\n\n/**\n * A {@link Writeable} is a an abstraction for a {@link Readable} destination to which data is written to.\n *\n * - On the server the argument passed the procedure handler for `subscription` and `stream` implements a {@link Writeable}\n * so you can write server's response data.\n * - On the client the returned value of `upload` or `stream` invocation implements a {@link Writeable}\n * so you can write client's request data.\n *\n * Once closed, a {@link Writeable} can't be re-opened.` `\n */\nexport interface Writable<T> {\n /**\n * {@link write} writes a value to the pipe. An error is thrown if writing to a closed {@link Writable}.\n */\n write(value: T): undefined;\n /**\n * {@link close} signals the closure of the {@link Writeable}, informing the {@link Readable} end that\n * all data has been transmitted and we've cleanly closed.\n *\n * Calling {@link close} multiple times is a no-op.\n */\n close(): undefined;\n /**\n * {@link isWritable} returns true if it's safe to call {@link write}, which\n * means that the {@link Writable} hasn't been closed due to {@link close} being called\n * on this {@link Writable} or the procedure invocation ending for any reason.\n */\n isWritable(): boolean;\n}\n\n/**\n * @internal\n *\n * @see {@link createPromiseWithResolvers}\n */\ninterface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T) => void;\n reject: (reason: unknown) => void;\n}\n\n/**\n * @internal\n *\n * Same as https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers\n * but we support versions where it doesn't exist\n */\nfunction createPromiseWithResolvers<T>(): PromiseWithResolvers<T> {\n let resolve: (value: T) => void;\n let reject: (reason: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return {\n promise,\n // @ts-expect-error promise callbacks are sync\n resolve,\n // @ts-expect-error promise callbacks are sync\n reject,\n };\n}\n\n/**\n * @internal\n *\n * Internal implementation of a {@link Readable}.\n * This won't be exposed as an interface to river\n * consumers directly.\n */\nexport class ReadableImpl<T, E extends Static<BaseErrorSchemaType>>\n implements Readable<T, E>\n{\n /**\n * Whether the {@link Readable} is closed.\n *\n * Closed {@link Readable}s are done receiving values, but that doesn't affect\n * any other aspect of the {@link Readable} such as it's consumability.\n */\n private closed = false;\n /**\n * Whether the {@link Readable} is locked.\n *\n * @see {@link Readable}'s typedoc to understand locking\n */\n private locked = false;\n /**\n * Whether {@link break} was called.\n *\n * @see {@link break} for more information\n */\n private broken = false;\n /**\n * This flag allows us to avoid emitting a {@link ReadableBrokenError} after {@link break} was called\n * in cases where the {@link queue} is fully consumed and {@link ReadableImpl} is {@link closed}. This is just an\n * ergonomic feature to avoid emitting an error in our iteration when we don't have to.\n */\n private brokenWithValuesLeftToRead = false;\n /**\n * A list of values that have been pushed to the {@link ReadableImpl} but not yet emitted to the user.\n */\n private queue: Array<ReadableResult<T, E>> = [];\n /**\n * Used by methods in the class to signal to the iterator that it\n * should check for the next value.\n */\n private next: PromiseWithResolvers<void> | null = null;\n\n public [Symbol.asyncIterator]() {\n if (this.locked) {\n throw new TypeError('Readable is already locked');\n }\n\n this.locked = true;\n\n /**\n * First iteration with {@link break} signals an error, the following one signals end of iteration.\n * This variable is used to signal the end of iteration.\n */\n let didSignalBreak = false;\n\n return {\n next: async () => {\n if (didSignalBreak) {\n return {\n done: true,\n value: undefined,\n } as const;\n }\n\n /**\n * In a normal iteration case the while loop can be structured as a couple of if statements,\n * in other words the loop will run at most a couple of times:\n * - it will run 0 times if we have something in the queue to consume\n * - it will run 1 time if we have nothing in the queue and then get something in the queue\n * - it will run 2 times if we have nothing in the queue and then the readable closes or breaks\n *\n * However, in a degenerate case where something has the handle to the iterator and is calling `next`\n * eagerly multiple times this loop will come in handy by queuing them up and looping as needed.\n */\n while (this.queue.length === 0) {\n if (this.closed && !this.brokenWithValuesLeftToRead) {\n return {\n done: true,\n value: undefined,\n } as const;\n }\n\n if (this.broken) {\n didSignalBreak = true;\n\n return {\n done: false,\n value: Err(ReadableBrokenError),\n } as const;\n }\n\n if (!this.next) {\n this.next = createPromiseWithResolvers();\n }\n\n await this.next.promise;\n this.next = null;\n }\n\n // Unfortunately we have to use non-null assertion here, because T can be undefined\n // we already check for array length above anyway\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const value = this.queue.shift()!;\n\n return { done: false, value } as const;\n },\n return: () => {\n this.break();\n\n return { done: true, value: undefined } as const;\n },\n };\n }\n\n public async collect(): Promise<Array<ReadableResult<T, E>>> {\n const array: Array<ReadableResult<T, E>> = [];\n for await (const value of this) {\n array.push(value);\n }\n\n return array;\n }\n\n public break(): undefined {\n if (this.broken) {\n return;\n }\n\n this.locked = true;\n this.broken = true;\n this.brokenWithValuesLeftToRead = this.queue.length > 0;\n this.queue.length = 0;\n\n // if we have any iterators waiting for the next value,\n this.next?.resolve();\n }\n\n public isReadable(): boolean {\n return !this.locked && !this.broken;\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n *\n * Pushes a value to be read.\n */\n public _pushValue(value: Result<T, E>): undefined {\n if (this.broken) {\n return;\n }\n\n if (this.closed) {\n throw new Error('Cannot push to closed Readable');\n }\n\n this.queue.push(value);\n this.next?.resolve();\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n *\n * Triggers the close of the {@link Readable}. Make sure to push all remaining\n * values before calling this method.\n */\n public _triggerClose(): undefined {\n if (this.closed) {\n throw new Error('Unexpected closing multiple times');\n }\n\n this.closed = true;\n this.next?.resolve();\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n */\n public _hasValuesInQueue(): boolean {\n return this.queue.length > 0;\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n */\n public isClosed(): boolean {\n return this.closed;\n }\n}\n\n/**\n * Internal implementation of a {@link Writable}.\n * This won't be exposed as an interface to river\n * consumers directly.\n */\nexport class WritableImpl<T> implements Writable<T> {\n /**\n * Passed via constructor to pass on calls to {@link write}\n */\n private writeCb: (value: T) => void;\n\n /**\n * Passed via constructor to pass on calls to {@link close}\n */\n private closeCb: () => void;\n /**\n * Whether {@link close} was called, and {@link Writable} is not writable anymore.\n */\n private closed = false;\n\n constructor(callbacks: { writeCb: (value: T) => void; closeCb: () => void }) {\n this.writeCb = callbacks.writeCb;\n this.closeCb = callbacks.closeCb;\n }\n\n public write(value: T): undefined {\n if (this.closed) {\n throw new Error('Cannot write to closed Writable');\n }\n\n this.writeCb(value);\n }\n\n public isWritable(): boolean {\n return !this.closed;\n }\n\n public close(): undefined {\n if (this.closed) {\n return;\n }\n\n this.closed = true;\n this.writeCb = () => undefined;\n this.closeCb();\n this.closeCb = () => undefined;\n }\n\n /**\n * @internal meant for use within river, not exposed as a public API\n */\n public isClosed(): boolean {\n return this.closed;\n }\n}\n","import { Codec } from './types';\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\n// Convert Uint8Array to base64\nfunction uint8ArrayToBase64(uint8Array: Uint8Array) {\n let binary = '';\n uint8Array.forEach((byte) => {\n binary += String.fromCharCode(byte);\n });\n\n return btoa(binary);\n}\n\n// Convert base64 to Uint8Array\nfunction base64ToUint8Array(base64: string) {\n const binaryString = atob(base64);\n const uint8Array = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n uint8Array[i] = binaryString.charCodeAt(i);\n }\n\n return uint8Array;\n}\n\ninterface Base64EncodedValue {\n $t: string;\n}\n\n/**\n * Naive JSON codec implementation using JSON.stringify and JSON.parse.\n * @type {Codec}\n */\nexport const NaiveJsonCodec: Codec = {\n toBuffer: (obj: object) => {\n return encoder.encode(\n JSON.stringify(obj, function replacer<\n T extends object,\n >(this: T, key: keyof T) {\n const val = this[key];\n if (val instanceof Uint8Array) {\n return { $t: uint8ArrayToBase64(val) } satisfies Base64EncodedValue;\n } else {\n return val;\n }\n }),\n );\n },\n fromBuffer: (buff: Uint8Array) => {\n try {\n const parsed = JSON.parse(\n decoder.decode(buff),\n function reviver(_key, val: unknown) {\n if ((val as Base64EncodedValue | undefined)?.$t) {\n return base64ToUint8Array((val as Base64EncodedValue).$t);\n } else {\n return val;\n }\n },\n ) as unknown;\n\n if (typeof parsed === 'object') return parsed;\n\n return null;\n } catch {\n return null;\n }\n },\n};\n","import { NaiveJsonCodec } from '../codec/json';\nimport { ConnectionRetryOptions } from './rateLimit';\nimport { SessionOptions } from './sessionStateMachine/common';\n\nexport type TransportOptions = SessionOptions;\n\nexport type ProvidedTransportOptions = Partial<TransportOptions>;\n\nexport const defaultTransportOptions: TransportOptions = {\n heartbeatIntervalMs: 1_000,\n heartbeatsUntilDead: 2,\n sessionDisconnectGraceMs: 5_000,\n connectionTimeoutMs: 2_000,\n handshakeTimeoutMs: 1_000,\n enableTransparentSessionReconnects: true,\n codec: NaiveJsonCodec,\n};\n\nexport type ClientTransportOptions = TransportOptions & ConnectionRetryOptions;\n\nexport type ProvidedClientTransportOptions = Partial<ClientTransportOptions>;\n\nconst defaultConnectionRetryOptions: ConnectionRetryOptions = {\n baseIntervalMs: 150,\n maxJitterMs: 200,\n maxBackoffMs: 32_000,\n attemptBudgetCapacity: 5,\n budgetRestoreIntervalMs: 200,\n};\n\nexport const defaultClientTransportOptions: ClientTransportOptions = {\n ...defaultTransportOptions,\n ...defaultConnectionRetryOptions,\n};\n\nexport type ServerTransportOptions = TransportOptions;\n\nexport type ProvidedServerTransportOptions = Partial<ServerTransportOptions>;\n\nexport const defaultServerTransportOptions: ServerTransportOptions = {\n ...defaultTransportOptions,\n};\n","import { Logger, MessageMetadata } from '../../logging';\nimport { TelemetryInfo } from '../../tracing';\nimport {\n OpaqueTransportMessage,\n OpaqueTransportMessageSchema,\n PartialTransportMessage,\n ProtocolVersion,\n TransportClientId,\n TransportMessage,\n} from '../message';\nimport { Value } from '@sinclair/typebox/value';\nimport { Codec } from '../../codec';\nimport { generateId } from '../id';\n\nexport const enum SessionState {\n NoConnection = 'NoConnection',\n BackingOff = 'BackingOff',\n Connecting = 'Connecting',\n Handshaking = 'Handshaking',\n Connected = 'Connected',\n WaitingForHandshake = 'WaitingForHandshake',\n}\n\nexport const ERR_CONSUMED = `session state has been consumed and is no longer valid`;\n\nabstract class StateMachineState {\n abstract readonly state: SessionState;\n\n /*\n * Whether this state has been consumed\n * and we've moved on to another state\n */\n _isConsumed: boolean;\n\n // called when we're transitioning to another state\n // note that this is internal and should not be called directly\n // by consumers, the proxy will call this when the state is consumed\n // and we're transitioning to another state\n abstract _handleStateExit(): void;\n\n // called when we exit the state machine entirely\n // note that this is internal and should not be called directly\n // by consumers, the proxy will call this when .close is closed\n abstract _handleClose(): void;\n\n close(): void {\n this._handleClose();\n }\n\n constructor() {\n this._isConsumed = false;\n\n // proxy helps us prevent access to properties after the state has been consumed\n // e.g. if we hold a reference to a state and try to access it after it's been consumed\n // we intercept the access and throw an error to help catch bugs\n return new Proxy(this, {\n get(target, prop) {\n // always allow access to _isConsumed, id, and state\n if (prop === '_isConsumed' || prop === 'id' || prop === 'state') {\n return Reflect.get(target, prop);\n }\n\n // modify _handleStateExit\n if (prop === '_handleStateExit') {\n return () => {\n target._isConsumed = true;\n target._handleStateExit();\n };\n }\n\n // modify _handleClose\n if (prop === '_handleClose') {\n return () => {\n // target is the non-proxied object, we need to set _isConsumed again\n target._isConsumed = true;\n target._handleStateExit();\n target._handleClose();\n };\n }\n\n if (target._isConsumed) {\n throw new Error(\n `${ERR_CONSUMED}: getting ${prop.toString()} on consumed state`,\n );\n }\n\n return Reflect.get(target, prop);\n },\n set(target, prop, value) {\n if (target._isConsumed) {\n throw new Error(\n `${ERR_CONSUMED}: setting ${prop.toString()} on consumed state`,\n );\n }\n\n return Reflect.set(target, prop, value);\n },\n });\n }\n}\n\nexport interface SessionOptions {\n /**\n * Frequency at which to send heartbeat acknowledgements\n */\n heartbeatIntervalMs: number;\n /**\n * Number of elapsed heartbeats without a response message before we consider\n * the connection dead.\n */\n heartbeatsUntilDead: number;\n /**\n * Max duration that a session can be without a connection before we consider\n * it dead. This deadline is carried between states and is used to determine\n * when to consider the session a lost cause and delete it entirely.\n * Generally, this should be strictly greater than the sum of\n * {@link connectionTimeoutMs} and {@link handshakeTimeoutMs}.\n */\n sessionDisconnectGraceMs: number;\n /**\n * Connection timeout in milliseconds\n */\n connectionTimeoutMs: number;\n /**\n * Handshake timeout in milliseconds\n */\n handshakeTimeoutMs: number;\n /**\n * Whether to enable transparent session reconnects\n */\n enableTransparentSessionReconnects: boolean;\n /**\n * The codec to use for encoding/decoding messages over the wire\n */\n codec: Codec;\n}\n\n// all session states have a from and options\nexport interface CommonSessionProps {\n from: TransportClientId;\n options: SessionOptions;\n log: Logger | undefined;\n}\n\nexport abstract class CommonSession extends StateMachineState {\n readonly from: TransportClientId;\n readonly options: SessionOptions;\n\n log?: Logger;\n abstract get loggingMetadata(): MessageMetadata;\n\n constructor({ from, options, log }: CommonSessionProps) {\n super();\n this.from = from;\n this.options = options;\n this.log = log;\n }\n\n parseMsg(msg: Uint8Array): OpaqueTransportMessage | null {\n const parsedMsg = this.options.codec.fromBuffer(msg);\n\n if (parsedMsg === null) {\n const decodedBuffer = new TextDecoder().decode(Buffer.from(msg));\n this.log?.error(\n `received malformed msg: ${decodedBuffer}`,\n this.loggingMetadata,\n );\n\n return null;\n }\n\n if (!Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {\n this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {\n ...this.loggingMetadata,\n validationErrors: [\n ...Value.Errors(OpaqueTransportMessageSchema, parsedMsg),\n ],\n });\n\n return null;\n }\n\n return parsedMsg;\n }\n}\n\nexport type InheritedProperties = Pick<\n IdentifiedSession,\n 'id' | 'from' | 'to' | 'seq' | 'ack' | 'sendBuffer' | 'telemetry' | 'options'\n>;\n\nexport type SessionId = string;\n\n// all sessions where we know the other side's client id\nexport interface IdentifiedSessionProps extends CommonSessionProps {\n id: SessionId;\n to: TransportClientId;\n seq: number;\n ack: number;\n sendBuffer: Array<OpaqueTransportMessage>;\n telemetry: TelemetryInfo;\n protocolVersion: ProtocolVersion;\n}\n\nexport abstract class IdentifiedSession extends CommonSession {\n readonly id: SessionId;\n readonly telemetry: TelemetryInfo;\n readonly to: TransportClientId;\n readonly protocolVersion: ProtocolVersion;\n\n /**\n * Index of the message we will send next (excluding handshake)\n */\n seq: number;\n\n /**\n * Number of unique messages we've received this session (excluding handshake)\n */\n ack: number;\n sendBuffer: Array<OpaqueTransportMessage>;\n\n constructor(props: IdentifiedSessionProps) {\n const { id, to, seq, ack, sendBuffer, telemetry, log, protocolVersion } =\n props;\n super(props);\n this.id = id;\n this.to = to;\n this.seq = seq;\n this.ack = ack;\n this.sendBuffer = sendBuffer;\n this.telemetry = telemetry;\n this.log = log;\n this.protocolVersion = protocolVersion;\n }\n\n get loggingMetadata(): MessageMetadata {\n const spanContext = this.telemetry.span.spanContext();\n\n const metadata: MessageMetadata = {\n clientId: this.from,\n connectedTo: this.to,\n sessionId: this.id,\n };\n\n if (this.telemetry.span.isRecording()) {\n metadata.telemetry = {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n };\n }\n\n return metadata;\n }\n\n constructMsg<Payload>(\n partialMsg: PartialTransportMessage<Payload>,\n ): TransportMessage<Payload> {\n const msg = {\n ...partialMsg,\n id: generateId(),\n to: this.to,\n from: this.from,\n seq: this.seq,\n ack: this.ack,\n };\n\n this.seq++;\n\n return msg;\n }\n\n nextSeq(): number {\n return this.sendBuffer.length > 0 ? this.sendBuffer[0].seq : this.seq;\n }\n\n send(msg: PartialTransportMessage): string {\n const constructedMsg = this.constructMsg(msg);\n this.sendBuffer.push(constructedMsg);\n\n return constructedMsg.id;\n }\n\n _handleStateExit(): void {\n // noop\n }\n\n _handleClose(): void {\n // zero out the buffer\n this.sendBuffer.length = 0;\n this.telemetry.span.end();\n }\n}\n\nexport interface IdentifiedSessionWithGracePeriodListeners {\n onSessionGracePeriodElapsed: () => void;\n}\n\nexport interface IdentifiedSessionWithGracePeriodProps\n extends IdentifiedSessionProps {\n graceExpiryTime: number;\n listeners: IdentifiedSessionWithGracePeriodListeners;\n}\n\nexport abstract class IdentifiedSessionWithGracePeriod extends IdentifiedSession {\n graceExpiryTime: number;\n protected gracePeriodTimeout?: ReturnType<typeof setTimeout>;\n\n listeners: IdentifiedSessionWithGracePeriodListeners;\n\n constructor(props: IdentifiedSessionWithGracePeriodProps) {\n super(props);\n this.listeners = props.listeners;\n\n this.graceExpiryTime = props.graceExpiryTime;\n this.gracePeriodTimeout = setTimeout(() => {\n this.listeners.onSessionGracePeriodElapsed();\n }, this.graceExpiryTime - Date.now());\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.gracePeriodTimeout) {\n clearTimeout(this.gracePeriodTimeout);\n this.gracePeriodTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n super._handleClose();\n }\n}\n","import { Connection } from '../connection';\nimport {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionConnectingListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onConnectionEstablished: (conn: Connection) => void;\n onConnectionFailed: (err: unknown) => void;\n\n // timeout related\n onConnectionTimeout: () => void;\n}\n\nexport interface SessionConnectingProps<ConnType extends Connection>\n extends IdentifiedSessionWithGracePeriodProps {\n connPromise: Promise<ConnType>;\n listeners: SessionConnectingListeners;\n}\n\n/*\n * A session that is connecting but we don't have access to the raw connection yet.\n * See transitions.ts for valid transitions.\n */\nexport class SessionConnecting<\n ConnType extends Connection,\n> extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.Connecting as const;\n connPromise: Promise<ConnType>;\n listeners: SessionConnectingListeners;\n\n connectionTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionConnectingProps<ConnType>) {\n super(props);\n this.connPromise = props.connPromise;\n this.listeners = props.listeners;\n\n this.connPromise.then(\n (conn) => {\n if (this._isConsumed) return;\n this.listeners.onConnectionEstablished(conn);\n },\n (err) => {\n if (this._isConsumed) return;\n this.listeners.onConnectionFailed(err);\n },\n );\n\n this.connectionTimeout = setTimeout(() => {\n this.listeners.onConnectionTimeout();\n }, this.options.connectionTimeoutMs);\n }\n\n // close a pending connection if it resolves, ignore errors if the promise\n // ends up rejected anyways\n bestEffortClose() {\n // these can technically be stale if the connPromise resolves after the\n // state has transitioned, but that's fine, this is best effort anyways\n // we pull these out so even if the state has transitioned, we can still log\n // without erroring out\n const logger = this.log;\n const metadata = this.loggingMetadata;\n\n this.connPromise\n .then((conn) => {\n conn.close();\n logger?.info(\n 'connection eventually resolved but session has transitioned, closed connection',\n {\n ...metadata,\n ...conn.loggingMetadata,\n },\n );\n })\n .catch(() => {\n // ignore errors\n });\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.connectionTimeout) {\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n // close the pending connection if it resolves\n this.bestEffortClose();\n super._handleClose();\n }\n}\n","import {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport type SessionNoConnectionListeners =\n IdentifiedSessionWithGracePeriodListeners;\n\nexport type SessionNoConnectionProps = IdentifiedSessionWithGracePeriodProps;\n\n/*\n * A session that is not connected and cannot send or receive messages.\n * See transitions.ts for valid transitions.\n */\nexport class SessionNoConnection extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.NoConnection as const;\n\n _handleClose(): void {\n super._handleClose();\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n }\n}\n","import {\n Context,\n Span,\n SpanKind,\n context,\n propagation,\n trace,\n} from '@opentelemetry/api';\nimport { version as RIVER_VERSION } from '../package.json';\nimport { ValidProcType } from '../router';\nimport { ClientTransport, Connection } from '../transport';\n\nexport interface PropagationContext {\n traceparent: string;\n tracestate: string;\n}\n\nexport interface TelemetryInfo {\n span: Span;\n ctx: Context;\n}\n\nexport function getPropagationContext(\n ctx: Context,\n): PropagationContext | undefined {\n const tracing = {\n traceparent: '',\n tracestate: '',\n };\n propagation.inject(ctx, tracing);\n\n return tracing;\n}\n\nexport function createSessionTelemetryInfo(\n sessionId: string,\n to: string,\n from: string,\n propagationCtx?: PropagationContext,\n): TelemetryInfo {\n const parentCtx = propagationCtx\n ? propagation.extract(context.active(), propagationCtx)\n : context.active();\n\n const span = tracer.startSpan(\n `session ${sessionId}`,\n {\n attributes: {\n component: 'river',\n 'river.session.id': sessionId,\n 'river.session.to': to,\n 'river.session.from': from,\n },\n },\n parentCtx,\n );\n\n const ctx = trace.setSpan(parentCtx, span);\n\n return { span, ctx };\n}\n\nexport function createConnectionTelemetryInfo(\n connection: Connection,\n info: TelemetryInfo,\n): TelemetryInfo {\n const span = tracer.startSpan(\n `connection ${connection.id}`,\n {\n attributes: {\n component: 'river',\n 'river.connection.id': connection.id,\n },\n links: [{ context: info.span.spanContext() }],\n },\n info.ctx,\n );\n\n const ctx = trace.setSpan(info.ctx, span);\n\n return { span, ctx };\n}\n\nexport function createProcTelemetryInfo(\n transport: ClientTransport<Connection>,\n kind: ValidProcType,\n serviceName: string,\n procedureName: string,\n streamId: string,\n): TelemetryInfo {\n const baseCtx = context.active();\n const span = tracer.startSpan(\n `procedure call ${serviceName}.${procedureName}`,\n {\n attributes: {\n component: 'river',\n 'river.method.kind': kind,\n 'river.method.service': serviceName,\n 'river.method.name': procedureName,\n 'river.streamId': streamId,\n 'span.kind': 'client',\n },\n kind: SpanKind.CLIENT,\n },\n baseCtx,\n );\n\n const ctx = trace.setSpan(baseCtx, span);\n\n transport.log?.info(`invoked ${serviceName}.${procedureName}`, {\n clientId: transport.clientId,\n transportMessage: {\n procedureName,\n serviceName,\n },\n telemetry: {\n traceId: span.spanContext().traceId,\n spanId: span.spanContext().spanId,\n },\n });\n\n return { span, ctx };\n}\n\nexport function createHandlerSpan<Fn extends (span: Span) => unknown>(\n kind: ValidProcType,\n serviceName: string,\n procedureName: string,\n streamId: string,\n tracing: PropagationContext | undefined,\n fn: Fn,\n): ReturnType<Fn> {\n const ctx = tracing\n ? propagation.extract(context.active(), tracing)\n : context.active();\n\n return tracer.startActiveSpan<Fn>(\n `procedure handler ${serviceName}.${procedureName}`,\n {\n attributes: {\n component: 'river',\n 'river.method.kind': kind,\n 'river.method.service': serviceName,\n 'river.method.name': procedureName,\n 'river.streamId': streamId,\n 'span.kind': 'server',\n },\n kind: SpanKind.SERVER,\n },\n ctx,\n fn,\n );\n}\n\nconst tracer = trace.getTracer('river', RIVER_VERSION);\nexport default tracer;\n","{\n \"name\": \"@replit/river\",\n \"description\": \"It's like tRPC but... with JSON Schema Support, duplex streaming and support for service multiplexing. Transport agnostic!\",\n \"version\": \"0.200.5\",\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/router/index.js\",\n \"require\": \"./dist/router/index.cjs\"\n },\n \"./logging\": {\n \"import\": \"./dist/logging/index.js\",\n \"require\": \"./dist/logging/index.cjs\"\n },\n \"./codec\": {\n \"import\": \"./dist/codec/index.js\",\n \"require\": \"./dist/codec/index.cjs\"\n },\n \"./transport\": {\n \"import\": \"./dist/transport/index.js\",\n \"require\": \"./dist/transport/index.cjs\"\n },\n \"./transport/ws/client\": {\n \"import\": \"./dist/transport/impls/ws/client.js\",\n \"require\": \"./dist/transport/impls/ws/client.cjs\"\n },\n \"./transport/ws/server\": {\n \"import\": \"./dist/transport/impls/ws/server.js\",\n \"require\": \"./dist/transport/impls/ws/server.cjs\"\n },\n \"./transport/uds/client\": {\n \"import\": \"./dist/transport/impls/uds/client.js\",\n \"require\": \"./dist/transport/impls/uds/client.cjs\"\n },\n \"./transport/uds/server\": {\n \"import\": \"./dist/transport/impls/uds/server.js\",\n \"require\": \"./dist/transport/impls/uds/server.cjs\"\n },\n \"./test-util\": {\n \"import\": \"./dist/util/testHelpers.js\",\n \"require\": \"./dist/util/testHelpers.cjs\"\n }\n },\n \"sideEffects\": [\n \"./dist/logging/index.js\"\n ],\n \"files\": [\n \"dist\"\n ],\n \"dependencies\": {\n \"@msgpack/msgpack\": \"^3.0.0-beta2\",\n \"nanoid\": \"^4.0.2\",\n \"ws\": \"^8.17.0\"\n },\n \"peerDependencies\": {\n \"@opentelemetry/api\": \"^1.7.0\",\n \"@sinclair/typebox\": \"~0.32.8\"\n },\n \"devDependencies\": {\n \"@opentelemetry/core\": \"^1.7.0\",\n \"@opentelemetry/sdk-trace-base\": \"^1.24.1\",\n \"@opentelemetry/sdk-trace-web\": \"^1.24.1\",\n \"@stylistic/eslint-plugin\": \"^2.6.4\",\n \"@types/ws\": \"^8.5.5\",\n \"@typescript-eslint/eslint-plugin\": \"^7.8.0\",\n \"@typescript-eslint/parser\": \"^7.8.0\",\n \"@vitest/ui\": \"^2.0.5\",\n \"eslint\": \"^8.57.0\",\n \"eslint-config-prettier\": \"^9.1.0\",\n \"eslint-plugin-prettier\": \"^5.1.3\",\n \"prettier\": \"^3.0.0\",\n \"tsup\": \"^7.2.0\",\n \"typescript\": \"^5.4.5\",\n \"vitest\": \"^2.0.5\"\n },\n \"scripts\": {\n \"check\": \"tsc --noEmit && npm run format && npm run lint\",\n \"format\": \"npx prettier . --check\",\n \"format:fix\": \"npx prettier . --write\",\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"fix\": \"npm run format:fix && npm run lint:fix\",\n \"build\": \"rm -rf dist && tsup && du -sh dist\",\n \"prepack\": \"npm run build\",\n \"release\": \"npm publish --access public\",\n \"test:ui\": \"echo \\\"remember to go to /__vitest__ in the webview\\\" && vitest --ui --api.host 0.0.0.0 --api.port 3000\",\n \"test\": \"vitest\",\n \"test:single\": \"vitest run --reporter=dot\",\n \"test:flake\": \"./flake.sh\",\n \"bench\": \"vitest bench\"\n },\n \"engines\": {\n \"node\": \">=16\"\n },\n \"keywords\": [\n \"rpc\",\n \"websockets\",\n \"jsonschema\"\n ],\n \"author\": \"Jacky Zhao\",\n \"license\": \"MIT\"\n}\n","import { Static } from '@sinclair/typebox';\nimport { Connection } from '../connection';\nimport {\n HandshakeErrorResponseCodes,\n OpaqueTransportMessage,\n TransportMessage,\n} from '../message';\nimport { CommonSession, CommonSessionProps, SessionState } from './common';\n\nexport interface SessionWaitingForHandshakeListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onHandshake: (msg: OpaqueTransportMessage) => void;\n onInvalidHandshake: (\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n ) => void;\n\n // timeout related\n onHandshakeTimeout: () => void;\n}\n\nexport interface SessionWaitingForHandshakeProps<ConnType extends Connection>\n extends CommonSessionProps {\n conn: ConnType;\n listeners: SessionWaitingForHandshakeListeners;\n}\n\n/*\n * Server-side session that has a connection but is waiting for the client to identify itself.\n * See transitions.ts for valid transitions.\n */\nexport class SessionWaitingForHandshake<\n ConnType extends Connection,\n> extends CommonSession {\n readonly state = SessionState.WaitingForHandshake as const;\n conn: ConnType;\n listeners: SessionWaitingForHandshakeListeners;\n\n handshakeTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionWaitingForHandshakeProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.handshakeTimeout = setTimeout(() => {\n this.listeners.onHandshakeTimeout();\n }, this.options.handshakeTimeoutMs);\n\n this.conn.addDataListener(this.onHandshakeData);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n }\n\n get loggingMetadata() {\n return {\n clientId: this.from,\n connId: this.conn.id,\n ...this.conn.loggingMetadata,\n };\n }\n\n onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake(\n 'could not parse message',\n 'MALFORMED_HANDSHAKE',\n );\n\n return;\n }\n\n // after this fires, the listener is responsible for transitioning the session\n // and thus removing the handshake timeout\n this.listeners.onHandshake(parsedMsg);\n };\n\n sendHandshake(msg: TransportMessage): boolean {\n return this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n _handleStateExit(): void {\n this.conn.removeDataListener(this.onHandshakeData);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n clearTimeout(this.handshakeTimeout);\n this.handshakeTimeout = undefined;\n }\n\n _handleClose(): void {\n this.conn.close();\n }\n}\n","import { Static } from '@sinclair/typebox';\nimport { Connection } from '../connection';\nimport {\n OpaqueTransportMessage,\n TransportMessage,\n HandshakeErrorResponseCodes,\n} from '../message';\nimport {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionHandshakingListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onHandshake: (msg: OpaqueTransportMessage) => void;\n onInvalidHandshake: (\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n ) => void;\n\n // timeout related\n onHandshakeTimeout: () => void;\n}\n\nexport interface SessionHandshakingProps<ConnType extends Connection>\n extends IdentifiedSessionWithGracePeriodProps {\n conn: ConnType;\n listeners: SessionHandshakingListeners;\n}\n\n/*\n * A session that is handshaking and waiting for the other side to identify itself.\n * See transitions.ts for valid transitions.\n */\nexport class SessionHandshaking<\n ConnType extends Connection,\n> extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.Handshaking as const;\n conn: ConnType;\n listeners: SessionHandshakingListeners;\n\n handshakeTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionHandshakingProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.handshakeTimeout = setTimeout(() => {\n this.listeners.onHandshakeTimeout();\n }, this.options.handshakeTimeoutMs);\n\n this.conn.addDataListener(this.onHandshakeData);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n }\n\n get loggingMetadata() {\n return {\n ...super.loggingMetadata,\n ...this.conn.loggingMetadata,\n };\n }\n\n onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake(\n 'could not parse message',\n 'MALFORMED_HANDSHAKE',\n );\n\n return;\n }\n\n this.listeners.onHandshake(parsedMsg);\n };\n\n sendHandshake(msg: TransportMessage): boolean {\n return this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n this.conn.removeDataListener(this.onHandshakeData);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n\n if (this.handshakeTimeout) {\n clearTimeout(this.handshakeTimeout);\n this.handshakeTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import { Static } from '@sinclair/typebox';\nimport {\n ControlFlags,\n ControlMessageAckSchema,\n OpaqueTransportMessage,\n PartialTransportMessage,\n isAck,\n} from '../message';\nimport {\n IdentifiedSession,\n IdentifiedSessionProps,\n SessionState,\n} from './common';\nimport { Connection } from '../connection';\nimport { SpanStatusCode } from '@opentelemetry/api';\n\nexport interface SessionConnectedListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onMessage: (msg: OpaqueTransportMessage) => void;\n onInvalidMessage: (reason: string) => void;\n}\n\nexport interface SessionConnectedProps<ConnType extends Connection>\n extends IdentifiedSessionProps {\n conn: ConnType;\n listeners: SessionConnectedListeners;\n}\n\n/*\n * A session that is connected and can send and receive messages.\n * See transitions.ts for valid transitions.\n */\nexport class SessionConnected<\n ConnType extends Connection,\n> extends IdentifiedSession {\n readonly state = SessionState.Connected as const;\n conn: ConnType;\n listeners: SessionConnectedListeners;\n\n private heartbeatHandle?: ReturnType<typeof setInterval> | undefined;\n private heartbeatMisses = 0;\n isActivelyHeartbeating: boolean;\n\n updateBookkeeping(ack: number, seq: number) {\n this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);\n this.ack = seq + 1;\n this.heartbeatMisses = 0;\n }\n\n send(msg: PartialTransportMessage): string {\n const constructedMsg = this.constructMsg(msg);\n this.sendBuffer.push(constructedMsg);\n this.conn.send(this.options.codec.toBuffer(constructedMsg));\n\n return constructedMsg.id;\n }\n\n constructor(props: SessionConnectedProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.conn.addDataListener(this.onMessageData);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n\n // send any buffered messages\n if (this.sendBuffer.length > 0) {\n this.log?.info(\n `sending ${\n this.sendBuffer.length\n } buffered messages, starting at seq ${this.nextSeq()}`,\n this.loggingMetadata,\n );\n\n for (const msg of this.sendBuffer) {\n this.conn.send(this.options.codec.toBuffer(msg));\n }\n }\n\n // dont explicity clear the buffer, we'll just filter out old messages\n // when we receive an ack\n\n // setup heartbeat\n this.isActivelyHeartbeating = false;\n this.heartbeatHandle = setInterval(() => {\n const misses = this.heartbeatMisses;\n const missDuration = misses * this.options.heartbeatIntervalMs;\n if (misses >= this.options.heartbeatsUntilDead) {\n this.log?.info(\n `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,\n this.loggingMetadata,\n );\n this.telemetry.span.addEvent('closing connection due to inactivity');\n\n // it is OK to close this even on the client when we can't trust the client timer\n // due to browser throttling or hibernation\n // at worst, this interval will fire later than what the server expects and the server\n // will have already closed the connection\n // this just helps us in cases where we have a proxying setup where the server has closed\n // the connection but the proxy hasn't synchronized the server-side close to the client so\n // the client isn't stuck with a pseudo-dead connection forever\n this.conn.close();\n clearInterval(this.heartbeatHandle);\n this.heartbeatHandle = undefined;\n\n return;\n }\n\n if (this.isActivelyHeartbeating) {\n this.sendHeartbeat();\n }\n\n this.heartbeatMisses++;\n }, this.options.heartbeatIntervalMs);\n }\n\n get loggingMetadata() {\n return {\n ...super.loggingMetadata,\n ...this.conn.loggingMetadata,\n };\n }\n\n startActiveHeartbeat() {\n this.isActivelyHeartbeating = true;\n }\n\n private sendHeartbeat() {\n this.log?.debug('sending heartbeat', this.loggingMetadata);\n this.send({\n streamId: 'heartbeat',\n controlFlags: ControlFlags.AckBit,\n payload: {\n type: 'ACK',\n } satisfies Static<typeof ControlMessageAckSchema>,\n });\n }\n\n closeConnection() {\n this.conn.removeDataListener(this.onMessageData);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.close();\n }\n\n onMessageData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidMessage('could not parse message');\n\n return;\n }\n\n // check message ordering here\n if (parsedMsg.seq !== this.ack) {\n if (parsedMsg.seq < this.ack) {\n this.log?.debug(\n `received duplicate msg (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack}), discarding`,\n {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n },\n );\n } else {\n const reason = `received out-of-order msg, closing connection (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack})`;\n this.log?.warn(reason, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n tags: ['invariant-violation'],\n });\n\n this.telemetry.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: reason,\n });\n\n // try to recover by closing the connection and re-handshaking\n // with the session intact\n this.closeConnection();\n }\n\n return;\n }\n\n // message is ok to update bookkeeping with\n this.log?.debug(`received msg`, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n });\n\n this.updateBookkeeping(parsedMsg.ack, parsedMsg.seq);\n\n // dispatch directly if its not an explicit ack\n if (!isAck(parsedMsg.controlFlags)) {\n this.listeners.onMessage(parsedMsg);\n\n return;\n }\n\n // discard acks (unless we aren't heartbeating in which case just respond)\n this.log?.debug(`discarding msg (ack bit set)`, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n });\n\n // if we are not actively heartbeating, we are in passive\n // heartbeat mode and should send a response to the ack\n if (!this.isActivelyHeartbeating) {\n this.sendHeartbeat();\n }\n };\n\n _handleStateExit(): void {\n super._handleStateExit();\n this.conn.removeDataListener(this.onMessageData);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n\n if (this.heartbeatHandle) {\n clearInterval(this.heartbeatHandle);\n this.heartbeatHandle = undefined;\n }\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionBackingOffListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onBackoffFinished: () => void;\n}\n\nexport interface SessionBackingOffProps\n extends IdentifiedSessionWithGracePeriodProps {\n backoffMs: number;\n listeners: SessionBackingOffListeners;\n}\n\n/*\n * A session that is backing off before attempting to connect.\n * See transitions.ts for valid transitions.\n */\nexport class SessionBackingOff extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.BackingOff as const;\n listeners: SessionBackingOffListeners;\n\n backoffTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionBackingOffProps) {\n super(props);\n this.listeners = props.listeners;\n\n this.backoffTimeout = setTimeout(() => {\n this.listeners.onBackoffFinished();\n }, props.backoffMs);\n }\n\n _handleClose(): void {\n super._handleClose();\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.backoffTimeout) {\n clearTimeout(this.backoffTimeout);\n this.backoffTimeout = undefined;\n }\n }\n}\n","import { OpaqueTransportMessage, TransportClientId } from '..';\nimport {\n SessionConnecting,\n SessionConnectingListeners,\n} from './SessionConnecting';\nimport {\n SessionNoConnection,\n SessionNoConnectionListeners,\n} from './SessionNoConnection';\nimport {\n IdentifiedSession,\n IdentifiedSessionProps,\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodProps,\n SessionOptions,\n} from './common';\nimport { PropagationContext, createSessionTelemetryInfo } from '../../tracing';\nimport {\n SessionWaitingForHandshake,\n SessionWaitingForHandshakeListeners,\n} from './SessionWaitingForHandshake';\nimport {\n SessionHandshaking,\n SessionHandshakingListeners,\n} from './SessionHandshaking';\nimport {\n SessionConnected,\n SessionConnectedListeners,\n} from './SessionConnected';\nimport { generateId } from '../id';\nimport { Connection } from '../connection';\nimport { Logger } from '../../logging';\nimport {\n SessionBackingOff,\n SessionBackingOffListeners,\n} from './SessionBackingOff';\nimport { ProtocolVersion } from '../message';\n\nfunction inheritSharedSession(\n session: IdentifiedSession,\n): IdentifiedSessionProps {\n return {\n id: session.id,\n from: session.from,\n to: session.to,\n seq: session.seq,\n ack: session.ack,\n sendBuffer: session.sendBuffer,\n telemetry: session.telemetry,\n options: session.options,\n log: session.log,\n protocolVersion: session.protocolVersion,\n };\n}\n\nfunction inheritSharedSessionWithGrace(\n session: IdentifiedSessionWithGracePeriod,\n): Omit<IdentifiedSessionWithGracePeriodProps, 'listeners'> {\n return {\n ...inheritSharedSession(session),\n graceExpiryTime: session.graceExpiryTime,\n };\n}\n\nexport const SessionStateGraph = {\n entrypoints: {\n NoConnection: (\n to: TransportClientId,\n from: TransportClientId,\n listeners: SessionNoConnectionListeners,\n options: SessionOptions,\n protocolVersion: ProtocolVersion,\n log?: Logger,\n ) => {\n const id = `session-${generateId()}`;\n const telemetry = createSessionTelemetryInfo(id, to, from);\n const sendBuffer: Array<OpaqueTransportMessage> = [];\n\n const session = new SessionNoConnection({\n listeners,\n id,\n from,\n to,\n seq: 0,\n ack: 0,\n graceExpiryTime: Date.now() + options.sessionDisconnectGraceMs,\n sendBuffer,\n telemetry,\n options,\n protocolVersion,\n log,\n });\n\n session.log?.info(`session ${session.id} created in NoConnection state`, {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n });\n\n return session;\n },\n WaitingForHandshake: <ConnType extends Connection>(\n from: TransportClientId,\n conn: ConnType,\n listeners: SessionWaitingForHandshakeListeners,\n options: SessionOptions,\n log?: Logger,\n ): SessionWaitingForHandshake<ConnType> => {\n const session = new SessionWaitingForHandshake({\n conn,\n listeners,\n from,\n options,\n log,\n });\n\n session.log?.info(`session created in WaitingForHandshake state`, {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n });\n\n return session;\n },\n },\n // All of the transitions 'move'/'consume' the old session and return a new one.\n // After a session is transitioned, any usage of the old session will throw.\n transition: {\n // happy path transitions\n NoConnectionToBackingOff: (\n oldSession: SessionNoConnection,\n backoffMs: number,\n listeners: SessionBackingOffListeners,\n ): SessionBackingOff => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionBackingOff({\n backoffMs,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from NoConnection to BackingOff`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n BackingOffToConnecting: <ConnType extends Connection>(\n oldSession: SessionBackingOff,\n connPromise: Promise<ConnType>,\n listeners: SessionConnectingListeners,\n ): SessionConnecting<ConnType> => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionConnecting({\n connPromise,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from BackingOff to Connecting`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectingToHandshaking: <ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n conn: ConnType,\n listeners: SessionHandshakingListeners,\n ): SessionHandshaking<ConnType> => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionHandshaking({\n conn,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from Connecting to Handshaking`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n HandshakingToConnected: <ConnType extends Connection>(\n oldSession: SessionHandshaking<ConnType>,\n listeners: SessionConnectedListeners,\n ): SessionConnected<ConnType> => {\n const carriedState = inheritSharedSession(oldSession);\n const conn = oldSession.conn;\n oldSession._handleStateExit();\n\n const session = new SessionConnected({\n conn,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from Handshaking to Connected`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n WaitingForHandshakeToConnected: <ConnType extends Connection>(\n pendingSession: SessionWaitingForHandshake<ConnType>,\n oldSession: SessionNoConnection | undefined,\n sessionId: string,\n to: TransportClientId,\n propagationCtx: PropagationContext | undefined,\n listeners: SessionConnectedListeners,\n protocolVersion: ProtocolVersion,\n ): SessionConnected<ConnType> => {\n const conn = pendingSession.conn;\n const { from, options } = pendingSession;\n const carriedState: IdentifiedSessionProps = oldSession\n ? // old session exists, inherit state\n inheritSharedSession(oldSession)\n : // old session does not exist, create new state\n {\n id: sessionId,\n from,\n to,\n seq: 0,\n ack: 0,\n sendBuffer: [],\n telemetry: createSessionTelemetryInfo(\n sessionId,\n to,\n from,\n propagationCtx,\n ),\n options,\n log: pendingSession.log,\n protocolVersion,\n };\n\n pendingSession._handleStateExit();\n oldSession?._handleStateExit();\n\n const session = new SessionConnected({\n conn,\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from WaitingForHandshake to Connected`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n // disconnect paths\n BackingOffToNoConnection: (\n oldSession: SessionBackingOff,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from BackingOff to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectingToNoConnection: <ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession.bestEffortClose();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Connecting to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n HandshakingToNoConnection: <ConnType extends Connection>(\n oldSession: SessionHandshaking<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Handshaking to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectedToNoConnection: <ConnType extends Connection>(\n oldSession: SessionConnected<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSession(oldSession);\n const graceExpiryTime =\n Date.now() + oldSession.options.sessionDisconnectGraceMs;\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n graceExpiryTime,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Connected to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n },\n} as const;\n\nconst transitions = SessionStateGraph.transition;\n\nexport const ClientSessionStateGraph = {\n entrypoint: SessionStateGraph.entrypoints.NoConnection,\n transition: {\n // happy paths\n // NoConnection -> BackingOff: attempt to connect\n NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,\n // BackingOff -> Connecting: backoff period elapsed, start connection\n BackingOffToConnecting: transitions.BackingOffToConnecting,\n // Connecting -> Handshaking: connection established, start handshake\n ConnectingToHandshaking: transitions.ConnectingToHandshaking,\n // Handshaking -> Connected: handshake complete, session ready\n HandshakingToConnected: transitions.HandshakingToConnected,\n\n // disconnect paths\n // BackingOff -> NoConnection: unused\n BackingOffToNoConnection: transitions.BackingOffToNoConnection,\n // Connecting -> NoConnection: connection failed or connection timeout\n ConnectingToNoConnection: transitions.ConnectingToNoConnection,\n // Handshaking -> NoConnection: connection closed or handshake timeout\n HandshakingToNoConnection: transitions.HandshakingToNoConnection,\n // Connected -> NoConnection: connection closed\n ConnectedToNoConnection: transitions.ConnectedToNoConnection,\n\n // destroy/close paths\n // NoConnection -> x: grace period elapsed\n // BackingOff -> x: grace period elapsed\n // Connecting -> x: grace period elapsed\n // Handshaking -> x: grace period elapsed or invalid handshake message or handshake rejection\n // Connected -> x: grace period elapsed or invalid message\n },\n};\n\nexport type ClientSession<ConnType extends Connection> =\n | SessionNoConnection\n | SessionBackingOff\n | SessionConnecting<ConnType>\n | SessionHandshaking<ConnType>\n | SessionConnected<ConnType>;\n\nexport const ServerSessionStateGraph = {\n entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,\n transition: {\n // happy paths\n // WaitingForHandshake -> Connected: handshake complete, session ready\n WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,\n\n // disconnect paths\n // Connected -> NoConnection: connection closed\n ConnectedToNoConnection: transitions.ConnectedToNoConnection,\n\n // destroy/close paths\n // WaitingForHandshake -> x: handshake timeout elapsed or invalid handshake message or handshake rejection or connection closed\n },\n};\n\nexport type ServerSession<ConnType extends Connection> =\n // SessionWaitingForHandshake<ConnType> is stored separately in the server transport\n SessionConnected<ConnType> | SessionNoConnection;\n\nexport type Session<ConnType extends Connection> =\n | ClientSession<ConnType>\n | ServerSession<ConnType>;\n","import {\n Kind,\n TLiteral,\n TNever,\n TObject,\n TSchema,\n TString,\n TUnion,\n Type,\n} from '@sinclair/typebox';\n\n/**\n * {@link UNCAUGHT_ERROR_CODE} is the code that is used when an error is thrown\n * inside a procedure handler that's not required.\n */\nexport const UNCAUGHT_ERROR_CODE = 'UNCAUGHT_ERROR';\n/**\n * {@link UNEXPECTED_DISCONNECT_CODE} is the code used the stream's session\n * disconnect unexpetedly.\n */\nexport const UNEXPECTED_DISCONNECT_CODE = 'UNEXPECTED_DISCONNECT';\n/**\n * {@link INVALID_REQUEST_CODE} is the code used when a client's request is invalid.\n */\nexport const INVALID_REQUEST_CODE = 'INVALID_REQUEST';\n/**\n * {@link CANCEL_CODE} is the code used when either server or client cancels the stream.\n */\nexport const CANCEL_CODE = 'CANCEL';\n\ntype TLiteralString = TLiteral<string>;\n\nexport type BaseErrorSchemaType =\n | TObject<{\n code: TLiteralString;\n message: TLiteralString | TString;\n }>\n | TObject<{\n code: TLiteralString;\n message: TLiteralString | TString;\n extras: TSchema;\n }>;\n\n/**\n * Takes in a specific error schema and returns a result schema the error\n */\nexport const ErrResultSchema = <T extends ProcedureErrorSchemaType>(t: T) =>\n Type.Object({\n ok: Type.Literal(false),\n payload: t,\n });\n\n/**\n * {@link ReaderErrorSchema} is the schema for all the built-in river errors that\n * can be emitted to a reader (request reader on the server, and response reader\n * on the client).\n */\nexport const ReaderErrorSchema = Type.Union([\n Type.Object({\n code: Type.Literal(UNCAUGHT_ERROR_CODE),\n message: Type.String(),\n }),\n Type.Object({\n code: Type.Literal(UNEXPECTED_DISCONNECT_CODE),\n message: Type.String(),\n }),\n Type.Object({\n code: Type.Literal(INVALID_REQUEST_CODE),\n message: Type.String(),\n }),\n Type.Object({\n code: Type.Literal(CANCEL_CODE),\n message: Type.String(),\n }),\n]) satisfies ProcedureErrorSchemaType;\n\n/**\n * Represents an acceptable schema to pass to a procedure.\n * Just a type of a schema, not an actual schema.\n *\n */\nexport type ProcedureErrorSchemaType =\n | TNever\n | BaseErrorSchemaType\n | TUnion<Array<BaseErrorSchemaType>>;\n\n// arbitrarily nested unions\n// river doesn't accept this by default, use the `flattenErrorType` helper\ntype NestableProcedureErrorSchemaType =\n | BaseErrorSchemaType\n | TUnion<NestableProcedureErrorSchemaTypeArray>;\n\n// use an interface to defer the type definition to be evaluated lazily\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\ninterface NestableProcedureErrorSchemaTypeArray\n extends Array<NestableProcedureErrorSchemaType> {}\n\nfunction isUnion(schema: TSchema): schema is TUnion {\n return schema[Kind] === 'Union';\n}\n\ntype Flatten<T> = T extends BaseErrorSchemaType\n ? T\n : T extends TUnion<Array<infer U extends TSchema>>\n ? Flatten<U>\n : unknown;\n\n/**\n * In the case where API consumers for some god-forsaken reason want to use\n * arbitrarily nested unions, this helper flattens them to a single level.\n *\n * Note that loses some metadata information on the nested unions like\n * nested description fields, etc.\n *\n * @param errType - An arbitrarily union-nested error schema.\n * @returns The flattened error schema.\n */\nexport function flattenErrorType<T extends NestableProcedureErrorSchemaType>(\n errType: T,\n): Flatten<T>;\nexport function flattenErrorType(\n errType: NestableProcedureErrorSchemaType,\n): ProcedureErrorSchemaType {\n if (!isUnion(errType)) {\n return errType;\n }\n\n const flattenedTypes: Array<BaseErrorSchemaType> = [];\n function flatten(type: NestableProcedureErrorSchemaType) {\n if (isUnion(type)) {\n for (const t of type.anyOf) {\n flatten(t);\n }\n } else {\n flattenedTypes.push(type);\n }\n }\n\n flatten(errType);\n\n return Type.Union(flattenedTypes);\n}\n"],"mappings":"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","names":["import_typebox","import_api","import_typebox","NodeWs"]}
|