{"version":3,"file":"ws-CnhJbg02.mjs","names":["jsonEncoder: Encoder","opts: WSSHandlerOptions<TRouter>","client: ws.WebSocket","req: IncomingMessage","untransformedJSON: TRPCResponseMessage","getConnectionParams: () => TRPCRequestInfo['connectionParams']","ctx: Context | undefined","msg: TRPCClientOutgoingMessage","batchIndex: number","abortController","next:\n            | null\n            | TRPCError\n            | Awaited<\n                typeof abortPromise | ReturnType<(typeof iterator)['next']>\n              >","result: null | TRPCResultMessage<unknown>['result']","id","data: string | Uint8Array","msgJSON: unknown","msgs: unknown[]","timeout: NodeJS.Timeout | undefined","ping: NodeJS.Timeout | undefined","response: TRPCReconnectNotification"],"sources":["../src/adapters/wsEncoder.ts","../src/adapters/ws.ts"],"sourcesContent":["/**\n * Encoder for WebSocket wire format.\n * Encodes outgoing messages and decodes incoming messages.\n *\n * @example\n * ```ts\n * const customEncoder: Encoder = {\n *   encode: (data) => myFormat.stringify(data),\n *   decode: (data) => myFormat.parse(data),\n * };\n * ```\n */\nexport interface Encoder {\n  /** Encode data for transmission over the wire */\n  encode(data: unknown): string | Uint8Array;\n  /** Decode data received from the wire */\n  decode(data: string | ArrayBuffer | Uint8Array): unknown;\n}\n\n/**\n * Default JSON encoder - used when no encoder is specified.\n * This maintains backwards compatibility with existing behavior.\n */\nexport const jsonEncoder: Encoder = {\n  encode: (data) => JSON.stringify(data),\n  decode: (data) => {\n    if (typeof data !== 'string') {\n      throw new Error(\n        'jsonEncoder received binary data. JSON uses text frames. ' +\n          'Use a binary encoder for binary data.',\n      );\n    }\n    return JSON.parse(data);\n  },\n};\n","import type { IncomingMessage } from 'http';\nimport type ws from 'ws';\nimport type {\n  AnyRouter,\n  CreateContextCallback,\n  inferRouterContext,\n} from '../@trpc/server';\nimport {\n  callTRPCProcedure,\n  getErrorShape,\n  getTRPCErrorFromUnknown,\n  transformTRPCResponse,\n  TRPCError,\n} from '../@trpc/server';\nimport type { TRPCRequestInfo } from '../@trpc/server/http';\nimport { type BaseHandlerOptions } from '../@trpc/server/http';\nimport { parseTRPCMessage } from '../@trpc/server/rpc';\n// @trpc/server/rpc\nimport type {\n  TRPCClientOutgoingMessage,\n  TRPCConnectionParamsMessage,\n  TRPCReconnectNotification,\n  TRPCResponseMessage,\n  TRPCResultMessage,\n} from '../@trpc/server/rpc';\nimport { parseConnectionParamsFromUnknown } from '../http';\nimport { isObservable, observableToAsyncIterable } from '../observable';\n// eslint-disable-next-line no-restricted-imports\nimport {\n  isAsyncIterable,\n  isObject,\n  isTrackedEnvelope,\n  run,\n  type MaybePromise,\n} from '../unstable-core-do-not-import';\n// eslint-disable-next-line no-restricted-imports\nimport type { Result } from '../unstable-core-do-not-import';\n// eslint-disable-next-line no-restricted-imports\nimport { iteratorResource } from '../unstable-core-do-not-import/stream/utils/asyncIterable';\nimport { Unpromise } from '../vendor/unpromise';\nimport { createURL, type NodeHTTPCreateContextFnOptions } from './node-http';\nimport type { Encoder } from './wsEncoder';\nimport { jsonEncoder } from './wsEncoder';\n\n/**\n * Importing ws causes a build error\n * @see https://github.com/trpc/trpc/pull/5279\n */\nconst WEBSOCKET_OPEN = 1; /* ws.WebSocket.OPEN */\n\n/**\n * @public\n */\nexport type CreateWSSContextFnOptions = NodeHTTPCreateContextFnOptions<\n  IncomingMessage,\n  ws.WebSocket\n>;\n\n/**\n * @public\n */\nexport type CreateWSSContextFn<TRouter extends AnyRouter> = (\n  opts: CreateWSSContextFnOptions,\n) => MaybePromise<inferRouterContext<TRouter>>;\n\nexport type WSConnectionHandlerOptions<TRouter extends AnyRouter> =\n  BaseHandlerOptions<TRouter, IncomingMessage> &\n    CreateContextCallback<\n      inferRouterContext<TRouter>,\n      CreateWSSContextFn<TRouter>\n    >;\n\n/**\n * Web socket server handler\n */\nexport type WSSHandlerOptions<TRouter extends AnyRouter> =\n  WSConnectionHandlerOptions<TRouter> & {\n    wss: ws.WebSocketServer;\n    prefix?: string;\n    keepAlive?: {\n      /**\n       * Enable heartbeat messages\n       * @default false\n       */\n      enabled: boolean;\n      /**\n       * Heartbeat interval in milliseconds\n       * @default 30_000\n       */\n      pingMs?: number;\n      /**\n       * Terminate the WebSocket if no pong is received after this many milliseconds\n       * @default 5_000\n       */\n      pongWaitMs?: number;\n    };\n    /**\n     * Disable responding to ping messages from the client\n     * **Not recommended** - this is mainly used for testing\n     * @default false\n     */\n    dangerouslyDisablePong?: boolean;\n    /**\n     * Custom encoder for wire encoding (e.g. custom binary formats)\n     * @default jsonEncoder\n     */\n    experimental_encoder?: Encoder;\n  };\n\nexport function getWSConnectionHandler<TRouter extends AnyRouter>(\n  opts: WSSHandlerOptions<TRouter>,\n) {\n  const { createContext, router } = opts;\n  const { transformer } = router._def._config;\n  const encoder = opts.experimental_encoder ?? jsonEncoder;\n\n  return (client: ws.WebSocket, req: IncomingMessage) => {\n    type Context = inferRouterContext<TRouter>;\n    type ContextResult = Result<Context>;\n\n    const clientSubscriptions = new Map<number | string, AbortController>();\n    const abortController = new AbortController();\n\n    if (opts.keepAlive?.enabled) {\n      const { pingMs, pongWaitMs } = opts.keepAlive;\n      handleKeepAlive(client, pingMs, pongWaitMs);\n    }\n\n    function respond(untransformedJSON: TRPCResponseMessage) {\n      client.send(\n        encoder.encode(\n          transformTRPCResponse(router._def._config, untransformedJSON),\n        ),\n      );\n    }\n\n    async function createCtxPromise(\n      getConnectionParams: () => TRPCRequestInfo['connectionParams'],\n    ): Promise<ContextResult> {\n      try {\n        return await run(async (): Promise<ContextResult> => {\n          ctx = await createContext?.({\n            req,\n            res: client,\n            info: {\n              connectionParams: getConnectionParams(),\n              calls: [],\n              isBatchCall: false,\n              accept: null,\n              type: 'unknown',\n              signal: abortController.signal,\n              url: null,\n            },\n          });\n\n          return {\n            ok: true,\n            value: ctx,\n          };\n        });\n      } catch (cause) {\n        const error = getTRPCErrorFromUnknown(cause);\n        opts.onError?.({\n          error,\n          path: undefined,\n          type: 'unknown',\n          ctx,\n          req,\n          input: undefined,\n        });\n        respond({\n          id: null,\n          error: getErrorShape({\n            config: router._def._config,\n            error,\n            type: 'unknown',\n            path: undefined,\n            input: undefined,\n            ctx,\n          }),\n        });\n\n        // close in next tick\n        (globalThis.setImmediate ?? globalThis.setTimeout)(() => {\n          client.close();\n        });\n        return {\n          ok: false,\n          error,\n        };\n      }\n    }\n\n    let ctx: Context | undefined = undefined;\n\n    /**\n     * promise for initializing the context\n     *\n     * - the context promise will be created immediately on connection if no connectionParams are expected\n     * - if connection params are expected, they will be created once received\n     */\n    let ctxPromise =\n      createURL(req).searchParams.get('connectionParams') === '1'\n        ? null\n        : createCtxPromise(() => null);\n\n    function handleRequest(msg: TRPCClientOutgoingMessage, batchIndex: number) {\n      const { id, jsonrpc } = msg;\n\n      if (id === null) {\n        const error = getTRPCErrorFromUnknown(\n          new TRPCError({\n            code: 'PARSE_ERROR',\n            message: '`id` is required',\n          }),\n        );\n        opts.onError?.({\n          error,\n          path: undefined,\n          type: 'unknown',\n          ctx,\n          req,\n          input: undefined,\n        });\n        respond({\n          id,\n          jsonrpc,\n          error: getErrorShape({\n            config: router._def._config,\n            error,\n            type: 'unknown',\n            path: undefined,\n            input: undefined,\n            ctx,\n          }),\n        });\n        return;\n      }\n      if (msg.method === 'subscription.stop') {\n        clientSubscriptions.get(id)?.abort();\n        return;\n      }\n      const { path, lastEventId } = msg.params;\n      let { input } = msg.params;\n      const type = msg.method;\n\n      if (lastEventId !== undefined) {\n        if (isObject(input)) {\n          input = {\n            ...input,\n            lastEventId: lastEventId,\n          };\n        } else {\n          input ??= {\n            lastEventId: lastEventId,\n          };\n        }\n      }\n      run(async () => {\n        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n        const res = await ctxPromise!; // asserts context has been set\n        if (!res.ok) {\n          throw res.error;\n        }\n\n        const abortController = new AbortController();\n        const result = await callTRPCProcedure({\n          router,\n          path,\n          getRawInput: async () => input,\n          ctx,\n          type,\n          signal: abortController.signal,\n          batchIndex,\n        });\n\n        const isIterableResult =\n          isAsyncIterable(result) || isObservable(result);\n\n        if (type !== 'subscription') {\n          if (isIterableResult) {\n            throw new TRPCError({\n              code: 'UNSUPPORTED_MEDIA_TYPE',\n              message: `Cannot return an async iterable or observable from a ${type} procedure with WebSockets`,\n            });\n          }\n          // send the value as data if the method is not a subscription\n          respond({\n            id,\n            jsonrpc,\n            result: {\n              type: 'data',\n              data: result,\n            },\n          });\n          return;\n        }\n\n        if (!isIterableResult) {\n          throw new TRPCError({\n            message: `Subscription ${path} did not return an observable or a AsyncGenerator`,\n            code: 'INTERNAL_SERVER_ERROR',\n          });\n        }\n\n        /* istanbul ignore next -- @preserve */\n        if (client.readyState !== WEBSOCKET_OPEN) {\n          // if the client got disconnected whilst initializing the subscription\n          // no need to send stopped message if the client is disconnected\n\n          return;\n        }\n\n        /* istanbul ignore next -- @preserve */\n        if (clientSubscriptions.has(id)) {\n          // duplicate request ids for client\n\n          throw new TRPCError({\n            message: `Duplicate id ${id}`,\n            code: 'BAD_REQUEST',\n          });\n        }\n\n        const iterable = isObservable(result)\n          ? observableToAsyncIterable(result, abortController.signal)\n          : result;\n\n        run(async () => {\n          await using iterator = iteratorResource(iterable);\n\n          const abortPromise = new Promise<'abort'>((resolve) => {\n            abortController.signal.onabort = () => resolve('abort');\n          });\n          // We need those declarations outside the loop for garbage collection reasons. If they\n          // were declared inside, they would not be freed until the next value is present.\n          let next:\n            | null\n            | TRPCError\n            | Awaited<\n                typeof abortPromise | ReturnType<(typeof iterator)['next']>\n              >;\n          let result: null | TRPCResultMessage<unknown>['result'];\n\n          while (true) {\n            next = await Unpromise.race([\n              iterator.next().catch(getTRPCErrorFromUnknown),\n              abortPromise,\n            ]);\n\n            if (next === 'abort') {\n              await iterator.return?.();\n              break;\n            }\n            if (next instanceof Error) {\n              const error = getTRPCErrorFromUnknown(next);\n              opts.onError?.({ error, path, type, ctx, req, input });\n              respond({\n                id,\n                jsonrpc,\n                error: getErrorShape({\n                  config: router._def._config,\n                  error,\n                  type,\n                  path,\n                  input,\n                  ctx,\n                }),\n              });\n              break;\n            }\n            if (next.done) {\n              break;\n            }\n\n            result = {\n              type: 'data',\n              data: next.value,\n            };\n\n            if (isTrackedEnvelope(next.value)) {\n              const [id, data] = next.value;\n              result.id = id;\n              result.data = {\n                id,\n                data,\n              };\n            }\n\n            respond({\n              id,\n              jsonrpc,\n              result,\n            });\n\n            // free up references for garbage collection\n            next = null;\n            result = null;\n          }\n\n          respond({\n            id,\n            jsonrpc,\n            result: {\n              type: 'stopped',\n            },\n          });\n          clientSubscriptions.delete(id);\n        }).catch((cause) => {\n          const error = getTRPCErrorFromUnknown(cause);\n          opts.onError?.({ error, path, type, ctx, req, input });\n          respond({\n            id,\n            jsonrpc,\n            error: getErrorShape({\n              config: router._def._config,\n              error,\n              type,\n              path,\n              input,\n              ctx,\n            }),\n          });\n          abortController.abort();\n        });\n        clientSubscriptions.set(id, abortController);\n\n        respond({\n          id,\n          jsonrpc,\n          result: {\n            type: 'started',\n          },\n        });\n      }).catch((cause) => {\n        // procedure threw an error\n        const error = getTRPCErrorFromUnknown(cause);\n        opts.onError?.({ error, path, type, ctx, req, input });\n        respond({\n          id,\n          jsonrpc,\n          error: getErrorShape({\n            config: router._def._config,\n            error,\n            type,\n            path,\n            input,\n            ctx,\n          }),\n        });\n      });\n    }\n    client.on('message', (rawData, isBinary) => {\n      // Handle PING/PONG as text regardless of encoder\n      if (!isBinary) {\n        // eslint-disable-next-line @typescript-eslint/no-base-to-string\n        const msgStr = rawData.toString();\n        if (msgStr === 'PONG') {\n          return;\n        }\n        if (msgStr === 'PING') {\n          if (!opts.dangerouslyDisablePong) {\n            client.send('PONG');\n          }\n          return;\n        }\n      }\n\n      // Convert rawData to a format our encoder accepts\n      // ws gives us Buffer for both text and binary frames\n      if (!Buffer.isBuffer(rawData)) {\n        const error = new TRPCError({\n          code: 'UNPROCESSABLE_CONTENT',\n          message: 'Unexpected WebSocket message format',\n        });\n        respond({\n          id: null,\n          error: getErrorShape({\n            config: router._def._config,\n            error,\n            type: 'unknown',\n            path: undefined,\n            input: undefined,\n            ctx,\n          }),\n        });\n        return;\n      }\n      const data: string | Uint8Array = isBinary\n        ? rawData\n        : rawData.toString('utf8');\n\n      if (!ctxPromise) {\n        // If the ctxPromise wasn't created immediately, we're expecting the first message to be a TRPCConnectionParamsMessage\n        ctxPromise = createCtxPromise(() => {\n          let msg;\n          try {\n            msg = encoder.decode(data) as TRPCConnectionParamsMessage;\n\n            if (!isObject(msg)) {\n              throw new Error('Message was not an object');\n            }\n          } catch (cause) {\n            throw new TRPCError({\n              code: 'PARSE_ERROR',\n              message: `Malformed TRPCConnectionParamsMessage`,\n              cause,\n            });\n          }\n\n          const connectionParams = parseConnectionParamsFromUnknown(msg.data);\n\n          return connectionParams;\n        });\n        return;\n      }\n\n      const parsedMsgs = run(() => {\n        try {\n          const msgJSON: unknown = encoder.decode(data);\n          const msgs: unknown[] = Array.isArray(msgJSON) ? msgJSON : [msgJSON];\n\n          return msgs.map((raw) => parseTRPCMessage(raw, transformer));\n        } catch (cause) {\n          const error = new TRPCError({\n            code: 'PARSE_ERROR',\n            cause,\n          });\n\n          respond({\n            id: null,\n            error: getErrorShape({\n              config: router._def._config,\n              error,\n              type: 'unknown',\n              path: undefined,\n              input: undefined,\n              ctx,\n            }),\n          });\n\n          return [];\n        }\n      });\n\n      parsedMsgs.map((msg, index) => handleRequest(msg, index));\n    });\n\n    // WebSocket errors should be handled, as otherwise unhandled exceptions will crash Node.js.\n    // This line was introduced after the following error brought down production systems:\n    // \"RangeError: Invalid WebSocket frame: RSV2 and RSV3 must be clear\"\n    // Here is the relevant discussion: https://github.com/websockets/ws/issues/1354#issuecomment-774616962\n    client.on('error', (cause) => {\n      opts.onError?.({\n        ctx,\n        error: getTRPCErrorFromUnknown(cause),\n        input: undefined,\n        path: undefined,\n        type: 'unknown',\n        req,\n      });\n    });\n\n    client.once('close', () => {\n      for (const sub of clientSubscriptions.values()) {\n        sub.abort();\n      }\n      clientSubscriptions.clear();\n      abortController.abort();\n    });\n  };\n}\n\n/**\n * Handle WebSocket keep-alive messages\n */\nexport function handleKeepAlive(\n  client: ws.WebSocket,\n  pingMs = 30_000,\n  pongWaitMs = 5_000,\n) {\n  let timeout: NodeJS.Timeout | undefined = undefined;\n  let ping: NodeJS.Timeout | undefined = undefined;\n\n  const schedulePing = () => {\n    const scheduleTimeout = () => {\n      timeout = setTimeout(() => {\n        client.terminate();\n      }, pongWaitMs) as any;\n    };\n    ping = setTimeout(() => {\n      client.send('PING');\n\n      scheduleTimeout();\n    }, pingMs) as any;\n  };\n\n  const onMessage = () => {\n    clearTimeout(ping);\n    clearTimeout(timeout);\n\n    schedulePing();\n  };\n\n  client.on('message', onMessage);\n\n  client.on('close', () => {\n    clearTimeout(ping);\n    clearTimeout(timeout);\n  });\n\n  schedulePing();\n}\n\nexport function applyWSSHandler<TRouter extends AnyRouter>(\n  opts: WSSHandlerOptions<TRouter>,\n) {\n  const encoder = opts.experimental_encoder ?? jsonEncoder;\n  const onConnection = getWSConnectionHandler(opts);\n  opts.wss.on('connection', (client, req) => {\n    if (opts.prefix && !req.url?.startsWith(opts.prefix)) {\n      return;\n    }\n\n    onConnection(client, req);\n  });\n\n  return {\n    broadcastReconnectNotification: () => {\n      const response: TRPCReconnectNotification = {\n        id: null,\n        method: 'reconnect',\n      };\n      const data = encoder.encode(response);\n      for (const client of opts.wss.clients) {\n        if (client.readyState === WEBSOCKET_OPEN) {\n          client.send(data);\n        }\n      }\n    },\n  };\n}\n\nexport type { Encoder } from './wsEncoder';\nexport { jsonEncoder } from './wsEncoder';\n"],"mappings":"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"}