@replit/river 0.25.2 → 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.
- package/dist/{chunk-PF74DCPQ.js → chunk-5FDAIAQ5.js} +3 -3
- package/dist/{chunk-ONIPHO7J.js → chunk-5S64PXTU.js} +4 -4
- package/dist/{chunk-QXMZJ7LF.js → chunk-7ETNUCOL.js} +41 -40
- package/dist/chunk-7ETNUCOL.js.map +1 -0
- package/dist/{chunk-GDHQCPWW.js → chunk-BNNELZM4.js} +2 -2
- package/dist/{chunk-GDHQCPWW.js.map → chunk-BNNELZM4.js.map} +1 -1
- package/dist/{chunk-EHD2JJBW.js → chunk-CCUYKR5C.js} +14 -4
- package/dist/chunk-CCUYKR5C.js.map +1 -0
- package/dist/{chunk-Q3PZBJXR.js → chunk-JSU2KACV.js} +2 -2
- package/dist/{chunk-ZWMWRM23.js → chunk-KP4UB5NW.js} +2 -2
- package/dist/{client-edc8e2de.d.ts → client-162c509c.d.ts} +2 -2
- package/dist/{connection-ef50ac3a.d.ts → connection-6a404bb8.d.ts} +1 -1
- package/dist/{handshake-12d57161.d.ts → handshake-3342bb94.d.ts} +2 -2
- package/dist/logging/index.d.cts +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/{message-e6c560fd.d.ts → message-1a434848.d.ts} +2 -1
- package/dist/router/index.cjs +12 -3
- 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 +2 -2
- package/dist/{server-f8228636.d.ts → server-1b695374.d.ts} +2 -2
- package/dist/{services-4b9e5232.d.ts → services-c17f7eff.d.ts} +3 -3
- package/dist/transport/impls/ws/client.cjs +12 -3
- 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 +5 -5
- package/dist/transport/impls/ws/server.cjs +48 -39
- 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 +5 -5
- package/dist/transport/index.cjs +48 -39
- 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 +5 -5
- package/dist/util/testHelpers.cjs +12 -3
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +4 -4
- package/dist/util/testHelpers.d.ts +4 -4
- package/dist/util/testHelpers.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-EHD2JJBW.js.map +0 -1
- package/dist/chunk-QXMZJ7LF.js.map +0 -1
- /package/dist/{chunk-PF74DCPQ.js.map → chunk-5FDAIAQ5.js.map} +0 -0
- /package/dist/{chunk-ONIPHO7J.js.map → chunk-5S64PXTU.js.map} +0 -0
- /package/dist/{chunk-Q3PZBJXR.js.map → chunk-JSU2KACV.js.map} +0 -0
- /package/dist/{chunk-ZWMWRM23.js.map → chunk-KP4UB5NW.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../transport/id.ts","../transport/message.ts","../package.json","../util/stringify.ts","../tracing/index.ts"],"sourcesContent":["import { customAlphabet } from 'nanoid';\n\nconst alphabet = customAlphabet(\n '1234567890abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ',\n);\nexport const generateId = () => alphabet(12);\n","import { Type, TSchema, Static } from '@sinclair/typebox';\nimport { PropagationContext } from '../tracing';\nimport { generateId } from './id';\n\n/**\n * Control flags for transport messages.\n * An RPC message is coded with StreamOpenBit | StreamClosedBit.\n * Streams are expected to start with StreamOpenBit sent and the client SHOULD send an empty\n * message with StreamClosedBit to close the stream handler on the server, indicating that\n * it will not be using the stream anymore.\n */\nexport const enum ControlFlags {\n AckBit = 0b0001,\n StreamOpenBit = 0b0010,\n StreamClosedBit = 0b0100,\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 const PROTOCOL_VERSION = 'v1.1';\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 // TODO: remove optional once we know all servers\n // are nextSentSeq here\n // what the server expects the client to send next\n nextSentSeq: Type.Optional(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 HandshakeErrorFatalResponseCodes = Type.Union([\n Type.Literal('MALFORMED_HANDSHAKE_META'),\n Type.Literal('MALFORMED_HANDSHAKE'),\n Type.Literal('PROTOCOL_VERSION_MISMATCH'),\n Type.Literal('REJECTED_BY_CUSTOM_HANDLER'),\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 // TODO: remove optional once we know all servers\n // are sending code here\n code: Type.Optional(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: string;\n to: string;\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: PROTOCOL_VERSION,\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\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 \"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.25.2\",\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 \"it-pushable\": \"^3.2.3\",\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/sdk-trace-base\": \"^1.24.1\",\n \"@opentelemetry/sdk-trace-web\": \"^1.24.1\",\n \"@opentelemetry/core\": \"^1.7.0\",\n \"@types/ws\": \"^8.5.5\",\n \"@typescript-eslint/eslint-plugin\": \"^7.8.0\",\n \"@typescript-eslint/parser\": \"^7.8.0\",\n \"@vitest/ui\": \"^1.3.1\",\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\": \"^1.3.1\"\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","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 {\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 {\n ClientTransport,\n Connection,\n OpaqueTransportMessage,\n} 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 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 return { span, ctx };\n}\n\nexport function createHandlerSpan(\n kind: ValidProcType,\n message: OpaqueTransportMessage,\n fn: (span: Span) => Promise<unknown>,\n) {\n const ctx = message.tracing\n ? propagation.extract(context.active(), message.tracing)\n : context.active();\n\n return tracer.startActiveSpan(\n `procedure handler ${message.serviceName}.${message.procedureName}`,\n {\n attributes: {\n component: 'river',\n 'river.method.kind': kind,\n 'river.method.service': message.serviceName,\n 'river.method.name': message.procedureName,\n 'river.streamId': message.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"],"mappings":";AAAA,SAAS,sBAAsB;AAE/B,IAAM,WAAW;AAAA,EACf;AACF;AACO,IAAM,aAAa,MAAM,SAAS,EAAE;;;ACL3C,SAAS,YAA6B;AAuB/B,IAAM,yBAAyB,CAAoB,MACxD,KAAK,OAAO;AAAA,EACV,IAAI,KAAK,OAAO;AAAA,EAChB,MAAM,KAAK,OAAO;AAAA,EAClB,IAAI,KAAK,OAAO;AAAA,EAChB,KAAK,KAAK,QAAQ;AAAA,EAClB,KAAK,KAAK,QAAQ;AAAA,EAClB,aAAa,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,EACxC,eAAe,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,EAC1C,UAAU,KAAK,OAAO;AAAA,EACtB,cAAc,KAAK,QAAQ;AAAA,EAC3B,SAAS,KAAK;AAAA,IACZ,KAAK,OAAO;AAAA,MACV,aAAa,KAAK,OAAO;AAAA,MACzB,YAAY,KAAK,OAAO;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA,EACA,SAAS;AACX,CAAC;AAOI,IAAM,0BAA0B,KAAK,OAAO;AAAA,EACjD,MAAM,KAAK,QAAQ,KAAK;AAC1B,CAAC;AAMM,IAAM,4BAA4B,KAAK,OAAO;AAAA,EACnD,MAAM,KAAK,QAAQ,OAAO;AAC5B,CAAC;AAEM,IAAM,mBAAmB;AACzB,IAAM,uCAAuC,KAAK,OAAO;AAAA,EAC9D,MAAM,KAAK,QAAQ,eAAe;AAAA,EAClC,iBAAiB,KAAK,OAAO;AAAA,EAC7B,WAAW,KAAK,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,sBAAsB,KAAK,OAAO;AAAA;AAAA,IAEhC,iBAAiB,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA,IAI9B,aAAa,KAAK,SAAS,KAAK,QAAQ,CAAC;AAAA,EAC3C,CAAC;AAAA,EAED,UAAU,KAAK,SAAS,KAAK,QAAQ,CAAC;AACxC,CAAC;AAEM,IAAM,uCAAuC,KAAK,MAAM;AAAA,EAC7D,KAAK,QAAQ,wBAAwB;AACvC,CAAC;AAEM,IAAM,mCAAmC,KAAK,MAAM;AAAA,EACzD,KAAK,QAAQ,0BAA0B;AAAA,EACvC,KAAK,QAAQ,qBAAqB;AAAA,EAClC,KAAK,QAAQ,2BAA2B;AAAA,EACxC,KAAK,QAAQ,4BAA4B;AAC3C,CAAC;AAEM,IAAM,8BAA8B,KAAK,MAAM;AAAA,EACpD;AAAA,EACA;AACF,CAAC;AAEM,IAAM,wCAAwC,KAAK,OAAO;AAAA,EAC/D,MAAM,KAAK,QAAQ,gBAAgB;AAAA,EACnC,QAAQ,KAAK,MAAM;AAAA,IACjB,KAAK,OAAO;AAAA,MACV,IAAI,KAAK,QAAQ,IAAI;AAAA,MACrB,WAAW,KAAK,OAAO;AAAA,IACzB,CAAC;AAAA,IACD,KAAK,OAAO;AAAA,MACV,IAAI,KAAK,QAAQ,KAAK;AAAA,MACtB,QAAQ,KAAK,OAAO;AAAA;AAAA;AAAA,MAGpB,MAAM,KAAK,SAAS,2BAA2B;AAAA,IACjD,CAAC;AAAA,EACH,CAAC;AACH,CAAC;AAEM,IAAM,8BAA8B,KAAK,MAAM;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOM,IAAM,+BAA+B;AAAA,EAC1C,KAAK,QAAQ;AACf;AAoCO,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAS0E;AACxE,SAAO;AAAA,IACL,IAAI,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,UAAU,WAAW;AAAA,IACrB,cAAc;AAAA,IACd;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAQO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AACF,GAI2E;AACzE,SAAO;AAAA,IACL,IAAI,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,UAAU,WAAW;AAAA,IACrB,cAAc;AAAA,IACd,SAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,UAA2C;AAC5E,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,SAAS;AAAA,MACP,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAcO,SAAS,MAAM,aAA8B;AAElD,UAAQ,cAAc,oBAAyB;AACjD;AAOO,SAAS,aAAa,aAA8B;AACzD;AAAA;AAAA,KAEG,cAAc,2BAAgC;AAAA;AAEnD;AAOO,SAAS,cAAc,aAA8B;AAC1D;AAAA;AAAA,KAEG,cAAc,6BACf;AAAA;AAEJ;;;ACtRE,cAAW;;;ACHN,SAAS,kBAAkB,KAAsB;AACtD,MAAI,eAAe,OAAO;AACxB,WAAO,IAAI,WAAW;AAAA,EACxB;AAEA,SAAO,sBAAsB,OAAO,GAAG,CAAC;AAC1C;;;ACNA;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAmBA,SAAS,sBACd,KACgC;AAChC,QAAM,UAAU;AAAA,IACd,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AACA,cAAY,OAAO,KAAK,OAAO;AAC/B,SAAO;AACT;AAEO,SAAS,2BACd,WACA,IACA,MACA,gBACe;AACf,QAAM,YAAY,iBACd,YAAY,QAAQ,QAAQ,OAAO,GAAG,cAAc,IACpD,QAAQ,OAAO;AAEnB,QAAM,OAAO,OAAO;AAAA,IAClB,WAAW,SAAS;AAAA,IACpB;AAAA,MACE,YAAY;AAAA,QACV,WAAW;AAAA,QACX,oBAAoB;AAAA,QACpB,oBAAoB;AAAA,QACpB,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAEA,QAAM,MAAM,MAAM,QAAQ,WAAW,IAAI;AAEzC,SAAO,EAAE,MAAM,IAAI;AACrB;AAuBO,SAAS,wBACd,WACA,MACA,aACA,eACA,UACe;AACf,QAAM,UAAU,QAAQ,OAAO;AAC/B,QAAM,OAAO,OAAO;AAAA,IAClB,kBAAkB,WAAW,IAAI,aAAa;AAAA,IAC9C;AAAA,MACE,YAAY;AAAA,QACV,WAAW;AAAA,QACX,qBAAqB;AAAA,QACrB,wBAAwB;AAAA,QACxB,qBAAqB;AAAA,QACrB,kBAAkB;AAAA,QAClB,aAAa;AAAA,MACf;AAAA,MACA,MAAM,SAAS;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AAEA,QAAM,MAAM,MAAM,QAAQ,SAAS,IAAI;AAEvC,YAAU,KAAK,KAAK,WAAW,WAAW,IAAI,aAAa,IAAI;AAAA,IAC7D,UAAU,UAAU;AAAA,IACpB,kBAAkB;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,IACA,WAAW;AAAA,MACT,SAAS,KAAK,YAAY,EAAE;AAAA,MAC5B,QAAQ,KAAK,YAAY,EAAE;AAAA,IAC7B;AAAA,EACF,CAAC;AACD,SAAO,EAAE,MAAM,IAAI;AACrB;AAEO,SAAS,kBACd,MACA,SACA,IACA;AACA,QAAM,MAAM,QAAQ,UAChB,YAAY,QAAQ,QAAQ,OAAO,GAAG,QAAQ,OAAO,IACrD,QAAQ,OAAO;AAEnB,SAAO,OAAO;AAAA,IACZ,qBAAqB,QAAQ,WAAW,IAAI,QAAQ,aAAa;AAAA,IACjE;AAAA,MACE,YAAY;AAAA,QACV,WAAW;AAAA,QACX,qBAAqB;AAAA,QACrB,wBAAwB,QAAQ;AAAA,QAChC,qBAAqB,QAAQ;AAAA,QAC7B,kBAAkB,QAAQ;AAAA,QAC1B,aAAa;AAAA,MACf;AAAA,MACA,MAAM,SAAS;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,SAAS,MAAM,UAAU,SAAS,OAAa;AACrD,IAAO,kBAAQ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../transport/server.ts"],"sourcesContent":["import { SpanStatusCode } from '@opentelemetry/api';\nimport { ParsedMetadata } from '../router/context';\nimport { ServerHandshakeOptions } from '../router/handshake';\nimport {\n ControlMessageHandshakeRequestSchema,\n HandshakeErrorResponseCodes,\n OpaqueTransportMessage,\n PROTOCOL_VERSION,\n PartialTransportMessage,\n TransportClientId,\n handshakeResponseMessage,\n} from './message';\nimport {\n ProvidedServerTransportOptions,\n ServerTransportOptions,\n defaultServerTransportOptions,\n} from './options';\nimport { Transport } from './transport';\nimport { coerceErrorString } from '../util/stringify';\nimport { Static } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport { ProtocolError } from './events';\nimport { Connection } from './connection';\nimport { MessageMetadata } from '../logging';\nimport { SessionWaitingForHandshake } from './sessionStateMachine/SessionWaitingForHandshake';\nimport { SessionState } from './sessionStateMachine/common';\nimport {\n ServerSession,\n ServerSessionStateGraph,\n} from './sessionStateMachine/transitions';\n\nexport abstract class ServerTransport<\n ConnType extends Connection,\n> extends Transport<ConnType> {\n /**\n * The options for this transport.\n */\n protected options: ServerTransportOptions;\n\n /**\n * Optional handshake options for the server.\n */\n handshakeExtensions?: ServerHandshakeOptions;\n\n /**\n * A map of session handshake data for each session.\n */\n sessionHandshakeMetadata = new Map<TransportClientId, ParsedMetadata>();\n\n sessions = new Map<TransportClientId, ServerSession<ConnType>>();\n pendingSessions = new Set<SessionWaitingForHandshake<ConnType>>();\n\n constructor(\n clientId: TransportClientId,\n providedOptions?: ProvidedServerTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.sessions = new Map();\n this.options = {\n ...defaultServerTransportOptions,\n ...providedOptions,\n };\n this.log?.info(`initiated server transport`, {\n clientId: this.clientId,\n protocolVersion: PROTOCOL_VERSION,\n });\n }\n\n extendHandshake(options: ServerHandshakeOptions) {\n this.handshakeExtensions = options;\n }\n\n send(to: string, msg: PartialTransportMessage): string {\n if (this.getStatus() === 'closed') {\n const err = 'transport is closed, cant send';\n this.log?.error(err, {\n clientId: this.clientId,\n transportMessage: msg,\n tags: ['invariant-violation'],\n });\n\n throw new Error(err);\n }\n\n const session = this.sessions.get(to);\n if (!session) {\n const err = `session to ${to} does not exist`;\n this.log?.error(err, {\n clientId: this.clientId,\n transportMessage: msg,\n tags: ['invariant-violation'],\n });\n\n throw new Error(err);\n }\n\n return session.send(msg);\n }\n\n protected deletePendingSession(\n pendingSession: SessionWaitingForHandshake<ConnType>,\n ) {\n pendingSession.close();\n // we don't dispatch a session disconnect event\n // for a non-identified session, just delete directly\n\n this.pendingSessions.delete(pendingSession);\n }\n\n protected deleteSession(session: ServerSession<ConnType>): void {\n this.sessionHandshakeMetadata.delete(session.to);\n super.deleteSession(session);\n }\n\n protected handleConnection(conn: ConnType) {\n if (this.getStatus() !== 'open') return;\n\n this.log?.info(`new incoming connection`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n });\n\n let receivedHandshake = false;\n const pendingSession = ServerSessionStateGraph.entrypoint(\n this.clientId,\n conn,\n {\n onConnectionClosed: () => {\n this.log?.warn(\n `connection from unknown closed before handshake finished`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onConnectionErrored: (err) => {\n const errorString = coerceErrorString(err);\n this.log?.warn(\n `connection from unknown errored before handshake finished: ${errorString}`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onHandshakeTimeout: () => {\n this.log?.warn(\n `connection from unknown timed out before handshake finished`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onHandshake: (msg) => {\n if (receivedHandshake) {\n this.log?.error(\n `received multiple handshake messages from pending session`,\n {\n ...pendingSession.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n this.deletePendingSession(pendingSession);\n return;\n }\n\n // let this resolve async, we just need to make sure its only\n // called once so we don't race while transitioning to connected\n // onHandshakeRequest is async as custom validation may be async\n receivedHandshake = true;\n void this.onHandshakeRequest(pendingSession, msg);\n },\n onInvalidHandshake: (reason) => {\n this.log?.error(\n `invalid handshake: ${reason}`,\n pendingSession.loggingMetadata,\n );\n this.deletePendingSession(pendingSession);\n this.protocolError(ProtocolError.HandshakeFailed, reason);\n },\n },\n this.options,\n this.log,\n );\n\n this.pendingSessions.add(pendingSession);\n }\n\n private rejectHandshakeRequest(\n session: SessionWaitingForHandshake<ConnType>,\n to: TransportClientId,\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n metadata: MessageMetadata,\n ) {\n session.conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: reason,\n });\n\n this.log?.warn(reason, metadata);\n\n session.sendHandshake(\n handshakeResponseMessage({\n from: this.clientId,\n to,\n status: {\n ok: false,\n code,\n reason,\n },\n }),\n );\n\n this.protocolError(ProtocolError.HandshakeFailed, reason);\n this.deletePendingSession(session);\n }\n\n protected async onHandshakeRequest(\n session: SessionWaitingForHandshake<ConnType>,\n msg: OpaqueTransportMessage,\n ) {\n // invariant: msg is a handshake request\n if (!Value.Check(ControlMessageHandshakeRequestSchema, msg.payload)) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n 'received invalid handshake request',\n 'MALFORMED_HANDSHAKE',\n {\n ...session.loggingMetadata,\n transportMessage: msg,\n connectedTo: msg.from,\n validationErrors: [\n ...Value.Errors(ControlMessageHandshakeRequestSchema, msg.payload),\n ],\n },\n );\n\n return;\n }\n\n // invariant: handshake request passes all the validation\n const gotVersion = msg.payload.protocolVersion;\n if (gotVersion !== PROTOCOL_VERSION) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `expected protocol version ${PROTOCOL_VERSION}, got ${gotVersion}`,\n 'PROTOCOL_VERSION_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n let oldSession = this.sessions.get(msg.from);\n\n // invariant: must pass custom validation if defined\n const parsedMetadata = await this.validateHandshakeMetadata(\n session,\n oldSession,\n msg.payload.metadata,\n msg.from,\n );\n\n if (parsedMetadata === false) {\n return;\n }\n\n // 4 connect cases\n // 1. new session\n // we dont have a session and the client is requesting a new one\n // we can create the session as normal\n // 2. client is reconnecting to an existing session but we don't have it\n // reject this handshake, there's nothing we can do to salvage it\n // 3. transparent reconnect (old session exists and is the same as the client wants)\n // assign to old session\n // 4. hard reconnect (oldSession exists but but the client wants a new one)\n // we close the old session and create a new one\n let connectCase:\n | 'new session'\n | 'unknown session'\n | 'transparent reconnection'\n | 'hard reconnection' = 'new session';\n const clientNextExpectedSeq =\n msg.payload.expectedSessionState.nextExpectedSeq;\n const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq ?? 0;\n\n if (oldSession && oldSession.id === msg.payload.sessionId) {\n connectCase = 'transparent reconnection';\n\n // invariant: ordering must be correct\n const ourNextSeq = oldSession.nextSeq();\n const ourAck = oldSession.ack;\n\n // two incorrect cases where we cannot permit a reconnect:\n // - if the client is about to send a message in the future w.r.t to the server\n // - client.seq > server.ack => nextSentSeq > oldSession.ack\n if (clientNextSentSeq > ourAck) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `client is in the future: server wanted next message to be ${ourAck} but client would have sent ${clientNextSentSeq}`,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n // - if the server is about to send a message in the future w.r.t to the client\n // - server.seq > client.ack => oldSession.nextSeq() > nextExpectedSeq\n if (ourNextSeq > clientNextExpectedSeq) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `server is in the future: client wanted next message to be ${clientNextExpectedSeq} but server would have sent ${ourNextSeq}`,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n // transparent reconnect seems ok, proceed by transitioning old session\n // to not connected\n if (oldSession.state !== SessionState.NoConnection) {\n const noConnectionSession =\n ServerSessionStateGraph.transition.ConnectedToNoConnection(\n oldSession,\n {\n onSessionGracePeriodElapsed: () => {\n this.onSessionGracePeriodElapsed(noConnectionSession);\n },\n },\n );\n\n oldSession = noConnectionSession;\n }\n\n this.updateSession(oldSession);\n } else if (oldSession) {\n connectCase = 'hard reconnection';\n\n // just nuke the old session entirely and proceed as if this was new\n this.log?.info(\n `client is reconnecting to a new session (${msg.payload.sessionId}) with an old session (${oldSession.id}) already existing, closing old session`,\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n sessionId: msg.payload.sessionId,\n },\n );\n this.deleteSession(oldSession);\n oldSession = undefined;\n }\n\n if (!oldSession && (clientNextSentSeq > 0 || clientNextExpectedSeq > 0)) {\n // we don't have a session, but the client is trying to reconnect\n // to an old session. we can't do anything about this, so we reject\n connectCase = 'unknown session';\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `client is trying to reconnect to a session the server don't know about: ${msg.payload.sessionId}`,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n return;\n }\n\n // from this point on, we're committed to connecting\n const sessionId = msg.payload.sessionId;\n this.log?.info(\n `handshake from ${msg.from} ok (${connectCase}), responding with handshake success`,\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n },\n );\n const responseMsg = handshakeResponseMessage({\n from: this.clientId,\n to: msg.from,\n status: {\n ok: true,\n sessionId,\n },\n });\n session.sendHandshake(responseMsg);\n\n // transition\n const connectedSession =\n ServerSessionStateGraph.transition.WaitingForHandshakeToConnected(\n session,\n // by this point oldSession is either no connection or we dont have an old session\n oldSession,\n sessionId,\n msg.from,\n msg.tracing,\n {\n onConnectionErrored: (err) => {\n // just log, when we error we also emit close\n const errStr = coerceErrorString(err);\n this.log?.warn(\n `connection to ${connectedSession.to} errored: ${errStr}`,\n connectedSession.loggingMetadata,\n );\n },\n onConnectionClosed: () => {\n this.log?.info(\n `connection to ${connectedSession.to} closed`,\n connectedSession.loggingMetadata,\n );\n this.onConnClosed(connectedSession);\n },\n onMessage: (msg) => this.handleMsg(msg),\n onInvalidMessage: (reason) => {\n this.protocolError(ProtocolError.MessageOrderingViolated, reason);\n this.deleteSession(connectedSession);\n },\n },\n );\n\n this.sessionHandshakeMetadata.set(connectedSession.to, parsedMetadata);\n this.updateSession(connectedSession);\n this.pendingSessions.delete(session);\n connectedSession.startActiveHeartbeat();\n }\n\n private async validateHandshakeMetadata(\n handshakingSession: SessionWaitingForHandshake<ConnType>,\n existingSession: ServerSession<ConnType> | undefined,\n rawMetadata: Static<\n typeof ControlMessageHandshakeRequestSchema\n >['metadata'],\n from: TransportClientId,\n ): Promise<ParsedMetadata | false> {\n let parsedMetadata: ParsedMetadata = {};\n if (this.handshakeExtensions) {\n // check that the metadata that was sent is the correct shape\n if (!Value.Check(this.handshakeExtensions.schema, rawMetadata)) {\n this.rejectHandshakeRequest(\n handshakingSession,\n from,\n 'received malformed handshake metadata',\n 'MALFORMED_HANDSHAKE_META',\n {\n ...handshakingSession.loggingMetadata,\n connectedTo: from,\n validationErrors: [\n ...Value.Errors(this.handshakeExtensions.schema, rawMetadata),\n ],\n },\n );\n\n return false;\n }\n\n const previousParsedMetadata = existingSession\n ? this.sessionHandshakeMetadata.get(existingSession.to)\n : undefined;\n\n parsedMetadata = await this.handshakeExtensions.validate(\n rawMetadata,\n previousParsedMetadata,\n );\n\n // handler rejected the connection\n if (parsedMetadata === false) {\n this.rejectHandshakeRequest(\n handshakingSession,\n from,\n 'rejected by handshake handler',\n 'REJECTED_BY_CUSTOM_HANDLER',\n {\n ...handshakingSession.loggingMetadata,\n connectedTo: from,\n clientId: this.clientId,\n },\n );\n\n return false;\n }\n }\n\n return parsedMetadata;\n }\n}\n"],"mappings":"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","names":["msg"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|