{"version":3,"sources":["../../event-target-impl/src/index.node.ts","../../ws-impl/src/index.node.ts","../src/websocket-channel.ts"],"names":["EventTarget","args","setMaxListeners","index_node_default","WebSocketImpl"],"mappings":"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","file":"index.node.mjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","// When building the browser bundle, this import gets replaced by `globalThis.WebSocket`.\nimport WebSocketImpl from 'ws';\n\nexport default globalThis.WebSocket\n ? globalThis.WebSocket // Use native `WebSocket` in runtimes that support it (eg. Deno)\n : WebSocketImpl;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel) => void;\n return new Promise>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}