import { TUnion, TLiteral, Type, Static } from 'typebox'; import { Span, Context } from '@opentelemetry/api'; interface PropagationContext { traceparent: string; tracestate: string; } interface TelemetryInfo { span: Span; ctx: Context; } /** * Generic Typebox schema for a transport message. * @template T The type of the payload. * @param {T} t The payload schema. * @returns The transport message schema. */ declare const TransportMessageSchema: (t: T) => Type.TObject<{ id: Type.TString; from: Type.TString; to: Type.TString; seq: Type.TInteger; ack: Type.TInteger; serviceName: Type.TOptional; procedureName: Type.TOptional; streamId: Type.TString; controlFlags: Type.TInteger; tracing: Type.TOptional>; payload: T; }>; type ProtocolVersion = 'v1.1' | 'v2.0'; declare const HandshakeErrorCustomHandlerFatalResponseCodes: Type.TUnion<[Type.TLiteral<"REJECTED_UNSUPPORTED_CLIENT">, Type.TLiteral<"REJECTED_BY_CUSTOM_HANDLER">]>; declare const HandshakeErrorResponseCodes: Type.TUnion<[Type.TUnion<[Type.TLiteral<"SESSION_STATE_MISMATCH">]>, Type.TUnion<[Type.TUnion<[Type.TLiteral<"REJECTED_UNSUPPORTED_CLIENT">, Type.TLiteral<"REJECTED_BY_CUSTOM_HANDLER">]>, Type.TLiteral<"MALFORMED_HANDSHAKE_META">, Type.TLiteral<"MALFORMED_HANDSHAKE">, Type.TLiteral<"PROTOCOL_VERSION_MISMATCH">]>]>; /** * A TypeBox union of literals declaring the custom handshake rejection codes. */ type CustomHandshakeErrorCodeSchema = TUnion>>; /** * The union of codes declared by a rejection code schema. Widened literal * schemas (`TLiteral` rather than a specific literal) contribute no * codes. */ type CustomHandshakeErrorCode = string extends Static ? never : Static; /** * The protocol-level handshake error codes River can emit without any custom * rejection codes. */ type BuiltInHandshakeErrorCode = Static; /** * The protocol-level handshake error codes plus any custom rejection codes * registered in the handshake options. */ type HandshakeErrorCode = BuiltInHandshakeErrorCode | CustomHandshakeErrorCode; declare const ControlMessageHandshakeResponseSchema: Type.TObject<{ type: Type.TLiteral<"HANDSHAKE_RESP">; status: Type.TUnion<[Type.TObject<{ ok: Type.TLiteral; sessionId: Type.TString; }>, Type.TObject<{ ok: Type.TLiteral; reason: Type.TString; code: Type.TUnion<[Type.TUnion<[Type.TLiteral<"SESSION_STATE_MISMATCH">]>, Type.TUnion<[Type.TUnion<[Type.TLiteral<"REJECTED_UNSUPPORTED_CLIENT">, Type.TLiteral<"REJECTED_BY_CUSTOM_HANDLER">]>, Type.TLiteral<"MALFORMED_HANDSHAKE_META">, Type.TLiteral<"MALFORMED_HANDSHAKE">, Type.TLiteral<"PROTOCOL_VERSION_MISMATCH">]>]>; }>]>; }>; /** * A handshake response schema that additionally accepts custom * rejection codes. Both peers must be configured with the same codes: an * unconfigured peer rejects a custom code as a malformed response. */ declare const ControlMessageHandshakeResponseSchemaWithCodes: (rejectionCodeSchema: RejectionCodeSchema) => Type.TObject<{ type: Type.TLiteral<"HANDSHAKE_RESP">; status: Type.TUnion<[Type.TObject<{ ok: Type.TLiteral; sessionId: Type.TString; }>, Type.TObject<{ ok: Type.TLiteral; reason: Type.TString; code: Type.TUnion<[Type.TUnion<[Type.TUnion<[Type.TLiteral<"SESSION_STATE_MISMATCH">]>, Type.TUnion<[Type.TUnion<[Type.TLiteral<"REJECTED_UNSUPPORTED_CLIENT">, Type.TLiteral<"REJECTED_BY_CUSTOM_HANDLER">]>, Type.TLiteral<"MALFORMED_HANDSHAKE_META">, Type.TLiteral<"MALFORMED_HANDSHAKE">, Type.TLiteral<"PROTOCOL_VERSION_MISMATCH">]>]>, RejectionCodeSchema]>; }>]>; }>; /** * Defines the schema for an opaque transport message that is agnostic to any * procedure/service. * @returns The transport message schema. */ declare const OpaqueTransportMessageSchema: Type.TObject<{ id: Type.TString; from: Type.TString; to: Type.TString; seq: Type.TInteger; ack: Type.TInteger; serviceName: Type.TOptional; procedureName: Type.TOptional; streamId: Type.TString; controlFlags: Type.TInteger; tracing: Type.TOptional>; payload: Type.TUnknown; }>; /** * Represents a transport message. This is the same type as {@link TransportMessageSchema} but * we can't statically infer generics from generic Typebox schemas so we have to define it again here. * * TypeScript can't enforce types when a bitmask is involved, so these are the semantics of * `controlFlags`: * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `streamId` must be set to a unique value * (suggestion: use `nanoid`). * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `serviceName` and `procedureName` must be set. * * If `controlFlags & StreamClosedBit == StreamClosedBit` and the kind is `stream` or `subscription`, * `payload` should be discarded (usually contains a control message). * * If `controlFlags & AckBit == AckBit`, the message is an explicit acknowledgement message and doesn't * contain any payload that is relevant to the application so should not be delivered. * @template Payload The type of the payload. */ interface TransportMessage { id: string; from: TransportClientId; to: TransportClientId; seq: number; ack: number; serviceName?: string; procedureName?: string; streamId: string; controlFlags: number; tracing?: PropagationContext; payload: Payload; } type PartialTransportMessage = Omit, 'id' | 'from' | 'to' | 'seq' | 'ack'>; /** * A type alias for a transport message with an opaque payload. * @template T - The type of the opaque payload. */ type OpaqueTransportMessage = TransportMessage; type TransportClientId = string; /** * An encoded message that is ready to be sent over the transport. * The seq number is kept to track which messages have been * acked by the peer and can be dropped from the send buffer. */ interface EncodedTransportMessage { id: string; seq: number; msg: PartialTransportMessage; data: Uint8Array; } /** * Checks if the given control flag (usually found in msg.controlFlag) is a stream open message. * @param controlFlag - The control flag to check. * @returns True if the control flag contains the StreamOpenBit, false otherwise. */ declare function isStreamOpen(controlFlag: number): boolean; /** * Checks if the given control flag (usually found in msg.controlFlag) is a stream close message. * @param controlFlag - The control flag to check. * @returns True if the control flag contains the StreamCloseBit, false otherwise. */ declare function isStreamClose(controlFlag: number): boolean; export { type BuiltInHandshakeErrorCode as B, type CustomHandshakeErrorCodeSchema as C, type EncodedTransportMessage as E, type HandshakeErrorCode as H, type OpaqueTransportMessage as O, type ProtocolVersion as P, type TransportClientId as T, OpaqueTransportMessageSchema as a, type TransportMessage as b, TransportMessageSchema as c, isStreamOpen as d, ControlMessageHandshakeResponseSchema as e, ControlMessageHandshakeResponseSchemaWithCodes as f, HandshakeErrorResponseCodes as g, type PartialTransportMessage as h, isStreamClose as i, HandshakeErrorCustomHandlerFatalResponseCodes as j, type CustomHandshakeErrorCode as k, type TelemetryInfo as l };