@zimic/ws 0.2.0-canary.4 → 0.2.0-canary.6

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport const DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport interface WebSocketClientOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketClient(socket: WebSocket, options: WebSocketClientOpenOptions = {}) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleOpenSuccess() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport type WebSocketClientCloseOptions = WebSocketClientOpenOptions;\n\nexport async function closeWebSocketClient(\n socket: WebSocket,\n options: WebSocketClientCloseOptions & { code?: number; reason?: string },\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(closeTimeout);\n\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleClose() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { PossiblePromise } from '@zimic/utils/types';\n\nimport { WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport {\n closeWebSocketClient,\n openWebSocketClient,\n WebSocketClientCloseOptions,\n WebSocketClientOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketClient {\n export type ReadyState =\n | typeof WebSocketClient.CONNECTING\n | typeof WebSocketClient.OPEN\n | typeof WebSocketClient.CLOSING\n | typeof WebSocketClient.CLOSED;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type OpenEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n export type MessageEvent<Schema extends WebSocketSchema> = globalThis.MessageEvent<WebSocketMessageData<Schema>>;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type CloseEvent<_Schema extends WebSocketSchema> = globalThis.CloseEvent;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type ErrorEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n interface Events<Schema extends WebSocketSchema = WebSocketSchema> {\n open: OpenEvent<Schema>;\n message: MessageEvent<Schema>;\n close: CloseEvent<Schema>;\n error: ErrorEvent<Schema>;\n }\n\n export type EventType = keyof Events<WebSocketSchema>;\n\n export type Event<\n Schema extends WebSocketSchema = WebSocketSchema,\n Type extends EventType = EventType,\n > = Events<Schema>[Type];\n\n interface EventListenerParameters<Schema extends WebSocketSchema> {\n open: [event: Event<Schema, 'open'>];\n message: [event: Event<Schema, 'message'>];\n close: [event: Event<Schema, 'close'>];\n error: [event: Event<Schema, 'error'>];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketClient<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\ntype WebSocketClientRawEventListener = (this: WebSocket, event: Event) => PossiblePromise<void>;\n\nexport class WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: WebSocket;\n\n #url: string;\n #protocols?: string | string[];\n #binaryType: BinaryType = 'blob';\n\n private unitaryListeners: {\n [Type in WebSocketClient.EventType]: WebSocketClient.EventListener<Schema, Type> | null;\n } = {\n open: null,\n message: null,\n close: null,\n error: null,\n };\n\n private listenerToRawListener: {\n [Type in WebSocketClient.EventType]: Map<\n WebSocketClient.EventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(socket: WebSocket);\n constructor(_url: string, protocols?: string | string[]);\n constructor(urlOrSocket: WebSocket | string, protocols?: string | string[]) {\n if (typeof urlOrSocket === 'string') {\n this.#url = urlOrSocket;\n } else {\n this.#url = urlOrSocket.url;\n this.socket = urlOrSocket;\n }\n\n this.#protocols = protocols;\n }\n\n static get CONNECTING() {\n return WebSocket.CONNECTING;\n }\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static get OPEN() {\n return WebSocket.OPEN;\n }\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static get CLOSING() {\n return WebSocket.CLOSING;\n }\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static get CLOSED() {\n return WebSocket.CLOSED;\n }\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this.#binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this.#binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this.#url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState(): WebSocketClient.ReadyState {\n const readyState = this.socket?.readyState ?? WebSocket.CLOSED;\n return readyState as WebSocketClient.ReadyState;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options?: WebSocketClientOpenOptions) {\n if (this.readyState === WebSocketClient.OPEN) {\n return;\n }\n\n await this.close();\n\n const socket = new WebSocket(this.#url, this.#protocols);\n\n try {\n if (socket.binaryType !== this.binaryType) {\n socket.binaryType = this.binaryType;\n }\n\n this.applyListeners(socket);\n\n await openWebSocketClient(socket, options);\n } catch (error) {\n socket.close();\n throw error;\n }\n\n this.socket = socket;\n }\n\n private applyListeners(socket: WebSocket) {\n for (const type of ['open', 'message', 'close', 'error'] as const) {\n const unitaryListener = this[`on${type}`] as WebSocketClient.EventListener<Schema, typeof type> | null;\n const rawUnitaryListener = unitaryListener ? this.listenerToRawListener[type].get(unitaryListener) : undefined;\n\n if (rawUnitaryListener) {\n socket[`on${type}`] = rawUnitaryListener;\n }\n\n for (const rawListener of this.listenerToRawListener[type].values()) {\n const isRawUnitaryListener = rawListener === rawUnitaryListener;\n\n if (!isRawUnitaryListener) {\n socket.addEventListener(type, rawListener);\n }\n }\n }\n }\n\n async close(code?: number, reason?: string, options?: WebSocketClientCloseOptions) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeWebSocketClient(this.socket, { ...options, code, reason });\n } finally {\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listenerToRawListener[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listenerToRawListener[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listenerToRawListener[type].delete(listener);\n }\n }\n\n get onopen() {\n return this.unitaryListeners.open;\n }\n\n set onopen(listener: WebSocketClient.EventListener<Schema, 'open'> | null) {\n this.setEventListener('open', listener);\n }\n\n get onmessage() {\n return this.unitaryListeners.message;\n }\n\n set onmessage(listener: WebSocketClient.EventListener<Schema, 'message'> | null) {\n this.setEventListener('message', listener);\n }\n\n get onclose() {\n return this.unitaryListeners.close;\n }\n\n set onclose(listener: WebSocketClient.EventListener<Schema, 'close'> | null) {\n this.setEventListener('close', listener);\n }\n\n get onerror() {\n return this.unitaryListeners.error;\n }\n\n set onerror(listener: WebSocketClient.EventListener<Schema, 'error'> | null) {\n this.setEventListener('error', listener);\n }\n\n private setEventListener<\n Type extends WebSocketClient.EventType,\n Listener extends WebSocketClient.EventListener<Schema, Type> | null,\n >(type: Type, listener: Listener) {\n const currentListener = this.unitaryListeners[type];\n\n if (currentListener) {\n const rawListener = this.listenerToRawListener[type].get(currentListener);\n\n if (this.socket && rawListener) {\n this.socket[`on${type}`] = null;\n }\n\n this.listenerToRawListener[type].delete(currentListener);\n }\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listenerToRawListener[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this.unitaryListeners[type] as Listener) = listener;\n } else {\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this.unitaryListeners[type] as Listener | null) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketClient.EventType>(event: WebSocketClient.Event<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport const DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport interface WebSocketClientOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketClient(socket: WebSocket, options: WebSocketClientOpenOptions = {}) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleOpenSuccess() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport type WebSocketClientCloseOptions = WebSocketClientOpenOptions;\n\nexport async function closeWebSocketClient(\n socket: WebSocket,\n options: WebSocketClientCloseOptions & { code?: number; reason?: string },\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(closeTimeout);\n\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleClose() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { PossiblePromise } from '@zimic/utils/types';\n\nimport { WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport {\n closeWebSocketClient,\n openWebSocketClient,\n WebSocketClientCloseOptions,\n WebSocketClientOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketClient {\n export type ReadyState =\n | typeof WebSocketClient.CONNECTING\n | typeof WebSocketClient.OPEN\n | typeof WebSocketClient.CLOSING\n | typeof WebSocketClient.CLOSED;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type OpenEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n export type MessageEvent<Schema extends WebSocketSchema> = globalThis.MessageEvent<WebSocketMessageData<Schema>>;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type CloseEvent<_Schema extends WebSocketSchema> = globalThis.CloseEvent;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type ErrorEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n interface Events<Schema extends WebSocketSchema = WebSocketSchema> {\n open: OpenEvent<Schema>;\n message: MessageEvent<Schema>;\n close: CloseEvent<Schema>;\n error: ErrorEvent<Schema>;\n }\n\n export type EventType = keyof Events<WebSocketSchema>;\n\n export type Event<\n Schema extends WebSocketSchema = WebSocketSchema,\n Type extends EventType = EventType,\n > = Events<Schema>[Type];\n\n interface EventListenerParameters<Schema extends WebSocketSchema> {\n open: [event: Event<Schema, 'open'>];\n message: [event: Event<Schema, 'message'>];\n close: [event: Event<Schema, 'close'>];\n error: [event: Event<Schema, 'error'>];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketClient<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\ntype WebSocketClientRawEventListener = (this: WebSocket, event: Event) => PossiblePromise<void>;\n\nexport class WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: WebSocket;\n\n #url: string;\n #protocols?: string | string[];\n #binaryType: BinaryType = 'blob';\n\n private unitaryListeners: {\n [Type in WebSocketClient.EventType]: WebSocketClient.EventListener<Schema, Type> | null;\n } = {\n open: null,\n message: null,\n close: null,\n error: null,\n };\n\n private listenerToRawListener: {\n [Type in WebSocketClient.EventType]: Map<\n WebSocketClient.EventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(socket: WebSocket);\n constructor(_url: string, protocols?: string | string[]);\n constructor(urlOrSocket: WebSocket | string, protocols?: string | string[]) {\n if (typeof urlOrSocket === 'string') {\n this.#url = urlOrSocket;\n } else {\n this.#url = urlOrSocket.url;\n this.socket = urlOrSocket;\n }\n\n this.#protocols = protocols;\n }\n\n static get CONNECTING() {\n return WebSocket.CONNECTING;\n }\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static get OPEN() {\n return WebSocket.OPEN;\n }\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static get CLOSING() {\n return WebSocket.CLOSING;\n }\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static get CLOSED() {\n return WebSocket.CLOSED;\n }\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this.#binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this.#binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this.#url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState(): WebSocketClient.ReadyState {\n const readyState = this.socket?.readyState ?? WebSocket.CLOSED;\n return readyState;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options?: WebSocketClientOpenOptions) {\n if (this.readyState === WebSocketClient.OPEN) {\n return;\n }\n\n await this.close();\n\n const socket = new WebSocket(this.#url, this.#protocols);\n\n try {\n if (socket.binaryType !== this.binaryType) {\n socket.binaryType = this.binaryType;\n }\n\n this.applyListeners(socket);\n\n await openWebSocketClient(socket, options);\n } catch (error) {\n socket.close();\n throw error;\n }\n\n this.socket = socket;\n }\n\n private applyListeners(socket: WebSocket) {\n for (const type of ['open', 'message', 'close', 'error'] as const) {\n const unitaryListener = this[`on${type}`] as WebSocketClient.EventListener<Schema, typeof type> | null;\n const rawUnitaryListener = unitaryListener ? this.listenerToRawListener[type].get(unitaryListener) : undefined;\n\n if (rawUnitaryListener) {\n socket[`on${type}`] = rawUnitaryListener;\n }\n\n for (const rawListener of this.listenerToRawListener[type].values()) {\n const isRawUnitaryListener = rawListener === rawUnitaryListener;\n\n if (!isRawUnitaryListener) {\n socket.addEventListener(type, rawListener);\n }\n }\n }\n }\n\n async close(code?: number, reason?: string, options?: WebSocketClientCloseOptions) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeWebSocketClient(this.socket, { ...options, code, reason });\n } finally {\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listenerToRawListener[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listenerToRawListener[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listenerToRawListener[type].delete(listener);\n }\n }\n\n get onopen() {\n return this.unitaryListeners.open;\n }\n\n set onopen(listener: WebSocketClient.EventListener<Schema, 'open'> | null) {\n this.setEventListener('open', listener);\n }\n\n get onmessage() {\n return this.unitaryListeners.message;\n }\n\n set onmessage(listener: WebSocketClient.EventListener<Schema, 'message'> | null) {\n this.setEventListener('message', listener);\n }\n\n get onclose() {\n return this.unitaryListeners.close;\n }\n\n set onclose(listener: WebSocketClient.EventListener<Schema, 'close'> | null) {\n this.setEventListener('close', listener);\n }\n\n get onerror() {\n return this.unitaryListeners.error;\n }\n\n set onerror(listener: WebSocketClient.EventListener<Schema, 'error'> | null) {\n this.setEventListener('error', listener);\n }\n\n private setEventListener<\n Type extends WebSocketClient.EventType,\n Listener extends WebSocketClient.EventListener<Schema, Type> | null,\n >(type: Type, listener: Listener) {\n const currentListener = this.unitaryListeners[type];\n\n if (currentListener) {\n const rawListener = this.listenerToRawListener[type].get(currentListener);\n\n if (this.socket && rawListener) {\n this.socket[`on${type}`] = null;\n }\n\n this.listenerToRawListener[type].delete(currentListener);\n }\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listenerToRawListener[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this.unitaryListeners[type] as Listener) = listener;\n } else {\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this.unitaryListeners[type] as Listener | null) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketClient.EventType>(event: WebSocketClient.Event<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport const DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport interface WebSocketClientOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketClient(socket: WebSocket, options: WebSocketClientOpenOptions = {}) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleOpenSuccess() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport type WebSocketClientCloseOptions = WebSocketClientOpenOptions;\n\nexport async function closeWebSocketClient(\n socket: WebSocket,\n options: WebSocketClientCloseOptions & { code?: number; reason?: string },\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(closeTimeout);\n\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleClose() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { PossiblePromise } from '@zimic/utils/types';\n\nimport { WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport {\n closeWebSocketClient,\n openWebSocketClient,\n WebSocketClientCloseOptions,\n WebSocketClientOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketClient {\n export type ReadyState =\n | typeof WebSocketClient.CONNECTING\n | typeof WebSocketClient.OPEN\n | typeof WebSocketClient.CLOSING\n | typeof WebSocketClient.CLOSED;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type OpenEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n export type MessageEvent<Schema extends WebSocketSchema> = globalThis.MessageEvent<WebSocketMessageData<Schema>>;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type CloseEvent<_Schema extends WebSocketSchema> = globalThis.CloseEvent;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type ErrorEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n interface Events<Schema extends WebSocketSchema = WebSocketSchema> {\n open: OpenEvent<Schema>;\n message: MessageEvent<Schema>;\n close: CloseEvent<Schema>;\n error: ErrorEvent<Schema>;\n }\n\n export type EventType = keyof Events<WebSocketSchema>;\n\n export type Event<\n Schema extends WebSocketSchema = WebSocketSchema,\n Type extends EventType = EventType,\n > = Events<Schema>[Type];\n\n interface EventListenerParameters<Schema extends WebSocketSchema> {\n open: [event: Event<Schema, 'open'>];\n message: [event: Event<Schema, 'message'>];\n close: [event: Event<Schema, 'close'>];\n error: [event: Event<Schema, 'error'>];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketClient<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\ntype WebSocketClientRawEventListener = (this: WebSocket, event: Event) => PossiblePromise<void>;\n\nexport class WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: WebSocket;\n\n #url: string;\n #protocols?: string | string[];\n #binaryType: BinaryType = 'blob';\n\n private unitaryListeners: {\n [Type in WebSocketClient.EventType]: WebSocketClient.EventListener<Schema, Type> | null;\n } = {\n open: null,\n message: null,\n close: null,\n error: null,\n };\n\n private listenerToRawListener: {\n [Type in WebSocketClient.EventType]: Map<\n WebSocketClient.EventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(socket: WebSocket);\n constructor(_url: string, protocols?: string | string[]);\n constructor(urlOrSocket: WebSocket | string, protocols?: string | string[]) {\n if (typeof urlOrSocket === 'string') {\n this.#url = urlOrSocket;\n } else {\n this.#url = urlOrSocket.url;\n this.socket = urlOrSocket;\n }\n\n this.#protocols = protocols;\n }\n\n static get CONNECTING() {\n return WebSocket.CONNECTING;\n }\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static get OPEN() {\n return WebSocket.OPEN;\n }\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static get CLOSING() {\n return WebSocket.CLOSING;\n }\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static get CLOSED() {\n return WebSocket.CLOSED;\n }\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this.#binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this.#binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this.#url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState(): WebSocketClient.ReadyState {\n const readyState = this.socket?.readyState ?? WebSocket.CLOSED;\n return readyState as WebSocketClient.ReadyState;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options?: WebSocketClientOpenOptions) {\n if (this.readyState === WebSocketClient.OPEN) {\n return;\n }\n\n await this.close();\n\n const socket = new WebSocket(this.#url, this.#protocols);\n\n try {\n if (socket.binaryType !== this.binaryType) {\n socket.binaryType = this.binaryType;\n }\n\n this.applyListeners(socket);\n\n await openWebSocketClient(socket, options);\n } catch (error) {\n socket.close();\n throw error;\n }\n\n this.socket = socket;\n }\n\n private applyListeners(socket: WebSocket) {\n for (const type of ['open', 'message', 'close', 'error'] as const) {\n const unitaryListener = this[`on${type}`] as WebSocketClient.EventListener<Schema, typeof type> | null;\n const rawUnitaryListener = unitaryListener ? this.listenerToRawListener[type].get(unitaryListener) : undefined;\n\n if (rawUnitaryListener) {\n socket[`on${type}`] = rawUnitaryListener;\n }\n\n for (const rawListener of this.listenerToRawListener[type].values()) {\n const isRawUnitaryListener = rawListener === rawUnitaryListener;\n\n if (!isRawUnitaryListener) {\n socket.addEventListener(type, rawListener);\n }\n }\n }\n }\n\n async close(code?: number, reason?: string, options?: WebSocketClientCloseOptions) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeWebSocketClient(this.socket, { ...options, code, reason });\n } finally {\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listenerToRawListener[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listenerToRawListener[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listenerToRawListener[type].delete(listener);\n }\n }\n\n get onopen() {\n return this.unitaryListeners.open;\n }\n\n set onopen(listener: WebSocketClient.EventListener<Schema, 'open'> | null) {\n this.setEventListener('open', listener);\n }\n\n get onmessage() {\n return this.unitaryListeners.message;\n }\n\n set onmessage(listener: WebSocketClient.EventListener<Schema, 'message'> | null) {\n this.setEventListener('message', listener);\n }\n\n get onclose() {\n return this.unitaryListeners.close;\n }\n\n set onclose(listener: WebSocketClient.EventListener<Schema, 'close'> | null) {\n this.setEventListener('close', listener);\n }\n\n get onerror() {\n return this.unitaryListeners.error;\n }\n\n set onerror(listener: WebSocketClient.EventListener<Schema, 'error'> | null) {\n this.setEventListener('error', listener);\n }\n\n private setEventListener<\n Type extends WebSocketClient.EventType,\n Listener extends WebSocketClient.EventListener<Schema, Type> | null,\n >(type: Type, listener: Listener) {\n const currentListener = this.unitaryListeners[type];\n\n if (currentListener) {\n const rawListener = this.listenerToRawListener[type].get(currentListener);\n\n if (this.socket && rawListener) {\n this.socket[`on${type}`] = null;\n }\n\n this.listenerToRawListener[type].delete(currentListener);\n }\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listenerToRawListener[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this.unitaryListeners[type] as Listener) = listener;\n } else {\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this.unitaryListeners[type] as Listener | null) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketClient.EventType>(event: WebSocketClient.Event<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport const DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport interface WebSocketClientOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketClient(socket: WebSocket, options: WebSocketClientOpenOptions = {}) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleOpenSuccess() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport type WebSocketClientCloseOptions = WebSocketClientOpenOptions;\n\nexport async function closeWebSocketClient(\n socket: WebSocket,\n options: WebSocketClientCloseOptions & { code?: number; reason?: string },\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(closeTimeout);\n\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleClose() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { PossiblePromise } from '@zimic/utils/types';\n\nimport { WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport {\n closeWebSocketClient,\n openWebSocketClient,\n WebSocketClientCloseOptions,\n WebSocketClientOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketClient {\n export type ReadyState =\n | typeof WebSocketClient.CONNECTING\n | typeof WebSocketClient.OPEN\n | typeof WebSocketClient.CLOSING\n | typeof WebSocketClient.CLOSED;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type OpenEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n export type MessageEvent<Schema extends WebSocketSchema> = globalThis.MessageEvent<WebSocketMessageData<Schema>>;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type CloseEvent<_Schema extends WebSocketSchema> = globalThis.CloseEvent;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type ErrorEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n interface Events<Schema extends WebSocketSchema = WebSocketSchema> {\n open: OpenEvent<Schema>;\n message: MessageEvent<Schema>;\n close: CloseEvent<Schema>;\n error: ErrorEvent<Schema>;\n }\n\n export type EventType = keyof Events<WebSocketSchema>;\n\n export type Event<\n Schema extends WebSocketSchema = WebSocketSchema,\n Type extends EventType = EventType,\n > = Events<Schema>[Type];\n\n interface EventListenerParameters<Schema extends WebSocketSchema> {\n open: [event: Event<Schema, 'open'>];\n message: [event: Event<Schema, 'message'>];\n close: [event: Event<Schema, 'close'>];\n error: [event: Event<Schema, 'error'>];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketClient<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\ntype WebSocketClientRawEventListener = (this: WebSocket, event: Event) => PossiblePromise<void>;\n\nexport class WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: WebSocket;\n\n #url: string;\n #protocols?: string | string[];\n #binaryType: BinaryType = 'blob';\n\n private unitaryListeners: {\n [Type in WebSocketClient.EventType]: WebSocketClient.EventListener<Schema, Type> | null;\n } = {\n open: null,\n message: null,\n close: null,\n error: null,\n };\n\n private listenerToRawListener: {\n [Type in WebSocketClient.EventType]: Map<\n WebSocketClient.EventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(socket: WebSocket);\n constructor(_url: string, protocols?: string | string[]);\n constructor(urlOrSocket: WebSocket | string, protocols?: string | string[]) {\n if (typeof urlOrSocket === 'string') {\n this.#url = urlOrSocket;\n } else {\n this.#url = urlOrSocket.url;\n this.socket = urlOrSocket;\n }\n\n this.#protocols = protocols;\n }\n\n static get CONNECTING() {\n return WebSocket.CONNECTING;\n }\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static get OPEN() {\n return WebSocket.OPEN;\n }\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static get CLOSING() {\n return WebSocket.CLOSING;\n }\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static get CLOSED() {\n return WebSocket.CLOSED;\n }\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this.#binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this.#binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this.#url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState(): WebSocketClient.ReadyState {\n const readyState = this.socket?.readyState ?? WebSocket.CLOSED;\n return readyState;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options?: WebSocketClientOpenOptions) {\n if (this.readyState === WebSocketClient.OPEN) {\n return;\n }\n\n await this.close();\n\n const socket = new WebSocket(this.#url, this.#protocols);\n\n try {\n if (socket.binaryType !== this.binaryType) {\n socket.binaryType = this.binaryType;\n }\n\n this.applyListeners(socket);\n\n await openWebSocketClient(socket, options);\n } catch (error) {\n socket.close();\n throw error;\n }\n\n this.socket = socket;\n }\n\n private applyListeners(socket: WebSocket) {\n for (const type of ['open', 'message', 'close', 'error'] as const) {\n const unitaryListener = this[`on${type}`] as WebSocketClient.EventListener<Schema, typeof type> | null;\n const rawUnitaryListener = unitaryListener ? this.listenerToRawListener[type].get(unitaryListener) : undefined;\n\n if (rawUnitaryListener) {\n socket[`on${type}`] = rawUnitaryListener;\n }\n\n for (const rawListener of this.listenerToRawListener[type].values()) {\n const isRawUnitaryListener = rawListener === rawUnitaryListener;\n\n if (!isRawUnitaryListener) {\n socket.addEventListener(type, rawListener);\n }\n }\n }\n }\n\n async close(code?: number, reason?: string, options?: WebSocketClientCloseOptions) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeWebSocketClient(this.socket, { ...options, code, reason });\n } finally {\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listenerToRawListener[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listenerToRawListener[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listenerToRawListener[type].delete(listener);\n }\n }\n\n get onopen() {\n return this.unitaryListeners.open;\n }\n\n set onopen(listener: WebSocketClient.EventListener<Schema, 'open'> | null) {\n this.setEventListener('open', listener);\n }\n\n get onmessage() {\n return this.unitaryListeners.message;\n }\n\n set onmessage(listener: WebSocketClient.EventListener<Schema, 'message'> | null) {\n this.setEventListener('message', listener);\n }\n\n get onclose() {\n return this.unitaryListeners.close;\n }\n\n set onclose(listener: WebSocketClient.EventListener<Schema, 'close'> | null) {\n this.setEventListener('close', listener);\n }\n\n get onerror() {\n return this.unitaryListeners.error;\n }\n\n set onerror(listener: WebSocketClient.EventListener<Schema, 'error'> | null) {\n this.setEventListener('error', listener);\n }\n\n private setEventListener<\n Type extends WebSocketClient.EventType,\n Listener extends WebSocketClient.EventListener<Schema, Type> | null,\n >(type: Type, listener: Listener) {\n const currentListener = this.unitaryListeners[type];\n\n if (currentListener) {\n const rawListener = this.listenerToRawListener[type].get(currentListener);\n\n if (this.socket && rawListener) {\n this.socket[`on${type}`] = null;\n }\n\n this.listenerToRawListener[type].delete(currentListener);\n }\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listenerToRawListener[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this.unitaryListeners[type] as Listener) = listener;\n } else {\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this.unitaryListeners[type] as Listener | null) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketClient.EventType>(event: WebSocketClient.Event<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../zimic-utils/src/server/lifecycle.ts","../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts","../src/server/errors/ClosedWebSocketServerError.ts","../src/server/utils/lifecycle.ts","../src/server/WebSocketServer.ts"],"names":["HttpsServer","NodeWebSocketServer"],"mappings":"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","file":"server.js","sourcesContent":["import { Server as HttpServer } from 'http';\n\nexport const DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport class HttpServerTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HttpServerTimeoutError';\n }\n}\n\nexport class HttpServerStartTimeoutError extends HttpServerTimeoutError {\n constructor(reachedTimeout: number) {\n super(`HTTP server start timed out after ${reachedTimeout}ms.`);\n this.name = 'HttpServerStartTimeoutError';\n }\n}\n\nexport class HttpServerStopTimeoutError extends HttpServerTimeoutError {\n constructor(reachedTimeout: number) {\n super(`HTTP server stop timed out after ${reachedTimeout}ms.`);\n this.name = 'HttpServerStopTimeoutError';\n }\n}\n\nexport async function startHttpServer(\n server: HttpServer,\n options: {\n hostname?: string;\n port?: number;\n timeout?: number;\n } = {},\n) {\n const { hostname, port, timeout: timeoutDuration = DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT } = options;\n\n await new Promise<void>((resolve, reject) => {\n function handleStartError(error: unknown) {\n server.off('listening', handleStartSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n reject(error);\n }\n\n const startTimeout = setTimeout(() => {\n const timeoutError = new HttpServerStartTimeoutError(timeoutDuration);\n handleStartError(timeoutError);\n }, timeoutDuration);\n\n function handleStartSuccess() {\n server.off('error', handleStartError);\n clearTimeout(startTimeout);\n resolve();\n }\n\n server.once('error', handleStartError);\n server.listen(port, hostname, handleStartSuccess);\n });\n}\n\nexport async function stopHttpServer(server: HttpServer, options: { timeout?: number } = {}) {\n const { timeout: timeoutDuration = DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT } = options;\n\n if (!server.listening) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const stopTimeout = setTimeout(() => {\n const timeoutError = new HttpServerStopTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n server.close((error) => {\n clearTimeout(stopTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is expected not to happen since the servers are not stopped unless they are running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n\n server.closeAllConnections();\n });\n}\n\nexport function getHttpServerHostname(server: HttpServer) {\n const address = server.address();\n\n if (typeof address === 'string') {\n return undefined;\n } else {\n return address?.address;\n }\n}\n\nexport function getHttpServerPort(server: HttpServer) {\n const address = server.address();\n\n if (typeof address === 'string') {\n return undefined;\n } else {\n return address?.port;\n }\n}\n","export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport const DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport interface WebSocketClientOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketClient(socket: WebSocket, options: WebSocketClientOpenOptions = {}) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleOpenSuccess() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport type WebSocketClientCloseOptions = WebSocketClientOpenOptions;\n\nexport async function closeWebSocketClient(\n socket: WebSocket,\n options: WebSocketClientCloseOptions & { code?: number; reason?: string },\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(closeTimeout);\n\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleClose() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { PossiblePromise } from '@zimic/utils/types';\n\nimport { WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport {\n closeWebSocketClient,\n openWebSocketClient,\n WebSocketClientCloseOptions,\n WebSocketClientOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketClient {\n export type ReadyState =\n | typeof WebSocketClient.CONNECTING\n | typeof WebSocketClient.OPEN\n | typeof WebSocketClient.CLOSING\n | typeof WebSocketClient.CLOSED;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type OpenEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n export type MessageEvent<Schema extends WebSocketSchema> = globalThis.MessageEvent<WebSocketMessageData<Schema>>;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type CloseEvent<_Schema extends WebSocketSchema> = globalThis.CloseEvent;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type ErrorEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n interface Events<Schema extends WebSocketSchema = WebSocketSchema> {\n open: OpenEvent<Schema>;\n message: MessageEvent<Schema>;\n close: CloseEvent<Schema>;\n error: ErrorEvent<Schema>;\n }\n\n export type EventType = keyof Events<WebSocketSchema>;\n\n export type Event<\n Schema extends WebSocketSchema = WebSocketSchema,\n Type extends EventType = EventType,\n > = Events<Schema>[Type];\n\n interface EventListenerParameters<Schema extends WebSocketSchema> {\n open: [event: Event<Schema, 'open'>];\n message: [event: Event<Schema, 'message'>];\n close: [event: Event<Schema, 'close'>];\n error: [event: Event<Schema, 'error'>];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketClient<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\ntype WebSocketClientRawEventListener = (this: WebSocket, event: Event) => PossiblePromise<void>;\n\nexport class WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: WebSocket;\n\n #url: string;\n #protocols?: string | string[];\n #binaryType: BinaryType = 'blob';\n\n private unitaryListeners: {\n [Type in WebSocketClient.EventType]: WebSocketClient.EventListener<Schema, Type> | null;\n } = {\n open: null,\n message: null,\n close: null,\n error: null,\n };\n\n private listenerToRawListener: {\n [Type in WebSocketClient.EventType]: Map<\n WebSocketClient.EventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(socket: WebSocket);\n constructor(_url: string, protocols?: string | string[]);\n constructor(urlOrSocket: WebSocket | string, protocols?: string | string[]) {\n if (typeof urlOrSocket === 'string') {\n this.#url = urlOrSocket;\n } else {\n this.#url = urlOrSocket.url;\n this.socket = urlOrSocket;\n }\n\n this.#protocols = protocols;\n }\n\n static get CONNECTING() {\n return WebSocket.CONNECTING;\n }\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static get OPEN() {\n return WebSocket.OPEN;\n }\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static get CLOSING() {\n return WebSocket.CLOSING;\n }\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static get CLOSED() {\n return WebSocket.CLOSED;\n }\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this.#binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this.#binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this.#url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState(): WebSocketClient.ReadyState {\n const readyState = this.socket?.readyState ?? WebSocket.CLOSED;\n return readyState as WebSocketClient.ReadyState;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options?: WebSocketClientOpenOptions) {\n if (this.readyState === WebSocketClient.OPEN) {\n return;\n }\n\n await this.close();\n\n const socket = new WebSocket(this.#url, this.#protocols);\n\n try {\n if (socket.binaryType !== this.binaryType) {\n socket.binaryType = this.binaryType;\n }\n\n this.applyListeners(socket);\n\n await openWebSocketClient(socket, options);\n } catch (error) {\n socket.close();\n throw error;\n }\n\n this.socket = socket;\n }\n\n private applyListeners(socket: WebSocket) {\n for (const type of ['open', 'message', 'close', 'error'] as const) {\n const unitaryListener = this[`on${type}`] as WebSocketClient.EventListener<Schema, typeof type> | null;\n const rawUnitaryListener = unitaryListener ? this.listenerToRawListener[type].get(unitaryListener) : undefined;\n\n if (rawUnitaryListener) {\n socket[`on${type}`] = rawUnitaryListener;\n }\n\n for (const rawListener of this.listenerToRawListener[type].values()) {\n const isRawUnitaryListener = rawListener === rawUnitaryListener;\n\n if (!isRawUnitaryListener) {\n socket.addEventListener(type, rawListener);\n }\n }\n }\n }\n\n async close(code?: number, reason?: string, options?: WebSocketClientCloseOptions) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeWebSocketClient(this.socket, { ...options, code, reason });\n } finally {\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listenerToRawListener[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listenerToRawListener[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listenerToRawListener[type].delete(listener);\n }\n }\n\n get onopen() {\n return this.unitaryListeners.open;\n }\n\n set onopen(listener: WebSocketClient.EventListener<Schema, 'open'> | null) {\n this.setEventListener('open', listener);\n }\n\n get onmessage() {\n return this.unitaryListeners.message;\n }\n\n set onmessage(listener: WebSocketClient.EventListener<Schema, 'message'> | null) {\n this.setEventListener('message', listener);\n }\n\n get onclose() {\n return this.unitaryListeners.close;\n }\n\n set onclose(listener: WebSocketClient.EventListener<Schema, 'close'> | null) {\n this.setEventListener('close', listener);\n }\n\n get onerror() {\n return this.unitaryListeners.error;\n }\n\n set onerror(listener: WebSocketClient.EventListener<Schema, 'error'> | null) {\n this.setEventListener('error', listener);\n }\n\n private setEventListener<\n Type extends WebSocketClient.EventType,\n Listener extends WebSocketClient.EventListener<Schema, Type> | null,\n >(type: Type, listener: Listener) {\n const currentListener = this.unitaryListeners[type];\n\n if (currentListener) {\n const rawListener = this.listenerToRawListener[type].get(currentListener);\n\n if (this.socket && rawListener) {\n this.socket[`on${type}`] = null;\n }\n\n this.listenerToRawListener[type].delete(currentListener);\n }\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listenerToRawListener[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this.unitaryListeners[type] as Listener) = listener;\n } else {\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this.unitaryListeners[type] as Listener | null) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketClient.EventType>(event: WebSocketClient.Event<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n","class ClosedWebSocketServerError extends Error {\n constructor() {\n super('The WebSocket server is closed. Did you forget to open it?');\n this.name = 'ClosedWebSocketServerError';\n }\n}\n\nexport default ClosedWebSocketServerError;\n","import { Server as HttpServer } from 'http';\nimport { Server as HttpsServer } from 'https';\nimport { WebSocketServer as NodeWebSocketServer } from 'ws';\n\nimport { DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } from '@/client/utils/lifecycle';\nimport { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport interface WebSocketServerOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketServer(\n httpServer: HttpServer | HttpsServer,\n webSocketServer: NodeWebSocketServer,\n options: WebSocketServerOpenOptions = {},\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = httpServer.listening;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n webSocketServer.off('listening', handleListening); // eslint-disable-line @typescript-eslint/no-use-before-define\n webSocketServer.off('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n /* istanbul ignore next -- @preserve\n * This is not expected since the server is not started unless it is not running. */\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleListening() {\n removeListenersAndTimeout();\n resolve();\n }\n\n webSocketServer.on('listening', handleListening);\n webSocketServer.on('error', handleError);\n });\n}\n\nexport type WebSocketServerCloseOptions = WebSocketServerOpenOptions;\n\nexport async function closeWebSocketServer(\n webSocketServer: NodeWebSocketServer,\n options: WebSocketServerCloseOptions = {},\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n for (const client of webSocketServer.clients) {\n client.close();\n }\n\n webSocketServer.close((error) => {\n clearTimeout(closeTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is not expected since the server is not stopped unless it is running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n","import { getHttpServerHostname, getHttpServerPort } from '@zimic/utils/server';\nimport { PossiblePromise } from '@zimic/utils/types';\nimport { Server as HttpServer, IncomingMessage } from 'http';\nimport { Server as HttpsServer } from 'https';\nimport { WebSocketServer as NodeWebSocketServer } from 'ws';\n\nimport { WebSocketClient } from '@/client/WebSocketClient';\nimport { WebSocketSchema } from '@/types/schema';\n\nimport ClosedWebSocketServerError from './errors/ClosedWebSocketServerError';\nimport {\n closeWebSocketServer,\n openWebSocketServer,\n WebSocketServerCloseOptions,\n WebSocketServerOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketServer {\n export type EventType = 'listening' | 'connection' | 'error' | 'close';\n\n export interface EventListenerParameters<Schema extends WebSocketSchema> {\n connection: [client: WebSocketClient<Schema>, request: IncomingMessage];\n error: [error: Error];\n close: [];\n listening: [];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketServer<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\nexport interface WebSocketServerOptions {\n httpServer: HttpServer | HttpsServer;\n}\n\nexport interface WebSocketServerRawEventListenerParameters {\n connection: [client: WebSocket, request: IncomingMessage];\n error: [error: Error];\n close: [];\n listening: [];\n}\n\ntype WebSocketServerRawEventListener<Type extends WebSocketServer.EventType> = (\n ...parameters: WebSocketServerRawEventListenerParameters[Type]\n) => void;\n\nexport class WebSocketServer<Schema extends WebSocketSchema> {\n #httpServer: HttpServer | HttpsServer;\n #webSocketServer?: NodeWebSocketServer;\n\n private listeners: {\n [Type in WebSocketServer.EventType]: Map<\n WebSocketServer.EventListener<Schema, Type>,\n WebSocketServerRawEventListener<Type>\n >;\n } = {\n connection: new Map(),\n listening: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(options: WebSocketServerOptions) {\n this.#httpServer = options.httpServer;\n }\n\n get baseURL() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return `${this.protocol}://${this.hostname}:${this.port}`;\n }\n\n get protocol() {\n return this.#httpServer instanceof HttpsServer ? 'wss' : 'ws';\n }\n\n get hostname() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return getHttpServerHostname(this.#httpServer);\n }\n\n get port() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return getHttpServerPort(this.#httpServer);\n }\n\n get isOpen() {\n return this.#httpServer.listening && this.#webSocketServer !== undefined;\n }\n\n async open(options?: WebSocketServerOpenOptions) {\n if (this.isOpen) {\n return;\n }\n\n const webSocketServer = new NodeWebSocketServer({ server: this.#httpServer });\n\n try {\n for (const [type, listeners] of Object.entries(this.listeners)) {\n for (const [_listener, rawListener] of listeners) {\n webSocketServer.addListener(type, rawListener);\n }\n }\n\n await openWebSocketServer(this.#httpServer, webSocketServer, options);\n } catch (error) {\n await closeWebSocketServer(webSocketServer);\n throw error;\n }\n\n this.#webSocketServer = webSocketServer;\n }\n\n async close(options?: WebSocketServerCloseOptions) {\n if (!this.#webSocketServer) {\n return;\n }\n\n await closeWebSocketServer(this.#webSocketServer, options);\n\n this.#webSocketServer = undefined;\n }\n\n addEventListener(type: 'connection', listener: WebSocketServer.EventListener<Schema, 'connection'>): void;\n addEventListener(type: 'error', listener: WebSocketServer.EventListener<Schema, 'error'>): void;\n addEventListener(\n type: 'listening' | 'close',\n listener: WebSocketServer.EventListener<Schema, 'listening' | 'close'>,\n ): void;\n addEventListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n const rawListener = this.createRawListener(type, listener);\n this.#webSocketServer?.on(type, rawListener);\n this.listeners[type].set(listener, rawListener);\n }\n\n private createRawListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n switch (type) {\n case 'connection': {\n const typedListener = listener as WebSocketServer.EventListener<Schema, 'connection'>;\n\n return ((...[rawClient, ...parameters]: WebSocketServerRawEventListenerParameters['connection']) => {\n const wrappedClient =\n rawClient instanceof WebSocketClient ? rawClient : new WebSocketClient<Schema>(rawClient);\n\n typedListener.call(this, wrappedClient, ...parameters);\n }) as WebSocketServerRawEventListener<Type>;\n }\n\n case 'listening':\n case 'error':\n case 'close':\n default:\n return listener.bind(this) as WebSocketServerRawEventListener<Type>;\n }\n }\n\n removeEventListener(type: 'connection', listener: WebSocketServer.EventListener<Schema, 'connection'>): void;\n removeEventListener(type: 'error', listener: WebSocketServer.EventListener<Schema, 'error'>): void;\n removeEventListener(\n type: 'listening' | 'close',\n listener: WebSocketServer.EventListener<Schema, 'listening' | 'close'>,\n ): void;\n removeEventListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n const rawListener = this.listeners[type].get(listener);\n\n if (rawListener) {\n this.#webSocketServer?.off(type, rawListener);\n this.listeners[type].delete(listener);\n }\n }\n\n emit<Type extends WebSocketServer.EventType>(\n type: Type,\n ...parameters: WebSocketServer.EventListenerParameters<Schema>[Type]\n ) {\n if (this.#webSocketServer) {\n this.#webSocketServer.emit(type, ...parameters);\n } else {\n for (const [listener] of this.listeners[type]) {\n listener.call(this, ...parameters);\n }\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../../zimic-utils/src/server/lifecycle.ts","../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts","../src/server/errors/ClosedWebSocketServerError.ts","../src/server/utils/lifecycle.ts","../src/server/WebSocketServer.ts"],"names":["HttpsServer","NodeWebSocketServer"],"mappings":";;;;;;AAsFO,SAAS,sBAAsB,MAAA,EAAoB;AACxD,EAAA,MAAM,OAAA,GAAU,OAAO,OAAA,EAAA;AAEvB,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,OAAO,MAAA;EACT,CAAA,MAAO;AACL,IAAA,OAAO,OAAA,EAAS,OAAA;AAClB,EAAA;AACF;AAEO,SAAS,kBAAkB,MAAA,EAAoB;AACpD,EAAA,MAAM,OAAA,GAAU,OAAO,OAAA,EAAA;AAEvB,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,OAAO,MAAA;EACT,CAAA,MAAO;AACL,IAAA,OAAO,OAAA,EAAS,IAAA;AAClB,EAAA;AACF;;;ACxGO,IAAM,qBAAA,GAAN,cAAoC,KAAA,CAAM;AAAA,EAC/C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AAAA,EACd;AACF,CAAA;;;ACHO,IAAM,0BAAA,GAAN,cAAyC,qBAAA,CAAsB;AAAA,EACpE,YAAY,cAAA,EAAwB;AAClC,IAAA,KAAA,CAAM,CAAA,iCAAA,EAAoC,cAAc,CAAA,GAAA,CAAK,CAAA;AAC7D,IAAA,IAAA,CAAK,IAAA,GAAO,4BAAA;AAAA,EACd;AACF,CAAA;;;ACLO,IAAM,yBAAA,GAAN,cAAwC,qBAAA,CAAsB;AAAA,EACnE,YAAY,cAAA,EAAwB;AAClC,IAAA,KAAA,CAAM,CAAA,gCAAA,EAAmC,cAAc,CAAA,GAAA,CAAK,CAAA;AAC5D,IAAA,IAAA,CAAK,IAAA,GAAO,2BAAA;AAAA,EACd;AACF,CAAA;;;ACJO,IAAM,uCAAuC,EAAA,GAAK,GAAA;AAMzD,eAAsB,mBAAA,CAAoB,MAAA,EAAmB,OAAA,GAAsC,EAAC,EAAG;AACrG,EAAA,MAAM,EAAE,OAAA,EAAS,eAAA,GAAkB,oCAAA,EAAqC,GAAI,OAAA;AAE5E,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,UAAA,KAAe,MAAA,CAAO,IAAA;AAEnD,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC3C,IAAA,MAAM,WAAA,GAAc,WAAW,MAAM;AACnC,MAAA,MAAM,YAAA,GAAe,IAAI,yBAAA,CAA0B,eAAe,CAAA;AAClE,MAAA,WAAA,CAAY,YAAY,CAAA;AAAA,IAC1B,GAAG,eAAe,CAAA;AAElB,IAAA,SAAS,yBAAA,GAA4B;AACnC,MAAA,YAAA,CAAa,WAAW,CAAA;AAExB,MAAA,MAAA,CAAO,mBAAA,CAAoB,QAAQ,iBAAiB,CAAA;AACpD,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAC/C,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAAA,IACjD;AAEA,IAAA,SAAS,YAAY,KAAA,EAAgB;AACnC,MAAA,yBAAA,EAA0B;AAC1B,MAAA,MAAA,CAAO,KAAK,CAAA;AAAA,IACd;AAEA,IAAA,SAAS,iBAAA,GAAoB;AAC3B,MAAA,yBAAA,EAA0B;AAC1B,MAAA,OAAA,EAAQ;AAAA,IACV;AAEA,IAAA,MAAA,CAAO,gBAAA,CAAiB,QAAQ,iBAAiB,CAAA;AACjD,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAC5C,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAAA,EAC9C,CAAC,CAAA;AACH;AAIA,eAAsB,oBAAA,CACpB,QACA,OAAA,EACA;AACA,EAAA,MAAM,EAAE,OAAA,EAAS,eAAA,GAAkB,oCAAA,EAAqC,GAAI,OAAA;AAE5E,EAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,UAAA,KAAe,MAAA,CAAO,MAAA;AAErD,EAAA,IAAI,eAAA,EAAiB;AACnB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC3C,IAAA,MAAM,YAAA,GAAe,WAAW,MAAM;AACpC,MAAA,MAAM,YAAA,GAAe,IAAI,0BAAA,CAA2B,eAAe,CAAA;AACnE,MAAA,WAAA,CAAY,YAAY,CAAA;AAAA,IAC1B,GAAG,eAAe,CAAA;AAElB,IAAA,SAAS,yBAAA,GAA4B;AACnC,MAAA,YAAA,CAAa,YAAY,CAAA;AAEzB,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAC/C,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAAA,IACjD;AAEA,IAAA,SAAS,YAAY,KAAA,EAAgB;AACnC,MAAA,yBAAA,EAA0B;AAC1B,MAAA,MAAA,CAAO,KAAK,CAAA;AAAA,IACd;AAEA,IAAA,SAAS,WAAA,GAAc;AACrB,MAAA,yBAAA,EAA0B;AAC1B,MAAA,OAAA,EAAQ;AAAA,IACV;AAEA,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAC5C,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAE5C,IAAA,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,OAAA,CAAQ,MAAM,CAAA;AAAA,EAC3C,CAAC,CAAA;AACH;;;AC7BO,IAAM,eAAA,GAAN,MAAM,gBAAA,CAGX;AAAA,EACQ,MAAA;AAAA,EAER,IAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA,GAA0B,MAAA;AAAA,EAElB,gBAAA,GAEJ;AAAA,IACF,IAAA,EAAM,IAAA;AAAA,IACN,OAAA,EAAS,IAAA;AAAA,IACT,KAAA,EAAO,IAAA;AAAA,IACP,KAAA,EAAO;AAAA,GACT;AAAA,EAEQ,qBAAA,GAKJ;AAAA,IACF,IAAA,sBAAU,GAAA,EAAI;AAAA,IACd,OAAA,sBAAa,GAAA,EAAI;AAAA,IACjB,KAAA,sBAAW,GAAA,EAAI;AAAA,IACf,KAAA,sBAAW,GAAA;AAAI,GACjB;AAAA,EAIA,WAAA,CAAY,aAAiC,SAAA,EAA+B;AAC1E,IAAA,IAAI,OAAO,gBAAgB,QAAA,EAAU;AACnC,MAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AAAA,IACd,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,OAAO,WAAA,CAAY,GAAA;AACxB,MAAA,IAAA,CAAK,MAAA,GAAS,WAAA;AAAA,IAChB;AAEA,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAAA,EACpB;AAAA,EAEA,WAAW,UAAA,GAAa;AACtB,IAAA,OAAO,SAAA,CAAU,UAAA;AAAA,EACnB;AAAA,EAEA,IAAI,UAAA,GAAa;AACf,IAAA,OAAO,gBAAA,CAAgB,UAAA;AAAA,EACzB;AAAA,EAEA,WAAW,IAAA,GAAO;AAChB,IAAA,OAAO,SAAA,CAAU,IAAA;AAAA,EACnB;AAAA,EAEA,IAAI,IAAA,GAAO;AACT,IAAA,OAAO,gBAAA,CAAgB,IAAA;AAAA,EACzB;AAAA,EAEA,WAAW,OAAA,GAAU;AACnB,IAAA,OAAO,SAAA,CAAU,OAAA;AAAA,EACnB;AAAA,EAEA,IAAI,OAAA,GAAU;AACZ,IAAA,OAAO,gBAAA,CAAgB,OAAA;AAAA,EACzB;AAAA,EAEA,WAAW,MAAA,GAAS;AAClB,IAAA,OAAO,SAAA,CAAU,MAAA;AAAA,EACnB;AAAA,EAEA,IAAI,MAAA,GAAS;AACX,IAAA,OAAO,gBAAA,CAAgB,MAAA;AAAA,EACzB;AAAA,EAEA,IAAI,UAAA,GAAa;AACf,IAAA,OAAO,IAAA,CAAK,MAAA,EAAQ,UAAA,IAAc,IAAA,CAAK,WAAA;AAAA,EACzC;AAAA,EAEA,IAAI,WAAW,KAAA,EAA+B;AAC5C,IAAA,IAAA,CAAK,WAAA,GAAc,KAAA;AAEnB,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,IAAA,CAAK,OAAO,UAAA,GAAa,KAAA;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,IAAI,GAAA,GAAM;AACR,IAAA,OAAO,IAAA,CAAK,MAAA,EAAQ,GAAA,IAAO,IAAA,CAAK,IAAA;AAAA,EAClC;AAAA,EAEA,IAAI,QAAA,GAAW;AACb,IAAA,OAAO,IAAA,CAAK,QAAQ,QAAA,IAAY,EAAA;AAAA,EAClC;AAAA,EAEA,IAAI,UAAA,GAAa;AACf,IAAA,OAAO,IAAA,CAAK,QAAQ,UAAA,IAAc,EAAA;AAAA,EACpC;AAAA,EAEA,IAAI,UAAA,GAAyC;AAC3C,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,MAAA,EAAQ,UAAA,IAAc,SAAA,CAAU,MAAA;AACxD,IAAA,OAAO,UAAA;AAAA,EACT;AAAA,EAEA,IAAI,cAAA,GAAiB;AACnB,IAAA,OAAO,IAAA,CAAK,QAAQ,cAAA,IAAkB,CAAA;AAAA,EACxC;AAAA,EAEA,MAAM,KAAK,OAAA,EAAsC;AAC/C,IAAA,IAAI,IAAA,CAAK,UAAA,KAAe,gBAAA,CAAgB,IAAA,EAAM;AAC5C,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAK,KAAA,EAAM;AAEjB,IAAA,MAAM,SAAS,IAAI,SAAA,CAAU,IAAA,CAAK,IAAA,EAAM,KAAK,UAAU,CAAA;AAEvD,IAAA,IAAI;AACF,MAAA,IAAI,MAAA,CAAO,UAAA,KAAe,IAAA,CAAK,UAAA,EAAY;AACzC,QAAA,MAAA,CAAO,aAAa,IAAA,CAAK,UAAA;AAAA,MAC3B;AAEA,MAAA,IAAA,CAAK,eAAe,MAAM,CAAA;AAE1B,MAAA,MAAM,mBAAA,CAAoB,QAAQ,OAAO,CAAA;AAAA,IAC3C,SAAS,KAAA,EAAO;AACd,MAAA,MAAA,CAAO,KAAA,EAAM;AACb,MAAA,MAAM,KAAA;AAAA,IACR;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEQ,eAAe,MAAA,EAAmB;AACxC,IAAA,KAAA,MAAW,QAAQ,CAAC,MAAA,EAAQ,SAAA,EAAW,OAAA,EAAS,OAAO,CAAA,EAAY;AACjE,MAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA;AACxC,MAAA,MAAM,kBAAA,GAAqB,kBAAkB,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,CAAE,GAAA,CAAI,eAAe,CAAA,GAAI,MAAA;AAErG,MAAA,IAAI,kBAAA,EAAoB;AACtB,QAAA,MAAA,CAAO,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA,GAAI,kBAAA;AAAA,MACxB;AAEA,MAAA,KAAA,MAAW,eAAe,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,CAAE,QAAO,EAAG;AACnE,QAAA,MAAM,uBAAuB,WAAA,KAAgB,kBAAA;AAE7C,QAAA,IAAI,CAAC,oBAAA,EAAsB;AACzB,UAAA,MAAA,CAAO,gBAAA,CAAiB,MAAM,WAAW,CAAA;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,KAAA,CAAM,IAAA,EAAe,MAAA,EAAiB,OAAA,EAAuC;AACjF,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,oBAAA,CAAqB,KAAK,MAAA,EAAQ,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,QAAQ,CAAA;AAAA,IACtE,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,KAAK,IAAA,EAAoC;AACvC,IAAA,IAAA,CAAK,MAAA,EAAQ,KAAK,IAAI,CAAA;AAAA,EACxB;AAAA,EAEA,gBAAA,CACE,IAAA,EACA,QAAA,EACA,OAAA,EACA;AACA,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA;AAEtC,IAAA,IAAA,CAAK,MAAA,EAAQ,gBAAA,CAAiB,IAAA,EAAM,WAAA,EAAa,OAAO,CAAA;AACxD,IAAA,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,CAAE,GAAA,CAAI,UAAU,WAAW,CAAA;AAAA,EAC5D;AAAA,EAEA,mBAAA,CACE,IAAA,EACA,QAAA,EACA,OAAA,EACA;AACA,IAAA,MAAM,cAAc,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,CAAE,IAAI,QAAQ,CAAA;AAEjE,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,IAAA,CAAK,MAAA,EAAQ,mBAAA,CAAoB,IAAA,EAAM,WAAA,EAAa,OAAO,CAAA;AAC3D,MAAA,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,CAAE,MAAA,CAAO,QAAQ,CAAA;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,IAAI,MAAA,GAAS;AACX,IAAA,OAAO,KAAK,gBAAA,CAAiB,IAAA;AAAA,EAC/B;AAAA,EAEA,IAAI,OAAO,QAAA,EAAgE;AACzE,IAAA,IAAA,CAAK,gBAAA,CAAiB,QAAQ,QAAQ,CAAA;AAAA,EACxC;AAAA,EAEA,IAAI,SAAA,GAAY;AACd,IAAA,OAAO,KAAK,gBAAA,CAAiB,OAAA;AAAA,EAC/B;AAAA,EAEA,IAAI,UAAU,QAAA,EAAmE;AAC/E,IAAA,IAAA,CAAK,gBAAA,CAAiB,WAAW,QAAQ,CAAA;AAAA,EAC3C;AAAA,EAEA,IAAI,OAAA,GAAU;AACZ,IAAA,OAAO,KAAK,gBAAA,CAAiB,KAAA;AAAA,EAC/B;AAAA,EAEA,IAAI,QAAQ,QAAA,EAAiE;AAC3E,IAAA,IAAA,CAAK,gBAAA,CAAiB,SAAS,QAAQ,CAAA;AAAA,EACzC;AAAA,EAEA,IAAI,OAAA,GAAU;AACZ,IAAA,OAAO,KAAK,gBAAA,CAAiB,KAAA;AAAA,EAC/B;AAAA,EAEA,IAAI,QAAQ,QAAA,EAAiE;AAC3E,IAAA,IAAA,CAAK,gBAAA,CAAiB,SAAS,QAAQ,CAAA;AAAA,EACzC;AAAA,EAEQ,gBAAA,CAGN,MAAY,QAAA,EAAoB;AAChC,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA;AAElD,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,MAAM,cAAc,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,CAAE,IAAI,eAAe,CAAA;AAExE,MAAA,IAAI,IAAA,CAAK,UAAU,WAAA,EAAa;AAC9B,QAAA,IAAA,CAAK,MAAA,CAAO,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA,GAAI,IAAA;AAAA,MAC7B;AAEA,MAAA,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,CAAE,MAAA,CAAO,eAAe,CAAA;AAAA,IACzD;AAEA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,WAAA,GAAc,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA;AACtC,MAAA,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,CAAE,GAAA,CAAI,UAAU,WAAW,CAAA;AAE1D,MAAA,IAAI,KAAK,MAAA,EAAQ;AACf,QAAA,IAAA,CAAK,MAAA,CAAO,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA,GAAI,WAAA;AAAA,MAC7B;AAEA,MAAC,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA,GAAiB,QAAA;AAAA,IAC9C,CAAA,MAAO;AACL,MAAA,IAAI,KAAK,MAAA,EAAQ;AACf,QAAA,IAAA,CAAK,MAAA,CAAO,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA,GAAI,IAAA;AAAA,MAC7B;AAEA,MAAC,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA,GAAwB,IAAA;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,cAAsD,KAAA,EAA4C;AAChG,IAAA,OAAO,IAAA,CAAK,MAAA,EAAQ,aAAA,CAAc,KAAK,CAAA,IAAK,KAAA;AAAA,EAC9C;AACF,CAAA;;;ACnUA,IAAM,0BAAA,GAAN,cAAyC,KAAA,CAAM;AAAA,EAC7C,WAAA,GAAc;AACZ,IAAA,KAAA,CAAM,4DAA4D,CAAA;AAClE,IAAA,IAAA,CAAK,IAAA,GAAO,4BAAA;AAAA,EACd;AACF,CAAA;AAEA,IAAO,kCAAA,GAAQ,0BAAA;;;ACKf,eAAsB,mBAAA,CACpB,UAAA,EACA,eAAA,EACA,OAAA,GAAsC,EAAC,EACvC;AACA,EAAA,MAAM,EAAE,OAAA,EAAS,eAAA,GAAkB,oCAAA,EAAqC,GAAI,OAAA;AAE5E,EAAA,MAAM,gBAAgB,UAAA,CAAW,SAAA;AAEjC,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC3C,IAAA,MAAM,WAAA,GAAc,WAAW,MAAM;AACnC,MAAA,MAAM,YAAA,GAAe,IAAI,yBAAA,CAA0B,eAAe,CAAA;AAClE,MAAA,MAAA,CAAO,YAAY,CAAA;AAAA,IACrB,GAAG,eAAe,CAAA;AAElB,IAAA,SAAS,yBAAA,GAA4B;AACnC,MAAA,YAAA,CAAa,WAAW,CAAA;AAExB,MAAA,eAAA,CAAgB,GAAA,CAAI,aAAa,eAAe,CAAA;AAChD,MAAA,eAAA,CAAgB,GAAA,CAAI,SAAS,WAAW,CAAA;AAAA,IAC1C;AAIA,IAAA,SAAS,YAAY,KAAA,EAAgB;AACnC,MAAA,yBAAA,EAA0B;AAC1B,MAAA,MAAA,CAAO,KAAK,CAAA;AAAA,IACd;AAEA,IAAA,SAAS,eAAA,GAAkB;AACzB,MAAA,yBAAA,EAA0B;AAC1B,MAAA,OAAA,EAAQ;AAAA,IACV;AAEA,IAAA,eAAA,CAAgB,EAAA,CAAG,aAAa,eAAe,CAAA;AAC/C,IAAA,eAAA,CAAgB,EAAA,CAAG,SAAS,WAAW,CAAA;AAAA,EACzC,CAAC,CAAA;AACH;AAIA,eAAsB,oBAAA,CACpB,eAAA,EACA,OAAA,GAAuC,EAAC,EACxC;AACA,EAAA,MAAM,EAAE,OAAA,EAAS,eAAA,GAAkB,oCAAA,EAAqC,GAAI,OAAA;AAE5E,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC3C,IAAA,MAAM,YAAA,GAAe,WAAW,MAAM;AACpC,MAAA,MAAM,YAAA,GAAe,IAAI,0BAAA,CAA2B,eAAe,CAAA;AACnE,MAAA,MAAA,CAAO,YAAY,CAAA;AAAA,IACrB,GAAG,eAAe,CAAA;AAElB,IAAA,KAAA,MAAW,MAAA,IAAU,gBAAgB,OAAA,EAAS;AAC5C,MAAA,MAAA,CAAO,KAAA,EAAM;AAAA,IACf;AAEA,IAAA,eAAA,CAAgB,KAAA,CAAM,CAAC,KAAA,KAAU;AAC/B,MAAA,YAAA,CAAa,YAAY,CAAA;AAIzB,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,MAAA,CAAO,KAAK,CAAA;AAAA,MACd,CAAA,MAAO;AACL,QAAA,OAAA,EAAQ;AAAA,MACV;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;;;ACrCO,IAAM,kBAAN,MAAsD;AAAA,EAC3D,WAAA;AAAA,EACA,gBAAA;AAAA,EAEQ,SAAA,GAKJ;AAAA,IACF,UAAA,sBAAgB,GAAA,EAAI;AAAA,IACpB,SAAA,sBAAe,GAAA,EAAI;AAAA,IACnB,KAAA,sBAAW,GAAA,EAAI;AAAA,IACf,KAAA,sBAAW,GAAA;AAAI,GACjB;AAAA,EAEA,YAAY,OAAA,EAAiC;AAC3C,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,UAAA;AAAA,EAC7B;AAAA,EAEA,IAAI,OAAA,GAAU;AACZ,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,MAAA,MAAM,IAAI,kCAAA,EAA2B;AAAA,IACvC;AACA,IAAA,OAAO,CAAA,EAAG,KAAK,QAAQ,CAAA,GAAA,EAAM,KAAK,QAAQ,CAAA,CAAA,EAAI,KAAK,IAAI,CAAA,CAAA;AAAA,EACzD;AAAA,EAEA,IAAI,QAAA,GAAW;AACb,IAAA,OAAO,IAAA,CAAK,WAAA,YAAuBA,YAAA,GAAc,KAAA,GAAQ,IAAA;AAAA,EAC3D;AAAA,EAEA,IAAI,QAAA,GAAW;AACb,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,MAAA,MAAM,IAAI,kCAAA,EAA2B;AAAA,IACvC;AACA,IAAA,OAAO,qBAAA,CAAsB,KAAK,WAAW,CAAA;AAAA,EAC/C;AAAA,EAEA,IAAI,IAAA,GAAO;AACT,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,MAAA,MAAM,IAAI,kCAAA,EAA2B;AAAA,IACvC;AACA,IAAA,OAAO,iBAAA,CAAkB,KAAK,WAAW,CAAA;AAAA,EAC3C;AAAA,EAEA,IAAI,MAAA,GAAS;AACX,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,SAAA,IAAa,IAAA,CAAK,gBAAA,KAAqB,MAAA;AAAA,EACjE;AAAA,EAEA,MAAM,KAAK,OAAA,EAAsC;AAC/C,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,kBAAkB,IAAIC,kBAAA,CAAoB,EAAE,MAAA,EAAQ,IAAA,CAAK,aAAa,CAAA;AAE5E,IAAA,IAAI;AACF,MAAA,KAAA,MAAW,CAAC,MAAM,SAAS,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA,EAAG;AAC9D,QAAA,KAAA,MAAW,CAAC,SAAA,EAAW,WAAW,CAAA,IAAK,SAAA,EAAW;AAChD,UAAA,eAAA,CAAgB,WAAA,CAAY,MAAM,WAAW,CAAA;AAAA,QAC/C;AAAA,MACF;AAEA,MAAA,MAAM,mBAAA,CAAoB,IAAA,CAAK,WAAA,EAAa,eAAA,EAAiB,OAAO,CAAA;AAAA,IACtE,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,qBAAqB,eAAe,CAAA;AAC1C,MAAA,MAAM,KAAA;AAAA,IACR;AAEA,IAAA,IAAA,CAAK,gBAAA,GAAmB,eAAA;AAAA,EAC1B;AAAA,EAEA,MAAM,MAAM,OAAA,EAAuC;AACjD,IAAA,IAAI,CAAC,KAAK,gBAAA,EAAkB;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,oBAAA,CAAqB,IAAA,CAAK,gBAAA,EAAkB,OAAO,CAAA;AAEzD,IAAA,IAAA,CAAK,gBAAA,GAAmB,MAAA;AAAA,EAC1B;AAAA,EAQA,gBAAA,CACE,MACA,QAAA,EACA;AACA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,iBAAA,CAAkB,IAAA,EAAM,QAAQ,CAAA;AACzD,IAAA,IAAA,CAAK,gBAAA,EAAkB,EAAA,CAAG,IAAA,EAAM,WAAW,CAAA;AAC3C,IAAA,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,CAAE,GAAA,CAAI,UAAU,WAAW,CAAA;AAAA,EAChD;AAAA,EAEQ,iBAAA,CACN,MACA,QAAA,EACA;AACA,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,YAAA,EAAc;AACjB,QAAA,MAAM,aAAA,GAAgB,QAAA;AAEtB,QAAA,QAAQ,CAAA,GAAI,CAAC,SAAA,EAAc,GAAA,UAAU,CAAA,KAA+D;AAClG,UAAA,MAAM,gBACJ,SAAA,YAAqB,eAAA,GAAkB,SAAA,GAAY,IAAI,gBAAwB,SAAS,CAAA;AAE1F,UAAA,aAAA,CAAc,IAAA,CAAK,IAAA,EAAM,aAAA,EAAe,GAAG,UAAU,CAAA;AAAA,QACvD,CAAA;AAAA,MACF;AAAA,MAEA,KAAK,WAAA;AAAA,MACL,KAAK,OAAA;AAAA,MACL,KAAK,OAAA;AAAA,MACL;AACE,QAAA,OAAO,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA;AAC7B,EACF;AAAA,EAQA,mBAAA,CACE,MACA,QAAA,EACA;AACA,IAAA,MAAM,cAAc,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,CAAE,IAAI,QAAQ,CAAA;AAErD,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,IAAA,CAAK,gBAAA,EAAkB,GAAA,CAAI,IAAA,EAAM,WAAW,CAAA;AAC5C,MAAA,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,CAAE,MAAA,CAAO,QAAQ,CAAA;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,IAAA,CACE,SACG,UAAA,EACH;AACA,IAAA,IAAI,KAAK,gBAAA,EAAkB;AACzB,MAAA,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,IAAA,EAAM,GAAG,UAAU,CAAA;AAAA,IAChD,CAAA,MAAO;AACL,MAAA,KAAA,MAAW,CAAC,QAAQ,CAAA,IAAK,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAC7C,QAAA,QAAA,CAAS,IAAA,CAAK,IAAA,EAAM,GAAG,UAAU,CAAA;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF","file":"server.js","sourcesContent":["import { Server as HttpServer } from 'http';\n\nexport const DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport class HttpServerTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HttpServerTimeoutError';\n }\n}\n\nexport class HttpServerStartTimeoutError extends HttpServerTimeoutError {\n constructor(reachedTimeout: number) {\n super(`HTTP server start timed out after ${reachedTimeout}ms.`);\n this.name = 'HttpServerStartTimeoutError';\n }\n}\n\nexport class HttpServerStopTimeoutError extends HttpServerTimeoutError {\n constructor(reachedTimeout: number) {\n super(`HTTP server stop timed out after ${reachedTimeout}ms.`);\n this.name = 'HttpServerStopTimeoutError';\n }\n}\n\nexport async function startHttpServer(\n server: HttpServer,\n options: {\n hostname?: string;\n port?: number;\n timeout?: number;\n } = {},\n) {\n const { hostname, port, timeout: timeoutDuration = DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT } = options;\n\n await new Promise<void>((resolve, reject) => {\n function handleStartError(error: unknown) {\n server.off('listening', handleStartSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n reject(error);\n }\n\n const startTimeout = setTimeout(() => {\n const timeoutError = new HttpServerStartTimeoutError(timeoutDuration);\n handleStartError(timeoutError);\n }, timeoutDuration);\n\n function handleStartSuccess() {\n server.off('error', handleStartError);\n clearTimeout(startTimeout);\n resolve();\n }\n\n server.once('error', handleStartError);\n server.listen(port, hostname, handleStartSuccess);\n });\n}\n\nexport async function stopHttpServer(server: HttpServer, options: { timeout?: number } = {}) {\n const { timeout: timeoutDuration = DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT } = options;\n\n if (!server.listening) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const stopTimeout = setTimeout(() => {\n const timeoutError = new HttpServerStopTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n server.close((error) => {\n clearTimeout(stopTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is expected not to happen since the servers are not stopped unless they are running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n\n server.closeAllConnections();\n });\n}\n\nexport function getHttpServerHostname(server: HttpServer) {\n const address = server.address();\n\n if (typeof address === 'string') {\n return undefined;\n } else {\n return address?.address;\n }\n}\n\nexport function getHttpServerPort(server: HttpServer) {\n const address = server.address();\n\n if (typeof address === 'string') {\n return undefined;\n } else {\n return address?.port;\n }\n}\n","export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport const DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport interface WebSocketClientOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketClient(socket: WebSocket, options: WebSocketClientOpenOptions = {}) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleOpenSuccess() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport type WebSocketClientCloseOptions = WebSocketClientOpenOptions;\n\nexport async function closeWebSocketClient(\n socket: WebSocket,\n options: WebSocketClientCloseOptions & { code?: number; reason?: string },\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(closeTimeout);\n\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleClose() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { PossiblePromise } from '@zimic/utils/types';\n\nimport { WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport {\n closeWebSocketClient,\n openWebSocketClient,\n WebSocketClientCloseOptions,\n WebSocketClientOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketClient {\n export type ReadyState =\n | typeof WebSocketClient.CONNECTING\n | typeof WebSocketClient.OPEN\n | typeof WebSocketClient.CLOSING\n | typeof WebSocketClient.CLOSED;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type OpenEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n export type MessageEvent<Schema extends WebSocketSchema> = globalThis.MessageEvent<WebSocketMessageData<Schema>>;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type CloseEvent<_Schema extends WebSocketSchema> = globalThis.CloseEvent;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type ErrorEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n interface Events<Schema extends WebSocketSchema = WebSocketSchema> {\n open: OpenEvent<Schema>;\n message: MessageEvent<Schema>;\n close: CloseEvent<Schema>;\n error: ErrorEvent<Schema>;\n }\n\n export type EventType = keyof Events<WebSocketSchema>;\n\n export type Event<\n Schema extends WebSocketSchema = WebSocketSchema,\n Type extends EventType = EventType,\n > = Events<Schema>[Type];\n\n interface EventListenerParameters<Schema extends WebSocketSchema> {\n open: [event: Event<Schema, 'open'>];\n message: [event: Event<Schema, 'message'>];\n close: [event: Event<Schema, 'close'>];\n error: [event: Event<Schema, 'error'>];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketClient<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\ntype WebSocketClientRawEventListener = (this: WebSocket, event: Event) => PossiblePromise<void>;\n\nexport class WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: WebSocket;\n\n #url: string;\n #protocols?: string | string[];\n #binaryType: BinaryType = 'blob';\n\n private unitaryListeners: {\n [Type in WebSocketClient.EventType]: WebSocketClient.EventListener<Schema, Type> | null;\n } = {\n open: null,\n message: null,\n close: null,\n error: null,\n };\n\n private listenerToRawListener: {\n [Type in WebSocketClient.EventType]: Map<\n WebSocketClient.EventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(socket: WebSocket);\n constructor(_url: string, protocols?: string | string[]);\n constructor(urlOrSocket: WebSocket | string, protocols?: string | string[]) {\n if (typeof urlOrSocket === 'string') {\n this.#url = urlOrSocket;\n } else {\n this.#url = urlOrSocket.url;\n this.socket = urlOrSocket;\n }\n\n this.#protocols = protocols;\n }\n\n static get CONNECTING() {\n return WebSocket.CONNECTING;\n }\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static get OPEN() {\n return WebSocket.OPEN;\n }\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static get CLOSING() {\n return WebSocket.CLOSING;\n }\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static get CLOSED() {\n return WebSocket.CLOSED;\n }\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this.#binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this.#binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this.#url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState(): WebSocketClient.ReadyState {\n const readyState = this.socket?.readyState ?? WebSocket.CLOSED;\n return readyState;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options?: WebSocketClientOpenOptions) {\n if (this.readyState === WebSocketClient.OPEN) {\n return;\n }\n\n await this.close();\n\n const socket = new WebSocket(this.#url, this.#protocols);\n\n try {\n if (socket.binaryType !== this.binaryType) {\n socket.binaryType = this.binaryType;\n }\n\n this.applyListeners(socket);\n\n await openWebSocketClient(socket, options);\n } catch (error) {\n socket.close();\n throw error;\n }\n\n this.socket = socket;\n }\n\n private applyListeners(socket: WebSocket) {\n for (const type of ['open', 'message', 'close', 'error'] as const) {\n const unitaryListener = this[`on${type}`] as WebSocketClient.EventListener<Schema, typeof type> | null;\n const rawUnitaryListener = unitaryListener ? this.listenerToRawListener[type].get(unitaryListener) : undefined;\n\n if (rawUnitaryListener) {\n socket[`on${type}`] = rawUnitaryListener;\n }\n\n for (const rawListener of this.listenerToRawListener[type].values()) {\n const isRawUnitaryListener = rawListener === rawUnitaryListener;\n\n if (!isRawUnitaryListener) {\n socket.addEventListener(type, rawListener);\n }\n }\n }\n }\n\n async close(code?: number, reason?: string, options?: WebSocketClientCloseOptions) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeWebSocketClient(this.socket, { ...options, code, reason });\n } finally {\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listenerToRawListener[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listenerToRawListener[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listenerToRawListener[type].delete(listener);\n }\n }\n\n get onopen() {\n return this.unitaryListeners.open;\n }\n\n set onopen(listener: WebSocketClient.EventListener<Schema, 'open'> | null) {\n this.setEventListener('open', listener);\n }\n\n get onmessage() {\n return this.unitaryListeners.message;\n }\n\n set onmessage(listener: WebSocketClient.EventListener<Schema, 'message'> | null) {\n this.setEventListener('message', listener);\n }\n\n get onclose() {\n return this.unitaryListeners.close;\n }\n\n set onclose(listener: WebSocketClient.EventListener<Schema, 'close'> | null) {\n this.setEventListener('close', listener);\n }\n\n get onerror() {\n return this.unitaryListeners.error;\n }\n\n set onerror(listener: WebSocketClient.EventListener<Schema, 'error'> | null) {\n this.setEventListener('error', listener);\n }\n\n private setEventListener<\n Type extends WebSocketClient.EventType,\n Listener extends WebSocketClient.EventListener<Schema, Type> | null,\n >(type: Type, listener: Listener) {\n const currentListener = this.unitaryListeners[type];\n\n if (currentListener) {\n const rawListener = this.listenerToRawListener[type].get(currentListener);\n\n if (this.socket && rawListener) {\n this.socket[`on${type}`] = null;\n }\n\n this.listenerToRawListener[type].delete(currentListener);\n }\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listenerToRawListener[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this.unitaryListeners[type] as Listener) = listener;\n } else {\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this.unitaryListeners[type] as Listener | null) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketClient.EventType>(event: WebSocketClient.Event<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n","class ClosedWebSocketServerError extends Error {\n constructor() {\n super('The WebSocket server is closed. Did you forget to open it?');\n this.name = 'ClosedWebSocketServerError';\n }\n}\n\nexport default ClosedWebSocketServerError;\n","import { Server as HttpServer } from 'http';\nimport { Server as HttpsServer } from 'https';\nimport { WebSocketServer as NodeWebSocketServer } from 'ws';\n\nimport { DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } from '@/client/utils/lifecycle';\nimport { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport interface WebSocketServerOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketServer(\n httpServer: HttpServer | HttpsServer,\n webSocketServer: NodeWebSocketServer,\n options: WebSocketServerOpenOptions = {},\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = httpServer.listening;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n webSocketServer.off('listening', handleListening); // eslint-disable-line @typescript-eslint/no-use-before-define\n webSocketServer.off('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n /* istanbul ignore next -- @preserve\n * This is not expected since the server is not started unless it is not running. */\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleListening() {\n removeListenersAndTimeout();\n resolve();\n }\n\n webSocketServer.on('listening', handleListening);\n webSocketServer.on('error', handleError);\n });\n}\n\nexport type WebSocketServerCloseOptions = WebSocketServerOpenOptions;\n\nexport async function closeWebSocketServer(\n webSocketServer: NodeWebSocketServer,\n options: WebSocketServerCloseOptions = {},\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n for (const client of webSocketServer.clients) {\n client.close();\n }\n\n webSocketServer.close((error) => {\n clearTimeout(closeTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is not expected since the server is not stopped unless it is running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n","import { getHttpServerHostname, getHttpServerPort } from '@zimic/utils/server';\nimport { PossiblePromise } from '@zimic/utils/types';\nimport { Server as HttpServer, IncomingMessage } from 'http';\nimport { Server as HttpsServer } from 'https';\nimport { WebSocketServer as NodeWebSocketServer } from 'ws';\n\nimport { WebSocketClient } from '@/client/WebSocketClient';\nimport { WebSocketSchema } from '@/types/schema';\n\nimport ClosedWebSocketServerError from './errors/ClosedWebSocketServerError';\nimport {\n closeWebSocketServer,\n openWebSocketServer,\n WebSocketServerCloseOptions,\n WebSocketServerOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketServer {\n export type EventType = 'listening' | 'connection' | 'error' | 'close';\n\n export interface EventListenerParameters<Schema extends WebSocketSchema> {\n connection: [client: WebSocketClient<Schema>, request: IncomingMessage];\n error: [error: Error];\n close: [];\n listening: [];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketServer<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\nexport interface WebSocketServerOptions {\n httpServer: HttpServer | HttpsServer;\n}\n\nexport interface WebSocketServerRawEventListenerParameters {\n connection: [client: WebSocket, request: IncomingMessage];\n error: [error: Error];\n close: [];\n listening: [];\n}\n\ntype WebSocketServerRawEventListener<Type extends WebSocketServer.EventType> = (\n ...parameters: WebSocketServerRawEventListenerParameters[Type]\n) => void;\n\nexport class WebSocketServer<Schema extends WebSocketSchema> {\n #httpServer: HttpServer | HttpsServer;\n #webSocketServer?: NodeWebSocketServer;\n\n private listeners: {\n [Type in WebSocketServer.EventType]: Map<\n WebSocketServer.EventListener<Schema, Type>,\n WebSocketServerRawEventListener<Type>\n >;\n } = {\n connection: new Map(),\n listening: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(options: WebSocketServerOptions) {\n this.#httpServer = options.httpServer;\n }\n\n get baseURL() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return `${this.protocol}://${this.hostname}:${this.port}`;\n }\n\n get protocol() {\n return this.#httpServer instanceof HttpsServer ? 'wss' : 'ws';\n }\n\n get hostname() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return getHttpServerHostname(this.#httpServer);\n }\n\n get port() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return getHttpServerPort(this.#httpServer);\n }\n\n get isOpen() {\n return this.#httpServer.listening && this.#webSocketServer !== undefined;\n }\n\n async open(options?: WebSocketServerOpenOptions) {\n if (this.isOpen) {\n return;\n }\n\n const webSocketServer = new NodeWebSocketServer({ server: this.#httpServer });\n\n try {\n for (const [type, listeners] of Object.entries(this.listeners)) {\n for (const [_listener, rawListener] of listeners) {\n webSocketServer.addListener(type, rawListener);\n }\n }\n\n await openWebSocketServer(this.#httpServer, webSocketServer, options);\n } catch (error) {\n await closeWebSocketServer(webSocketServer);\n throw error;\n }\n\n this.#webSocketServer = webSocketServer;\n }\n\n async close(options?: WebSocketServerCloseOptions) {\n if (!this.#webSocketServer) {\n return;\n }\n\n await closeWebSocketServer(this.#webSocketServer, options);\n\n this.#webSocketServer = undefined;\n }\n\n addEventListener(type: 'connection', listener: WebSocketServer.EventListener<Schema, 'connection'>): void;\n addEventListener(type: 'error', listener: WebSocketServer.EventListener<Schema, 'error'>): void;\n addEventListener(\n type: 'listening' | 'close',\n listener: WebSocketServer.EventListener<Schema, 'listening' | 'close'>,\n ): void;\n addEventListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n const rawListener = this.createRawListener(type, listener);\n this.#webSocketServer?.on(type, rawListener);\n this.listeners[type].set(listener, rawListener);\n }\n\n private createRawListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n switch (type) {\n case 'connection': {\n const typedListener = listener as WebSocketServer.EventListener<Schema, 'connection'>;\n\n return ((...[rawClient, ...parameters]: WebSocketServerRawEventListenerParameters['connection']) => {\n const wrappedClient =\n rawClient instanceof WebSocketClient ? rawClient : new WebSocketClient<Schema>(rawClient);\n\n typedListener.call(this, wrappedClient, ...parameters);\n }) as WebSocketServerRawEventListener<Type>;\n }\n\n case 'listening':\n case 'error':\n case 'close':\n default:\n return listener.bind(this) as WebSocketServerRawEventListener<Type>;\n }\n }\n\n removeEventListener(type: 'connection', listener: WebSocketServer.EventListener<Schema, 'connection'>): void;\n removeEventListener(type: 'error', listener: WebSocketServer.EventListener<Schema, 'error'>): void;\n removeEventListener(\n type: 'listening' | 'close',\n listener: WebSocketServer.EventListener<Schema, 'listening' | 'close'>,\n ): void;\n removeEventListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n const rawListener = this.listeners[type].get(listener);\n\n if (rawListener) {\n this.#webSocketServer?.off(type, rawListener);\n this.listeners[type].delete(listener);\n }\n }\n\n emit<Type extends WebSocketServer.EventType>(\n type: Type,\n ...parameters: WebSocketServer.EventListenerParameters<Schema>[Type]\n ) {\n if (this.#webSocketServer) {\n this.#webSocketServer.emit(type, ...parameters);\n } else {\n for (const [listener] of this.listeners[type]) {\n listener.call(this, ...parameters);\n }\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../zimic-utils/src/server/lifecycle.ts","../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts","../src/server/errors/ClosedWebSocketServerError.ts","../src/server/utils/lifecycle.ts","../src/server/WebSocketServer.ts"],"names":["HttpsServer","NodeWebSocketServer"],"mappings":"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","file":"server.mjs","sourcesContent":["import { Server as HttpServer } from 'http';\n\nexport const DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport class HttpServerTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HttpServerTimeoutError';\n }\n}\n\nexport class HttpServerStartTimeoutError extends HttpServerTimeoutError {\n constructor(reachedTimeout: number) {\n super(`HTTP server start timed out after ${reachedTimeout}ms.`);\n this.name = 'HttpServerStartTimeoutError';\n }\n}\n\nexport class HttpServerStopTimeoutError extends HttpServerTimeoutError {\n constructor(reachedTimeout: number) {\n super(`HTTP server stop timed out after ${reachedTimeout}ms.`);\n this.name = 'HttpServerStopTimeoutError';\n }\n}\n\nexport async function startHttpServer(\n server: HttpServer,\n options: {\n hostname?: string;\n port?: number;\n timeout?: number;\n } = {},\n) {\n const { hostname, port, timeout: timeoutDuration = DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT } = options;\n\n await new Promise<void>((resolve, reject) => {\n function handleStartError(error: unknown) {\n server.off('listening', handleStartSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n reject(error);\n }\n\n const startTimeout = setTimeout(() => {\n const timeoutError = new HttpServerStartTimeoutError(timeoutDuration);\n handleStartError(timeoutError);\n }, timeoutDuration);\n\n function handleStartSuccess() {\n server.off('error', handleStartError);\n clearTimeout(startTimeout);\n resolve();\n }\n\n server.once('error', handleStartError);\n server.listen(port, hostname, handleStartSuccess);\n });\n}\n\nexport async function stopHttpServer(server: HttpServer, options: { timeout?: number } = {}) {\n const { timeout: timeoutDuration = DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT } = options;\n\n if (!server.listening) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const stopTimeout = setTimeout(() => {\n const timeoutError = new HttpServerStopTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n server.close((error) => {\n clearTimeout(stopTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is expected not to happen since the servers are not stopped unless they are running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n\n server.closeAllConnections();\n });\n}\n\nexport function getHttpServerHostname(server: HttpServer) {\n const address = server.address();\n\n if (typeof address === 'string') {\n return undefined;\n } else {\n return address?.address;\n }\n}\n\nexport function getHttpServerPort(server: HttpServer) {\n const address = server.address();\n\n if (typeof address === 'string') {\n return undefined;\n } else {\n return address?.port;\n }\n}\n","export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport const DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport interface WebSocketClientOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketClient(socket: WebSocket, options: WebSocketClientOpenOptions = {}) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleOpenSuccess() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport type WebSocketClientCloseOptions = WebSocketClientOpenOptions;\n\nexport async function closeWebSocketClient(\n socket: WebSocket,\n options: WebSocketClientCloseOptions & { code?: number; reason?: string },\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(closeTimeout);\n\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleClose() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { PossiblePromise } from '@zimic/utils/types';\n\nimport { WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport {\n closeWebSocketClient,\n openWebSocketClient,\n WebSocketClientCloseOptions,\n WebSocketClientOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketClient {\n export type ReadyState =\n | typeof WebSocketClient.CONNECTING\n | typeof WebSocketClient.OPEN\n | typeof WebSocketClient.CLOSING\n | typeof WebSocketClient.CLOSED;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type OpenEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n export type MessageEvent<Schema extends WebSocketSchema> = globalThis.MessageEvent<WebSocketMessageData<Schema>>;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type CloseEvent<_Schema extends WebSocketSchema> = globalThis.CloseEvent;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type ErrorEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n interface Events<Schema extends WebSocketSchema = WebSocketSchema> {\n open: OpenEvent<Schema>;\n message: MessageEvent<Schema>;\n close: CloseEvent<Schema>;\n error: ErrorEvent<Schema>;\n }\n\n export type EventType = keyof Events<WebSocketSchema>;\n\n export type Event<\n Schema extends WebSocketSchema = WebSocketSchema,\n Type extends EventType = EventType,\n > = Events<Schema>[Type];\n\n interface EventListenerParameters<Schema extends WebSocketSchema> {\n open: [event: Event<Schema, 'open'>];\n message: [event: Event<Schema, 'message'>];\n close: [event: Event<Schema, 'close'>];\n error: [event: Event<Schema, 'error'>];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketClient<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\ntype WebSocketClientRawEventListener = (this: WebSocket, event: Event) => PossiblePromise<void>;\n\nexport class WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: WebSocket;\n\n #url: string;\n #protocols?: string | string[];\n #binaryType: BinaryType = 'blob';\n\n private unitaryListeners: {\n [Type in WebSocketClient.EventType]: WebSocketClient.EventListener<Schema, Type> | null;\n } = {\n open: null,\n message: null,\n close: null,\n error: null,\n };\n\n private listenerToRawListener: {\n [Type in WebSocketClient.EventType]: Map<\n WebSocketClient.EventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(socket: WebSocket);\n constructor(_url: string, protocols?: string | string[]);\n constructor(urlOrSocket: WebSocket | string, protocols?: string | string[]) {\n if (typeof urlOrSocket === 'string') {\n this.#url = urlOrSocket;\n } else {\n this.#url = urlOrSocket.url;\n this.socket = urlOrSocket;\n }\n\n this.#protocols = protocols;\n }\n\n static get CONNECTING() {\n return WebSocket.CONNECTING;\n }\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static get OPEN() {\n return WebSocket.OPEN;\n }\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static get CLOSING() {\n return WebSocket.CLOSING;\n }\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static get CLOSED() {\n return WebSocket.CLOSED;\n }\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this.#binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this.#binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this.#url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState(): WebSocketClient.ReadyState {\n const readyState = this.socket?.readyState ?? WebSocket.CLOSED;\n return readyState as WebSocketClient.ReadyState;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options?: WebSocketClientOpenOptions) {\n if (this.readyState === WebSocketClient.OPEN) {\n return;\n }\n\n await this.close();\n\n const socket = new WebSocket(this.#url, this.#protocols);\n\n try {\n if (socket.binaryType !== this.binaryType) {\n socket.binaryType = this.binaryType;\n }\n\n this.applyListeners(socket);\n\n await openWebSocketClient(socket, options);\n } catch (error) {\n socket.close();\n throw error;\n }\n\n this.socket = socket;\n }\n\n private applyListeners(socket: WebSocket) {\n for (const type of ['open', 'message', 'close', 'error'] as const) {\n const unitaryListener = this[`on${type}`] as WebSocketClient.EventListener<Schema, typeof type> | null;\n const rawUnitaryListener = unitaryListener ? this.listenerToRawListener[type].get(unitaryListener) : undefined;\n\n if (rawUnitaryListener) {\n socket[`on${type}`] = rawUnitaryListener;\n }\n\n for (const rawListener of this.listenerToRawListener[type].values()) {\n const isRawUnitaryListener = rawListener === rawUnitaryListener;\n\n if (!isRawUnitaryListener) {\n socket.addEventListener(type, rawListener);\n }\n }\n }\n }\n\n async close(code?: number, reason?: string, options?: WebSocketClientCloseOptions) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeWebSocketClient(this.socket, { ...options, code, reason });\n } finally {\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listenerToRawListener[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listenerToRawListener[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listenerToRawListener[type].delete(listener);\n }\n }\n\n get onopen() {\n return this.unitaryListeners.open;\n }\n\n set onopen(listener: WebSocketClient.EventListener<Schema, 'open'> | null) {\n this.setEventListener('open', listener);\n }\n\n get onmessage() {\n return this.unitaryListeners.message;\n }\n\n set onmessage(listener: WebSocketClient.EventListener<Schema, 'message'> | null) {\n this.setEventListener('message', listener);\n }\n\n get onclose() {\n return this.unitaryListeners.close;\n }\n\n set onclose(listener: WebSocketClient.EventListener<Schema, 'close'> | null) {\n this.setEventListener('close', listener);\n }\n\n get onerror() {\n return this.unitaryListeners.error;\n }\n\n set onerror(listener: WebSocketClient.EventListener<Schema, 'error'> | null) {\n this.setEventListener('error', listener);\n }\n\n private setEventListener<\n Type extends WebSocketClient.EventType,\n Listener extends WebSocketClient.EventListener<Schema, Type> | null,\n >(type: Type, listener: Listener) {\n const currentListener = this.unitaryListeners[type];\n\n if (currentListener) {\n const rawListener = this.listenerToRawListener[type].get(currentListener);\n\n if (this.socket && rawListener) {\n this.socket[`on${type}`] = null;\n }\n\n this.listenerToRawListener[type].delete(currentListener);\n }\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listenerToRawListener[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this.unitaryListeners[type] as Listener) = listener;\n } else {\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this.unitaryListeners[type] as Listener | null) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketClient.EventType>(event: WebSocketClient.Event<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n","class ClosedWebSocketServerError extends Error {\n constructor() {\n super('The WebSocket server is closed. Did you forget to open it?');\n this.name = 'ClosedWebSocketServerError';\n }\n}\n\nexport default ClosedWebSocketServerError;\n","import { Server as HttpServer } from 'http';\nimport { Server as HttpsServer } from 'https';\nimport { WebSocketServer as NodeWebSocketServer } from 'ws';\n\nimport { DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } from '@/client/utils/lifecycle';\nimport { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport interface WebSocketServerOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketServer(\n httpServer: HttpServer | HttpsServer,\n webSocketServer: NodeWebSocketServer,\n options: WebSocketServerOpenOptions = {},\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = httpServer.listening;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n webSocketServer.off('listening', handleListening); // eslint-disable-line @typescript-eslint/no-use-before-define\n webSocketServer.off('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n /* istanbul ignore next -- @preserve\n * This is not expected since the server is not started unless it is not running. */\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleListening() {\n removeListenersAndTimeout();\n resolve();\n }\n\n webSocketServer.on('listening', handleListening);\n webSocketServer.on('error', handleError);\n });\n}\n\nexport type WebSocketServerCloseOptions = WebSocketServerOpenOptions;\n\nexport async function closeWebSocketServer(\n webSocketServer: NodeWebSocketServer,\n options: WebSocketServerCloseOptions = {},\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n for (const client of webSocketServer.clients) {\n client.close();\n }\n\n webSocketServer.close((error) => {\n clearTimeout(closeTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is not expected since the server is not stopped unless it is running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n","import { getHttpServerHostname, getHttpServerPort } from '@zimic/utils/server';\nimport { PossiblePromise } from '@zimic/utils/types';\nimport { Server as HttpServer, IncomingMessage } from 'http';\nimport { Server as HttpsServer } from 'https';\nimport { WebSocketServer as NodeWebSocketServer } from 'ws';\n\nimport { WebSocketClient } from '@/client/WebSocketClient';\nimport { WebSocketSchema } from '@/types/schema';\n\nimport ClosedWebSocketServerError from './errors/ClosedWebSocketServerError';\nimport {\n closeWebSocketServer,\n openWebSocketServer,\n WebSocketServerCloseOptions,\n WebSocketServerOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketServer {\n export type EventType = 'listening' | 'connection' | 'error' | 'close';\n\n export interface EventListenerParameters<Schema extends WebSocketSchema> {\n connection: [client: WebSocketClient<Schema>, request: IncomingMessage];\n error: [error: Error];\n close: [];\n listening: [];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketServer<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\nexport interface WebSocketServerOptions {\n httpServer: HttpServer | HttpsServer;\n}\n\nexport interface WebSocketServerRawEventListenerParameters {\n connection: [client: WebSocket, request: IncomingMessage];\n error: [error: Error];\n close: [];\n listening: [];\n}\n\ntype WebSocketServerRawEventListener<Type extends WebSocketServer.EventType> = (\n ...parameters: WebSocketServerRawEventListenerParameters[Type]\n) => void;\n\nexport class WebSocketServer<Schema extends WebSocketSchema> {\n #httpServer: HttpServer | HttpsServer;\n #webSocketServer?: NodeWebSocketServer;\n\n private listeners: {\n [Type in WebSocketServer.EventType]: Map<\n WebSocketServer.EventListener<Schema, Type>,\n WebSocketServerRawEventListener<Type>\n >;\n } = {\n connection: new Map(),\n listening: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(options: WebSocketServerOptions) {\n this.#httpServer = options.httpServer;\n }\n\n get baseURL() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return `${this.protocol}://${this.hostname}:${this.port}`;\n }\n\n get protocol() {\n return this.#httpServer instanceof HttpsServer ? 'wss' : 'ws';\n }\n\n get hostname() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return getHttpServerHostname(this.#httpServer);\n }\n\n get port() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return getHttpServerPort(this.#httpServer);\n }\n\n get isOpen() {\n return this.#httpServer.listening && this.#webSocketServer !== undefined;\n }\n\n async open(options?: WebSocketServerOpenOptions) {\n if (this.isOpen) {\n return;\n }\n\n const webSocketServer = new NodeWebSocketServer({ server: this.#httpServer });\n\n try {\n for (const [type, listeners] of Object.entries(this.listeners)) {\n for (const [_listener, rawListener] of listeners) {\n webSocketServer.addListener(type, rawListener);\n }\n }\n\n await openWebSocketServer(this.#httpServer, webSocketServer, options);\n } catch (error) {\n await closeWebSocketServer(webSocketServer);\n throw error;\n }\n\n this.#webSocketServer = webSocketServer;\n }\n\n async close(options?: WebSocketServerCloseOptions) {\n if (!this.#webSocketServer) {\n return;\n }\n\n await closeWebSocketServer(this.#webSocketServer, options);\n\n this.#webSocketServer = undefined;\n }\n\n addEventListener(type: 'connection', listener: WebSocketServer.EventListener<Schema, 'connection'>): void;\n addEventListener(type: 'error', listener: WebSocketServer.EventListener<Schema, 'error'>): void;\n addEventListener(\n type: 'listening' | 'close',\n listener: WebSocketServer.EventListener<Schema, 'listening' | 'close'>,\n ): void;\n addEventListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n const rawListener = this.createRawListener(type, listener);\n this.#webSocketServer?.on(type, rawListener);\n this.listeners[type].set(listener, rawListener);\n }\n\n private createRawListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n switch (type) {\n case 'connection': {\n const typedListener = listener as WebSocketServer.EventListener<Schema, 'connection'>;\n\n return ((...[rawClient, ...parameters]: WebSocketServerRawEventListenerParameters['connection']) => {\n const wrappedClient =\n rawClient instanceof WebSocketClient ? rawClient : new WebSocketClient<Schema>(rawClient);\n\n typedListener.call(this, wrappedClient, ...parameters);\n }) as WebSocketServerRawEventListener<Type>;\n }\n\n case 'listening':\n case 'error':\n case 'close':\n default:\n return listener.bind(this) as WebSocketServerRawEventListener<Type>;\n }\n }\n\n removeEventListener(type: 'connection', listener: WebSocketServer.EventListener<Schema, 'connection'>): void;\n removeEventListener(type: 'error', listener: WebSocketServer.EventListener<Schema, 'error'>): void;\n removeEventListener(\n type: 'listening' | 'close',\n listener: WebSocketServer.EventListener<Schema, 'listening' | 'close'>,\n ): void;\n removeEventListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n const rawListener = this.listeners[type].get(listener);\n\n if (rawListener) {\n this.#webSocketServer?.off(type, rawListener);\n this.listeners[type].delete(listener);\n }\n }\n\n emit<Type extends WebSocketServer.EventType>(\n type: Type,\n ...parameters: WebSocketServer.EventListenerParameters<Schema>[Type]\n ) {\n if (this.#webSocketServer) {\n this.#webSocketServer.emit(type, ...parameters);\n } else {\n for (const [listener] of this.listeners[type]) {\n listener.call(this, ...parameters);\n }\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../../zimic-utils/src/server/lifecycle.ts","../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts","../src/server/errors/ClosedWebSocketServerError.ts","../src/server/utils/lifecycle.ts","../src/server/WebSocketServer.ts"],"names":["HttpsServer","NodeWebSocketServer"],"mappings":"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","file":"server.mjs","sourcesContent":["import { Server as HttpServer } from 'http';\n\nexport const DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport class HttpServerTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HttpServerTimeoutError';\n }\n}\n\nexport class HttpServerStartTimeoutError extends HttpServerTimeoutError {\n constructor(reachedTimeout: number) {\n super(`HTTP server start timed out after ${reachedTimeout}ms.`);\n this.name = 'HttpServerStartTimeoutError';\n }\n}\n\nexport class HttpServerStopTimeoutError extends HttpServerTimeoutError {\n constructor(reachedTimeout: number) {\n super(`HTTP server stop timed out after ${reachedTimeout}ms.`);\n this.name = 'HttpServerStopTimeoutError';\n }\n}\n\nexport async function startHttpServer(\n server: HttpServer,\n options: {\n hostname?: string;\n port?: number;\n timeout?: number;\n } = {},\n) {\n const { hostname, port, timeout: timeoutDuration = DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT } = options;\n\n await new Promise<void>((resolve, reject) => {\n function handleStartError(error: unknown) {\n server.off('listening', handleStartSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n reject(error);\n }\n\n const startTimeout = setTimeout(() => {\n const timeoutError = new HttpServerStartTimeoutError(timeoutDuration);\n handleStartError(timeoutError);\n }, timeoutDuration);\n\n function handleStartSuccess() {\n server.off('error', handleStartError);\n clearTimeout(startTimeout);\n resolve();\n }\n\n server.once('error', handleStartError);\n server.listen(port, hostname, handleStartSuccess);\n });\n}\n\nexport async function stopHttpServer(server: HttpServer, options: { timeout?: number } = {}) {\n const { timeout: timeoutDuration = DEFAULT_HTTP_SERVER_LIFECYCLE_TIMEOUT } = options;\n\n if (!server.listening) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const stopTimeout = setTimeout(() => {\n const timeoutError = new HttpServerStopTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n server.close((error) => {\n clearTimeout(stopTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is expected not to happen since the servers are not stopped unless they are running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n\n server.closeAllConnections();\n });\n}\n\nexport function getHttpServerHostname(server: HttpServer) {\n const address = server.address();\n\n if (typeof address === 'string') {\n return undefined;\n } else {\n return address?.address;\n }\n}\n\nexport function getHttpServerPort(server: HttpServer) {\n const address = server.address();\n\n if (typeof address === 'string') {\n return undefined;\n } else {\n return address?.port;\n }\n}\n","export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport const DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1000;\n\nexport interface WebSocketClientOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketClient(socket: WebSocket, options: WebSocketClientOpenOptions = {}) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleOpenSuccess() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport type WebSocketClientCloseOptions = WebSocketClientOpenOptions;\n\nexport async function closeWebSocketClient(\n socket: WebSocket,\n options: WebSocketClientCloseOptions & { code?: number; reason?: string },\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(closeTimeout);\n\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleClose() {\n removeListenersAndTimeout();\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { PossiblePromise } from '@zimic/utils/types';\n\nimport { WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport {\n closeWebSocketClient,\n openWebSocketClient,\n WebSocketClientCloseOptions,\n WebSocketClientOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketClient {\n export type ReadyState =\n | typeof WebSocketClient.CONNECTING\n | typeof WebSocketClient.OPEN\n | typeof WebSocketClient.CLOSING\n | typeof WebSocketClient.CLOSED;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type OpenEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n export type MessageEvent<Schema extends WebSocketSchema> = globalThis.MessageEvent<WebSocketMessageData<Schema>>;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type CloseEvent<_Schema extends WebSocketSchema> = globalThis.CloseEvent;\n\n // The schema is not used in the event types, but it's included for consistency and future extensibility.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n export type ErrorEvent<_Schema extends WebSocketSchema> = globalThis.Event;\n\n interface Events<Schema extends WebSocketSchema = WebSocketSchema> {\n open: OpenEvent<Schema>;\n message: MessageEvent<Schema>;\n close: CloseEvent<Schema>;\n error: ErrorEvent<Schema>;\n }\n\n export type EventType = keyof Events<WebSocketSchema>;\n\n export type Event<\n Schema extends WebSocketSchema = WebSocketSchema,\n Type extends EventType = EventType,\n > = Events<Schema>[Type];\n\n interface EventListenerParameters<Schema extends WebSocketSchema> {\n open: [event: Event<Schema, 'open'>];\n message: [event: Event<Schema, 'message'>];\n close: [event: Event<Schema, 'close'>];\n error: [event: Event<Schema, 'error'>];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketClient<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\ntype WebSocketClientRawEventListener = (this: WebSocket, event: Event) => PossiblePromise<void>;\n\nexport class WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: WebSocket;\n\n #url: string;\n #protocols?: string | string[];\n #binaryType: BinaryType = 'blob';\n\n private unitaryListeners: {\n [Type in WebSocketClient.EventType]: WebSocketClient.EventListener<Schema, Type> | null;\n } = {\n open: null,\n message: null,\n close: null,\n error: null,\n };\n\n private listenerToRawListener: {\n [Type in WebSocketClient.EventType]: Map<\n WebSocketClient.EventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(socket: WebSocket);\n constructor(_url: string, protocols?: string | string[]);\n constructor(urlOrSocket: WebSocket | string, protocols?: string | string[]) {\n if (typeof urlOrSocket === 'string') {\n this.#url = urlOrSocket;\n } else {\n this.#url = urlOrSocket.url;\n this.socket = urlOrSocket;\n }\n\n this.#protocols = protocols;\n }\n\n static get CONNECTING() {\n return WebSocket.CONNECTING;\n }\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static get OPEN() {\n return WebSocket.OPEN;\n }\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static get CLOSING() {\n return WebSocket.CLOSING;\n }\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static get CLOSED() {\n return WebSocket.CLOSED;\n }\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this.#binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this.#binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this.#url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState(): WebSocketClient.ReadyState {\n const readyState = this.socket?.readyState ?? WebSocket.CLOSED;\n return readyState;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options?: WebSocketClientOpenOptions) {\n if (this.readyState === WebSocketClient.OPEN) {\n return;\n }\n\n await this.close();\n\n const socket = new WebSocket(this.#url, this.#protocols);\n\n try {\n if (socket.binaryType !== this.binaryType) {\n socket.binaryType = this.binaryType;\n }\n\n this.applyListeners(socket);\n\n await openWebSocketClient(socket, options);\n } catch (error) {\n socket.close();\n throw error;\n }\n\n this.socket = socket;\n }\n\n private applyListeners(socket: WebSocket) {\n for (const type of ['open', 'message', 'close', 'error'] as const) {\n const unitaryListener = this[`on${type}`] as WebSocketClient.EventListener<Schema, typeof type> | null;\n const rawUnitaryListener = unitaryListener ? this.listenerToRawListener[type].get(unitaryListener) : undefined;\n\n if (rawUnitaryListener) {\n socket[`on${type}`] = rawUnitaryListener;\n }\n\n for (const rawListener of this.listenerToRawListener[type].values()) {\n const isRawUnitaryListener = rawListener === rawUnitaryListener;\n\n if (!isRawUnitaryListener) {\n socket.addEventListener(type, rawListener);\n }\n }\n }\n }\n\n async close(code?: number, reason?: string, options?: WebSocketClientCloseOptions) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeWebSocketClient(this.socket, { ...options, code, reason });\n } finally {\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listenerToRawListener[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketClient.EventType>(\n type: Type,\n listener: WebSocketClient.EventListener<Schema, Type>,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listenerToRawListener[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listenerToRawListener[type].delete(listener);\n }\n }\n\n get onopen() {\n return this.unitaryListeners.open;\n }\n\n set onopen(listener: WebSocketClient.EventListener<Schema, 'open'> | null) {\n this.setEventListener('open', listener);\n }\n\n get onmessage() {\n return this.unitaryListeners.message;\n }\n\n set onmessage(listener: WebSocketClient.EventListener<Schema, 'message'> | null) {\n this.setEventListener('message', listener);\n }\n\n get onclose() {\n return this.unitaryListeners.close;\n }\n\n set onclose(listener: WebSocketClient.EventListener<Schema, 'close'> | null) {\n this.setEventListener('close', listener);\n }\n\n get onerror() {\n return this.unitaryListeners.error;\n }\n\n set onerror(listener: WebSocketClient.EventListener<Schema, 'error'> | null) {\n this.setEventListener('error', listener);\n }\n\n private setEventListener<\n Type extends WebSocketClient.EventType,\n Listener extends WebSocketClient.EventListener<Schema, Type> | null,\n >(type: Type, listener: Listener) {\n const currentListener = this.unitaryListeners[type];\n\n if (currentListener) {\n const rawListener = this.listenerToRawListener[type].get(currentListener);\n\n if (this.socket && rawListener) {\n this.socket[`on${type}`] = null;\n }\n\n this.listenerToRawListener[type].delete(currentListener);\n }\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listenerToRawListener[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this.unitaryListeners[type] as Listener) = listener;\n } else {\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this.unitaryListeners[type] as Listener | null) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketClient.EventType>(event: WebSocketClient.Event<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n","class ClosedWebSocketServerError extends Error {\n constructor() {\n super('The WebSocket server is closed. Did you forget to open it?');\n this.name = 'ClosedWebSocketServerError';\n }\n}\n\nexport default ClosedWebSocketServerError;\n","import { Server as HttpServer } from 'http';\nimport { Server as HttpsServer } from 'https';\nimport { WebSocketServer as NodeWebSocketServer } from 'ws';\n\nimport { DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } from '@/client/utils/lifecycle';\nimport { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nexport interface WebSocketServerOpenOptions {\n timeout?: number;\n}\n\nexport async function openWebSocketServer(\n httpServer: HttpServer | HttpsServer,\n webSocketServer: NodeWebSocketServer,\n options: WebSocketServerOpenOptions = {},\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n const isAlreadyOpen = httpServer.listening;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout = setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n function removeListenersAndTimeout() {\n clearTimeout(openTimeout);\n\n webSocketServer.off('listening', handleListening); // eslint-disable-line @typescript-eslint/no-use-before-define\n webSocketServer.off('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n /* istanbul ignore next -- @preserve\n * This is not expected since the server is not started unless it is not running. */\n function handleError(error: unknown) {\n removeListenersAndTimeout();\n reject(error);\n }\n\n function handleListening() {\n removeListenersAndTimeout();\n resolve();\n }\n\n webSocketServer.on('listening', handleListening);\n webSocketServer.on('error', handleError);\n });\n}\n\nexport type WebSocketServerCloseOptions = WebSocketServerOpenOptions;\n\nexport async function closeWebSocketServer(\n webSocketServer: NodeWebSocketServer,\n options: WebSocketServerCloseOptions = {},\n) {\n const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout = setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n for (const client of webSocketServer.clients) {\n client.close();\n }\n\n webSocketServer.close((error) => {\n clearTimeout(closeTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is not expected since the server is not stopped unless it is running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n","import { getHttpServerHostname, getHttpServerPort } from '@zimic/utils/server';\nimport { PossiblePromise } from '@zimic/utils/types';\nimport { Server as HttpServer, IncomingMessage } from 'http';\nimport { Server as HttpsServer } from 'https';\nimport { WebSocketServer as NodeWebSocketServer } from 'ws';\n\nimport { WebSocketClient } from '@/client/WebSocketClient';\nimport { WebSocketSchema } from '@/types/schema';\n\nimport ClosedWebSocketServerError from './errors/ClosedWebSocketServerError';\nimport {\n closeWebSocketServer,\n openWebSocketServer,\n WebSocketServerCloseOptions,\n WebSocketServerOpenOptions,\n} from './utils/lifecycle';\n\nexport namespace WebSocketServer {\n export type EventType = 'listening' | 'connection' | 'error' | 'close';\n\n export interface EventListenerParameters<Schema extends WebSocketSchema> {\n connection: [client: WebSocketClient<Schema>, request: IncomingMessage];\n error: [error: Error];\n close: [];\n listening: [];\n }\n\n export type EventListener<Schema extends WebSocketSchema, Type extends EventType> = (\n this: WebSocketServer<Schema>,\n ...parameters: EventListenerParameters<Schema>[Type]\n ) => PossiblePromise<void>;\n}\n\nexport interface WebSocketServerOptions {\n httpServer: HttpServer | HttpsServer;\n}\n\nexport interface WebSocketServerRawEventListenerParameters {\n connection: [client: WebSocket, request: IncomingMessage];\n error: [error: Error];\n close: [];\n listening: [];\n}\n\ntype WebSocketServerRawEventListener<Type extends WebSocketServer.EventType> = (\n ...parameters: WebSocketServerRawEventListenerParameters[Type]\n) => void;\n\nexport class WebSocketServer<Schema extends WebSocketSchema> {\n #httpServer: HttpServer | HttpsServer;\n #webSocketServer?: NodeWebSocketServer;\n\n private listeners: {\n [Type in WebSocketServer.EventType]: Map<\n WebSocketServer.EventListener<Schema, Type>,\n WebSocketServerRawEventListener<Type>\n >;\n } = {\n connection: new Map(),\n listening: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(options: WebSocketServerOptions) {\n this.#httpServer = options.httpServer;\n }\n\n get baseURL() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return `${this.protocol}://${this.hostname}:${this.port}`;\n }\n\n get protocol() {\n return this.#httpServer instanceof HttpsServer ? 'wss' : 'ws';\n }\n\n get hostname() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return getHttpServerHostname(this.#httpServer);\n }\n\n get port() {\n if (!this.isOpen) {\n throw new ClosedWebSocketServerError();\n }\n return getHttpServerPort(this.#httpServer);\n }\n\n get isOpen() {\n return this.#httpServer.listening && this.#webSocketServer !== undefined;\n }\n\n async open(options?: WebSocketServerOpenOptions) {\n if (this.isOpen) {\n return;\n }\n\n const webSocketServer = new NodeWebSocketServer({ server: this.#httpServer });\n\n try {\n for (const [type, listeners] of Object.entries(this.listeners)) {\n for (const [_listener, rawListener] of listeners) {\n webSocketServer.addListener(type, rawListener);\n }\n }\n\n await openWebSocketServer(this.#httpServer, webSocketServer, options);\n } catch (error) {\n await closeWebSocketServer(webSocketServer);\n throw error;\n }\n\n this.#webSocketServer = webSocketServer;\n }\n\n async close(options?: WebSocketServerCloseOptions) {\n if (!this.#webSocketServer) {\n return;\n }\n\n await closeWebSocketServer(this.#webSocketServer, options);\n\n this.#webSocketServer = undefined;\n }\n\n addEventListener(type: 'connection', listener: WebSocketServer.EventListener<Schema, 'connection'>): void;\n addEventListener(type: 'error', listener: WebSocketServer.EventListener<Schema, 'error'>): void;\n addEventListener(\n type: 'listening' | 'close',\n listener: WebSocketServer.EventListener<Schema, 'listening' | 'close'>,\n ): void;\n addEventListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n const rawListener = this.createRawListener(type, listener);\n this.#webSocketServer?.on(type, rawListener);\n this.listeners[type].set(listener, rawListener);\n }\n\n private createRawListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n switch (type) {\n case 'connection': {\n const typedListener = listener as WebSocketServer.EventListener<Schema, 'connection'>;\n\n return ((...[rawClient, ...parameters]: WebSocketServerRawEventListenerParameters['connection']) => {\n const wrappedClient =\n rawClient instanceof WebSocketClient ? rawClient : new WebSocketClient<Schema>(rawClient);\n\n typedListener.call(this, wrappedClient, ...parameters);\n }) as WebSocketServerRawEventListener<Type>;\n }\n\n case 'listening':\n case 'error':\n case 'close':\n default:\n return listener.bind(this) as WebSocketServerRawEventListener<Type>;\n }\n }\n\n removeEventListener(type: 'connection', listener: WebSocketServer.EventListener<Schema, 'connection'>): void;\n removeEventListener(type: 'error', listener: WebSocketServer.EventListener<Schema, 'error'>): void;\n removeEventListener(\n type: 'listening' | 'close',\n listener: WebSocketServer.EventListener<Schema, 'listening' | 'close'>,\n ): void;\n removeEventListener<Type extends WebSocketServer.EventType>(\n type: Type,\n listener: WebSocketServer.EventListener<Schema, Type>,\n ) {\n const rawListener = this.listeners[type].get(listener);\n\n if (rawListener) {\n this.#webSocketServer?.off(type, rawListener);\n this.listeners[type].delete(listener);\n }\n }\n\n emit<Type extends WebSocketServer.EventType>(\n type: Type,\n ...parameters: WebSocketServer.EventListenerParameters<Schema>[Type]\n ) {\n if (this.#webSocketServer) {\n this.#webSocketServer.emit(type, ...parameters);\n } else {\n for (const [listener] of this.listeners[type]) {\n listener.call(this, ...parameters);\n }\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "api",
15
15
  "static"
16
16
  ],
17
- "version": "0.2.0-canary.4",
17
+ "version": "0.2.0-canary.6",
18
18
  "homepage": "https://zimic.dev/docs/ws",
19
19
  "repository": {
20
20
  "type": "git",
@@ -161,7 +161,7 @@ export class WebSocketClient<Schema extends WebSocketSchema> implements Omit<
161
161
 
162
162
  get readyState(): WebSocketClient.ReadyState {
163
163
  const readyState = this.socket?.readyState ?? WebSocket.CLOSED;
164
- return readyState as WebSocketClient.ReadyState;
164
+ return readyState;
165
165
  }
166
166
 
167
167
  get bufferedAmount() {