@replit/river 0.200.2 → 0.200.4
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-PJB2Y2AV.js → chunk-6EORIAZJ.js} +4 -4
- package/dist/{chunk-HRKM7BIE.js → chunk-BBTXTDJ5.js} +2 -2
- package/dist/chunk-BBTXTDJ5.js.map +1 -0
- package/dist/{chunk-A4JKES5A.js → chunk-GKBNAMHM.js} +4 -4
- package/dist/{chunk-YTMS7OP6.js → chunk-LHH5LQ7C.js} +1 -1
- package/dist/chunk-LHH5LQ7C.js.map +1 -0
- package/dist/{chunk-6BH2CXVE.js → chunk-LL4CB5UD.js} +2 -2
- package/dist/{chunk-GJUUVID2.js → chunk-Q7DD2FLX.js} +2 -2
- package/dist/{chunk-GJUUVID2.js.map → chunk-Q7DD2FLX.js.map} +1 -1
- package/dist/{chunk-QIDEN5PP.js → chunk-RWVZCH26.js} +4 -4
- package/dist/{chunk-Z4PX66JO.js → chunk-ZVWJN6V2.js} +1 -1
- package/dist/chunk-ZVWJN6V2.js.map +1 -0
- package/dist/{client-9292552a.d.ts → client-ba6815ae.d.ts} +2 -2
- package/dist/{connection-94dea547.d.ts → connection-d217c989.d.ts} +4 -4
- package/dist/{context-69f37ac1.d.ts → context-8d1ed9a1.d.ts} +3 -3
- package/dist/logging/index.cjs.map +1 -1
- package/dist/logging/index.d.cts +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +1 -1
- package/dist/{message-57bb8187.d.ts → message-45658364.d.ts} +2 -2
- package/dist/router/index.cjs +5 -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 +6 -4
- package/dist/router/index.js.map +1 -1
- package/dist/{server-8fdd7fb2.d.ts → server-eb7d2cfd.d.ts} +3 -3
- package/dist/{services-259f39a3.d.ts → services-94e0afc3.d.ts} +7 -4
- package/dist/transport/impls/ws/client.cjs +1 -1
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +4 -4
- package/dist/transport/impls/ws/client.d.ts +4 -4
- package/dist/transport/impls/ws/client.js +6 -6
- package/dist/transport/impls/ws/server.cjs +1 -1
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +4 -4
- package/dist/transport/impls/ws/server.d.ts +4 -4
- package/dist/transport/impls/ws/server.js +6 -6
- package/dist/transport/index.cjs +1 -1
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +4 -4
- package/dist/transport/index.d.ts +4 -4
- package/dist/transport/index.js +6 -6
- package/dist/util/testHelpers.cjs +1 -1
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +5 -5
- package/dist/util/testHelpers.d.ts +5 -5
- package/dist/util/testHelpers.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-HRKM7BIE.js.map +0 -1
- package/dist/chunk-YTMS7OP6.js.map +0 -1
- package/dist/chunk-Z4PX66JO.js.map +0 -1
- /package/dist/{chunk-PJB2Y2AV.js.map → chunk-6EORIAZJ.js.map} +0 -0
- /package/dist/{chunk-A4JKES5A.js.map → chunk-GKBNAMHM.js.map} +0 -0
- /package/dist/{chunk-6BH2CXVE.js.map → chunk-LL4CB5UD.js.map} +0 -0
- /package/dist/{chunk-QIDEN5PP.js.map → chunk-RWVZCH26.js.map} +0 -0
package/dist/router/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../router/services.ts","../../router/procedures.ts","../../router/client.ts","../../router/server.ts","../../router/handshake.ts"],"sourcesContent":["import { Type, TSchema, Static, Kind } from '@sinclair/typebox';\nimport {\n Branded,\n ProcedureMap,\n Unbranded,\n AnyProcedure,\n PayloadType,\n} from './procedures';\nimport { ServiceContext } from './context';\nimport {\n flattenErrorType,\n ProcedureErrorSchemaType,\n ReaderErrorSchema,\n} from './errors';\n\n/**\n * An instantiated service, probably from a {@link ServiceSchema}.\n *\n * You shouldn't construct these directly, use {@link ServiceSchema} instead.\n */\nexport interface Service<\n State extends object,\n Procs extends ProcedureMap<State>,\n> {\n readonly state: State;\n readonly procedures: Procs;\n}\n\n/**\n * Represents any {@link Service} object.\n */\nexport type AnyService = Service<object, ProcedureMap>;\n\n/**\n * Represents any {@link ServiceSchema} object.\n */\nexport type AnyServiceSchema = ServiceSchema<object, ProcedureMap>;\n\n/**\n * A dictionary of {@link ServiceSchema}s, where the key is the service name.\n */\nexport type AnyServiceSchemaMap = Record<string, AnyServiceSchema>;\n\n// This has the secret sauce to keep go to definition working, the structure is\n// somewhat delicate, so be careful when modifying it. Would be nice to add a\n// static test for this.\n/**\n * Takes a {@link AnyServiceSchemaMap} and returns a dictionary of instantiated\n * services.\n */\nexport type InstantiatedServiceSchemaMap<T extends AnyServiceSchemaMap> = {\n [K in keyof T]: T[K] extends ServiceSchema<infer S, infer P>\n ? Service<S, P>\n : never;\n};\n\n/**\n * Helper to get the type definition for a specific handler of a procedure in a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcHandler<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = S['procedures'][ProcName]['handler'];\n\n/**\n * Helper to get the type definition for the procedure init type of a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcInit<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = Static<S['procedures'][ProcName]['requestInit']>;\n\n/**\n * Helper to get the type definition for the procedure request of a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcRequest<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = S['procedures'][ProcName] extends { requestData: PayloadType }\n ? Static<S['procedures'][ProcName]['requestData']>\n : never;\n\n/**\n * Helper to get the type definition for the procedure response of a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcResponse<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = Static<S['procedures'][ProcName]['responseData']>;\n\n/**\n * Helper to get the type definition for the procedure errors of a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcErrors<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> =\n | Static<S['procedures'][ProcName]['responseError']>\n | Static<typeof ReaderErrorSchema>;\n\n/**\n * Helper to get the type of procedure in a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcType<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = S['procedures'][ProcName]['type'];\n\n/**\n * A list of procedures where every procedure is \"branded\", as-in the procedure\n * was created via the {@link Procedure} constructors.\n */\ntype BrandedProcedureMap<State> = Record<string, Branded<AnyProcedure<State>>>;\n\n/**\n * The configuration for a service.\n */\nexport interface ServiceConfiguration<State extends object> {\n /**\n * A factory function for creating a fresh state.\n */\n initializeState: (extendedContext: ServiceContext) => State;\n}\n\n// TODO remove once clients migrate to v2\nexport interface SerializedProcedureSchemaProtocolv1 {\n init?: PayloadType;\n input: PayloadType;\n output: PayloadType;\n errors?: ProcedureErrorSchemaType;\n type: 'rpc' | 'subscription' | 'upload' | 'stream';\n}\n\n// TODO remove once clients migrate to v2\nexport interface SerializedServiceSchemaProtocolv1 {\n procedures: Record<string, SerializedProcedureSchemaProtocolv1>;\n}\n\n// TODO remove once clients migrate to v2\nexport interface SerializedServerSchemaProtocolv1 {\n handshakeSchema?: TSchema;\n services: Record<string, SerializedServiceSchemaProtocolv1>;\n}\n\n// TODO remove once clients migrate to v2\n/**\n * Same as {@link serializeSchema} but with a format that is compatible with\n * protocolv1. This is useful to be able to continue to generate schemas for older\n * clients as they are still supported.\n */\nexport function serializeSchemaV1Compat(\n services: AnyServiceSchemaMap,\n handshakeSchema?: TSchema,\n): SerializedServerSchemaProtocolv1 {\n const serializedServiceObject = Object.entries(services).reduce<\n Record<string, SerializedServiceSchemaProtocolv1>\n >((acc, [name, value]) => {\n acc[name] = value.serializeV1Compat();\n\n return acc;\n }, {});\n\n const schema: SerializedServerSchemaProtocolv1 = {\n services: serializedServiceObject,\n };\n\n if (handshakeSchema) {\n schema.handshakeSchema = Type.Strict(handshakeSchema);\n }\n\n return schema;\n}\n\nexport interface SerializedProcedureSchema {\n init: PayloadType;\n input?: PayloadType;\n output: PayloadType;\n errors?: ProcedureErrorSchemaType;\n type: 'rpc' | 'subscription' | 'upload' | 'stream';\n}\n\nexport interface SerializedServiceSchema {\n procedures: Record<string, SerializedProcedureSchema>;\n}\n\nexport interface SerializedServerSchema {\n handshakeSchema?: TSchema;\n services: Record<string, SerializedServiceSchema>;\n}\n\n/**\n * Serializes a server schema into a plain object that is JSON compatible.\n */\nexport function serializeSchema(\n services: AnyServiceSchemaMap,\n handshakeSchema?: TSchema,\n): SerializedServerSchema {\n const serializedServiceObject = Object.entries(services).reduce<\n Record<string, SerializedServiceSchema>\n >((acc, [name, value]) => {\n acc[name] = value.serialize();\n\n return acc;\n }, {});\n\n const schema: SerializedServerSchema = {\n services: serializedServiceObject,\n };\n\n if (handshakeSchema) {\n schema.handshakeSchema = Type.Strict(handshakeSchema);\n }\n\n return schema;\n}\n\n/**\n * The schema for a {@link Service}. This is used to define a service, specifically\n * its initial state and procedures.\n *\n * There are two ways to define a service:\n * 1. the {@link ServiceSchema.define} static method, which takes a configuration and\n * a list of procedures directly. Use this to ergonomically define a service schema\n * in one go. Good for smaller services, especially if they're stateless.\n * 2. the {@link ServiceSchema.scaffold} static method, which creates a scaffold that\n * can be used to define procedures separately from the configuration. Use this to\n * better organize your service's definition, especially if it's a large service.\n * You can also use it in a builder pattern to define the service in a more\n * fluent way.\n *\n * See the static methods for more information and examples.\n *\n * When defining procedures, use the {@link Procedure} constructors to create them.\n */\nexport class ServiceSchema<\n State extends object,\n Procedures extends ProcedureMap<State>,\n> {\n /**\n * Factory function for creating a fresh state.\n */\n protected readonly initializeState: (\n extendedContext: ServiceContext,\n ) => State;\n\n /**\n * The procedures for this service.\n */\n readonly procedures: Procedures;\n\n /**\n * @param config - The configuration for this service.\n * @param procedures - The procedures for this service.\n */\n protected constructor(\n config: ServiceConfiguration<State>,\n procedures: Procedures,\n ) {\n this.initializeState = config.initializeState;\n this.procedures = procedures;\n }\n\n /**\n * Creates a {@link ServiceScaffold}, which can be used to define procedures\n * that can then be merged into a {@link ServiceSchema}, via the scaffold's\n * `finalize` method.\n *\n * There are two patterns that work well with this method. The first is using\n * it to separate the definition of procedures from the definition of the\n * service's configuration:\n * ```ts\n * const MyServiceScaffold = ServiceSchema.scaffold({\n * initializeState: () => ({ count: 0 }),\n * });\n *\n * const incrementProcedures = MyServiceScaffold.procedures({\n * increment: Procedure.rpc({\n * requestInit: Type.Object({ amount: Type.Number() }),\n * responseData: Type.Object({ current: Type.Number() }),\n * async handler(ctx, init) {\n * ctx.state.count += init.amount;\n * return Ok({ current: ctx.state.count });\n * }\n * }),\n * })\n *\n * const MyService = MyServiceScaffold.finalize({\n * ...incrementProcedures,\n * // you can also directly define procedures here\n * });\n * ```\n * This might be really handy if you have a very large service and you're\n * wanting to split it over multiple files. You can define the scaffold\n * in one file, and then import that scaffold in other files where you\n * define procedures - and then finally import the scaffolds and your\n * procedure objects in a final file where you finalize the scaffold into\n * a service schema.\n *\n * The other way is to use it like in a builder pattern:\n * ```ts\n * const MyService = ServiceSchema\n * .scaffold({ initializeState: () => ({ count: 0 }) })\n * .finalize({\n * increment: Procedure.rpc({\n * requestInit: Type.Object({ amount: Type.Number() }),\n * responseData: Type.Object({ current: Type.Number() }),\n * async handler(ctx, init) {\n * ctx.state.count += init.amount;\n * return Ok({ current: ctx.state.count });\n * }\n * }),\n * })\n * ```\n * Depending on your preferences, this may be a more appealing way to define\n * a schema versus using the {@link ServiceSchema.define} method.\n */\n static scaffold<State extends object>(config: ServiceConfiguration<State>) {\n return new ServiceScaffold(config);\n }\n\n /**\n * Creates a new {@link ServiceSchema} with the given configuration and procedures.\n *\n * All procedures must be created with the {@link Procedure} constructors.\n *\n * NOTE: There is an overload that lets you just provide the procedures alone if your\n * service has no state.\n *\n * @param config - The configuration for this service.\n * @param procedures - The procedures for this service.\n *\n * @example\n * ```\n * const service = ServiceSchema.define(\n * { initializeState: () => ({ count: 0 }) },\n * {\n * increment: Procedure.rpc({\n * requestInit: Type.Object({ amount: Type.Number() }),\n * responseData: Type.Object({ current: Type.Number() }),\n * async handler(ctx, init) {\n * ctx.state.count += init.amount;\n * return Ok({ current: ctx.state.count });\n * }\n * }),\n * },\n * );\n * ```\n */\n static define<\n State extends object,\n Procedures extends BrandedProcedureMap<State>,\n >(\n config: ServiceConfiguration<State>,\n procedures: Procedures,\n ): ServiceSchema<\n State,\n { [K in keyof Procedures]: Unbranded<Procedures[K]> }\n >;\n /**\n * Creates a new {@link ServiceSchema} with the given procedures.\n *\n * All procedures must be created with the {@link Procedure} constructors.\n *\n * NOTE: There is an overload that lets you provide configuration as well,\n * if your service has extra configuration like a state.\n *\n * @param procedures - The procedures for this service.\n *\n * @example\n * ```\n * const service = ServiceSchema.define({\n * add: Procedure.rpc({\n * requestInit: Type.Object({ a: Type.Number(), b: Type.Number() }),\n * responseData: Type.Object({ result: Type.Number() }),\n * async handler(ctx, init) {\n * return Ok({ result: init.a + init.b });\n * }\n * }),\n * });\n */\n static define<Procedures extends BrandedProcedureMap<Record<string, never>>>(\n procedures: Procedures,\n ): ServiceSchema<\n Record<string, never>,\n { [K in keyof Procedures]: Unbranded<Procedures[K]> }\n >;\n // actual implementation\n static define(\n configOrProcedures:\n | ServiceConfiguration<object>\n | BrandedProcedureMap<object>,\n maybeProcedures?: BrandedProcedureMap<object>,\n ): ServiceSchema<object, ProcedureMap> {\n let config: ServiceConfiguration<object>;\n let procedures: BrandedProcedureMap<object>;\n\n if (\n 'initializeState' in configOrProcedures &&\n typeof configOrProcedures.initializeState === 'function'\n ) {\n if (!maybeProcedures) {\n throw new Error('Expected procedures to be defined');\n }\n\n config = configOrProcedures as ServiceConfiguration<object>;\n procedures = maybeProcedures;\n } else {\n config = { initializeState: () => ({}) };\n procedures = configOrProcedures as BrandedProcedureMap<object>;\n }\n\n return new ServiceSchema(config, procedures);\n }\n\n /**\n * Serializes this schema's procedures into a plain object that is JSON compatible.\n */\n serialize(): SerializedServiceSchema {\n return {\n procedures: Object.fromEntries(\n Object.entries(this.procedures).map(([procName, procDef]) => [\n procName,\n {\n init: Type.Strict(procDef.requestInit),\n output: Type.Strict(procDef.responseData),\n errors: getSerializedProcErrors(procDef),\n // Only add `description` field if the type declares it.\n ...('description' in procDef\n ? { description: procDef.description }\n : {}),\n type: procDef.type,\n // Only add the `input` field if the type declares it.\n ...('requestData' in procDef\n ? {\n input: Type.Strict(procDef.requestData),\n }\n : {}),\n },\n ]),\n ),\n };\n }\n\n // TODO remove once clients migrate to v2\n /**\n * Same as {@link ServiceSchema.serialize}, but with a format that is compatible with\n * protocol v1. This is useful to be able to continue to generate schemas for older\n * clients as they are still supported.\n */\n serializeV1Compat(): SerializedServiceSchemaProtocolv1 {\n return {\n procedures: Object.fromEntries(\n Object.entries(this.procedures).map(\n ([procName, procDef]): [\n string,\n SerializedProcedureSchemaProtocolv1,\n ] => {\n if (procDef.type === 'rpc' || procDef.type === 'subscription') {\n return [\n procName,\n {\n // BACKWARDS COMPAT: map init to input for protocolv1\n // this is the only change needed to make it compatible.\n input: Type.Strict(procDef.requestInit),\n output: Type.Strict(procDef.responseData),\n errors: getSerializedProcErrors(procDef),\n // Only add `description` field if the type declares it.\n ...('description' in procDef\n ? { description: procDef.description }\n : {}),\n type: procDef.type,\n },\n ];\n }\n\n // No backwards compatibility needed for upload and stream types, as having an `init`\n // all the time is compatible with protocol v1.\n return [\n procName,\n {\n init: Type.Strict(procDef.requestInit),\n output: Type.Strict(procDef.responseData),\n errors: getSerializedProcErrors(procDef),\n // Only add `description` field if the type declares it.\n ...('description' in procDef\n ? { description: procDef.description }\n : {}),\n type: procDef.type,\n input: Type.Strict(procDef.requestData),\n },\n ];\n },\n ),\n ),\n };\n }\n\n /**\n * Instantiates this schema into a {@link Service} object.\n *\n * You probably don't need this, usually the River server will handle this\n * for you.\n */\n instantiate(extendedContext: ServiceContext): Service<State, Procedures> {\n return Object.freeze({\n state: this.initializeState(extendedContext),\n procedures: this.procedures,\n });\n }\n}\n\nfunction getSerializedProcErrors(\n procDef: AnyProcedure,\n): ProcedureErrorSchemaType {\n if (\n !('responseError' in procDef) ||\n procDef.responseError[Kind] === 'Never'\n ) {\n return Type.Strict(ReaderErrorSchema);\n }\n\n const withProtocolErrors = flattenErrorType(\n Type.Union([procDef.responseError, ReaderErrorSchema]),\n );\n\n return Type.Strict(withProtocolErrors);\n}\n\n/**\n * A scaffold for defining a service's procedures.\n *\n * @see {@link ServiceSchema.scaffold}\n */\n// note that this isn't exported\nclass ServiceScaffold<State extends object> {\n /**\n * The configuration for this service.\n */\n protected readonly config: ServiceConfiguration<State>;\n\n /**\n * @param config - The configuration for this service.\n */\n constructor(config: ServiceConfiguration<State>) {\n this.config = config;\n }\n\n /**\n * Define procedures for this service. Use the {@link Procedure} constructors\n * to create them. This returns the procedures object, which can then be\n * passed to {@link ServiceSchema.finalize} to create a {@link ServiceSchema}.\n *\n * @example\n * ```\n * const myProcedures = MyServiceScaffold.procedures({\n * myRPC: Procedure.rpc({\n * // ...\n * }),\n * });\n *\n * const MyService = MyServiceScaffold.finalize({\n * ...myProcedures,\n * });\n * ```\n *\n * @param procedures - The procedures for this service.\n */\n procedures<T extends BrandedProcedureMap<State>>(procedures: T): T {\n return procedures;\n }\n\n /**\n * Finalizes the scaffold into a {@link ServiceSchema}. This is where you\n * provide the service's procedures and get a {@link ServiceSchema} in return.\n *\n * You can directly define procedures here, or you can define them separately\n * with the {@link ServiceScaffold.procedures} method, and then pass them here.\n *\n * @example\n * ```\n * const MyService = MyServiceScaffold.finalize({\n * myRPC: Procedure.rpc({\n * // ...\n * }),\n * // e.g. from the procedures method\n * ...myOtherProcedures,\n * });\n * ```\n */\n finalize<T extends BrandedProcedureMap<State>>(\n procedures: T,\n ): ServiceSchema<State, { [K in keyof T]: Unbranded<T[K]> }> {\n return ServiceSchema.define(this.config, procedures);\n }\n}\n","/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */\nimport { Static, TNever, TSchema, Type } from '@sinclair/typebox';\nimport { ProcedureHandlerContext } from './context';\nimport { Result } from './result';\nimport { Readable, Writable } from './streams';\nimport { ProcedureErrorSchemaType, ReaderErrorSchema } from './errors';\n\n/**\n * Brands a type to prevent it from being directly constructed.\n */\nexport type Branded<T> = T & { readonly __BRAND_DO_NOT_USE: unique symbol };\n\n/**\n * Unbrands a {@link Branded} type.\n */\nexport type Unbranded<T> = T extends Branded<infer U> ? U : never;\n\n/**\n * The valid {@link Procedure} types. The `stream` and `upload` types can optionally have a\n * different type for the very first initialization message. The suffixless types correspond to\n * gRPC's four combinations of stream / non-stream in each direction.\n */\nexport type ValidProcType =\n // Single message in both directions (1:1).\n | 'rpc'\n // Client-stream single message from server (n:1).\n | 'upload'\n // Single message from client, stream from server (1:n).\n | 'subscription'\n // Bidirectional stream (n:n).\n | 'stream';\n\n/**\n * Represents the payload type for {@link Procedure}s.\n */\nexport type PayloadType = TSchema;\n\n/**\n * Procedure for a single message in both directions (1:1).\n *\n * @template State - The context state object.\n * @template RequestInit - The TypeBox schema of the initialization object.\n * @template ResponseData - The TypeBox schema of the response object.\n * @template ResponseErr - The TypeBox schema of the error object.\n */\nexport interface RpcProcedure<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> {\n type: 'rpc';\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler(param: {\n ctx: ProcedureHandlerContext<State>;\n reqInit: Static<RequestInit>;\n }): Promise<Result<Static<ResponseData>, Static<ResponseErr>>>;\n}\n\n/**\n * Procedure for a client-stream (potentially preceded by an initialization message),\n * single message from server (n:1).\n *\n * @template State - The context state object.\n * @template RequestInit - The TypeBox schema of the initialization object.\n * @template RequestData - The TypeBox schema of the request object.\n * @template ResponseData - The TypeBox schema of the response object.\n * @template ResponseErr - The TypeBox schema of the error object.\n */\nexport interface UploadProcedure<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> {\n type: 'upload';\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler(param: {\n ctx: ProcedureHandlerContext<State>;\n reqInit: Static<RequestInit>;\n reqReadable: Readable<\n Static<RequestData>,\n Static<typeof ReaderErrorSchema>\n >;\n }): Promise<Result<Static<ResponseData>, Static<ResponseErr>>>;\n}\n\n/**\n * Procedure for a single message from client, stream from server (1:n).\n *\n * @template State - The context state object.\n * @template RequestInit - The TypeBox schema of the initialization object.\n * @template ResponseData - The TypeBox schema of the response object.\n * @template ResponseErr - The TypeBox schema of the error object.\n */\nexport interface SubscriptionProcedure<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> {\n type: 'subscription';\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler(param: {\n ctx: ProcedureHandlerContext<State>;\n reqInit: Static<RequestInit>;\n resWritable: Writable<Result<Static<ResponseData>, Static<ResponseErr>>>;\n }): Promise<void | undefined>;\n}\n\n/**\n * Procedure for a bidirectional stream (potentially preceded by an initialization message),\n * (n:n).\n *\n * @template State - The context state object.\n * @template RequestInit - The TypeBox schema of the initialization object.\n * @template RequestData - The TypeBox schema of the request object.\n * @template ResponseData - The TypeBox schema of the response object.\n * @template ResponseErr - The TypeBox schema of the error object.\n */\nexport interface StreamProcedure<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> {\n type: 'stream';\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler(param: {\n ctx: ProcedureHandlerContext<State>;\n reqInit: Static<RequestInit>;\n reqReadable: Readable<\n Static<RequestData>,\n Static<typeof ReaderErrorSchema>\n >;\n resWritable: Writable<Result<Static<ResponseData>, Static<ResponseErr>>>;\n }): Promise<void | undefined>;\n}\n\n/**\n * Defines a Procedure type that can be a:\n * - {@link RpcProcedure} for a single message in both directions (1:1)\n * - {@link UploadProcedure} for a client-stream (potentially preceded by an\n * initialization message)\n * - {@link SubscriptionProcedure} for a single message from client, stream from server (1:n)\n * - {@link StreamProcedure} for a bidirectional stream (potentially preceded by an\n * initialization message)\n *\n * @template State - The TypeBox schema of the state object.\n * @template Ty - The type of the procedure.\n * @template RequestData - The TypeBox schema of the request object.\n * @template RequestInit - The TypeBox schema of the request initialization object, if any.\n * @template ResponseData - The TypeBox schema of the response object.\n */\nexport type Procedure<\n State,\n Ty extends ValidProcType,\n RequestInit extends PayloadType,\n RequestData extends PayloadType | null,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> = { type: Ty } & (RequestData extends PayloadType\n ? Ty extends 'upload'\n ? UploadProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n ResponseErr\n >\n : Ty extends 'stream'\n ? StreamProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n ResponseErr\n >\n : never\n : Ty extends 'rpc'\n ? RpcProcedure<State, RequestInit, ResponseData, ResponseErr>\n : Ty extends 'subscription'\n ? SubscriptionProcedure<State, RequestInit, ResponseData, ResponseErr>\n : never);\n\n/**\n * Represents any {@link Procedure} type.\n *\n * @template State - The context state object. You can provide this to constrain\n * the type of procedures.\n */\nexport type AnyProcedure<State = object> = Procedure<\n State,\n ValidProcType,\n PayloadType,\n PayloadType | null,\n PayloadType,\n ProcedureErrorSchemaType\n>;\n\n/**\n * Represents a map of {@link Procedure}s.\n *\n * @template State - The context state object. You can provide this to constrain\n * the type of procedures.\n */\nexport type ProcedureMap<State = object> = Record<string, AnyProcedure<State>>;\n\n// typescript is funky so with these upcoming procedure constructors, the overloads\n// which handle the `init` case _must_ come first, otherwise the `init` property\n// is not recognized as optional, for some reason\n\n/**\n * Creates an {@link RpcProcedure}.\n */\n// signature: default errors\nfunction rpc<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n>(def: {\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError?: never;\n description?: string;\n handler: RpcProcedure<State, RequestInit, ResponseData, TNever>['handler'];\n}): Branded<RpcProcedure<State, RequestInit, ResponseData, TNever>>;\n\n// signature: explicit errors\nfunction rpc<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n>(def: {\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler: RpcProcedure<\n State,\n RequestInit,\n ResponseData,\n ResponseErr\n >['handler'];\n}): Branded<RpcProcedure<State, RequestInit, ResponseData, ResponseErr>>;\n\n// implementation\nfunction rpc({\n requestInit,\n responseData,\n responseError = Type.Never(),\n description,\n handler,\n}: {\n requestInit: PayloadType;\n responseData: PayloadType;\n responseError?: ProcedureErrorSchemaType;\n description?: string;\n handler: RpcProcedure<\n object,\n PayloadType,\n PayloadType,\n ProcedureErrorSchemaType\n >['handler'];\n}) {\n return {\n ...(description ? { description } : {}),\n type: 'rpc',\n requestInit,\n responseData,\n responseError,\n handler,\n };\n}\n\n/**\n * Creates an {@link UploadProcedure}, optionally with an initialization message.\n */\n// signature: init with default errors\nfunction upload<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n>(def: {\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError?: never;\n description?: string;\n handler: UploadProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n TNever\n >['handler'];\n}): Branded<\n UploadProcedure<State, RequestInit, RequestData, ResponseData, TNever>\n>;\n\n// signature: init with explicit errors\nfunction upload<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n>(def: {\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler: UploadProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n ResponseErr\n >['handler'];\n}): Branded<\n UploadProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr>\n>;\n\n// implementation\nfunction upload({\n requestInit,\n requestData,\n responseData,\n responseError = Type.Never(),\n description,\n handler,\n}: {\n requestInit: PayloadType;\n requestData: PayloadType;\n responseData: PayloadType;\n responseError?: ProcedureErrorSchemaType;\n description?: string;\n handler: UploadProcedure<\n object,\n PayloadType,\n PayloadType,\n PayloadType,\n ProcedureErrorSchemaType\n >['handler'];\n}) {\n return {\n type: 'upload',\n ...(description ? { description } : {}),\n requestInit,\n requestData,\n responseData,\n responseError,\n handler,\n };\n}\n\n/**\n * Creates a {@link SubscriptionProcedure}.\n */\n// signature: default errors\nfunction subscription<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n>(def: {\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError?: never;\n description?: string;\n handler: SubscriptionProcedure<\n State,\n RequestInit,\n ResponseData,\n TNever\n >['handler'];\n}): Branded<SubscriptionProcedure<State, RequestInit, ResponseData, TNever>>;\n\n// signature: explicit errors\nfunction subscription<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n>(def: {\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler: SubscriptionProcedure<\n State,\n RequestInit,\n ResponseData,\n ResponseErr\n >['handler'];\n}): Branded<\n SubscriptionProcedure<State, RequestInit, ResponseData, ResponseErr>\n>;\n\n// implementation\nfunction subscription({\n requestInit,\n responseData,\n responseError = Type.Never(),\n description,\n handler,\n}: {\n requestInit: PayloadType;\n responseData: PayloadType;\n responseError?: ProcedureErrorSchemaType;\n description?: string;\n handler: SubscriptionProcedure<\n object,\n PayloadType,\n PayloadType,\n ProcedureErrorSchemaType\n >['handler'];\n}) {\n return {\n type: 'subscription',\n ...(description ? { description } : {}),\n requestInit,\n responseData,\n responseError,\n handler,\n };\n}\n\n/**\n * Creates a {@link StreamProcedure}, optionally with an initialization message.\n */\n// signature: with default errors\nfunction stream<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n>(def: {\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError?: never;\n description?: string;\n handler: StreamProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n TNever\n >['handler'];\n}): Branded<\n StreamProcedure<State, RequestInit, RequestData, ResponseData, TNever>\n>;\n\n// signature: explicit errors\nfunction stream<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n>(def: {\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler: StreamProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n ResponseErr\n >['handler'];\n}): Branded<\n StreamProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr>\n>;\n\n// implementation\nfunction stream({\n requestInit,\n requestData,\n responseData,\n responseError = Type.Never(),\n description,\n handler,\n}: {\n requestInit: PayloadType;\n requestData: PayloadType;\n responseData: PayloadType;\n responseError?: ProcedureErrorSchemaType;\n description?: string;\n handler: StreamProcedure<\n object,\n PayloadType,\n PayloadType,\n PayloadType,\n ProcedureErrorSchemaType\n >['handler'];\n}) {\n return {\n type: 'stream',\n ...(description ? { description } : {}),\n requestInit,\n requestData,\n responseData,\n responseError,\n handler,\n };\n}\n\n/**\n * Holds the {@link Procedure} creation functions. Use these to create\n * procedures for services. You aren't allowed to create procedures directly.\n */\nexport const Procedure = {\n rpc,\n upload,\n subscription,\n stream,\n};\n","import {\n AnyService,\n ProcErrors,\n ProcInit,\n ProcRequest,\n ProcResponse,\n ProcType,\n AnyServiceSchemaMap,\n InstantiatedServiceSchemaMap,\n} from './services';\nimport {\n OpaqueTransportMessage,\n ControlFlags,\n TransportClientId,\n isStreamClose,\n ControlMessageCloseSchema,\n isStreamCancel,\n closeStreamMessage,\n cancelMessage,\n} from '../transport/message';\nimport { Static } from '@sinclair/typebox';\nimport { Err, Result, AnyResultSchema } from './result';\nimport { EventMap } from '../transport/events';\nimport { Connection } from '../transport/connection';\nimport { Logger } from '../logging';\nimport { createProcTelemetryInfo, getPropagationContext } from '../tracing';\nimport { ClientHandshakeOptions } from './handshake';\nimport { ClientTransport } from '../transport/client';\nimport { generateId } from '../transport/id';\nimport { Readable, ReadableImpl, Writable, WritableImpl } from './streams';\nimport { Value } from '@sinclair/typebox/value';\nimport { PayloadType, ValidProcType } from './procedures';\nimport {\n BaseErrorSchemaType,\n ErrResultSchema,\n CANCEL_CODE,\n ReaderErrorSchema,\n UNEXPECTED_DISCONNECT_CODE,\n} from './errors';\n\nconst ReaderErrResultSchema = ErrResultSchema(ReaderErrorSchema);\n\ninterface CallOptions {\n signal?: AbortSignal;\n}\n\ntype RpcFn<\n Service extends AnyService,\n ProcName extends keyof Service['procedures'],\n> = (\n reqInit: ProcInit<Service, ProcName>,\n options?: CallOptions,\n) => Promise<\n Result<ProcResponse<Service, ProcName>, ProcErrors<Service, ProcName>>\n>;\n\ntype UploadFn<\n Service extends AnyService,\n ProcName extends keyof Service['procedures'],\n> = (\n reqInit: ProcInit<Service, ProcName>,\n options?: CallOptions,\n) => {\n reqWritable: Writable<ProcRequest<Service, ProcName>>;\n finalize: () => Promise<\n Result<ProcResponse<Service, ProcName>, ProcErrors<Service, ProcName>>\n >;\n};\n\ntype StreamFn<\n Service extends AnyService,\n ProcName extends keyof Service['procedures'],\n> = (\n reqInit: ProcInit<Service, ProcName>,\n options?: CallOptions,\n) => {\n reqWritable: Writable<ProcRequest<Service, ProcName>>;\n resReadable: Readable<\n ProcResponse<Service, ProcName>,\n ProcErrors<Service, ProcName>\n >;\n};\n\ntype SubscriptionFn<\n Service extends AnyService,\n ProcName extends keyof Service['procedures'],\n> = (\n reqInit: ProcInit<Service, ProcName>,\n options?: CallOptions,\n) => {\n resReadable: Readable<\n ProcResponse<Service, ProcName>,\n ProcErrors<Service, ProcName>\n >;\n};\n\n/**\n * A helper type to transform an actual service type into a type\n * we can case to in the proxy.\n * @template Service - The type of the Service.\n */\ntype ServiceClient<Service extends AnyService> = {\n [ProcName in keyof Service['procedures']]: ProcType<\n Service,\n ProcName\n > extends 'rpc'\n ? {\n // If your go-to-definition ended up here, you probably meant to\n // go to the procedure name. For example:\n // riverClient.myService.someprocedure.rpc({})\n // click here ^^^^^^^^^^^^^\n rpc: RpcFn<Service, ProcName>;\n }\n : ProcType<Service, ProcName> extends 'upload'\n ? {\n // If your go-to-definition ended up here, you probably meant to\n // go to the procedure name. For example:\n // riverClient.myService.someprocedure.upload({})\n // click here ^^^^^^^^^^^^^\n upload: UploadFn<Service, ProcName>;\n }\n : ProcType<Service, ProcName> extends 'stream'\n ? {\n // If your go-to-definition ended up here, you probably meant to\n // go to the procedure name. For example:\n // riverClient.myService.someprocedure.stream({})\n // click here ^^^^^^^^^^^^^\n stream: StreamFn<Service, ProcName>;\n }\n : ProcType<Service, ProcName> extends 'subscription'\n ? {\n // If your go-to-definition ended up here, you probably meant to\n // go to the procedure name. For example:\n // riverClient.myService.subscribe.stream({})\n // click here ^^^^^^^^^^^^^\n subscribe: SubscriptionFn<Service, ProcName>;\n }\n : never;\n};\n\n/**\n * Defines a type that represents a client for a server with a set of services.\n * @template Srv - The type of the server.\n */\nexport type Client<\n Services extends AnyServiceSchemaMap,\n IS extends\n InstantiatedServiceSchemaMap<Services> = InstantiatedServiceSchemaMap<Services>,\n> = {\n [SvcName in keyof IS]: ServiceClient<IS[SvcName]>;\n};\n\ninterface ProxyCallbackOptions {\n path: Array<string>;\n args: Array<unknown>;\n}\n\ntype ProxyCallback = (opts: ProxyCallbackOptions) => unknown;\n/* eslint-disable-next-line @typescript-eslint/no-empty-function */\nconst noop = () => {};\n\nfunction _createRecursiveProxy(\n callback: ProxyCallback,\n path: Array<string>,\n): unknown {\n const proxy: unknown = new Proxy(noop, {\n // property access, recurse and add field to path\n get(_obj, key) {\n if (typeof key !== 'string') return undefined;\n\n return _createRecursiveProxy(callback, [...path, key]);\n },\n // hit the end, let's invoke the handler\n apply(_target, _this, args) {\n return callback({\n path,\n args,\n });\n },\n });\n\n return proxy;\n}\n\nexport interface ClientOptions {\n connectOnInvoke: boolean;\n eagerlyConnect: boolean;\n}\n\nconst defaultClientOptions: ClientOptions = {\n connectOnInvoke: true,\n eagerlyConnect: true,\n};\n\n/**\n * Creates a client for a given server using the provided transport.\n * Note that the client only needs the type of the server, not the actual\n * server definition itself.\n *\n * This relies on a proxy to dynamically create the client, so the client\n * will be typed as if it were the actual server with the appropriate services\n * and procedures.\n *\n * @template Srv - The type of the server.\n * @param {Transport} transport - The transport to use for communication.\n * @param {TransportClientId} serverId - The ID of the server to connect to.\n * @param {Partial<ClientOptions>} providedClientOptions - The options for the client.\n * @returns The client for the server.\n */\nexport function createClient<ServiceSchemaMap extends AnyServiceSchemaMap>(\n transport: ClientTransport<Connection>,\n serverId: TransportClientId,\n providedClientOptions: Partial<\n ClientOptions & {\n handshakeOptions: ClientHandshakeOptions;\n }\n > = {},\n): Client<ServiceSchemaMap> {\n if (providedClientOptions.handshakeOptions) {\n transport.extendHandshake(providedClientOptions.handshakeOptions);\n }\n\n const clientOptions = { ...defaultClientOptions, ...providedClientOptions };\n if (clientOptions.eagerlyConnect) {\n transport.connect(serverId);\n }\n\n return _createRecursiveProxy((opts) => {\n const [serviceName, procName, procMethod] = [...opts.path];\n if (!(serviceName && procName && procMethod)) {\n throw new Error(\n 'invalid river call, ensure the service and procedure you are calling exists',\n );\n }\n\n const [init, callOptions] = opts.args;\n\n if (clientOptions.connectOnInvoke && !transport.sessions.has(serverId)) {\n transport.connect(serverId);\n }\n\n if (\n procMethod !== 'rpc' &&\n procMethod !== 'subscribe' &&\n procMethod !== 'stream' &&\n procMethod !== 'upload'\n ) {\n throw new Error(\n `invalid river call, unknown procedure type ${procMethod}`,\n );\n }\n\n return handleProc(\n procMethod === 'subscribe' ? 'subscription' : procMethod,\n transport,\n serverId,\n init,\n serviceName,\n procName,\n callOptions ? (callOptions as CallOptions).signal : undefined,\n );\n }, []) as Client<ServiceSchemaMap>;\n}\n\ntype AnyProcReturn =\n | ReturnType<RpcFn<AnyService, string>>\n | ReturnType<UploadFn<AnyService, string>>\n | ReturnType<StreamFn<AnyService, string>>\n | ReturnType<SubscriptionFn<AnyService, string>>;\n\nfunction handleProc(\n procType: ValidProcType,\n transport: ClientTransport<Connection>,\n serverId: TransportClientId,\n init: Static<PayloadType>,\n serviceName: string,\n procedureName: string,\n abortSignal?: AbortSignal,\n): AnyProcReturn {\n const session =\n transport.sessions.get(serverId) ??\n transport.createUnconnectedSession(serverId);\n const sessionScopedSend = transport.getSessionBoundSendFn(\n serverId,\n session.id,\n );\n\n const procClosesWithInit = procType === 'rpc' || procType === 'subscription';\n const streamId = generateId();\n const { span, ctx } = createProcTelemetryInfo(\n transport,\n procType,\n serviceName,\n procedureName,\n streamId,\n );\n let cleanClose = true;\n const reqWritable = new WritableImpl<Static<PayloadType>>({\n writeCb: (rawIn) => {\n sessionScopedSend({\n streamId,\n payload: rawIn,\n controlFlags: 0,\n });\n },\n // close callback\n closeCb: () => {\n span.addEvent('reqWritable closed');\n\n if (!procClosesWithInit && cleanClose) {\n sessionScopedSend(closeStreamMessage(streamId));\n }\n\n if (resReadable.isClosed()) {\n cleanup();\n }\n },\n });\n\n const resReadable = new ReadableImpl<\n Static<PayloadType>,\n Static<BaseErrorSchemaType>\n >();\n const closeReadable = () => {\n resReadable._triggerClose();\n\n span.addEvent('resReadable closed');\n\n if (reqWritable.isClosed()) {\n cleanup();\n }\n };\n\n function cleanup() {\n transport.removeEventListener('message', onMessage);\n transport.removeEventListener('sessionStatus', onSessionStatus);\n abortSignal?.removeEventListener('abort', onClientCancel);\n span.end();\n }\n\n function onClientCancel() {\n if (resReadable.isClosed() && reqWritable.isClosed()) {\n return;\n }\n\n span.addEvent('sending cancel');\n cleanClose = false;\n\n if (!resReadable.isClosed()) {\n resReadable._pushValue(\n Err({\n code: CANCEL_CODE,\n message: 'cancelled by client',\n }),\n );\n closeReadable();\n }\n\n reqWritable.close();\n sessionScopedSend(\n cancelMessage(\n streamId,\n Err({\n code: CANCEL_CODE,\n message: 'cancelled by client',\n }),\n ),\n );\n }\n\n function onMessage(msg: OpaqueTransportMessage) {\n if (msg.streamId !== streamId) return;\n if (msg.to !== transport.clientId) {\n transport.log?.error('got stream message from unexpected client', {\n clientId: transport.clientId,\n transportMessage: msg,\n });\n\n return;\n }\n\n if (isStreamCancel(msg.controlFlags)) {\n cleanClose = false;\n\n span.addEvent('received cancel');\n let cancelResult: Static<typeof ReaderErrResultSchema>;\n\n if (Value.Check(ReaderErrResultSchema, msg.payload)) {\n cancelResult = msg.payload;\n } else {\n cancelResult = Err({\n code: CANCEL_CODE,\n message: 'stream cancelled with invalid payload',\n });\n transport.log?.error(\n 'got stream cancel without a valid protocol error',\n {\n clientId: transport.clientId,\n transportMessage: msg,\n validationErrors: [\n ...Value.Errors(ReaderErrResultSchema, msg.payload),\n ],\n },\n );\n }\n\n if (!resReadable.isClosed()) {\n resReadable._pushValue(cancelResult);\n closeReadable();\n }\n\n reqWritable.close();\n\n return;\n }\n\n if (resReadable.isClosed()) {\n span.recordException('received message after response stream is closed');\n\n transport.log?.error('received message after response stream is closed', {\n clientId: transport.clientId,\n transportMessage: msg,\n });\n\n return;\n }\n\n if (!Value.Check(ControlMessageCloseSchema, msg.payload)) {\n if (Value.Check(AnyResultSchema, msg.payload)) {\n resReadable._pushValue(msg.payload);\n } else {\n transport.log?.error(\n 'Got non-control payload, but was not a valid result',\n {\n clientId: transport.clientId,\n transportMessage: msg,\n validationErrors: [...Value.Errors(AnyResultSchema, msg.payload)],\n },\n );\n }\n }\n\n if (isStreamClose(msg.controlFlags)) {\n span.addEvent('received response close');\n\n if (resReadable.isClosed()) {\n transport.log?.error(\n 'received stream close but readable was already closed',\n );\n } else {\n closeReadable();\n }\n }\n }\n\n function onSessionStatus(evt: EventMap['sessionStatus']) {\n if (\n evt.status !== 'disconnect' ||\n evt.session.to !== serverId ||\n session.id !== evt.session.id\n ) {\n return;\n }\n\n cleanClose = false;\n if (!resReadable.isClosed()) {\n resReadable._pushValue(\n Err({\n code: UNEXPECTED_DISCONNECT_CODE,\n message: `${serverId} unexpectedly disconnected`,\n }),\n );\n closeReadable();\n }\n\n reqWritable.close();\n }\n\n abortSignal?.addEventListener('abort', onClientCancel);\n transport.addEventListener('message', onMessage);\n transport.addEventListener('sessionStatus', onSessionStatus);\n\n sessionScopedSend({\n streamId,\n serviceName,\n procedureName,\n tracing: getPropagationContext(ctx),\n payload: init,\n controlFlags: procClosesWithInit\n ? ControlFlags.StreamOpenBit | ControlFlags.StreamClosedBit\n : ControlFlags.StreamOpenBit,\n });\n\n if (procClosesWithInit) {\n reqWritable.close();\n }\n\n if (procType === 'subscription') {\n return {\n resReadable: resReadable,\n };\n }\n\n if (procType === 'rpc') {\n return getSingleMessage(resReadable, transport.log);\n }\n\n if (procType === 'upload') {\n let didFinalize = false;\n\n return {\n reqWritable: reqWritable,\n finalize: () => {\n if (didFinalize) {\n throw new Error('upload stream already finalized');\n }\n\n didFinalize = true;\n\n if (!reqWritable.isClosed()) {\n reqWritable.close();\n }\n\n return getSingleMessage(resReadable, transport.log);\n },\n };\n }\n\n // good ol' `stream` procType\n return {\n resReadable: resReadable,\n reqWritable: reqWritable,\n };\n}\n\n/**\n * Waits for a message in the response AND the server to close.\n * Logs an error if we receive multiple messages.\n * Used in RPC and Upload.\n */\nasync function getSingleMessage(\n resReadable: Readable<unknown, Static<BaseErrorSchemaType>>,\n log?: Logger,\n): Promise<Result<unknown, Static<BaseErrorSchemaType>>> {\n const ret = await resReadable.collect();\n\n if (ret.length > 1) {\n log?.error('Expected single message from server, got multiple');\n }\n\n return ret[0];\n}\n","import { Static, Type } from '@sinclair/typebox';\nimport { PayloadType, AnyProcedure } from './procedures';\nimport {\n ReaderErrorSchema,\n UNCAUGHT_ERROR_CODE,\n UNEXPECTED_DISCONNECT_CODE,\n CANCEL_CODE,\n INVALID_REQUEST_CODE,\n BaseErrorSchemaType,\n ErrResultSchema,\n} from './errors';\nimport {\n AnyService,\n InstantiatedServiceSchemaMap,\n AnyServiceSchemaMap,\n} from './services';\nimport {\n ControlMessagePayloadSchema,\n OpaqueTransportMessage,\n isStreamClose,\n isStreamOpen,\n ControlFlags,\n isStreamCancel,\n closeStreamMessage,\n cancelMessage,\n ProtocolVersion,\n TransportClientId,\n} from '../transport/message';\nimport {\n ServiceContext,\n ProcedureHandlerContext,\n ParsedMetadata,\n} from './context';\nimport { Logger } from '../logging/log';\nimport { Value, ValueError } from '@sinclair/typebox/value';\nimport { Err, Result, Ok, ErrResult } from './result';\nimport { EventMap } from '../transport/events';\nimport { coerceErrorString } from '../util/stringify';\nimport { Span, SpanStatusCode } from '@opentelemetry/api';\nimport { createHandlerSpan, PropagationContext } from '../tracing';\nimport { ServerHandshakeOptions } from './handshake';\nimport { Connection } from '../transport/connection';\nimport { ServerTransport } from '../transport/server';\nimport { ReadableImpl, WritableImpl } from './streams';\nimport { IdentifiedSession } from '../transport/sessionStateMachine/common';\nimport { SessionBoundSendFn } from '../transport/transport';\n\ntype StreamId = string;\n\n/**\n * A schema for cancel payloads sent from the client\n */\nconst CancelResultSchema = ErrResultSchema(\n Type.Object({\n code: Type.Literal(CANCEL_CODE),\n message: Type.String(),\n }),\n);\n\n/**\n * Represents a server with a set of services. Use {@link createServer} to create it.\n * @template Services - The type of services provided by the server.\n */\nexport interface Server<Services extends AnyServiceSchemaMap> {\n /**\n * Services defined for this server.\n */\n services: InstantiatedServiceSchemaMap<Services>;\n /**\n * A set of stream ids that are currently open.\n */\n streams: Map<StreamId, ProcStream>;\n}\n\ntype ProcHandlerReturn = Promise<(() => void) | void>;\n\ninterface StreamInitProps {\n // msg derived\n streamId: StreamId;\n procedureName: string;\n serviceName: string;\n initPayload: Static<PayloadType>;\n tracingCtx: PropagationContext | undefined;\n // true if the first and only message is the init payload\n // i.e. rpc and subscription\n procClosesWithInit: boolean;\n\n // server level\n serviceContext: ServiceContext & { state: object };\n procedure: AnyProcedure;\n sessionMetadata: ParsedMetadata;\n\n // transport level\n initialSession: IdentifiedSession;\n\n // TODO remove once clients migrate to v2\n passInitAsDataForBackwardsCompat: boolean;\n}\n\ninterface ProcStream {\n streamId: StreamId;\n from: TransportClientId;\n procedureName: string;\n serviceName: string;\n sessionMetadata: ParsedMetadata;\n procedure: AnyProcedure;\n handleMsg: (msg: OpaqueTransportMessage) => void;\n handleSessionDisconnect: () => void;\n}\n\nclass RiverServer<Services extends AnyServiceSchemaMap>\n implements Server<Services>\n{\n private transport: ServerTransport<Connection>;\n private contextMap: Map<AnyService, ServiceContext & { state: object }>;\n private log?: Logger;\n\n /**\n * We create a tombstones for streams cancelled by the server\n * so that we don't hit errors when the client has inflight\n * requests it sent before it saw the cancel.\n * We track cancelled streams for every client separately, so\n * that bad clients don't affect good clients.\n */\n private serverCancelledStreams: Map<TransportClientId, LRUSet<StreamId>>;\n private maxCancelledStreamTombstonesPerSession: number;\n\n public streams: Map<StreamId, ProcStream>;\n public services: InstantiatedServiceSchemaMap<Services>;\n\n constructor(\n transport: ServerTransport<Connection>,\n services: Services,\n handshakeOptions?: ServerHandshakeOptions,\n extendedContext?: Omit<ServiceContext, 'state'>,\n maxCancelledStreamTombstonesPerSession = 200,\n ) {\n const instances: Record<string, AnyService> = {};\n\n this.services = instances as InstantiatedServiceSchemaMap<Services>;\n this.contextMap = new Map();\n\n for (const [name, service] of Object.entries(services)) {\n const instance = service.instantiate(extendedContext ?? {});\n instances[name] = instance;\n\n this.contextMap.set(instance, {\n ...extendedContext,\n state: instance.state,\n });\n }\n\n if (handshakeOptions) {\n transport.extendHandshake(handshakeOptions);\n }\n\n this.transport = transport;\n this.streams = new Map();\n this.serverCancelledStreams = new Map();\n this.maxCancelledStreamTombstonesPerSession =\n maxCancelledStreamTombstonesPerSession;\n this.log = transport.log;\n\n const handleCreatingNewStreams = (message: EventMap['message']) => {\n if (message.to !== this.transport.clientId) {\n this.log?.info(\n `got msg with destination that isn't this server, ignoring`,\n {\n clientId: this.transport.clientId,\n transportMessage: message,\n },\n );\n\n return;\n }\n\n const streamId = message.streamId;\n const stream = this.streams.get(streamId);\n if (stream) {\n stream.handleMsg(message);\n\n return;\n }\n\n // if this is a cancelled stream it's safe to ignore\n if (this.serverCancelledStreams.get(message.from)?.has(streamId)) {\n return;\n }\n\n // if this stream init request is invalid, don't bother creating a stream\n // and tell the client to cancel\n const newStreamProps = this.validateNewProcStream(message);\n if (!newStreamProps) {\n return;\n }\n\n // if its not a cancelled stream, validate and create a new stream\n const newStream = this.createNewProcStream({\n ...newStreamProps,\n ...message,\n });\n this.streams.set(streamId, newStream);\n };\n\n const handleSessionStatus = (evt: EventMap['sessionStatus']) => {\n if (evt.status !== 'disconnect') return;\n\n const disconnectedClientId = evt.session.to;\n this.log?.info(\n `got session disconnect from ${disconnectedClientId}, cleaning up streams`,\n evt.session.loggingMetadata,\n );\n\n for (const stream of this.streams.values()) {\n if (stream.from === disconnectedClientId) {\n stream.handleSessionDisconnect();\n }\n }\n\n this.serverCancelledStreams.delete(disconnectedClientId);\n };\n\n const handleTransportStatus = (evt: EventMap['transportStatus']) => {\n if (evt.status !== 'closed') return;\n this.transport.removeEventListener('message', handleCreatingNewStreams);\n this.transport.removeEventListener('sessionStatus', handleSessionStatus);\n this.transport.removeEventListener(\n 'transportStatus',\n handleTransportStatus,\n );\n };\n\n this.transport.addEventListener('message', handleCreatingNewStreams);\n this.transport.addEventListener('sessionStatus', handleSessionStatus);\n this.transport.addEventListener('transportStatus', handleTransportStatus);\n }\n\n private createNewProcStream(props: StreamInitProps): ProcStream {\n const {\n streamId,\n initialSession,\n procedureName,\n serviceName,\n procedure,\n sessionMetadata,\n serviceContext,\n initPayload,\n tracingCtx,\n procClosesWithInit,\n passInitAsDataForBackwardsCompat,\n } = props;\n\n const {\n to: from,\n loggingMetadata,\n protocolVersion,\n id: sessionId,\n } = initialSession;\n\n let cleanClose = true;\n const onMessage = (msg: OpaqueTransportMessage) => {\n if (msg.from !== from) {\n this.log?.error('got stream message from unexpected client', {\n ...loggingMetadata,\n transportMessage: msg,\n tags: ['invariant-violation'],\n });\n\n return;\n }\n\n if (isStreamCancelBackwardsCompat(msg.controlFlags, protocolVersion)) {\n let cancelResult: Static<typeof CancelResultSchema>;\n if (Value.Check(CancelResultSchema, msg.payload)) {\n cancelResult = msg.payload;\n } else {\n // If the payload is unexpected, then we just construct our own cancel result\n cancelResult = Err({\n code: CANCEL_CODE,\n message: 'stream cancelled, client sent invalid payload',\n });\n this.log?.warn('got stream cancel without a valid protocol error', {\n ...loggingMetadata,\n transportMessage: msg,\n validationErrors: [\n ...Value.Errors(CancelResultSchema, msg.payload),\n ],\n tags: ['invalid-request'],\n });\n }\n\n if (!reqReadable.isClosed()) {\n reqReadable._pushValue(cancelResult);\n closeReadable();\n }\n\n resWritable.close();\n\n return;\n }\n\n if (reqReadable.isClosed()) {\n this.log?.warn('received message after request stream is closed', {\n ...loggingMetadata,\n transportMessage: msg,\n tags: ['invalid-request'],\n });\n\n onServerCancel({\n code: INVALID_REQUEST_CODE,\n message: 'received message after request stream is closed',\n });\n\n return;\n }\n\n // normal request data for upload or stream\n if (\n 'requestData' in procedure &&\n Value.Check(procedure.requestData, msg.payload)\n ) {\n reqReadable._pushValue(Ok(msg.payload));\n\n if (isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)) {\n // It's atypical for any of our post-v1 clients to send a close with a\n // request payload, but it's technically legal, so we'll handle it.\n closeReadable();\n }\n\n return;\n }\n\n if (\n Value.Check(ControlMessagePayloadSchema, msg.payload) &&\n isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)\n ) {\n // Clients typically send this shape of close for stream and upload\n // after they're done.\n closeReadable();\n\n return;\n }\n\n // We couldn't make sense of the message, it's probably a bad request\n let validationErrors: Array<ValueError>;\n let errMessage: string;\n if ('requestData' in procedure) {\n errMessage = 'expected requestData or control payload';\n validationErrors = [\n ...Value.Errors(procedure.responseData, msg.payload),\n ];\n } else {\n validationErrors = [\n ...Value.Errors(ControlMessagePayloadSchema, msg.payload),\n ];\n errMessage = 'expected control payload';\n }\n\n this.log?.warn(errMessage, {\n ...loggingMetadata,\n transportMessage: msg,\n validationErrors,\n tags: ['invalid-request'],\n });\n\n onServerCancel({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n });\n };\n\n const procStream: ProcStream = {\n from: from,\n streamId,\n procedureName,\n serviceName,\n sessionMetadata,\n procedure,\n handleMsg: onMessage,\n handleSessionDisconnect: () => {\n cleanClose = false;\n const errPayload = {\n code: UNEXPECTED_DISCONNECT_CODE,\n message: 'client unexpectedly disconnected',\n } as const;\n\n if (!reqReadable.isClosed()) {\n reqReadable._pushValue(Err(errPayload));\n closeReadable();\n }\n\n resWritable.close();\n },\n };\n\n const sessionScopedSend = this.transport.getSessionBoundSendFn(\n from,\n sessionId,\n );\n\n const cancelStream = (\n streamId: StreamId,\n payload: ErrResult<Static<typeof ReaderErrorSchema>>,\n ) => {\n this.cancelStream(from, sessionScopedSend, streamId, payload);\n };\n\n const onServerCancel = (e: Static<typeof ReaderErrorSchema>) => {\n if (reqReadable.isClosed() && resWritable.isClosed()) {\n // Everything already closed, no-op.\n return;\n }\n\n cleanClose = false;\n const result = Err(e);\n if (!reqReadable.isClosed()) {\n reqReadable._pushValue(result);\n closeReadable();\n }\n\n resWritable.close();\n cancelStream(streamId, result);\n };\n\n const finishedController = new AbortController();\n const cleanup = () => {\n finishedController.abort();\n this.streams.delete(streamId);\n };\n\n const procClosesWithResponse =\n procedure.type === 'rpc' || procedure.type === 'upload';\n\n const reqReadable = new ReadableImpl<\n Static<PayloadType>,\n Static<typeof ReaderErrorSchema>\n >();\n const closeReadable = () => {\n reqReadable._triggerClose();\n\n // TODO remove once clients migrate to v2\n if (protocolVersion === 'v1.1') {\n // in v1.1 a close in either direction should close everything\n // for upload/rpc it will handle the close after it responds\n if (!procClosesWithResponse && !resWritable.isClosed()) {\n resWritable.close();\n }\n }\n\n if (resWritable.isClosed()) {\n cleanup();\n }\n };\n\n if (passInitAsDataForBackwardsCompat) {\n reqReadable._pushValue(Ok(initPayload));\n }\n\n const resWritable = new WritableImpl<\n Result<Static<PayloadType>, Static<BaseErrorSchemaType>>\n >({\n writeCb: (response) => {\n sessionScopedSend({\n streamId,\n controlFlags: procClosesWithResponse\n ? getStreamCloseBackwardsCompat(protocolVersion)\n : 0,\n payload: response,\n });\n\n if (procClosesWithResponse) {\n resWritable.close();\n }\n },\n // close callback\n closeCb: () => {\n if (!procClosesWithResponse && cleanClose) {\n // we ended, send a close bit back to the client\n // also, if the client has disconnected, we don't need to send a close\n\n const message = closeStreamMessage(streamId);\n // TODO remove once clients migrate to v2\n message.controlFlags = getStreamCloseBackwardsCompat(protocolVersion);\n\n sessionScopedSend(message);\n }\n\n // TODO remove once clients migrate to v2\n if (protocolVersion === 'v1.1') {\n // in v1.1 a close in either direction should close everything\n if (!reqReadable.isClosed()) {\n closeReadable();\n }\n }\n\n if (reqReadable.isClosed()) {\n cleanup();\n }\n },\n });\n\n const onHandlerError = (err: unknown, span: Span) => {\n const errorMsg = coerceErrorString(err);\n\n span.recordException(err instanceof Error ? err : new Error(errorMsg));\n span.setStatus({ code: SpanStatusCode.ERROR });\n\n this.log?.error(\n `${serviceName}.${procedureName} handler threw an uncaught error`,\n {\n ...loggingMetadata,\n transportMessage: {\n procedureName,\n serviceName,\n },\n extras: {\n error: errorMsg,\n },\n },\n );\n\n onServerCancel({\n code: UNCAUGHT_ERROR_CODE,\n message: errorMsg,\n });\n };\n\n // if the init message has a close flag then we know this stream\n // only consists of an init message and we shouldn't expect follow up data\n if (procClosesWithInit) {\n closeReadable();\n } else if (procedure.type === 'rpc' || procedure.type === 'subscription') {\n // Though things can work just fine if they eventually follow up with a stream\n // control message with a close bit set, it's an unusual client implementation!\n this.log?.warn('sent an init without a stream close', loggingMetadata);\n }\n\n const handlerContext: ProcedureHandlerContext<object> = {\n ...serviceContext,\n from: from,\n sessionId,\n metadata: sessionMetadata,\n cancel: () => {\n onServerCancel({\n code: CANCEL_CODE,\n message: 'cancelled by server procedure handler',\n });\n },\n signal: finishedController.signal,\n };\n\n switch (procedure.type) {\n case 'rpc':\n void createHandlerSpan(\n procedure.type,\n serviceName,\n procedureName,\n streamId,\n tracingCtx,\n async (span): ProcHandlerReturn => {\n try {\n const responsePayload = await procedure.handler({\n ctx: handlerContext,\n reqInit: initPayload,\n });\n\n if (resWritable.isClosed()) {\n // A disconnect happened\n return;\n }\n\n resWritable.write(responsePayload);\n } catch (err) {\n onHandlerError(err, span);\n } finally {\n span.end();\n }\n },\n );\n break;\n case 'stream':\n void createHandlerSpan(\n procedure.type,\n serviceName,\n procedureName,\n streamId,\n tracingCtx,\n async (span): ProcHandlerReturn => {\n try {\n await procedure.handler({\n ctx: handlerContext,\n reqInit: initPayload,\n reqReadable,\n resWritable,\n });\n } catch (err) {\n onHandlerError(err, span);\n } finally {\n span.end();\n }\n },\n );\n\n break;\n case 'subscription':\n void createHandlerSpan(\n procedure.type,\n serviceName,\n procedureName,\n streamId,\n tracingCtx,\n async (span): ProcHandlerReturn => {\n try {\n await procedure.handler({\n ctx: handlerContext,\n reqInit: initPayload,\n resWritable: resWritable,\n });\n } catch (err) {\n onHandlerError(err, span);\n } finally {\n span.end();\n }\n },\n );\n break;\n case 'upload':\n void createHandlerSpan(\n procedure.type,\n serviceName,\n procedureName,\n streamId,\n tracingCtx,\n async (span): ProcHandlerReturn => {\n try {\n const responsePayload = await procedure.handler({\n ctx: handlerContext,\n reqInit: initPayload,\n reqReadable: reqReadable,\n });\n\n if (resWritable.isClosed()) {\n // A disconnect happened\n return;\n }\n\n resWritable.write(responsePayload);\n } catch (err) {\n onHandlerError(err, span);\n } finally {\n span.end();\n }\n },\n );\n\n break;\n }\n\n return procStream;\n }\n\n private getContext(service: AnyService, serviceName: string) {\n const context = this.contextMap.get(service);\n if (!context) {\n const err = `no context found for ${serviceName}`;\n this.log?.error(err, {\n clientId: this.transport.clientId,\n tags: ['invariant-violation'],\n });\n throw new Error(err);\n }\n\n return context;\n }\n\n private validateNewProcStream(\n initMessage: OpaqueTransportMessage,\n ): StreamInitProps | null {\n // lifetime safety: this is a sync function so this session cant transition\n // to another state before we finish\n const session = this.transport.sessions.get(initMessage.from);\n if (!session) {\n // this should be impossible, how did we receive a message from a session that doesn't exist?\n // log anyways\n this.log?.error(`couldn't find session for ${initMessage.from}`, {\n clientId: this.transport.clientId,\n transportMessage: initMessage,\n tags: ['invariant-violation'],\n });\n\n return null;\n }\n\n const sessionScopedSend = this.transport.getSessionBoundSendFn(\n initMessage.from,\n session.id,\n );\n\n const cancelStream = (\n streamId: StreamId,\n payload: ErrResult<Static<typeof ReaderErrorSchema>>,\n ) => {\n this.cancelStream(initMessage.from, sessionScopedSend, streamId, payload);\n };\n\n const sessionMetadata = this.transport.sessionHandshakeMetadata.get(\n session.to,\n );\n\n if (!sessionMetadata) {\n const errMessage = `session doesn't have handshake metadata`;\n this.log?.error(errMessage, {\n ...session.loggingMetadata,\n tags: ['invariant-violation'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: UNCAUGHT_ERROR_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n if (!isStreamOpen(initMessage.controlFlags)) {\n const errMessage = `can't create a new procedure stream from a message that doesn't have the stream open bit set`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n clientId: this.transport.clientId,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n if (!initMessage.serviceName) {\n const errMessage = `missing service name in stream open message`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n if (!initMessage.procedureName) {\n const errMessage = `missing procedure name in stream open message`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n if (!(initMessage.serviceName in this.services)) {\n const errMessage = `couldn't find service ${initMessage.serviceName}`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n clientId: this.transport.clientId,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n const service = this.services[initMessage.serviceName];\n if (!(initMessage.procedureName in service.procedures)) {\n const errMessage = `couldn't find a matching procedure for ${initMessage.serviceName}.${initMessage.procedureName}`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n const serviceContext = this.getContext(service, initMessage.serviceName);\n\n const procedure: AnyProcedure =\n service.procedures[initMessage.procedureName];\n\n if (!['rpc', 'upload', 'stream', 'subscription'].includes(procedure.type)) {\n this.log?.error(\n `got request for invalid procedure type ${procedure.type} at ${initMessage.serviceName}.${initMessage.procedureName}`,\n {\n ...session.loggingMetadata,\n transportMessage: initMessage,\n tags: ['invariant-violation'],\n },\n );\n\n return null;\n }\n\n let passInitAsDataForBackwardsCompat = false;\n if (\n session.protocolVersion === 'v1.1' &&\n (procedure.type === 'upload' || procedure.type === 'stream') &&\n Value.Check(procedure.requestData, initMessage.payload) &&\n Value.Check(procedure.requestInit, {})\n ) {\n // TODO remove once clients migrate to v2\n // In v1.1 sometimes the first message is not `init`, but instead it's the `input`\n // this backwards compatibility path requires procedures to define their `init` as\n // an empty-object-compatible-schema (i.e. either actually empty or optional values)\n // The reason we don't check if `init` is satisified here is because false positives\n // are easy to hit, we'll err on the side of caution and treat it as a request, servers\n // that expect v1.1 clients should handle this case themselves.\n passInitAsDataForBackwardsCompat = true;\n } else if (!Value.Check(procedure.requestInit, initMessage.payload)) {\n const errMessage = `procedure init failed validation`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n clientId: this.transport.clientId,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n return {\n initialSession: session,\n streamId: initMessage.streamId,\n procedureName: initMessage.procedureName,\n serviceName: initMessage.serviceName,\n tracingCtx: initMessage.tracing,\n initPayload: initMessage.payload,\n sessionMetadata,\n procedure,\n serviceContext,\n procClosesWithInit: isStreamCloseBackwardsCompat(\n initMessage.controlFlags,\n session.protocolVersion,\n ),\n passInitAsDataForBackwardsCompat,\n };\n }\n\n cancelStream(\n to: TransportClientId,\n sessionScopedSend: SessionBoundSendFn,\n streamId: StreamId,\n payload: ErrResult<Static<typeof ReaderErrorSchema>>,\n ) {\n let cancelledStreamsInSession = this.serverCancelledStreams.get(to);\n if (!cancelledStreamsInSession) {\n cancelledStreamsInSession = new LRUSet(\n this.maxCancelledStreamTombstonesPerSession,\n );\n\n this.serverCancelledStreams.set(to, cancelledStreamsInSession);\n }\n\n cancelledStreamsInSession.add(streamId);\n const msg = cancelMessage(streamId, payload);\n sessionScopedSend(msg);\n }\n}\n\nclass LRUSet<T> {\n private items: Set<T>;\n private maxItems: number;\n\n constructor(maxItems: number) {\n this.items = new Set();\n this.maxItems = maxItems;\n }\n\n add(item: T) {\n if (this.items.has(item)) {\n this.items.delete(item);\n } else if (this.items.size >= this.maxItems) {\n const first = this.items.values().next();\n if (!first.done) {\n this.items.delete(first.value);\n }\n }\n this.items.add(item);\n }\n\n has(item: T) {\n return this.items.has(item);\n }\n}\n\n// TODO remove once clients migrate to v2\nfunction isStreamCancelBackwardsCompat(\n controlFlags: ControlFlags,\n protocolVersion: ProtocolVersion,\n) {\n if (protocolVersion === 'v1.1') {\n // in 1.1 we don't have abort\n return false;\n }\n\n return isStreamCancel(controlFlags);\n}\n\n// TODO remove once clients migrate to v2\nfunction isStreamCloseBackwardsCompat(\n controlFlags: ControlFlags,\n protocolVersion: ProtocolVersion,\n) {\n if (protocolVersion === 'v1.1') {\n // in v1.1 the bits for close is what we use for cancel now\n return isStreamCancel(controlFlags);\n }\n\n return isStreamClose(controlFlags);\n}\n\n// TODO remove once clients migrate to v2\nfunction getStreamCloseBackwardsCompat(protocolVersion: ProtocolVersion) {\n if (protocolVersion === 'v1.1') {\n // in v1.1 the bits for close is what we use for cancel now\n return ControlFlags.StreamCancelBit;\n }\n\n return ControlFlags.StreamClosedBit;\n}\n\n/**\n * Creates a server instance that listens for incoming messages from a transport and routes them to the appropriate service and procedure.\n * The server tracks the state of each service along with open streams and the extended context object.\n * @param transport - The transport to listen to.\n * @param services - An object containing all the services to be registered on the server.\n * @param handshakeOptions - An optional object containing additional handshake options to be passed to the transport.\n * @param extendedContext - An optional object containing additional context to be passed to all services.\n * @returns A promise that resolves to a server instance with the registered services.\n */\nexport function createServer<Services extends AnyServiceSchemaMap>(\n transport: ServerTransport<Connection>,\n services: Services,\n providedServerOptions?: Partial<{\n handshakeOptions?: ServerHandshakeOptions;\n extendedContext?: Omit<ServiceContext, 'state'>;\n /**\n * Maximum number of cancelled streams to keep track of to avoid\n * cascading stream errors.\n */\n maxCancelledStreamTombstonesPerSession?: number;\n }>,\n): Server<Services> {\n return new RiverServer(\n transport,\n services,\n providedServerOptions?.handshakeOptions,\n providedServerOptions?.extendedContext,\n providedServerOptions?.maxCancelledStreamTombstonesPerSession,\n );\n}\n","import { Static, TSchema } from '@sinclair/typebox';\nimport { ParsedMetadata } from './context';\nimport { HandshakeErrorCustomHandlerFatalResponseCodes } from '../transport/message';\n\ntype ConstructHandshake<T extends TSchema> = () =>\n | Static<T>\n | Promise<Static<T>>;\n\ntype ValidateHandshake<T extends TSchema> = (\n metadata: Static<T>,\n previousParsedMetadata?: ParsedMetadata,\n) =>\n | Static<typeof HandshakeErrorCustomHandlerFatalResponseCodes>\n | ParsedMetadata\n | Promise<\n | Static<typeof HandshakeErrorCustomHandlerFatalResponseCodes>\n | ParsedMetadata\n >;\n\nexport interface ClientHandshakeOptions<\n MetadataSchema extends TSchema = TSchema,\n> {\n /**\n * Schema for the metadata that the client sends to the server\n * during the handshake.\n */\n schema: MetadataSchema;\n\n /**\n * Gets the {@link HandshakeRequestMetadata} to send to the server.\n */\n construct: ConstructHandshake<MetadataSchema>;\n}\n\nexport interface ServerHandshakeOptions<\n MetadataSchema extends TSchema = TSchema,\n> {\n /**\n * Schema for the metadata that the server receives from the client\n * during the handshake.\n */\n schema: MetadataSchema;\n\n /**\n * Parses the {@link HandshakeRequestMetadata} sent by the client, transforming\n * it into {@link ParsedHandshakeMetadata}.\n *\n * May return `false` if the client should be rejected.\n *\n * @param metadata - The metadata sent by the client.\n * @param session - The session that the client would be associated with.\n * @param isReconnect - Whether the client is reconnecting to the session,\n * or if this is a new session.\n */\n validate: ValidateHandshake<MetadataSchema>;\n}\n\nexport function createClientHandshakeOptions<\n MetadataSchema extends TSchema = TSchema,\n>(\n schema: MetadataSchema,\n construct: ConstructHandshake<MetadataSchema>,\n): ClientHandshakeOptions {\n return { schema, construct };\n}\n\nexport function createServerHandshakeOptions<\n MetadataSchema extends TSchema = TSchema,\n>(\n schema: MetadataSchema,\n validate: ValidateHandshake<MetadataSchema>,\n): ServerHandshakeOptions {\n return { schema, validate: validate as ValidateHandshake<TSchema> };\n}\n"],"mappings":"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","names":["Type","Type","Value","Type","stream","Value","streamId"]}
|
|
1
|
+
{"version":3,"sources":["../../router/services.ts","../../router/procedures.ts","../../router/client.ts","../../router/server.ts","../../router/handshake.ts"],"sourcesContent":["import { Type, TSchema, Static, Kind } from '@sinclair/typebox';\nimport {\n Branded,\n ProcedureMap,\n Unbranded,\n AnyProcedure,\n PayloadType,\n} from './procedures';\nimport { ServiceContext } from './context';\nimport {\n flattenErrorType,\n ProcedureErrorSchemaType,\n ReaderErrorSchema,\n} from './errors';\n\n/**\n * An instantiated service, probably from a {@link ServiceSchema}.\n *\n * You shouldn't construct these directly, use {@link ServiceSchema} instead.\n */\nexport interface Service<\n State extends object,\n Procs extends ProcedureMap<State>,\n> {\n readonly state: State;\n readonly procedures: Procs;\n}\n\n/**\n * Represents any {@link Service} object.\n */\nexport type AnyService = Service<object, ProcedureMap>;\n\n/**\n * Represents any {@link ServiceSchema} object.\n */\nexport type AnyServiceSchema = ServiceSchema<object, ProcedureMap>;\n\n/**\n * A dictionary of {@link ServiceSchema}s, where the key is the service name.\n */\nexport type AnyServiceSchemaMap = Record<string, AnyServiceSchema>;\n\n// This has the secret sauce to keep go to definition working, the structure is\n// somewhat delicate, so be careful when modifying it. Would be nice to add a\n// static test for this.\n/**\n * Takes a {@link AnyServiceSchemaMap} and returns a dictionary of instantiated\n * services.\n */\nexport type InstantiatedServiceSchemaMap<T extends AnyServiceSchemaMap> = {\n [K in keyof T]: T[K] extends ServiceSchema<infer S, infer P>\n ? Service<S, P>\n : never;\n};\n\n/**\n * Helper to get the type definition for a specific handler of a procedure in a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcHandler<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = S['procedures'][ProcName]['handler'];\n\n/**\n * Helper to get the type definition for the procedure init type of a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcInit<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = Static<S['procedures'][ProcName]['requestInit']>;\n\n/**\n * Helper to get the type definition for the procedure request of a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcRequest<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = S['procedures'][ProcName] extends { requestData: PayloadType }\n ? Static<S['procedures'][ProcName]['requestData']>\n : never;\n\n/**\n * Helper to get the type definition for the procedure response of a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcResponse<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = Static<S['procedures'][ProcName]['responseData']>;\n\n/**\n * Helper to get the type definition for the procedure errors of a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcErrors<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> =\n | Static<S['procedures'][ProcName]['responseError']>\n | Static<typeof ReaderErrorSchema>;\n\n/**\n * Helper to get the type of procedure in a service.\n * @template S - The service.\n * @template ProcName - The name of the procedure.\n */\nexport type ProcType<\n S extends AnyService,\n ProcName extends keyof S['procedures'],\n> = S['procedures'][ProcName]['type'];\n\n/**\n * A list of procedures where every procedure is \"branded\", as-in the procedure\n * was created via the {@link Procedure} constructors.\n */\ntype BrandedProcedureMap<State> = Record<string, Branded<AnyProcedure<State>>>;\n\n/**\n * The configuration for a service.\n */\nexport interface ServiceConfiguration<State extends object> {\n /**\n * A factory function for creating a fresh state.\n */\n initializeState: (extendedContext: ServiceContext) => State;\n}\n\n// TODO remove once clients migrate to v2\nexport interface SerializedProcedureSchemaProtocolv1 {\n init?: PayloadType;\n input: PayloadType;\n output: PayloadType;\n errors?: ProcedureErrorSchemaType;\n type: 'rpc' | 'subscription' | 'upload' | 'stream';\n}\n\n// TODO remove once clients migrate to v2\nexport interface SerializedServiceSchemaProtocolv1 {\n procedures: Record<string, SerializedProcedureSchemaProtocolv1>;\n}\n\n// TODO remove once clients migrate to v2\nexport interface SerializedServerSchemaProtocolv1 {\n handshakeSchema?: TSchema;\n services: Record<string, SerializedServiceSchemaProtocolv1>;\n}\n\n// TODO remove once clients migrate to v2\n/**\n * Same as {@link serializeSchema} but with a format that is compatible with\n * protocolv1. This is useful to be able to continue to generate schemas for older\n * clients as they are still supported.\n */\nexport function serializeSchemaV1Compat(\n services: AnyServiceSchemaMap,\n handshakeSchema?: TSchema,\n): SerializedServerSchemaProtocolv1 {\n const serializedServiceObject = Object.entries(services).reduce<\n Record<string, SerializedServiceSchemaProtocolv1>\n >((acc, [name, value]) => {\n acc[name] = value.serializeV1Compat();\n\n return acc;\n }, {});\n\n const schema: SerializedServerSchemaProtocolv1 = {\n services: serializedServiceObject,\n };\n\n if (handshakeSchema) {\n schema.handshakeSchema = Type.Strict(handshakeSchema);\n }\n\n return schema;\n}\n\nexport interface SerializedProcedureSchema {\n init: PayloadType;\n input?: PayloadType;\n output: PayloadType;\n errors?: ProcedureErrorSchemaType;\n type: 'rpc' | 'subscription' | 'upload' | 'stream';\n}\n\nexport interface SerializedServiceSchema {\n procedures: Record<string, SerializedProcedureSchema>;\n}\n\nexport interface SerializedServerSchema {\n handshakeSchema?: TSchema;\n services: Record<string, SerializedServiceSchema>;\n}\n\n/**\n * Serializes a server schema into a plain object that is JSON compatible.\n */\nexport function serializeSchema(\n services: AnyServiceSchemaMap,\n handshakeSchema?: TSchema,\n): SerializedServerSchema {\n const serializedServiceObject = Object.entries(services).reduce<\n Record<string, SerializedServiceSchema>\n >((acc, [name, value]) => {\n acc[name] = value.serialize();\n\n return acc;\n }, {});\n\n const schema: SerializedServerSchema = {\n services: serializedServiceObject,\n };\n\n if (handshakeSchema) {\n schema.handshakeSchema = Type.Strict(handshakeSchema);\n }\n\n return schema;\n}\n\n/**\n * The schema for a {@link Service}. This is used to define a service, specifically\n * its initial state and procedures.\n *\n * There are two ways to define a service:\n * 1. the {@link ServiceSchema.define} static method, which takes a configuration and\n * a list of procedures directly. Use this to ergonomically define a service schema\n * in one go. Good for smaller services, especially if they're stateless.\n * 2. the {@link ServiceSchema.scaffold} static method, which creates a scaffold that\n * can be used to define procedures separately from the configuration. Use this to\n * better organize your service's definition, especially if it's a large service.\n * You can also use it in a builder pattern to define the service in a more\n * fluent way.\n *\n * See the static methods for more information and examples.\n *\n * When defining procedures, use the {@link Procedure} constructors to create them.\n */\nexport class ServiceSchema<\n State extends object,\n Procedures extends ProcedureMap<State>,\n> {\n /**\n * Factory function for creating a fresh state.\n */\n protected readonly initializeState: (\n extendedContext: ServiceContext,\n ) => State;\n\n /**\n * The procedures for this service.\n */\n readonly procedures: Procedures;\n\n /**\n * @param config - The configuration for this service.\n * @param procedures - The procedures for this service.\n */\n protected constructor(\n config: ServiceConfiguration<State>,\n procedures: Procedures,\n ) {\n this.initializeState = config.initializeState;\n this.procedures = procedures;\n }\n\n /**\n * Creates a {@link ServiceScaffold}, which can be used to define procedures\n * that can then be merged into a {@link ServiceSchema}, via the scaffold's\n * `finalize` method.\n *\n * There are two patterns that work well with this method. The first is using\n * it to separate the definition of procedures from the definition of the\n * service's configuration:\n * ```ts\n * const MyServiceScaffold = ServiceSchema.scaffold({\n * initializeState: () => ({ count: 0 }),\n * });\n *\n * const incrementProcedures = MyServiceScaffold.procedures({\n * increment: Procedure.rpc({\n * requestInit: Type.Object({ amount: Type.Number() }),\n * responseData: Type.Object({ current: Type.Number() }),\n * async handler(ctx, init) {\n * ctx.state.count += init.amount;\n * return Ok({ current: ctx.state.count });\n * }\n * }),\n * })\n *\n * const MyService = MyServiceScaffold.finalize({\n * ...incrementProcedures,\n * // you can also directly define procedures here\n * });\n * ```\n * This might be really handy if you have a very large service and you're\n * wanting to split it over multiple files. You can define the scaffold\n * in one file, and then import that scaffold in other files where you\n * define procedures - and then finally import the scaffolds and your\n * procedure objects in a final file where you finalize the scaffold into\n * a service schema.\n *\n * The other way is to use it like in a builder pattern:\n * ```ts\n * const MyService = ServiceSchema\n * .scaffold({ initializeState: () => ({ count: 0 }) })\n * .finalize({\n * increment: Procedure.rpc({\n * requestInit: Type.Object({ amount: Type.Number() }),\n * responseData: Type.Object({ current: Type.Number() }),\n * async handler(ctx, init) {\n * ctx.state.count += init.amount;\n * return Ok({ current: ctx.state.count });\n * }\n * }),\n * })\n * ```\n * Depending on your preferences, this may be a more appealing way to define\n * a schema versus using the {@link ServiceSchema.define} method.\n */\n static scaffold<State extends object>(config: ServiceConfiguration<State>) {\n return new ServiceScaffold(config);\n }\n\n /**\n * Creates a new {@link ServiceSchema} with the given configuration and procedures.\n *\n * All procedures must be created with the {@link Procedure} constructors.\n *\n * NOTE: There is an overload that lets you just provide the procedures alone if your\n * service has no state.\n *\n * @param config - The configuration for this service.\n * @param procedures - The procedures for this service.\n *\n * @example\n * ```\n * const service = ServiceSchema.define(\n * { initializeState: () => ({ count: 0 }) },\n * {\n * increment: Procedure.rpc({\n * requestInit: Type.Object({ amount: Type.Number() }),\n * responseData: Type.Object({ current: Type.Number() }),\n * async handler(ctx, init) {\n * ctx.state.count += init.amount;\n * return Ok({ current: ctx.state.count });\n * }\n * }),\n * },\n * );\n * ```\n */\n static define<\n State extends object,\n Procedures extends BrandedProcedureMap<State>,\n >(\n config: ServiceConfiguration<State>,\n procedures: Procedures,\n ): ServiceSchema<\n State,\n { [K in keyof Procedures]: Unbranded<Procedures[K]> }\n >;\n /**\n * Creates a new {@link ServiceSchema} with the given procedures.\n *\n * All procedures must be created with the {@link Procedure} constructors.\n *\n * NOTE: There is an overload that lets you provide configuration as well,\n * if your service has extra configuration like a state.\n *\n * @param procedures - The procedures for this service.\n *\n * @example\n * ```\n * const service = ServiceSchema.define({\n * add: Procedure.rpc({\n * requestInit: Type.Object({ a: Type.Number(), b: Type.Number() }),\n * responseData: Type.Object({ result: Type.Number() }),\n * async handler(ctx, init) {\n * return Ok({ result: init.a + init.b });\n * }\n * }),\n * });\n */\n static define<Procedures extends BrandedProcedureMap<Record<string, never>>>(\n procedures: Procedures,\n ): ServiceSchema<\n Record<string, never>,\n { [K in keyof Procedures]: Unbranded<Procedures[K]> }\n >;\n // actual implementation\n static define(\n configOrProcedures:\n | ServiceConfiguration<object>\n | BrandedProcedureMap<object>,\n maybeProcedures?: BrandedProcedureMap<object>,\n ): ServiceSchema<object, ProcedureMap> {\n let config: ServiceConfiguration<object>;\n let procedures: BrandedProcedureMap<object>;\n\n if (\n 'initializeState' in configOrProcedures &&\n typeof configOrProcedures.initializeState === 'function'\n ) {\n if (!maybeProcedures) {\n throw new Error('Expected procedures to be defined');\n }\n\n config = configOrProcedures as ServiceConfiguration<object>;\n procedures = maybeProcedures;\n } else {\n config = { initializeState: () => ({}) };\n procedures = configOrProcedures as BrandedProcedureMap<object>;\n }\n\n return new ServiceSchema(config, procedures);\n }\n\n /**\n * Serializes this schema's procedures into a plain object that is JSON compatible.\n */\n serialize(): SerializedServiceSchema {\n return {\n procedures: Object.fromEntries(\n Object.entries(this.procedures).map(([procName, procDef]) => [\n procName,\n {\n init: Type.Strict(procDef.requestInit),\n output: Type.Strict(procDef.responseData),\n errors: getSerializedProcErrors(procDef),\n // Only add `description` field if the type declares it.\n ...('description' in procDef\n ? { description: procDef.description }\n : {}),\n type: procDef.type,\n // Only add the `input` field if the type declares it.\n ...('requestData' in procDef\n ? {\n input: Type.Strict(procDef.requestData),\n }\n : {}),\n },\n ]),\n ),\n };\n }\n\n // TODO remove once clients migrate to v2\n /**\n * Same as {@link ServiceSchema.serialize}, but with a format that is compatible with\n * protocol v1. This is useful to be able to continue to generate schemas for older\n * clients as they are still supported.\n */\n serializeV1Compat(): SerializedServiceSchemaProtocolv1 {\n return {\n procedures: Object.fromEntries(\n Object.entries(this.procedures).map(\n ([procName, procDef]): [\n string,\n SerializedProcedureSchemaProtocolv1,\n ] => {\n if (procDef.type === 'rpc' || procDef.type === 'subscription') {\n return [\n procName,\n {\n // BACKWARDS COMPAT: map init to input for protocolv1\n // this is the only change needed to make it compatible.\n input: Type.Strict(procDef.requestInit),\n output: Type.Strict(procDef.responseData),\n errors: getSerializedProcErrors(procDef),\n // Only add `description` field if the type declares it.\n ...('description' in procDef\n ? { description: procDef.description }\n : {}),\n type: procDef.type,\n },\n ];\n }\n\n // No backwards compatibility needed for upload and stream types, as having an `init`\n // all the time is compatible with protocol v1.\n return [\n procName,\n {\n init: Type.Strict(procDef.requestInit),\n output: Type.Strict(procDef.responseData),\n errors: getSerializedProcErrors(procDef),\n // Only add `description` field if the type declares it.\n ...('description' in procDef\n ? { description: procDef.description }\n : {}),\n type: procDef.type,\n input: Type.Strict(procDef.requestData),\n },\n ];\n },\n ),\n ),\n };\n }\n\n /**\n * Instantiates this schema into a {@link Service} object.\n *\n * You probably don't need this, usually the River server will handle this\n * for you.\n */\n instantiate(extendedContext: ServiceContext): Service<State, Procedures> {\n return Object.freeze({\n state: this.initializeState(extendedContext),\n procedures: this.procedures,\n });\n }\n}\n\nfunction getSerializedProcErrors(\n procDef: AnyProcedure,\n): ProcedureErrorSchemaType {\n if (\n !('responseError' in procDef) ||\n procDef.responseError[Kind] === 'Never'\n ) {\n return Type.Strict(ReaderErrorSchema);\n }\n\n const withProtocolErrors = flattenErrorType(\n Type.Union([procDef.responseError, ReaderErrorSchema]),\n );\n\n return Type.Strict(withProtocolErrors);\n}\n\n/**\n * A scaffold for defining a service's procedures.\n *\n * @see {@link ServiceSchema.scaffold}\n */\n// note that this isn't exported\nclass ServiceScaffold<State extends object> {\n /**\n * The configuration for this service.\n */\n protected readonly config: ServiceConfiguration<State>;\n\n /**\n * @param config - The configuration for this service.\n */\n constructor(config: ServiceConfiguration<State>) {\n this.config = config;\n }\n\n /**\n * Define procedures for this service. Use the {@link Procedure} constructors\n * to create them. This returns the procedures object, which can then be\n * passed to {@link ServiceSchema.finalize} to create a {@link ServiceSchema}.\n *\n * @example\n * ```\n * const myProcedures = MyServiceScaffold.procedures({\n * myRPC: Procedure.rpc({\n * // ...\n * }),\n * });\n *\n * const MyService = MyServiceScaffold.finalize({\n * ...myProcedures,\n * });\n * ```\n *\n * @param procedures - The procedures for this service.\n */\n procedures<T extends BrandedProcedureMap<State>>(procedures: T): T {\n return procedures;\n }\n\n /**\n * Finalizes the scaffold into a {@link ServiceSchema}. This is where you\n * provide the service's procedures and get a {@link ServiceSchema} in return.\n *\n * You can directly define procedures here, or you can define them separately\n * with the {@link ServiceScaffold.procedures} method, and then pass them here.\n *\n * @example\n * ```\n * const MyService = MyServiceScaffold.finalize({\n * myRPC: Procedure.rpc({\n * // ...\n * }),\n * // e.g. from the procedures method\n * ...myOtherProcedures,\n * });\n * ```\n */\n finalize<T extends BrandedProcedureMap<State>>(\n procedures: T,\n ): ServiceSchema<State, { [K in keyof T]: Unbranded<T[K]> }> {\n return ServiceSchema.define(this.config, procedures);\n }\n}\n","/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */\nimport { Static, TNever, TSchema, Type } from '@sinclair/typebox';\nimport { ProcedureHandlerContext } from './context';\nimport { Result } from './result';\nimport { Readable, Writable } from './streams';\nimport { ProcedureErrorSchemaType, ReaderErrorSchema } from './errors';\n\n/**\n * Brands a type to prevent it from being directly constructed.\n */\nexport type Branded<T> = T & { readonly __BRAND_DO_NOT_USE: unique symbol };\n\n/**\n * Unbrands a {@link Branded} type.\n */\nexport type Unbranded<T> = T extends Branded<infer U> ? U : never;\n\n/**\n * The valid {@link Procedure} types. The `stream` and `upload` types can optionally have a\n * different type for the very first initialization message. The suffixless types correspond to\n * gRPC's four combinations of stream / non-stream in each direction.\n */\nexport type ValidProcType =\n // Single message in both directions (1:1).\n | 'rpc'\n // Client-stream single message from server (n:1).\n | 'upload'\n // Single message from client, stream from server (1:n).\n | 'subscription'\n // Bidirectional stream (n:n).\n | 'stream';\n\n/**\n * Represents the payload type for {@link Procedure}s.\n */\nexport type PayloadType = TSchema;\n\n/**\n * Procedure for a single message in both directions (1:1).\n *\n * @template State - The context state object.\n * @template RequestInit - The TypeBox schema of the initialization object.\n * @template ResponseData - The TypeBox schema of the response object.\n * @template ResponseErr - The TypeBox schema of the error object.\n */\nexport interface RpcProcedure<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> {\n type: 'rpc';\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler(param: {\n ctx: ProcedureHandlerContext<State>;\n reqInit: Static<RequestInit>;\n }): Promise<Result<Static<ResponseData>, Static<ResponseErr>>>;\n}\n\n/**\n * Procedure for a client-stream (potentially preceded by an initialization message),\n * single message from server (n:1).\n *\n * @template State - The context state object.\n * @template RequestInit - The TypeBox schema of the initialization object.\n * @template RequestData - The TypeBox schema of the request object.\n * @template ResponseData - The TypeBox schema of the response object.\n * @template ResponseErr - The TypeBox schema of the error object.\n */\nexport interface UploadProcedure<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> {\n type: 'upload';\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler(param: {\n ctx: ProcedureHandlerContext<State>;\n reqInit: Static<RequestInit>;\n reqReadable: Readable<\n Static<RequestData>,\n Static<typeof ReaderErrorSchema>\n >;\n }): Promise<Result<Static<ResponseData>, Static<ResponseErr>>>;\n}\n\n/**\n * Procedure for a single message from client, stream from server (1:n).\n *\n * @template State - The context state object.\n * @template RequestInit - The TypeBox schema of the initialization object.\n * @template ResponseData - The TypeBox schema of the response object.\n * @template ResponseErr - The TypeBox schema of the error object.\n */\nexport interface SubscriptionProcedure<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> {\n type: 'subscription';\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler(param: {\n ctx: ProcedureHandlerContext<State>;\n reqInit: Static<RequestInit>;\n resWritable: Writable<Result<Static<ResponseData>, Static<ResponseErr>>>;\n }): Promise<void | undefined>;\n}\n\n/**\n * Procedure for a bidirectional stream (potentially preceded by an initialization message),\n * (n:n).\n *\n * @template State - The context state object.\n * @template RequestInit - The TypeBox schema of the initialization object.\n * @template RequestData - The TypeBox schema of the request object.\n * @template ResponseData - The TypeBox schema of the response object.\n * @template ResponseErr - The TypeBox schema of the error object.\n */\nexport interface StreamProcedure<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> {\n type: 'stream';\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler(param: {\n ctx: ProcedureHandlerContext<State>;\n reqInit: Static<RequestInit>;\n reqReadable: Readable<\n Static<RequestData>,\n Static<typeof ReaderErrorSchema>\n >;\n resWritable: Writable<Result<Static<ResponseData>, Static<ResponseErr>>>;\n }): Promise<void | undefined>;\n}\n\n/**\n * Defines a Procedure type that can be a:\n * - {@link RpcProcedure} for a single message in both directions (1:1)\n * - {@link UploadProcedure} for a client-stream (potentially preceded by an\n * initialization message)\n * - {@link SubscriptionProcedure} for a single message from client, stream from server (1:n)\n * - {@link StreamProcedure} for a bidirectional stream (potentially preceded by an\n * initialization message)\n *\n * @template State - The TypeBox schema of the state object.\n * @template Ty - The type of the procedure.\n * @template RequestData - The TypeBox schema of the request object.\n * @template RequestInit - The TypeBox schema of the request initialization object, if any.\n * @template ResponseData - The TypeBox schema of the response object.\n */\nexport type Procedure<\n State,\n Ty extends ValidProcType,\n RequestInit extends PayloadType,\n RequestData extends PayloadType | null,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n> = { type: Ty } & (RequestData extends PayloadType\n ? Ty extends 'upload'\n ? UploadProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n ResponseErr\n >\n : Ty extends 'stream'\n ? StreamProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n ResponseErr\n >\n : never\n : Ty extends 'rpc'\n ? RpcProcedure<State, RequestInit, ResponseData, ResponseErr>\n : Ty extends 'subscription'\n ? SubscriptionProcedure<State, RequestInit, ResponseData, ResponseErr>\n : never);\n\n/**\n * Represents any {@link Procedure} type.\n *\n * @template State - The context state object. You can provide this to constrain\n * the type of procedures.\n */\nexport type AnyProcedure<State = object> = Procedure<\n State,\n ValidProcType,\n PayloadType,\n PayloadType | null,\n PayloadType,\n ProcedureErrorSchemaType\n>;\n\n/**\n * Represents a map of {@link Procedure}s.\n *\n * @template State - The context state object. You can provide this to constrain\n * the type of procedures.\n */\nexport type ProcedureMap<State = object> = Record<string, AnyProcedure<State>>;\n\n// typescript is funky so with these upcoming procedure constructors, the overloads\n// which handle the `init` case _must_ come first, otherwise the `init` property\n// is not recognized as optional, for some reason\n\n/**\n * Creates an {@link RpcProcedure}.\n */\n// signature: default errors\nfunction rpc<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n>(def: {\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError?: never;\n description?: string;\n handler: RpcProcedure<State, RequestInit, ResponseData, TNever>['handler'];\n}): Branded<RpcProcedure<State, RequestInit, ResponseData, TNever>>;\n\n// signature: explicit errors\nfunction rpc<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n>(def: {\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler: RpcProcedure<\n State,\n RequestInit,\n ResponseData,\n ResponseErr\n >['handler'];\n}): Branded<RpcProcedure<State, RequestInit, ResponseData, ResponseErr>>;\n\n// implementation\nfunction rpc({\n requestInit,\n responseData,\n responseError = Type.Never(),\n description,\n handler,\n}: {\n requestInit: PayloadType;\n responseData: PayloadType;\n responseError?: ProcedureErrorSchemaType;\n description?: string;\n handler: RpcProcedure<\n object,\n PayloadType,\n PayloadType,\n ProcedureErrorSchemaType\n >['handler'];\n}) {\n return {\n ...(description ? { description } : {}),\n type: 'rpc',\n requestInit,\n responseData,\n responseError,\n handler,\n };\n}\n\n/**\n * Creates an {@link UploadProcedure}, optionally with an initialization message.\n */\n// signature: init with default errors\nfunction upload<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n>(def: {\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError?: never;\n description?: string;\n handler: UploadProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n TNever\n >['handler'];\n}): Branded<\n UploadProcedure<State, RequestInit, RequestData, ResponseData, TNever>\n>;\n\n// signature: init with explicit errors\nfunction upload<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n>(def: {\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler: UploadProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n ResponseErr\n >['handler'];\n}): Branded<\n UploadProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr>\n>;\n\n// implementation\nfunction upload({\n requestInit,\n requestData,\n responseData,\n responseError = Type.Never(),\n description,\n handler,\n}: {\n requestInit: PayloadType;\n requestData: PayloadType;\n responseData: PayloadType;\n responseError?: ProcedureErrorSchemaType;\n description?: string;\n handler: UploadProcedure<\n object,\n PayloadType,\n PayloadType,\n PayloadType,\n ProcedureErrorSchemaType\n >['handler'];\n}) {\n return {\n type: 'upload',\n ...(description ? { description } : {}),\n requestInit,\n requestData,\n responseData,\n responseError,\n handler,\n };\n}\n\n/**\n * Creates a {@link SubscriptionProcedure}.\n */\n// signature: default errors\nfunction subscription<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n>(def: {\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError?: never;\n description?: string;\n handler: SubscriptionProcedure<\n State,\n RequestInit,\n ResponseData,\n TNever\n >['handler'];\n}): Branded<SubscriptionProcedure<State, RequestInit, ResponseData, TNever>>;\n\n// signature: explicit errors\nfunction subscription<\n State,\n RequestInit extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n>(def: {\n requestInit: RequestInit;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler: SubscriptionProcedure<\n State,\n RequestInit,\n ResponseData,\n ResponseErr\n >['handler'];\n}): Branded<\n SubscriptionProcedure<State, RequestInit, ResponseData, ResponseErr>\n>;\n\n// implementation\nfunction subscription({\n requestInit,\n responseData,\n responseError = Type.Never(),\n description,\n handler,\n}: {\n requestInit: PayloadType;\n responseData: PayloadType;\n responseError?: ProcedureErrorSchemaType;\n description?: string;\n handler: SubscriptionProcedure<\n object,\n PayloadType,\n PayloadType,\n ProcedureErrorSchemaType\n >['handler'];\n}) {\n return {\n type: 'subscription',\n ...(description ? { description } : {}),\n requestInit,\n responseData,\n responseError,\n handler,\n };\n}\n\n/**\n * Creates a {@link StreamProcedure}, optionally with an initialization message.\n */\n// signature: with default errors\nfunction stream<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n>(def: {\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError?: never;\n description?: string;\n handler: StreamProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n TNever\n >['handler'];\n}): Branded<\n StreamProcedure<State, RequestInit, RequestData, ResponseData, TNever>\n>;\n\n// signature: explicit errors\nfunction stream<\n State,\n RequestInit extends PayloadType,\n RequestData extends PayloadType,\n ResponseData extends PayloadType,\n ResponseErr extends ProcedureErrorSchemaType,\n>(def: {\n requestInit: RequestInit;\n requestData: RequestData;\n responseData: ResponseData;\n responseError: ResponseErr;\n description?: string;\n handler: StreamProcedure<\n State,\n RequestInit,\n RequestData,\n ResponseData,\n ResponseErr\n >['handler'];\n}): Branded<\n StreamProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr>\n>;\n\n// implementation\nfunction stream({\n requestInit,\n requestData,\n responseData,\n responseError = Type.Never(),\n description,\n handler,\n}: {\n requestInit: PayloadType;\n requestData: PayloadType;\n responseData: PayloadType;\n responseError?: ProcedureErrorSchemaType;\n description?: string;\n handler: StreamProcedure<\n object,\n PayloadType,\n PayloadType,\n PayloadType,\n ProcedureErrorSchemaType\n >['handler'];\n}) {\n return {\n type: 'stream',\n ...(description ? { description } : {}),\n requestInit,\n requestData,\n responseData,\n responseError,\n handler,\n };\n}\n\n/**\n * Holds the {@link Procedure} creation functions. Use these to create\n * procedures for services. You aren't allowed to create procedures directly.\n */\nexport const Procedure = {\n rpc,\n upload,\n subscription,\n stream,\n};\n","import {\n AnyService,\n ProcErrors,\n ProcInit,\n ProcRequest,\n ProcResponse,\n ProcType,\n AnyServiceSchemaMap,\n InstantiatedServiceSchemaMap,\n} from './services';\nimport {\n OpaqueTransportMessage,\n ControlFlags,\n TransportClientId,\n isStreamClose,\n ControlMessageCloseSchema,\n isStreamCancel,\n closeStreamMessage,\n cancelMessage,\n} from '../transport/message';\nimport { Static } from '@sinclair/typebox';\nimport { Err, Result, AnyResultSchema } from './result';\nimport { EventMap } from '../transport/events';\nimport { Connection } from '../transport/connection';\nimport { Logger } from '../logging';\nimport { createProcTelemetryInfo, getPropagationContext } from '../tracing';\nimport { ClientHandshakeOptions } from './handshake';\nimport { ClientTransport } from '../transport/client';\nimport { generateId } from '../transport/id';\nimport { Readable, ReadableImpl, Writable, WritableImpl } from './streams';\nimport { Value } from '@sinclair/typebox/value';\nimport { PayloadType, ValidProcType } from './procedures';\nimport {\n BaseErrorSchemaType,\n ErrResultSchema,\n CANCEL_CODE,\n ReaderErrorSchema,\n UNEXPECTED_DISCONNECT_CODE,\n} from './errors';\n\nconst ReaderErrResultSchema = ErrResultSchema(ReaderErrorSchema);\n\ninterface CallOptions {\n signal?: AbortSignal;\n}\n\ntype RpcFn<\n Service extends AnyService,\n ProcName extends keyof Service['procedures'],\n> = (\n reqInit: ProcInit<Service, ProcName>,\n options?: CallOptions,\n) => Promise<\n Result<ProcResponse<Service, ProcName>, ProcErrors<Service, ProcName>>\n>;\n\ntype UploadFn<\n Service extends AnyService,\n ProcName extends keyof Service['procedures'],\n> = (\n reqInit: ProcInit<Service, ProcName>,\n options?: CallOptions,\n) => {\n reqWritable: Writable<ProcRequest<Service, ProcName>>;\n finalize: () => Promise<\n Result<ProcResponse<Service, ProcName>, ProcErrors<Service, ProcName>>\n >;\n};\n\ntype StreamFn<\n Service extends AnyService,\n ProcName extends keyof Service['procedures'],\n> = (\n reqInit: ProcInit<Service, ProcName>,\n options?: CallOptions,\n) => {\n reqWritable: Writable<ProcRequest<Service, ProcName>>;\n resReadable: Readable<\n ProcResponse<Service, ProcName>,\n ProcErrors<Service, ProcName>\n >;\n};\n\ntype SubscriptionFn<\n Service extends AnyService,\n ProcName extends keyof Service['procedures'],\n> = (\n reqInit: ProcInit<Service, ProcName>,\n options?: CallOptions,\n) => {\n resReadable: Readable<\n ProcResponse<Service, ProcName>,\n ProcErrors<Service, ProcName>\n >;\n};\n\n/**\n * A helper type to transform an actual service type into a type\n * we can case to in the proxy.\n * @template Service - The type of the Service.\n */\ntype ServiceClient<Service extends AnyService> = {\n [ProcName in keyof Service['procedures']]: ProcType<\n Service,\n ProcName\n > extends 'rpc'\n ? {\n // If your go-to-definition ended up here, you probably meant to\n // go to the procedure name. For example:\n // riverClient.myService.someprocedure.rpc({})\n // click here ^^^^^^^^^^^^^\n rpc: RpcFn<Service, ProcName>;\n }\n : ProcType<Service, ProcName> extends 'upload'\n ? {\n // If your go-to-definition ended up here, you probably meant to\n // go to the procedure name. For example:\n // riverClient.myService.someprocedure.upload({})\n // click here ^^^^^^^^^^^^^\n upload: UploadFn<Service, ProcName>;\n }\n : ProcType<Service, ProcName> extends 'stream'\n ? {\n // If your go-to-definition ended up here, you probably meant to\n // go to the procedure name. For example:\n // riverClient.myService.someprocedure.stream({})\n // click here ^^^^^^^^^^^^^\n stream: StreamFn<Service, ProcName>;\n }\n : ProcType<Service, ProcName> extends 'subscription'\n ? {\n // If your go-to-definition ended up here, you probably meant to\n // go to the procedure name. For example:\n // riverClient.myService.subscribe.stream({})\n // click here ^^^^^^^^^^^^^\n subscribe: SubscriptionFn<Service, ProcName>;\n }\n : never;\n};\n\n/**\n * Defines a type that represents a client for a server with a set of services.\n * @template Srv - The type of the server.\n */\nexport type Client<\n Services extends AnyServiceSchemaMap,\n IS extends\n InstantiatedServiceSchemaMap<Services> = InstantiatedServiceSchemaMap<Services>,\n> = {\n [SvcName in keyof IS]: ServiceClient<IS[SvcName]>;\n};\n\ninterface ProxyCallbackOptions {\n path: Array<string>;\n args: Array<unknown>;\n}\n\ntype ProxyCallback = (opts: ProxyCallbackOptions) => unknown;\n/* eslint-disable-next-line @typescript-eslint/no-empty-function */\nconst noop = () => {};\n\nfunction _createRecursiveProxy(\n callback: ProxyCallback,\n path: Array<string>,\n): unknown {\n const proxy: unknown = new Proxy(noop, {\n // property access, recurse and add field to path\n get(_obj, key) {\n if (typeof key !== 'string') return undefined;\n\n return _createRecursiveProxy(callback, [...path, key]);\n },\n // hit the end, let's invoke the handler\n apply(_target, _this, args) {\n return callback({\n path,\n args,\n });\n },\n });\n\n return proxy;\n}\n\nexport interface ClientOptions {\n connectOnInvoke: boolean;\n eagerlyConnect: boolean;\n}\n\nconst defaultClientOptions: ClientOptions = {\n connectOnInvoke: true,\n eagerlyConnect: true,\n};\n\n/**\n * Creates a client for a given server using the provided transport.\n * Note that the client only needs the type of the server, not the actual\n * server definition itself.\n *\n * This relies on a proxy to dynamically create the client, so the client\n * will be typed as if it were the actual server with the appropriate services\n * and procedures.\n *\n * @template Srv - The type of the server.\n * @param {Transport} transport - The transport to use for communication.\n * @param {TransportClientId} serverId - The ID of the server to connect to.\n * @param {Partial<ClientOptions>} providedClientOptions - The options for the client.\n * @returns The client for the server.\n */\nexport function createClient<ServiceSchemaMap extends AnyServiceSchemaMap>(\n transport: ClientTransport<Connection>,\n serverId: TransportClientId,\n providedClientOptions: Partial<\n ClientOptions & {\n handshakeOptions: ClientHandshakeOptions;\n }\n > = {},\n): Client<ServiceSchemaMap> {\n if (providedClientOptions.handshakeOptions) {\n transport.extendHandshake(providedClientOptions.handshakeOptions);\n }\n\n const clientOptions = { ...defaultClientOptions, ...providedClientOptions };\n if (clientOptions.eagerlyConnect) {\n transport.connect(serverId);\n }\n\n return _createRecursiveProxy((opts) => {\n const [serviceName, procName, procMethod] = [...opts.path];\n if (!(serviceName && procName && procMethod)) {\n throw new Error(\n 'invalid river call, ensure the service and procedure you are calling exists',\n );\n }\n\n const [init, callOptions] = opts.args;\n\n if (clientOptions.connectOnInvoke && !transport.sessions.has(serverId)) {\n transport.connect(serverId);\n }\n\n if (\n procMethod !== 'rpc' &&\n procMethod !== 'subscribe' &&\n procMethod !== 'stream' &&\n procMethod !== 'upload'\n ) {\n throw new Error(\n `invalid river call, unknown procedure type ${procMethod}`,\n );\n }\n\n return handleProc(\n procMethod === 'subscribe' ? 'subscription' : procMethod,\n transport,\n serverId,\n init,\n serviceName,\n procName,\n callOptions ? (callOptions as CallOptions).signal : undefined,\n );\n }, []) as Client<ServiceSchemaMap>;\n}\n\ntype AnyProcReturn =\n | ReturnType<RpcFn<AnyService, string>>\n | ReturnType<UploadFn<AnyService, string>>\n | ReturnType<StreamFn<AnyService, string>>\n | ReturnType<SubscriptionFn<AnyService, string>>;\n\nfunction handleProc(\n procType: ValidProcType,\n transport: ClientTransport<Connection>,\n serverId: TransportClientId,\n init: Static<PayloadType>,\n serviceName: string,\n procedureName: string,\n abortSignal?: AbortSignal,\n): AnyProcReturn {\n const session =\n transport.sessions.get(serverId) ??\n transport.createUnconnectedSession(serverId);\n const sessionScopedSend = transport.getSessionBoundSendFn(\n serverId,\n session.id,\n );\n\n const procClosesWithInit = procType === 'rpc' || procType === 'subscription';\n const streamId = generateId();\n const { span, ctx } = createProcTelemetryInfo(\n transport,\n procType,\n serviceName,\n procedureName,\n streamId,\n );\n let cleanClose = true;\n const reqWritable = new WritableImpl<Static<PayloadType>>({\n writeCb: (rawIn) => {\n sessionScopedSend({\n streamId,\n payload: rawIn,\n controlFlags: 0,\n });\n },\n // close callback\n closeCb: () => {\n span.addEvent('reqWritable closed');\n\n if (!procClosesWithInit && cleanClose) {\n sessionScopedSend(closeStreamMessage(streamId));\n }\n\n if (resReadable.isClosed()) {\n cleanup();\n }\n },\n });\n\n const resReadable = new ReadableImpl<\n Static<PayloadType>,\n Static<BaseErrorSchemaType>\n >();\n const closeReadable = () => {\n resReadable._triggerClose();\n\n span.addEvent('resReadable closed');\n\n if (reqWritable.isClosed()) {\n cleanup();\n }\n };\n\n function cleanup() {\n transport.removeEventListener('message', onMessage);\n transport.removeEventListener('sessionStatus', onSessionStatus);\n abortSignal?.removeEventListener('abort', onClientCancel);\n span.end();\n }\n\n function onClientCancel() {\n if (resReadable.isClosed() && reqWritable.isClosed()) {\n return;\n }\n\n span.addEvent('sending cancel');\n cleanClose = false;\n\n if (!resReadable.isClosed()) {\n resReadable._pushValue(\n Err({\n code: CANCEL_CODE,\n message: 'cancelled by client',\n }),\n );\n closeReadable();\n }\n\n reqWritable.close();\n sessionScopedSend(\n cancelMessage(\n streamId,\n Err({\n code: CANCEL_CODE,\n message: 'cancelled by client',\n }),\n ),\n );\n }\n\n function onMessage(msg: OpaqueTransportMessage) {\n if (msg.streamId !== streamId) return;\n if (msg.to !== transport.clientId) {\n transport.log?.error('got stream message from unexpected client', {\n clientId: transport.clientId,\n transportMessage: msg,\n });\n\n return;\n }\n\n if (isStreamCancel(msg.controlFlags)) {\n cleanClose = false;\n\n span.addEvent('received cancel');\n let cancelResult: Static<typeof ReaderErrResultSchema>;\n\n if (Value.Check(ReaderErrResultSchema, msg.payload)) {\n cancelResult = msg.payload;\n } else {\n cancelResult = Err({\n code: CANCEL_CODE,\n message: 'stream cancelled with invalid payload',\n });\n transport.log?.error(\n 'got stream cancel without a valid protocol error',\n {\n clientId: transport.clientId,\n transportMessage: msg,\n validationErrors: [\n ...Value.Errors(ReaderErrResultSchema, msg.payload),\n ],\n },\n );\n }\n\n if (!resReadable.isClosed()) {\n resReadable._pushValue(cancelResult);\n closeReadable();\n }\n\n reqWritable.close();\n\n return;\n }\n\n if (resReadable.isClosed()) {\n span.recordException('received message after response stream is closed');\n\n transport.log?.error('received message after response stream is closed', {\n clientId: transport.clientId,\n transportMessage: msg,\n });\n\n return;\n }\n\n if (!Value.Check(ControlMessageCloseSchema, msg.payload)) {\n if (Value.Check(AnyResultSchema, msg.payload)) {\n resReadable._pushValue(msg.payload);\n } else {\n transport.log?.error(\n 'Got non-control payload, but was not a valid result',\n {\n clientId: transport.clientId,\n transportMessage: msg,\n validationErrors: [...Value.Errors(AnyResultSchema, msg.payload)],\n },\n );\n }\n }\n\n if (isStreamClose(msg.controlFlags)) {\n span.addEvent('received response close');\n\n if (resReadable.isClosed()) {\n transport.log?.error(\n 'received stream close but readable was already closed',\n );\n } else {\n closeReadable();\n }\n }\n }\n\n function onSessionStatus(evt: EventMap['sessionStatus']) {\n if (\n evt.status !== 'disconnect' ||\n evt.session.to !== serverId ||\n session.id !== evt.session.id\n ) {\n return;\n }\n\n cleanClose = false;\n if (!resReadable.isClosed()) {\n resReadable._pushValue(\n Err({\n code: UNEXPECTED_DISCONNECT_CODE,\n message: `${serverId} unexpectedly disconnected`,\n }),\n );\n closeReadable();\n }\n\n reqWritable.close();\n }\n\n abortSignal?.addEventListener('abort', onClientCancel);\n transport.addEventListener('message', onMessage);\n transport.addEventListener('sessionStatus', onSessionStatus);\n\n sessionScopedSend({\n streamId,\n serviceName,\n procedureName,\n tracing: getPropagationContext(ctx),\n payload: init,\n controlFlags: procClosesWithInit\n ? ControlFlags.StreamOpenBit | ControlFlags.StreamClosedBit\n : ControlFlags.StreamOpenBit,\n });\n\n if (procClosesWithInit) {\n reqWritable.close();\n }\n\n if (procType === 'subscription') {\n return {\n resReadable: resReadable,\n };\n }\n\n if (procType === 'rpc') {\n return getSingleMessage(resReadable, transport.log);\n }\n\n if (procType === 'upload') {\n let didFinalize = false;\n\n return {\n reqWritable: reqWritable,\n finalize: () => {\n if (didFinalize) {\n throw new Error('upload stream already finalized');\n }\n\n didFinalize = true;\n\n if (!reqWritable.isClosed()) {\n reqWritable.close();\n }\n\n return getSingleMessage(resReadable, transport.log);\n },\n };\n }\n\n // good ol' `stream` procType\n return {\n resReadable: resReadable,\n reqWritable: reqWritable,\n };\n}\n\n/**\n * Waits for a message in the response AND the server to close.\n * Logs an error if we receive multiple messages.\n * Used in RPC and Upload.\n */\nasync function getSingleMessage(\n resReadable: Readable<unknown, Static<BaseErrorSchemaType>>,\n log?: Logger,\n): Promise<Result<unknown, Static<BaseErrorSchemaType>>> {\n const ret = await resReadable.collect();\n\n if (ret.length > 1) {\n log?.error('Expected single message from server, got multiple');\n }\n\n return ret[0];\n}\n","import { Static, Type } from '@sinclair/typebox';\nimport { PayloadType, AnyProcedure } from './procedures';\nimport {\n ReaderErrorSchema,\n UNCAUGHT_ERROR_CODE,\n UNEXPECTED_DISCONNECT_CODE,\n CANCEL_CODE,\n INVALID_REQUEST_CODE,\n BaseErrorSchemaType,\n ErrResultSchema,\n} from './errors';\nimport {\n AnyService,\n InstantiatedServiceSchemaMap,\n AnyServiceSchemaMap,\n} from './services';\nimport {\n ControlMessagePayloadSchema,\n OpaqueTransportMessage,\n isStreamClose,\n isStreamOpen,\n ControlFlags,\n isStreamCancel,\n closeStreamMessage,\n cancelMessage,\n ProtocolVersion,\n TransportClientId,\n} from '../transport/message';\nimport {\n ServiceContext,\n ProcedureHandlerContext,\n ParsedMetadata,\n} from './context';\nimport { Logger } from '../logging/log';\nimport { Value, ValueError } from '@sinclair/typebox/value';\nimport { Err, Result, Ok, ErrResult } from './result';\nimport { EventMap } from '../transport/events';\nimport { coerceErrorString } from '../util/stringify';\nimport { Span, SpanStatusCode } from '@opentelemetry/api';\nimport { createHandlerSpan, PropagationContext } from '../tracing';\nimport { ServerHandshakeOptions } from './handshake';\nimport { Connection } from '../transport/connection';\nimport { ServerTransport } from '../transport/server';\nimport { ReadableImpl, WritableImpl } from './streams';\nimport { IdentifiedSession } from '../transport/sessionStateMachine/common';\nimport { SessionBoundSendFn } from '../transport/transport';\n\ntype StreamId = string;\n\n/**\n * A schema for cancel payloads sent from the client\n */\nconst CancelResultSchema = ErrResultSchema(\n Type.Object({\n code: Type.Literal(CANCEL_CODE),\n message: Type.String(),\n }),\n);\n\n/**\n * Represents a server with a set of services. Use {@link createServer} to create it.\n * @template Services - The type of services provided by the server.\n */\nexport interface Server<Services extends AnyServiceSchemaMap> {\n /**\n * Services defined for this server.\n */\n services: InstantiatedServiceSchemaMap<Services>;\n /**\n * A set of stream ids that are currently open.\n */\n streams: Map<StreamId, ProcStream>;\n}\n\ntype ProcHandlerReturn = Promise<(() => void) | void>;\n\ninterface StreamInitProps {\n // msg derived\n streamId: StreamId;\n procedureName: string;\n serviceName: string;\n initPayload: Static<PayloadType>;\n tracingCtx: PropagationContext | undefined;\n // true if the first and only message is the init payload\n // i.e. rpc and subscription\n procClosesWithInit: boolean;\n\n // server level\n serviceContext: ServiceContext & { state: object };\n procedure: AnyProcedure;\n sessionMetadata: ParsedMetadata;\n\n // transport level\n initialSession: IdentifiedSession;\n\n // TODO remove once clients migrate to v2\n passInitAsDataForBackwardsCompat: boolean;\n}\n\ninterface ProcStream {\n streamId: StreamId;\n from: TransportClientId;\n procedureName: string;\n serviceName: string;\n sessionMetadata: ParsedMetadata;\n procedure: AnyProcedure;\n handleMsg: (msg: OpaqueTransportMessage) => void;\n handleSessionDisconnect: () => void;\n}\n\nclass RiverServer<Services extends AnyServiceSchemaMap>\n implements Server<Services>\n{\n private transport: ServerTransport<Connection>;\n private contextMap: Map<AnyService, ServiceContext & { state: object }>;\n private log?: Logger;\n\n /**\n * We create a tombstones for streams cancelled by the server\n * so that we don't hit errors when the client has inflight\n * requests it sent before it saw the cancel.\n * We track cancelled streams for every client separately, so\n * that bad clients don't affect good clients.\n */\n private serverCancelledStreams: Map<TransportClientId, LRUSet<StreamId>>;\n private maxCancelledStreamTombstonesPerSession: number;\n\n public streams: Map<StreamId, ProcStream>;\n public services: InstantiatedServiceSchemaMap<Services>;\n\n constructor(\n transport: ServerTransport<Connection>,\n services: Services,\n handshakeOptions?: ServerHandshakeOptions,\n extendedContext?: Omit<ServiceContext, 'state'>,\n maxCancelledStreamTombstonesPerSession = 200,\n ) {\n const instances: Record<string, AnyService> = {};\n\n this.services = instances as InstantiatedServiceSchemaMap<Services>;\n this.contextMap = new Map();\n\n for (const [name, service] of Object.entries(services)) {\n const instance = service.instantiate(extendedContext ?? {});\n instances[name] = instance;\n\n this.contextMap.set(instance, {\n ...extendedContext,\n state: instance.state,\n });\n }\n\n if (handshakeOptions) {\n transport.extendHandshake(handshakeOptions);\n }\n\n this.transport = transport;\n this.streams = new Map();\n this.serverCancelledStreams = new Map();\n this.maxCancelledStreamTombstonesPerSession =\n maxCancelledStreamTombstonesPerSession;\n this.log = transport.log;\n\n const handleCreatingNewStreams = (message: EventMap['message']) => {\n if (message.to !== this.transport.clientId) {\n this.log?.info(\n `got msg with destination that isn't this server, ignoring`,\n {\n clientId: this.transport.clientId,\n transportMessage: message,\n },\n );\n\n return;\n }\n\n const streamId = message.streamId;\n const stream = this.streams.get(streamId);\n if (stream) {\n stream.handleMsg(message);\n\n return;\n }\n\n // if this is a cancelled stream it's safe to ignore\n if (this.serverCancelledStreams.get(message.from)?.has(streamId)) {\n return;\n }\n\n // if this stream init request is invalid, don't bother creating a stream\n // and tell the client to cancel\n const newStreamProps = this.validateNewProcStream(message);\n if (!newStreamProps) {\n return;\n }\n\n // if its not a cancelled stream, validate and create a new stream\n const newStream = this.createNewProcStream({\n ...newStreamProps,\n ...message,\n });\n this.streams.set(streamId, newStream);\n };\n\n const handleSessionStatus = (evt: EventMap['sessionStatus']) => {\n if (evt.status !== 'disconnect') return;\n\n const disconnectedClientId = evt.session.to;\n this.log?.info(\n `got session disconnect from ${disconnectedClientId}, cleaning up streams`,\n evt.session.loggingMetadata,\n );\n\n for (const stream of this.streams.values()) {\n if (stream.from === disconnectedClientId) {\n stream.handleSessionDisconnect();\n }\n }\n\n this.serverCancelledStreams.delete(disconnectedClientId);\n };\n\n const handleTransportStatus = (evt: EventMap['transportStatus']) => {\n if (evt.status !== 'closed') return;\n this.transport.removeEventListener('message', handleCreatingNewStreams);\n this.transport.removeEventListener('sessionStatus', handleSessionStatus);\n this.transport.removeEventListener(\n 'transportStatus',\n handleTransportStatus,\n );\n };\n\n this.transport.addEventListener('message', handleCreatingNewStreams);\n this.transport.addEventListener('sessionStatus', handleSessionStatus);\n this.transport.addEventListener('transportStatus', handleTransportStatus);\n }\n\n private createNewProcStream(props: StreamInitProps): ProcStream {\n const {\n streamId,\n initialSession,\n procedureName,\n serviceName,\n procedure,\n sessionMetadata,\n serviceContext,\n initPayload,\n tracingCtx,\n procClosesWithInit,\n passInitAsDataForBackwardsCompat,\n } = props;\n\n const {\n to: from,\n loggingMetadata,\n protocolVersion,\n id: sessionId,\n } = initialSession;\n\n let cleanClose = true;\n const onMessage = (msg: OpaqueTransportMessage) => {\n if (msg.from !== from) {\n this.log?.error('got stream message from unexpected client', {\n ...loggingMetadata,\n transportMessage: msg,\n tags: ['invariant-violation'],\n });\n\n return;\n }\n\n if (isStreamCancelBackwardsCompat(msg.controlFlags, protocolVersion)) {\n let cancelResult: Static<typeof CancelResultSchema>;\n if (Value.Check(CancelResultSchema, msg.payload)) {\n cancelResult = msg.payload;\n } else {\n // If the payload is unexpected, then we just construct our own cancel result\n cancelResult = Err({\n code: CANCEL_CODE,\n message: 'stream cancelled, client sent invalid payload',\n });\n this.log?.warn('got stream cancel without a valid protocol error', {\n ...loggingMetadata,\n transportMessage: msg,\n validationErrors: [\n ...Value.Errors(CancelResultSchema, msg.payload),\n ],\n tags: ['invalid-request'],\n });\n }\n\n if (!reqReadable.isClosed()) {\n reqReadable._pushValue(cancelResult);\n closeReadable();\n }\n\n resWritable.close();\n\n return;\n }\n\n if (reqReadable.isClosed()) {\n this.log?.warn('received message after request stream is closed', {\n ...loggingMetadata,\n transportMessage: msg,\n tags: ['invalid-request'],\n });\n\n onServerCancel({\n code: INVALID_REQUEST_CODE,\n message: 'received message after request stream is closed',\n });\n\n return;\n }\n\n // normal request data for upload or stream\n if (\n 'requestData' in procedure &&\n Value.Check(procedure.requestData, msg.payload)\n ) {\n reqReadable._pushValue(Ok(msg.payload));\n\n if (isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)) {\n // It's atypical for any of our post-v1 clients to send a close with a\n // request payload, but it's technically legal, so we'll handle it.\n closeReadable();\n }\n\n return;\n }\n\n if (\n Value.Check(ControlMessagePayloadSchema, msg.payload) &&\n isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)\n ) {\n // Clients typically send this shape of close for stream and upload\n // after they're done.\n closeReadable();\n\n return;\n }\n\n // We couldn't make sense of the message, it's probably a bad request\n let validationErrors: Array<ValueError>;\n let errMessage: string;\n if ('requestData' in procedure) {\n errMessage = 'expected requestData or control payload';\n validationErrors = [\n ...Value.Errors(procedure.responseData, msg.payload),\n ];\n } else {\n validationErrors = [\n ...Value.Errors(ControlMessagePayloadSchema, msg.payload),\n ];\n errMessage = 'expected control payload';\n }\n\n this.log?.warn(errMessage, {\n ...loggingMetadata,\n transportMessage: msg,\n validationErrors,\n tags: ['invalid-request'],\n });\n\n onServerCancel({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n });\n };\n\n const procStream: ProcStream = {\n from: from,\n streamId,\n procedureName,\n serviceName,\n sessionMetadata,\n procedure,\n handleMsg: onMessage,\n handleSessionDisconnect: () => {\n cleanClose = false;\n const errPayload = {\n code: UNEXPECTED_DISCONNECT_CODE,\n message: 'client unexpectedly disconnected',\n } as const;\n\n if (!reqReadable.isClosed()) {\n reqReadable._pushValue(Err(errPayload));\n closeReadable();\n }\n\n resWritable.close();\n },\n };\n\n const sessionScopedSend = this.transport.getSessionBoundSendFn(\n from,\n sessionId,\n );\n\n const cancelStream = (\n streamId: StreamId,\n payload: ErrResult<Static<typeof ReaderErrorSchema>>,\n ) => {\n this.cancelStream(from, sessionScopedSend, streamId, payload);\n };\n\n const onServerCancel = (e: Static<typeof ReaderErrorSchema>) => {\n if (reqReadable.isClosed() && resWritable.isClosed()) {\n // Everything already closed, no-op.\n return;\n }\n\n cleanClose = false;\n const result = Err(e);\n if (!reqReadable.isClosed()) {\n reqReadable._pushValue(result);\n closeReadable();\n }\n\n resWritable.close();\n cancelStream(streamId, result);\n };\n\n const finishedController = new AbortController();\n const cleanup = () => {\n finishedController.abort();\n this.streams.delete(streamId);\n };\n\n const procClosesWithResponse =\n procedure.type === 'rpc' || procedure.type === 'upload';\n\n const reqReadable = new ReadableImpl<\n Static<PayloadType>,\n Static<typeof ReaderErrorSchema>\n >();\n const closeReadable = () => {\n reqReadable._triggerClose();\n\n // TODO remove once clients migrate to v2\n if (protocolVersion === 'v1.1') {\n // in v1.1 a close in either direction should close everything\n // for upload/rpc it will handle the close after it responds\n if (!procClosesWithResponse && !resWritable.isClosed()) {\n resWritable.close();\n }\n }\n\n if (resWritable.isClosed()) {\n cleanup();\n }\n };\n\n if (passInitAsDataForBackwardsCompat) {\n reqReadable._pushValue(Ok(initPayload));\n }\n\n const resWritable = new WritableImpl<\n Result<Static<PayloadType>, Static<BaseErrorSchemaType>>\n >({\n writeCb: (response) => {\n sessionScopedSend({\n streamId,\n controlFlags: procClosesWithResponse\n ? getStreamCloseBackwardsCompat(protocolVersion)\n : 0,\n payload: response,\n });\n\n if (procClosesWithResponse) {\n resWritable.close();\n }\n },\n // close callback\n closeCb: () => {\n if (!procClosesWithResponse && cleanClose) {\n // we ended, send a close bit back to the client\n // also, if the client has disconnected, we don't need to send a close\n\n const message = closeStreamMessage(streamId);\n // TODO remove once clients migrate to v2\n message.controlFlags = getStreamCloseBackwardsCompat(protocolVersion);\n\n sessionScopedSend(message);\n }\n\n // TODO remove once clients migrate to v2\n if (protocolVersion === 'v1.1') {\n // in v1.1 a close in either direction should close everything\n if (!reqReadable.isClosed()) {\n closeReadable();\n }\n }\n\n if (reqReadable.isClosed()) {\n cleanup();\n }\n },\n });\n\n const onHandlerError = (err: unknown, span: Span) => {\n const errorMsg = coerceErrorString(err);\n\n span.recordException(err instanceof Error ? err : new Error(errorMsg));\n span.setStatus({ code: SpanStatusCode.ERROR });\n\n this.log?.error(\n `${serviceName}.${procedureName} handler threw an uncaught error`,\n {\n ...loggingMetadata,\n transportMessage: {\n procedureName,\n serviceName,\n },\n extras: {\n error: errorMsg,\n originalException: err,\n },\n tags: ['uncaught-handler-error'],\n },\n );\n\n onServerCancel({\n code: UNCAUGHT_ERROR_CODE,\n message: errorMsg,\n });\n };\n\n // if the init message has a close flag then we know this stream\n // only consists of an init message and we shouldn't expect follow up data\n if (procClosesWithInit) {\n closeReadable();\n } else if (procedure.type === 'rpc' || procedure.type === 'subscription') {\n // Though things can work just fine if they eventually follow up with a stream\n // control message with a close bit set, it's an unusual client implementation!\n this.log?.warn('sent an init without a stream close', loggingMetadata);\n }\n\n const handlerContext: ProcedureHandlerContext<object> = {\n ...serviceContext,\n from: from,\n sessionId,\n metadata: sessionMetadata,\n cancel: () => {\n onServerCancel({\n code: CANCEL_CODE,\n message: 'cancelled by server procedure handler',\n });\n },\n signal: finishedController.signal,\n };\n\n switch (procedure.type) {\n case 'rpc':\n void createHandlerSpan(\n procedure.type,\n serviceName,\n procedureName,\n streamId,\n tracingCtx,\n async (span): ProcHandlerReturn => {\n try {\n const responsePayload = await procedure.handler({\n ctx: handlerContext,\n reqInit: initPayload,\n });\n\n if (resWritable.isClosed()) {\n // A disconnect happened\n return;\n }\n\n resWritable.write(responsePayload);\n } catch (err) {\n onHandlerError(err, span);\n } finally {\n span.end();\n }\n },\n );\n break;\n case 'stream':\n void createHandlerSpan(\n procedure.type,\n serviceName,\n procedureName,\n streamId,\n tracingCtx,\n async (span): ProcHandlerReturn => {\n try {\n await procedure.handler({\n ctx: handlerContext,\n reqInit: initPayload,\n reqReadable,\n resWritable,\n });\n } catch (err) {\n onHandlerError(err, span);\n } finally {\n span.end();\n }\n },\n );\n\n break;\n case 'subscription':\n void createHandlerSpan(\n procedure.type,\n serviceName,\n procedureName,\n streamId,\n tracingCtx,\n async (span): ProcHandlerReturn => {\n try {\n await procedure.handler({\n ctx: handlerContext,\n reqInit: initPayload,\n resWritable: resWritable,\n });\n } catch (err) {\n onHandlerError(err, span);\n } finally {\n span.end();\n }\n },\n );\n break;\n case 'upload':\n void createHandlerSpan(\n procedure.type,\n serviceName,\n procedureName,\n streamId,\n tracingCtx,\n async (span): ProcHandlerReturn => {\n try {\n const responsePayload = await procedure.handler({\n ctx: handlerContext,\n reqInit: initPayload,\n reqReadable: reqReadable,\n });\n\n if (resWritable.isClosed()) {\n // A disconnect happened\n return;\n }\n\n resWritable.write(responsePayload);\n } catch (err) {\n onHandlerError(err, span);\n } finally {\n span.end();\n }\n },\n );\n\n break;\n }\n\n return procStream;\n }\n\n private getContext(service: AnyService, serviceName: string) {\n const context = this.contextMap.get(service);\n if (!context) {\n const err = `no context found for ${serviceName}`;\n this.log?.error(err, {\n clientId: this.transport.clientId,\n tags: ['invariant-violation'],\n });\n throw new Error(err);\n }\n\n return context;\n }\n\n private validateNewProcStream(\n initMessage: OpaqueTransportMessage,\n ): StreamInitProps | null {\n // lifetime safety: this is a sync function so this session cant transition\n // to another state before we finish\n const session = this.transport.sessions.get(initMessage.from);\n if (!session) {\n // this should be impossible, how did we receive a message from a session that doesn't exist?\n // log anyways\n this.log?.error(`couldn't find session for ${initMessage.from}`, {\n clientId: this.transport.clientId,\n transportMessage: initMessage,\n tags: ['invariant-violation'],\n });\n\n return null;\n }\n\n const sessionScopedSend = this.transport.getSessionBoundSendFn(\n initMessage.from,\n session.id,\n );\n\n const cancelStream = (\n streamId: StreamId,\n payload: ErrResult<Static<typeof ReaderErrorSchema>>,\n ) => {\n this.cancelStream(initMessage.from, sessionScopedSend, streamId, payload);\n };\n\n const sessionMetadata = this.transport.sessionHandshakeMetadata.get(\n session.to,\n );\n\n if (!sessionMetadata) {\n const errMessage = `session doesn't have handshake metadata`;\n this.log?.error(errMessage, {\n ...session.loggingMetadata,\n tags: ['invariant-violation'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: UNCAUGHT_ERROR_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n if (!isStreamOpen(initMessage.controlFlags)) {\n const errMessage = `can't create a new procedure stream from a message that doesn't have the stream open bit set`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n clientId: this.transport.clientId,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n if (!initMessage.serviceName) {\n const errMessage = `missing service name in stream open message`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n if (!initMessage.procedureName) {\n const errMessage = `missing procedure name in stream open message`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n if (!(initMessage.serviceName in this.services)) {\n const errMessage = `couldn't find service ${initMessage.serviceName}`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n clientId: this.transport.clientId,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n const service = this.services[initMessage.serviceName];\n if (!(initMessage.procedureName in service.procedures)) {\n const errMessage = `couldn't find a matching procedure for ${initMessage.serviceName}.${initMessage.procedureName}`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n const serviceContext = this.getContext(service, initMessage.serviceName);\n\n const procedure: AnyProcedure =\n service.procedures[initMessage.procedureName];\n\n if (!['rpc', 'upload', 'stream', 'subscription'].includes(procedure.type)) {\n this.log?.error(\n `got request for invalid procedure type ${procedure.type} at ${initMessage.serviceName}.${initMessage.procedureName}`,\n {\n ...session.loggingMetadata,\n transportMessage: initMessage,\n tags: ['invariant-violation'],\n },\n );\n\n return null;\n }\n\n let passInitAsDataForBackwardsCompat = false;\n if (\n session.protocolVersion === 'v1.1' &&\n (procedure.type === 'upload' || procedure.type === 'stream') &&\n Value.Check(procedure.requestData, initMessage.payload) &&\n Value.Check(procedure.requestInit, {})\n ) {\n // TODO remove once clients migrate to v2\n // In v1.1 sometimes the first message is not `init`, but instead it's the `input`\n // this backwards compatibility path requires procedures to define their `init` as\n // an empty-object-compatible-schema (i.e. either actually empty or optional values)\n // The reason we don't check if `init` is satisified here is because false positives\n // are easy to hit, we'll err on the side of caution and treat it as a request, servers\n // that expect v1.1 clients should handle this case themselves.\n passInitAsDataForBackwardsCompat = true;\n } else if (!Value.Check(procedure.requestInit, initMessage.payload)) {\n const errMessage = `procedure init failed validation`;\n this.log?.warn(errMessage, {\n ...session.loggingMetadata,\n clientId: this.transport.clientId,\n transportMessage: initMessage,\n tags: ['invalid-request'],\n });\n\n cancelStream(\n initMessage.streamId,\n Err({\n code: INVALID_REQUEST_CODE,\n message: errMessage,\n }),\n );\n\n return null;\n }\n\n return {\n initialSession: session,\n streamId: initMessage.streamId,\n procedureName: initMessage.procedureName,\n serviceName: initMessage.serviceName,\n tracingCtx: initMessage.tracing,\n initPayload: initMessage.payload,\n sessionMetadata,\n procedure,\n serviceContext,\n procClosesWithInit: isStreamCloseBackwardsCompat(\n initMessage.controlFlags,\n session.protocolVersion,\n ),\n passInitAsDataForBackwardsCompat,\n };\n }\n\n cancelStream(\n to: TransportClientId,\n sessionScopedSend: SessionBoundSendFn,\n streamId: StreamId,\n payload: ErrResult<Static<typeof ReaderErrorSchema>>,\n ) {\n let cancelledStreamsInSession = this.serverCancelledStreams.get(to);\n if (!cancelledStreamsInSession) {\n cancelledStreamsInSession = new LRUSet(\n this.maxCancelledStreamTombstonesPerSession,\n );\n\n this.serverCancelledStreams.set(to, cancelledStreamsInSession);\n }\n\n cancelledStreamsInSession.add(streamId);\n const msg = cancelMessage(streamId, payload);\n sessionScopedSend(msg);\n }\n}\n\nclass LRUSet<T> {\n private items: Set<T>;\n private maxItems: number;\n\n constructor(maxItems: number) {\n this.items = new Set();\n this.maxItems = maxItems;\n }\n\n add(item: T) {\n if (this.items.has(item)) {\n this.items.delete(item);\n } else if (this.items.size >= this.maxItems) {\n const first = this.items.values().next();\n if (!first.done) {\n this.items.delete(first.value);\n }\n }\n this.items.add(item);\n }\n\n has(item: T) {\n return this.items.has(item);\n }\n}\n\n// TODO remove once clients migrate to v2\nfunction isStreamCancelBackwardsCompat(\n controlFlags: ControlFlags,\n protocolVersion: ProtocolVersion,\n) {\n if (protocolVersion === 'v1.1') {\n // in 1.1 we don't have abort\n return false;\n }\n\n return isStreamCancel(controlFlags);\n}\n\n// TODO remove once clients migrate to v2\nfunction isStreamCloseBackwardsCompat(\n controlFlags: ControlFlags,\n protocolVersion: ProtocolVersion,\n) {\n if (protocolVersion === 'v1.1') {\n // in v1.1 the bits for close is what we use for cancel now\n return isStreamCancel(controlFlags);\n }\n\n return isStreamClose(controlFlags);\n}\n\n// TODO remove once clients migrate to v2\nfunction getStreamCloseBackwardsCompat(protocolVersion: ProtocolVersion) {\n if (protocolVersion === 'v1.1') {\n // in v1.1 the bits for close is what we use for cancel now\n return ControlFlags.StreamCancelBit;\n }\n\n return ControlFlags.StreamClosedBit;\n}\n\n/**\n * Creates a server instance that listens for incoming messages from a transport and routes them to the appropriate service and procedure.\n * The server tracks the state of each service along with open streams and the extended context object.\n * @param transport - The transport to listen to.\n * @param services - An object containing all the services to be registered on the server.\n * @param handshakeOptions - An optional object containing additional handshake options to be passed to the transport.\n * @param extendedContext - An optional object containing additional context to be passed to all services.\n * @returns A promise that resolves to a server instance with the registered services.\n */\nexport function createServer<Services extends AnyServiceSchemaMap>(\n transport: ServerTransport<Connection>,\n services: Services,\n providedServerOptions?: Partial<{\n handshakeOptions?: ServerHandshakeOptions;\n extendedContext?: Omit<ServiceContext, 'state'>;\n /**\n * Maximum number of cancelled streams to keep track of to avoid\n * cascading stream errors.\n */\n maxCancelledStreamTombstonesPerSession?: number;\n }>,\n): Server<Services> {\n return new RiverServer(\n transport,\n services,\n providedServerOptions?.handshakeOptions,\n providedServerOptions?.extendedContext,\n providedServerOptions?.maxCancelledStreamTombstonesPerSession,\n );\n}\n","import { Static, TSchema } from '@sinclair/typebox';\nimport { ParsedMetadata } from './context';\nimport { HandshakeErrorCustomHandlerFatalResponseCodes } from '../transport/message';\n\ntype ConstructHandshake<T extends TSchema> = () =>\n | Static<T>\n | Promise<Static<T>>;\n\ntype ValidateHandshake<T extends TSchema> = (\n metadata: Static<T>,\n previousParsedMetadata?: ParsedMetadata,\n) =>\n | Static<typeof HandshakeErrorCustomHandlerFatalResponseCodes>\n | ParsedMetadata\n | Promise<\n | Static<typeof HandshakeErrorCustomHandlerFatalResponseCodes>\n | ParsedMetadata\n >;\n\nexport interface ClientHandshakeOptions<\n MetadataSchema extends TSchema = TSchema,\n> {\n /**\n * Schema for the metadata that the client sends to the server\n * during the handshake.\n */\n schema: MetadataSchema;\n\n /**\n * Gets the {@link HandshakeRequestMetadata} to send to the server.\n */\n construct: ConstructHandshake<MetadataSchema>;\n}\n\nexport interface ServerHandshakeOptions<\n MetadataSchema extends TSchema = TSchema,\n> {\n /**\n * Schema for the metadata that the server receives from the client\n * during the handshake.\n */\n schema: MetadataSchema;\n\n /**\n * Parses the {@link HandshakeRequestMetadata} sent by the client, transforming\n * it into {@link ParsedHandshakeMetadata}.\n *\n * May return `false` if the client should be rejected.\n *\n * @param metadata - The metadata sent by the client.\n * @param session - The session that the client would be associated with.\n * @param isReconnect - Whether the client is reconnecting to the session,\n * or if this is a new session.\n */\n validate: ValidateHandshake<MetadataSchema>;\n}\n\nexport function createClientHandshakeOptions<\n MetadataSchema extends TSchema = TSchema,\n>(\n schema: MetadataSchema,\n construct: ConstructHandshake<MetadataSchema>,\n): ClientHandshakeOptions {\n return { schema, construct };\n}\n\nexport function createServerHandshakeOptions<\n MetadataSchema extends TSchema = TSchema,\n>(\n schema: MetadataSchema,\n validate: ValidateHandshake<MetadataSchema>,\n): ServerHandshakeOptions {\n return { schema, validate: validate as ValidateHandshake<TSchema> };\n}\n"],"mappings":"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","names":["Type","Type","Value","Type","stream","Value","streamId"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Connection, y as CommonSession, d as SessionState, z as CommonSessionProps, T as Transport, A as ServerTransportOptions, u as ServerHandshakeOptions, t as ParsedMetadata, B as ServerSession, c as ProvidedServerTransportOptions, D as DeleteSessionOptions } from './context-
|
|
2
|
-
import { e as ProtocolVersion, b as OpaqueTransportMessage, f as Tags, a as TransportMessage, H as HandshakeErrorResponseCodes, c as TransportClientId } from './message-
|
|
1
|
+
import { C as Connection, y as CommonSession, d as SessionState, z as CommonSessionProps, T as Transport, A as ServerTransportOptions, u as ServerHandshakeOptions, t as ParsedMetadata, B as ServerSession, c as ProvidedServerTransportOptions, D as DeleteSessionOptions } from './context-8d1ed9a1.js';
|
|
2
|
+
import { e as ProtocolVersion, b as OpaqueTransportMessage, f as Tags, a as TransportMessage, H as HandshakeErrorResponseCodes, c as TransportClientId } from './message-45658364.js';
|
|
3
3
|
import * as _sinclair_typebox_errors from '@sinclair/typebox/errors';
|
|
4
4
|
import { Static } from '@sinclair/typebox';
|
|
5
5
|
|
|
@@ -33,7 +33,7 @@ declare class SessionWaitingForHandshake<ConnType extends Connection> extends Co
|
|
|
33
33
|
traceId: string;
|
|
34
34
|
spanId: string;
|
|
35
35
|
} | undefined;
|
|
36
|
-
extras?: unknown;
|
|
36
|
+
extras?: Record<string, unknown> | undefined;
|
|
37
37
|
};
|
|
38
38
|
onHandshakeData: (msg: Uint8Array) => void;
|
|
39
39
|
sendHandshake(msg: TransportMessage): boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TObject, TString, TSchema, TUnion, TLiteral, TNever, Static } from '@sinclair/typebox';
|
|
2
|
-
import { C as Connection, q as ClientHandshakeOptions, v as ProcedureHandlerContext, p as ServiceContext } from './context-
|
|
3
|
-
import { c as TransportClientId } from './message-
|
|
4
|
-
import { C as ClientTransport } from './client-
|
|
2
|
+
import { C as Connection, q as ClientHandshakeOptions, v as ProcedureHandlerContext, p as ServiceContext } from './context-8d1ed9a1.js';
|
|
3
|
+
import { c as TransportClientId } from './message-45658364.js';
|
|
4
|
+
import { C as ClientTransport } from './client-ba6815ae.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* {@link UNCAUGHT_ERROR_CODE} is the code that is used when an error is thrown
|
|
@@ -70,7 +70,10 @@ type Flatten<T> = T extends BaseErrorSchemaType ? T : T extends TUnion<Array<inf
|
|
|
70
70
|
*/
|
|
71
71
|
declare function flattenErrorType<T extends NestableProcedureErrorSchemaType>(errType: T): Flatten<T>;
|
|
72
72
|
|
|
73
|
-
declare const ReadableBrokenError:
|
|
73
|
+
declare const ReadableBrokenError: {
|
|
74
|
+
readonly code: "READABLE_BROKEN";
|
|
75
|
+
readonly message: "Readable was broken before it is fully consumed";
|
|
76
|
+
};
|
|
74
77
|
/**
|
|
75
78
|
* Similar to {@link Result} but with an extra error to handle cases where {@link Readable.break} is called
|
|
76
79
|
*/
|
|
@@ -634,7 +634,7 @@ var SessionNoConnection = class extends IdentifiedSessionWithGracePeriod {
|
|
|
634
634
|
var import_api = require("@opentelemetry/api");
|
|
635
635
|
|
|
636
636
|
// package.json
|
|
637
|
-
var version = "0.200.
|
|
637
|
+
var version = "0.200.4";
|
|
638
638
|
|
|
639
639
|
// tracing/index.ts
|
|
640
640
|
function getPropagationContext(ctx) {
|