@replit/river 0.25.1 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/{chunk-D5O3ERJU.js → chunk-5FDAIAQ5.js} +3 -3
  2. package/dist/chunk-5FDAIAQ5.js.map +1 -0
  3. package/dist/{chunk-5CNNIOAO.js → chunk-5S64PXTU.js} +102 -95
  4. package/dist/chunk-5S64PXTU.js.map +1 -0
  5. package/dist/{chunk-PCBPPTXH.js → chunk-7ETNUCOL.js} +54 -62
  6. package/dist/chunk-7ETNUCOL.js.map +1 -0
  7. package/dist/{chunk-SGSRNAWJ.js → chunk-BNNELZM4.js} +2 -2
  8. package/dist/{chunk-SGSRNAWJ.js.map → chunk-BNNELZM4.js.map} +1 -1
  9. package/dist/{chunk-SZ5NBBX7.js → chunk-CCUYKR5C.js} +14 -4
  10. package/dist/chunk-CCUYKR5C.js.map +1 -0
  11. package/dist/{chunk-YM5Y4NAT.js → chunk-JSU2KACV.js} +199 -117
  12. package/dist/chunk-JSU2KACV.js.map +1 -0
  13. package/dist/{chunk-MBMEJIPU.js → chunk-KP4UB5NW.js} +2 -2
  14. package/dist/{client-1321630c.d.ts → client-162c509c.d.ts} +4 -2
  15. package/dist/{connection-bd907ca6.d.ts → connection-6a404bb8.d.ts} +1 -1
  16. package/dist/{handshake-3772d7ca.d.ts → handshake-3342bb94.d.ts} +132 -84
  17. package/dist/logging/index.d.cts +1 -1
  18. package/dist/logging/index.d.ts +1 -1
  19. package/dist/{message-e6c560fd.d.ts → message-1a434848.d.ts} +2 -1
  20. package/dist/router/index.cjs +12 -3
  21. package/dist/router/index.cjs.map +1 -1
  22. package/dist/router/index.d.cts +8 -8
  23. package/dist/router/index.d.ts +8 -8
  24. package/dist/router/index.js +2 -2
  25. package/dist/{server-f0fd2b98.d.ts → server-1b695374.d.ts} +9 -4
  26. package/dist/{services-8d14ae16.d.ts → services-c17f7eff.d.ts} +3 -3
  27. package/dist/transport/impls/ws/client.cjs +302 -207
  28. package/dist/transport/impls/ws/client.cjs.map +1 -1
  29. package/dist/transport/impls/ws/client.d.cts +4 -4
  30. package/dist/transport/impls/ws/client.d.ts +4 -4
  31. package/dist/transport/impls/ws/client.js +5 -5
  32. package/dist/transport/impls/ws/server.cjs +253 -174
  33. package/dist/transport/impls/ws/server.cjs.map +1 -1
  34. package/dist/transport/impls/ws/server.d.cts +4 -4
  35. package/dist/transport/impls/ws/server.d.ts +4 -4
  36. package/dist/transport/impls/ws/server.js +5 -5
  37. package/dist/transport/index.cjs +351 -264
  38. package/dist/transport/index.cjs.map +1 -1
  39. package/dist/transport/index.d.cts +4 -4
  40. package/dist/transport/index.d.ts +4 -4
  41. package/dist/transport/index.js +5 -5
  42. package/dist/util/testHelpers.cjs +208 -117
  43. package/dist/util/testHelpers.cjs.map +1 -1
  44. package/dist/util/testHelpers.d.cts +6 -5
  45. package/dist/util/testHelpers.d.ts +6 -5
  46. package/dist/util/testHelpers.js +6 -3
  47. package/dist/util/testHelpers.js.map +1 -1
  48. package/package.json +14 -13
  49. package/dist/chunk-5CNNIOAO.js.map +0 -1
  50. package/dist/chunk-D5O3ERJU.js.map +0 -1
  51. package/dist/chunk-PCBPPTXH.js.map +0 -1
  52. package/dist/chunk-SZ5NBBX7.js.map +0 -1
  53. package/dist/chunk-YM5Y4NAT.js.map +0 -1
  54. /package/dist/{chunk-MBMEJIPU.js.map → chunk-KP4UB5NW.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../transport/options.ts","../transport/sessionStateMachine/common.ts","../transport/sessionStateMachine/SessionConnecting.ts","../transport/sessionStateMachine/SessionNoConnection.ts","../transport/sessionStateMachine/SessionWaitingForHandshake.ts","../transport/sessionStateMachine/SessionHandshaking.ts","../transport/sessionStateMachine/SessionConnected.ts","../transport/sessionStateMachine/SessionBackingOff.ts","../transport/sessionStateMachine/transitions.ts"],"sourcesContent":["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 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 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._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 * Duration to wait between connection disconnect and actual session disconnect\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 * 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 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}\n\nexport abstract class IdentifiedSession extends CommonSession {\n readonly id: SessionId;\n readonly telemetry: TelemetryInfo;\n readonly to: TransportClientId;\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 } = 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 }\n\n get loggingMetadata(): MessageMetadata {\n const spanContext = this.telemetry.span.spanContext();\n\n return {\n clientId: this.from,\n connectedTo: this.to,\n sessionId: this.id,\n telemetry: {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n },\n };\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 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 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","import { Connection } from '../connection';\nimport {\n IdentifiedSession,\n IdentifiedSessionProps,\n SessionState,\n} from './common';\n\nexport interface SessionConnectingListeners {\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 IdentifiedSessionProps {\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 IdentifiedSession {\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.connectionTimeout = setTimeout(() => {\n this.listeners.onConnectionTimeout();\n }, this.options.connectionTimeoutMs);\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\n // close a pending connection if it resolves, ignore errors if the promise\n // ends up rejected anyways\n bestEffortClose() {\n void this.connPromise\n .then((conn) => conn.close())\n .catch(() => {\n // ignore errors\n });\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = undefined;\n }\n\n _handleClose(): void {\n // close the pending connection if it resolves\n this.bestEffortClose();\n super._handleClose();\n }\n}\n","import {\n IdentifiedSession,\n IdentifiedSessionProps,\n SessionState,\n} from './common';\n\nexport interface SessionNoConnectionListeners {\n // timeout related\n onSessionGracePeriodElapsed: () => void;\n}\n\nexport interface SessionNoConnectionProps extends IdentifiedSessionProps {\n listeners: SessionNoConnectionListeners;\n}\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 IdentifiedSession {\n readonly state = SessionState.NoConnection as const;\n listeners: SessionNoConnectionListeners;\n\n gracePeriodTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionNoConnectionProps) {\n super(props);\n this.listeners = props.listeners;\n this.gracePeriodTimeout = setTimeout(() => {\n this.listeners.onSessionGracePeriodElapsed();\n }, this.options.sessionDisconnectGraceMs);\n }\n\n _handleClose(): void {\n super._handleClose();\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","import { MessageMetadata } from '../../logging';\nimport { Connection } from '../connection';\nimport { TransportMessage } from '../message';\nimport { SessionHandshakingListeners } from './SessionHandshaking';\nimport { CommonSession, CommonSessionProps, SessionState } from './common';\n\nexport interface SessionWaitingForHandshakeProps<ConnType extends Connection>\n extends CommonSessionProps {\n conn: ConnType;\n listeners: SessionHandshakingListeners;\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: SessionHandshakingListeners;\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 onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake('could not parse message');\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 get loggingMetadata(): MessageMetadata {\n return {\n clientId: this.from,\n connId: this.conn.id,\n };\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 { Connection } from '../connection';\nimport { OpaqueTransportMessage, TransportMessage } from '../message';\nimport {\n IdentifiedSession,\n IdentifiedSessionProps,\n SessionState,\n} from './common';\n\nexport interface SessionHandshakingListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onHandshake: (msg: OpaqueTransportMessage) => void;\n onInvalidHandshake: (reason: string) => void;\n\n // timeout related\n onHandshakeTimeout: () => void;\n}\n\nexport interface SessionHandshakingProps<ConnType extends Connection>\n extends IdentifiedSessionProps {\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 IdentifiedSession {\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 onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake('could not parse message');\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 clearTimeout(this.handshakeTimeout);\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 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?.debug(\n `sending ${this.sendBuffer.length} buffered messages`,\n this.loggingMetadata,\n );\n }\n\n for (const msg of this.sendBuffer) {\n this.conn.send(this.options.codec.toBuffer(msg));\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 return;\n }\n\n if (this.isActivelyHeartbeating) {\n this.sendHeartbeat();\n }\n\n this.heartbeatMisses++;\n }, this.options.heartbeatIntervalMs);\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 onMessageData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) return;\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 (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack})`;\n this.log?.error(reason, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n tags: ['invariant-violation'],\n });\n this.telemetry.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: reason,\n });\n\n this.listeners.onInvalidMessage(reason);\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 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 clearInterval(this.heartbeatHandle);\n this.heartbeatHandle = undefined;\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import {\n IdentifiedSession,\n IdentifiedSessionProps,\n SessionState,\n} from './common';\n\nexport interface SessionBackingOffListeners {\n onBackoffFinished: () => void;\n}\n\nexport interface SessionBackingOffProps extends IdentifiedSessionProps {\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 IdentifiedSession {\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 SessionOptions,\n} from './common';\nimport { PropagationContext, createSessionTelemetryInfo } from '../../tracing';\nimport { SessionWaitingForHandshake } 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';\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 };\n}\n\nexport const SessionStateGraph = {\n entrypoints: {\n NoConnection: (\n to: TransportClientId,\n from: TransportClientId,\n listeners: SessionNoConnectionListeners,\n options: SessionOptions,\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 sendBuffer,\n telemetry,\n options,\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: SessionHandshakingListeners,\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 = inheritSharedSession(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 return session;\n },\n BackingOffToConnecting: <ConnType extends Connection>(\n oldSession: SessionBackingOff,\n connPromise: Promise<ConnType>,\n listeners: SessionConnectingListeners,\n ): SessionConnecting<ConnType> => {\n const carriedState = inheritSharedSession(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 return session;\n },\n ConnectingToHandshaking: <ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n conn: ConnType,\n listeners: SessionHandshakingListeners,\n ): SessionHandshaking<ConnType> => {\n const carriedState = inheritSharedSession(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 ): 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 };\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 = inheritSharedSession(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({ listeners, ...carriedState });\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 = inheritSharedSession(oldSession);\n oldSession.bestEffortClose();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({ listeners, ...carriedState });\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 = inheritSharedSession(oldSession);\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({ listeners, ...carriedState });\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 oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({ listeners, ...carriedState });\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\n/*\n * 0. SessionNoConnection ◄──┐\n * │ reconnect / connect attempt │\n * ▼ │\n * 1. SessionBackingOff │\n * │ ───┤ explicit close\n * ▼ │\n * 2. SessionConnecting │\n * │ connect success ──────────────┤ connect failure\n * ▼ │\n * 3. SessionHandshaking │\n * │ handshake success ┌──────┤ connection drop\n * │ handshake failure ─────┤ │\n * ▼ │ │ connection drop\n * 4. SessionConnected │ │ heartbeat misses\n * │ invalid message ───────┼──────┘\n * ▼ │\n * x. Destroy Session ◄─────┘\n */\nexport const ClientSessionStateGraph = {\n entrypoint: SessionStateGraph.entrypoints.NoConnection,\n transition: {\n // happy paths\n NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,\n BackingOffToConnecting: transitions.BackingOffToConnecting,\n ConnectingToHandshaking: transitions.ConnectingToHandshaking,\n HandshakingToConnected: transitions.HandshakingToConnected,\n // disconnect paths\n BackingOffToNoConnection: transitions.BackingOffToNoConnection,\n ConnectingToNoConnection: transitions.ConnectingToNoConnection,\n HandshakingToNoConnection: transitions.HandshakingToNoConnection,\n ConnectedToNoConnection: transitions.ConnectedToNoConnection,\n },\n};\n\nexport type ClientSession<ConnType extends Connection> =\n | SessionNoConnection\n | SessionBackingOff\n | SessionConnecting<ConnType>\n | SessionHandshaking<ConnType>\n | SessionConnected<ConnType>;\n\n/*\n * 0. SessionNoConnection ◄──┐\n * │ reconnect / connect attempt │\n * ▼ │\n * 1. WaitingForHandshake │\n * │ handshake success ┌──────┤ connection drop\n * │ handshake failure ─────┤ │\n * ▼ │ │ connection drop\n * 2. SessionConnected │ │ heartbeat misses\n * │ invalid message ───────┼──────┘\n * ▼ │\n * x. Destroy Session ◄─────┘\n */\nexport const ServerSessionStateGraph = {\n entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,\n transition: {\n // happy paths\n WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,\n // disconnect paths\n ConnectedToNoConnection: transitions.ConnectedToNoConnection,\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"],"mappings":"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","names":["SessionState"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Connection
3
- } from "./chunk-D5O3ERJU.js";
3
+ } from "./chunk-5FDAIAQ5.js";
4
4
 
5
5
  // transport/impls/ws/connection.ts
6
6
  var WebSocketConnection = class extends Connection {
@@ -47,4 +47,4 @@ var WebSocketConnection = class extends Connection {
47
47
  export {
48
48
  WebSocketConnection
49
49
  };
50
- //# sourceMappingURL=chunk-MBMEJIPU.js.map
50
+ //# sourceMappingURL=chunk-KP4UB5NW.js.map
@@ -1,5 +1,5 @@
1
- import { C as Connection, T as Transport, o as ClientTransportOptions, L as LeakyBucketRateLimit, p as ClientHandshakeOptions, b as ProvidedClientTransportOptions, f as SessionConnecting, e as SessionNoConnection, g as SessionHandshaking, h as SessionConnected } from './handshake-3772d7ca.js';
2
- import { c as TransportClientId, P as PartialTransportMessage, b as OpaqueTransportMessage } from './message-e6c560fd.js';
1
+ import { C as Connection, T as Transport, n as ClientTransportOptions, L as LeakyBucketRateLimit, p as ClientHandshakeOptions, q as ClientSession, b as ProvidedClientTransportOptions, f as SessionConnecting, e as SessionNoConnection, g as SessionHandshaking, h as SessionConnected, r as SessionBackingOff } from './handshake-3342bb94.js';
2
+ import { c as TransportClientId, P as PartialTransportMessage, b as OpaqueTransportMessage } from './message-1a434848.js';
3
3
 
4
4
  declare abstract class ClientTransport<ConnType extends Connection> extends Transport<ConnType> {
5
5
  /**
@@ -18,6 +18,7 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
18
18
  * Optional handshake options for this client.
19
19
  */
20
20
  handshakeExtensions?: ClientHandshakeOptions;
21
+ sessions: Map<TransportClientId, ClientSession<ConnType>>;
21
22
  constructor(clientId: TransportClientId, providedOptions?: ProvidedClientTransportOptions);
22
23
  extendHandshake(options: ClientHandshakeOptions): void;
23
24
  /**
@@ -42,6 +43,7 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
42
43
  * @param to The client ID of the node to connect to.
43
44
  */
44
45
  connect(to: TransportClientId): void;
46
+ protected onBackoffFinished(session: SessionBackingOff, connPromise: Promise<ConnType>): void;
45
47
  private sendHandshake;
46
48
  close(): void;
47
49
  }
@@ -1,4 +1,4 @@
1
- import { C as Connection } from './handshake-3772d7ca.js';
1
+ import { C as Connection } from './handshake-3342bb94.js';
2
2
  import { W as WsLike } from './wslike-e0b32dd5.js';
3
3
 
4
4
  declare class WebSocketConnection extends Connection {
@@ -1,4 +1,4 @@
1
- import { e as TelemetryInfo, M as MessageMetadata, a as TransportMessage, b as OpaqueTransportMessage, P as PartialTransportMessage, c as TransportClientId, L as Logger, f as LogFn, g as LoggingLevel } from './message-e6c560fd.js';
1
+ import { e as TelemetryInfo, M as MessageMetadata, c as TransportClientId, L as Logger, b as OpaqueTransportMessage, P as PartialTransportMessage, a as TransportMessage, f as LogFn, g as LoggingLevel, H as HandshakeErrorCustomHandlerFatalResponseCodes } from './message-1a434848.js';
2
2
  import { TSchema, Static } from '@sinclair/typebox';
3
3
  import { C as Codec } from './types-3e5768ec.js';
4
4
 
@@ -57,86 +57,14 @@ declare abstract class Connection {
57
57
  abstract close(): void;
58
58
  }
59
59
 
60
- interface SessionNoConnectionListeners {
61
- onSessionGracePeriodElapsed: () => void;
62
- }
63
- declare class SessionNoConnection extends IdentifiedSession {
64
- readonly state: SessionState.NoConnection;
65
- listeners: SessionNoConnectionListeners;
66
- gracePeriodTimeout?: ReturnType<typeof setTimeout>;
67
- constructor(listeners: SessionNoConnectionListeners, ...args: ConstructorParameters<typeof IdentifiedSession>);
68
- _handleClose(): void;
69
- _handleStateExit(): void;
70
- }
71
-
72
- interface SessionConnectingListeners {
73
- onConnectionEstablished: (conn: Connection) => void;
74
- onConnectionFailed: (err: unknown) => void;
75
- onConnectionTimeout: () => void;
76
- }
77
- declare class SessionConnecting<ConnType extends Connection> extends IdentifiedSession {
78
- readonly state: SessionState.Connecting;
79
- connPromise: Promise<ConnType>;
80
- listeners: SessionConnectingListeners;
81
- connectionTimeout?: ReturnType<typeof setTimeout>;
82
- constructor(connPromise: Promise<ConnType>, listeners: SessionConnectingListeners, ...args: ConstructorParameters<typeof IdentifiedSession>);
83
- bestEffortClose(): void;
84
- _handleStateExit(): void;
85
- _handleClose(): void;
86
- }
87
-
88
- interface SessionHandshakingListeners {
89
- onConnectionErrored: (err: unknown) => void;
90
- onConnectionClosed: () => void;
91
- onHandshake: (msg: OpaqueTransportMessage) => void;
92
- onInvalidHandshake: (reason: string) => void;
93
- onHandshakeTimeout: () => void;
94
- }
95
- declare class SessionHandshaking<ConnType extends Connection> extends IdentifiedSession {
96
- readonly state: SessionState.Handshaking;
97
- conn: ConnType;
98
- listeners: SessionHandshakingListeners;
99
- handshakeTimeout: ReturnType<typeof setTimeout>;
100
- constructor(conn: ConnType, listeners: SessionHandshakingListeners, ...args: ConstructorParameters<typeof IdentifiedSession>);
101
- onHandshakeData: (msg: Uint8Array) => void;
102
- sendHandshake(msg: TransportMessage): boolean;
103
- _handleStateExit(): void;
104
- _handleClose(): void;
105
- }
106
-
107
- interface SessionConnectedListeners {
108
- onConnectionErrored: (err: unknown) => void;
109
- onConnectionClosed: () => void;
110
- onMessage: (msg: OpaqueTransportMessage) => void;
111
- onInvalidMessage: (reason: string) => void;
112
- }
113
- declare class SessionConnected<ConnType extends Connection> extends IdentifiedSession {
114
- readonly state: SessionState.Connected;
115
- conn: ConnType;
116
- listeners: SessionConnectedListeners;
117
- private activeHeartbeatHandle?;
118
- private activeHeartbeatMisses;
119
- private passiveHeartbeatHandle?;
120
- get isActivelyHeartbeating(): boolean;
121
- updateBookkeeping(ack: number, seq: number): void;
122
- send(msg: PartialTransportMessage): string;
123
- constructor(conn: ConnType, listeners: SessionConnectedListeners, ...args: ConstructorParameters<typeof IdentifiedSession>);
124
- startActiveHeartbeat(): void;
125
- waitForNextHeartbeat(): void;
126
- private sendHeartbeat;
127
- onMessageData: (msg: Uint8Array) => void;
128
- _handleStateExit(): void;
129
- _handleClose(): void;
130
- }
131
-
132
60
  declare const enum SessionState {
133
61
  NoConnection = "NoConnection",
62
+ BackingOff = "BackingOff",
134
63
  Connecting = "Connecting",
135
64
  Handshaking = "Handshaking",
136
65
  Connected = "Connected",
137
66
  WaitingForHandshake = "WaitingForHandshake"
138
67
  }
139
- type Session<ConnType extends Connection> = SessionNoConnection | SessionConnecting<ConnType> | SessionHandshaking<ConnType> | SessionConnected<ConnType>;
140
68
  declare abstract class StateMachineState {
141
69
  abstract readonly state: SessionState;
142
70
  _isConsumed: boolean;
@@ -172,15 +100,28 @@ interface SessionOptions {
172
100
  */
173
101
  codec: Codec;
174
102
  }
103
+ interface CommonSessionProps {
104
+ from: TransportClientId;
105
+ options: SessionOptions;
106
+ log: Logger | undefined;
107
+ }
175
108
  declare abstract class CommonSession extends StateMachineState {
176
109
  readonly from: TransportClientId;
177
110
  readonly options: SessionOptions;
178
111
  log?: Logger;
179
112
  abstract get loggingMetadata(): MessageMetadata;
180
- constructor(from: TransportClientId, options: SessionOptions, log: Logger | undefined);
113
+ constructor({ from, options, log }: CommonSessionProps);
181
114
  parseMsg(msg: Uint8Array): OpaqueTransportMessage | null;
182
115
  }
183
116
  type SessionId = string;
117
+ interface IdentifiedSessionProps extends CommonSessionProps {
118
+ id: SessionId;
119
+ to: TransportClientId;
120
+ seq: number;
121
+ ack: number;
122
+ sendBuffer: Array<OpaqueTransportMessage>;
123
+ telemetry: TelemetryInfo;
124
+ }
184
125
  declare abstract class IdentifiedSession extends CommonSession {
185
126
  readonly id: SessionId;
186
127
  readonly telemetry: TelemetryInfo;
@@ -194,7 +135,7 @@ declare abstract class IdentifiedSession extends CommonSession {
194
135
  */
195
136
  ack: number;
196
137
  sendBuffer: Array<OpaqueTransportMessage>;
197
- constructor(id: SessionId, from: TransportClientId, to: TransportClientId, seq: number, ack: number, sendBuffer: Array<OpaqueTransportMessage>, telemetry: TelemetryInfo, options: SessionOptions, log: Logger | undefined);
138
+ constructor(props: IdentifiedSessionProps);
198
139
  get loggingMetadata(): MessageMetadata;
199
140
  constructMsg<Payload>(partialMsg: PartialTransportMessage<Payload>): TransportMessage<Payload>;
200
141
  nextSeq(): number;
@@ -203,6 +144,111 @@ declare abstract class IdentifiedSession extends CommonSession {
203
144
  _handleClose(): void;
204
145
  }
205
146
 
147
+ interface SessionHandshakingListeners {
148
+ onConnectionErrored: (err: unknown) => void;
149
+ onConnectionClosed: () => void;
150
+ onHandshake: (msg: OpaqueTransportMessage) => void;
151
+ onInvalidHandshake: (reason: string) => void;
152
+ onHandshakeTimeout: () => void;
153
+ }
154
+ interface SessionHandshakingProps<ConnType extends Connection> extends IdentifiedSessionProps {
155
+ conn: ConnType;
156
+ listeners: SessionHandshakingListeners;
157
+ }
158
+ declare class SessionHandshaking<ConnType extends Connection> extends IdentifiedSession {
159
+ readonly state: SessionState.Handshaking;
160
+ conn: ConnType;
161
+ listeners: SessionHandshakingListeners;
162
+ handshakeTimeout: ReturnType<typeof setTimeout>;
163
+ constructor(props: SessionHandshakingProps<ConnType>);
164
+ onHandshakeData: (msg: Uint8Array) => void;
165
+ sendHandshake(msg: TransportMessage): boolean;
166
+ _handleStateExit(): void;
167
+ _handleClose(): void;
168
+ }
169
+
170
+ interface SessionConnectingListeners {
171
+ onConnectionEstablished: (conn: Connection) => void;
172
+ onConnectionFailed: (err: unknown) => void;
173
+ onConnectionTimeout: () => void;
174
+ }
175
+ interface SessionConnectingProps<ConnType extends Connection> extends IdentifiedSessionProps {
176
+ connPromise: Promise<ConnType>;
177
+ listeners: SessionConnectingListeners;
178
+ }
179
+ declare class SessionConnecting<ConnType extends Connection> extends IdentifiedSession {
180
+ readonly state: SessionState.Connecting;
181
+ connPromise: Promise<ConnType>;
182
+ listeners: SessionConnectingListeners;
183
+ connectionTimeout?: ReturnType<typeof setTimeout>;
184
+ constructor(props: SessionConnectingProps<ConnType>);
185
+ bestEffortClose(): void;
186
+ _handleStateExit(): void;
187
+ _handleClose(): void;
188
+ }
189
+
190
+ interface SessionNoConnectionListeners {
191
+ onSessionGracePeriodElapsed: () => void;
192
+ }
193
+ interface SessionNoConnectionProps extends IdentifiedSessionProps {
194
+ listeners: SessionNoConnectionListeners;
195
+ }
196
+ declare class SessionNoConnection extends IdentifiedSession {
197
+ readonly state: SessionState.NoConnection;
198
+ listeners: SessionNoConnectionListeners;
199
+ gracePeriodTimeout?: ReturnType<typeof setTimeout>;
200
+ constructor(props: SessionNoConnectionProps);
201
+ _handleClose(): void;
202
+ _handleStateExit(): void;
203
+ }
204
+
205
+ interface SessionConnectedListeners {
206
+ onConnectionErrored: (err: unknown) => void;
207
+ onConnectionClosed: () => void;
208
+ onMessage: (msg: OpaqueTransportMessage) => void;
209
+ onInvalidMessage: (reason: string) => void;
210
+ }
211
+ interface SessionConnectedProps<ConnType extends Connection> extends IdentifiedSessionProps {
212
+ conn: ConnType;
213
+ listeners: SessionConnectedListeners;
214
+ }
215
+ declare class SessionConnected<ConnType extends Connection> extends IdentifiedSession {
216
+ readonly state: SessionState.Connected;
217
+ conn: ConnType;
218
+ listeners: SessionConnectedListeners;
219
+ private heartbeatHandle?;
220
+ private heartbeatMisses;
221
+ isActivelyHeartbeating: boolean;
222
+ updateBookkeeping(ack: number, seq: number): void;
223
+ send(msg: PartialTransportMessage): string;
224
+ constructor(props: SessionConnectedProps<ConnType>);
225
+ startActiveHeartbeat(): void;
226
+ private sendHeartbeat;
227
+ onMessageData: (msg: Uint8Array) => void;
228
+ _handleStateExit(): void;
229
+ _handleClose(): void;
230
+ }
231
+
232
+ interface SessionBackingOffListeners {
233
+ onBackoffFinished: () => void;
234
+ }
235
+ interface SessionBackingOffProps extends IdentifiedSessionProps {
236
+ backoffMs: number;
237
+ listeners: SessionBackingOffListeners;
238
+ }
239
+ declare class SessionBackingOff extends IdentifiedSession {
240
+ readonly state: SessionState.BackingOff;
241
+ listeners: SessionBackingOffListeners;
242
+ backoffTimeout?: ReturnType<typeof setTimeout>;
243
+ constructor(props: SessionBackingOffProps);
244
+ _handleClose(): void;
245
+ _handleStateExit(): void;
246
+ }
247
+
248
+ type ClientSession<ConnType extends Connection> = SessionNoConnection | SessionBackingOff | SessionConnecting<ConnType> | SessionHandshaking<ConnType> | SessionConnected<ConnType>;
249
+ type ServerSession<ConnType extends Connection> = SessionConnected<ConnType> | SessionNoConnection;
250
+ type Session<ConnType extends Connection> = ClientSession<ConnType> | ServerSession<ConnType>;
251
+
206
252
  declare const ProtocolError: {
207
253
  readonly RetriesExceeded: "conn_retry_exceeded";
208
254
  readonly HandshakeFailed: "handshake_failed";
@@ -221,6 +267,8 @@ interface EventMap {
221
267
  state: SessionState.Handshaking;
222
268
  } | {
223
269
  state: SessionState.Connecting;
270
+ } | {
271
+ state: SessionState.BackingOff;
224
272
  } | {
225
273
  state: SessionState.NoConnection;
226
274
  };
@@ -282,15 +330,15 @@ interface ConnectionRetryOptions {
282
330
  }
283
331
  declare class LeakyBucketRateLimit {
284
332
  private budgetConsumed;
285
- private intervalHandles;
333
+ private intervalHandle?;
286
334
  private readonly options;
287
335
  constructor(options: ConnectionRetryOptions);
288
- getBackoffMs(user: TransportClientId): number;
336
+ getBackoffMs(): number;
289
337
  get totalBudgetRestoreTime(): number;
290
- consumeBudget(user: TransportClientId): void;
291
- getBudgetConsumed(user: TransportClientId): number;
292
- hasBudget(user: TransportClientId): boolean;
293
- startRestoringBudget(user: TransportClientId): void;
338
+ consumeBudget(): void;
339
+ getBudgetConsumed(): number;
340
+ hasBudget(): boolean;
341
+ startRestoringBudget(): void;
294
342
  private stopLeak;
295
343
  close(): void;
296
344
  }
@@ -451,7 +499,7 @@ type ServiceContextWithTransportInfo<State> = ServiceContext & {
451
499
  };
452
500
 
453
501
  type ConstructHandshake<T extends TSchema> = () => Static<T> | Promise<Static<T>>;
454
- type ValidateHandshake<T extends TSchema> = (metadata: Static<T>, previousParsedMetadata?: ParsedMetadata) => false | ParsedMetadata | Promise<false | ParsedMetadata>;
502
+ type ValidateHandshake<T extends TSchema> = (metadata: Static<T>, previousParsedMetadata?: ParsedMetadata) => Static<typeof HandshakeErrorCustomHandlerFatalResponseCodes> | ParsedMetadata | Promise<Static<typeof HandshakeErrorCustomHandlerFatalResponseCodes> | ParsedMetadata>;
455
503
  interface ClientHandshakeOptions<MetadataSchema extends TSchema = TSchema> {
456
504
  /**
457
505
  * Schema for the metadata that the client sends to the server
@@ -485,4 +533,4 @@ interface ServerHandshakeOptions<MetadataSchema extends TSchema = TSchema> {
485
533
  declare function createClientHandshakeOptions<MetadataSchema extends TSchema = TSchema>(schema: MetadataSchema, construct: ConstructHandshake<MetadataSchema>): ClientHandshakeOptions;
486
534
  declare function createServerHandshakeOptions<MetadataSchema extends TSchema = TSchema>(schema: MetadataSchema, validate: ValidateHandshake<MetadataSchema>): ServerHandshakeOptions;
487
535
 
488
- export { Connection as C, EventMap as E, LeakyBucketRateLimit as L, ProvidedTransportOptions as P, Session as S, Transport as T, TransportStatus as a, ProvidedClientTransportOptions as b, ProvidedServerTransportOptions as c, SessionState as d, SessionNoConnection as e, SessionConnecting as f, SessionHandshaking as g, SessionConnected as h, EventTypes as i, EventHandler as j, ProtocolError as k, ProtocolErrorType as l, SessionOptions as m, ServiceContext as n, ClientTransportOptions as o, ClientHandshakeOptions as p, ServerHandshakeOptions as q, ParsedMetadata as r, ServiceContextWithState as s, ServiceContextWithTransportInfo as t, createClientHandshakeOptions as u, createServerHandshakeOptions as v, CommonSession as w, SessionHandshakingListeners as x, ServerTransportOptions as y };
536
+ export { CommonSessionProps as A, ServerTransportOptions as B, Connection as C, ServerSession as D, EventMap as E, LeakyBucketRateLimit as L, ProvidedTransportOptions as P, Session as S, Transport as T, TransportStatus as a, ProvidedClientTransportOptions as b, ProvidedServerTransportOptions as c, SessionState as d, SessionNoConnection as e, SessionConnecting as f, SessionHandshaking as g, SessionConnected as h, EventTypes as i, EventHandler as j, ProtocolError as k, ProtocolErrorType as l, SessionOptions as m, ClientTransportOptions as n, ServiceContext as o, ClientHandshakeOptions as p, ClientSession as q, SessionBackingOff as r, ServerHandshakeOptions as s, ParsedMetadata as t, ServiceContextWithState as u, ServiceContextWithTransportInfo as v, createClientHandshakeOptions as w, createServerHandshakeOptions as x, CommonSession as y, SessionHandshakingListeners as z };
@@ -1,4 +1,4 @@
1
- export { f as LogFn, L as Logger, M as MessageMetadata, h as coloredStringLogger, j as jsonLogger, s as stringLogger } from '../message-e6c560fd.js';
1
+ export { f as LogFn, L as Logger, M as MessageMetadata, h as coloredStringLogger, j as jsonLogger, s as stringLogger } from '../message-1a434848.js';
2
2
  import '@sinclair/typebox/value';
3
3
  import '@sinclair/typebox';
4
4
  import '@opentelemetry/api';
@@ -1,4 +1,4 @@
1
- export { f as LogFn, L as Logger, M as MessageMetadata, h as coloredStringLogger, j as jsonLogger, s as stringLogger } from '../message-e6c560fd.js';
1
+ export { f as LogFn, L as Logger, M as MessageMetadata, h as coloredStringLogger, j as jsonLogger, s as stringLogger } from '../message-1a434848.js';
2
2
  import '@sinclair/typebox/value';
3
3
  import '@sinclair/typebox';
4
4
  import '@opentelemetry/api';
@@ -64,6 +64,7 @@ declare const TransportMessageSchema: <T extends TSchema>(t: T) => _sinclair_typ
64
64
  }>>;
65
65
  payload: T;
66
66
  }>;
67
+ declare const HandshakeErrorCustomHandlerFatalResponseCodes: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"REJECTED_UNSUPPORTED_CLIENT">, _sinclair_typebox.TLiteral<"REJECTED_BY_CUSTOM_HANDLER">]>;
67
68
  /**
68
69
  * Defines the schema for an opaque transport message that is agnostic to any
69
70
  * procedure/service.
@@ -133,4 +134,4 @@ declare function isStreamOpen(controlFlag: number): boolean;
133
134
  */
134
135
  declare function isStreamClose(controlFlag: number): boolean;
135
136
 
136
- export { Logger as L, MessageMetadata as M, OpaqueTransportMessageSchema as O, PartialTransportMessage as P, TransportMessageSchema as T, TransportMessage as a, OpaqueTransportMessage as b, TransportClientId as c, isStreamClose as d, TelemetryInfo as e, LogFn as f, LoggingLevel as g, coloredStringLogger as h, isStreamOpen as i, jsonLogger as j, stringLogger as s };
137
+ export { HandshakeErrorCustomHandlerFatalResponseCodes as H, Logger as L, MessageMetadata as M, OpaqueTransportMessageSchema as O, PartialTransportMessage as P, TransportMessageSchema as T, TransportMessage as a, OpaqueTransportMessage as b, TransportClientId as c, isStreamClose as d, TelemetryInfo as e, LogFn as f, LoggingLevel as g, coloredStringLogger as h, isStreamOpen as i, jsonLogger as j, stringLogger as s };
@@ -667,11 +667,20 @@ var ControlMessageHandshakeRequestSchema = import_typebox3.Type.Object({
667
667
  var HandshakeErrorRetriableResponseCodes = import_typebox3.Type.Union([
668
668
  import_typebox3.Type.Literal("SESSION_STATE_MISMATCH")
669
669
  ]);
670
+ var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox3.Type.Union([
671
+ // The custom validation handler rejected the handler because the client is unsupported.
672
+ import_typebox3.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
673
+ // The custom validation handler rejected the handshake.
674
+ import_typebox3.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
675
+ ]);
670
676
  var HandshakeErrorFatalResponseCodes = import_typebox3.Type.Union([
677
+ HandshakeErrorCustomHandlerFatalResponseCodes,
678
+ // The ciient sent a handshake that doesn't comply with the extended handshake metadata.
671
679
  import_typebox3.Type.Literal("MALFORMED_HANDSHAKE_META"),
680
+ // The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.
672
681
  import_typebox3.Type.Literal("MALFORMED_HANDSHAKE"),
673
- import_typebox3.Type.Literal("PROTOCOL_VERSION_MISMATCH"),
674
- import_typebox3.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
682
+ // The client's protocol version does not match the server's.
683
+ import_typebox3.Type.Literal("PROTOCOL_VERSION_MISMATCH")
675
684
  ]);
676
685
  var HandshakeErrorResponseCodes = import_typebox3.Type.Union([
677
686
  HandshakeErrorRetriableResponseCodes,
@@ -752,7 +761,7 @@ function Err(error) {
752
761
  var import_api = require("@opentelemetry/api");
753
762
 
754
763
  // package.json
755
- var version = "0.25.1";
764
+ var version = "0.26.0";
756
765
 
757
766
  // tracing/index.ts
758
767
  function getPropagationContext(ctx) {