@rlanz/socket 0.0.1-5 → 0.0.1-7

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.
Files changed (64) hide show
  1. package/README.md +174 -160
  2. package/build/{types-C7Q36ryo.d.ts → base_channel-Dr40l7CW.d.ts} +178 -169
  3. package/build/chunk-2X6WGCH5.js +120 -0
  4. package/build/chunk-2X6WGCH5.js.map +1 -0
  5. package/build/chunk-6PJ4ALJD.js +115 -0
  6. package/build/chunk-6PJ4ALJD.js.map +1 -0
  7. package/build/chunk-E6ILCRL3.js +182 -0
  8. package/build/chunk-E6ILCRL3.js.map +1 -0
  9. package/build/{chunk-SHH6U4CI.js → chunk-G75J233Z.js} +1 -1
  10. package/build/chunk-G75J233Z.js.map +1 -0
  11. package/build/{chunk-B4Y3TNDI.js → chunk-IUQ3GYZZ.js} +5 -24
  12. package/build/chunk-IUQ3GYZZ.js.map +1 -0
  13. package/build/chunk-QNOOQXYY.js +899 -0
  14. package/build/chunk-QNOOQXYY.js.map +1 -0
  15. package/build/{chunk-ANT2E3LT.js → chunk-YVC7IMDN.js} +21 -5
  16. package/build/chunk-YVC7IMDN.js.map +1 -0
  17. package/build/framework-B-4kGmAw.d.ts +13 -0
  18. package/build/index-Fg-tkHhP.d.ts +150 -0
  19. package/build/index.d.ts +23 -12
  20. package/build/index.js +12 -14
  21. package/build/index.js.map +1 -1
  22. package/build/providers/socket_provider.d.ts +2 -2
  23. package/build/providers/socket_provider.js +474 -215
  24. package/build/providers/socket_provider.js.map +1 -1
  25. package/build/services/socket.d.ts +2 -2
  26. package/build/{socket_service-mybqv1hj.d.ts → socket_service-BYEB8LIN.d.ts} +7 -7
  27. package/build/src/assembler_hook.d.ts +6 -4
  28. package/build/src/assembler_hook.js +49 -63
  29. package/build/src/assembler_hook.js.map +1 -1
  30. package/build/src/client/index.d.ts +3 -147
  31. package/build/src/client/index.js +4 -837
  32. package/build/src/client/index.js.map +1 -1
  33. package/build/src/client/react.d.ts +13 -5
  34. package/build/src/client/react.js +27 -11
  35. package/build/src/client/react.js.map +1 -1
  36. package/build/src/client/types.d.ts +30 -35
  37. package/build/src/client/vue.d.ts +17 -5
  38. package/build/src/client/vue.js +31 -13
  39. package/build/src/client/vue.js.map +1 -1
  40. package/build/src/decorators.d.ts +3 -2
  41. package/build/src/decorators.js +1 -1
  42. package/build/src/health_check.d.ts +2 -2
  43. package/build/src/health_check.js +14 -3
  44. package/build/src/health_check.js.map +1 -1
  45. package/build/src/otel.js +0 -1
  46. package/build/src/otel.js.map +1 -1
  47. package/build/src/testing.d.ts +3 -12
  48. package/build/src/testing.js +1 -1
  49. package/build/src/types/tracing_channels.d.ts +1 -2
  50. package/build/src/types.d.ts +1 -1
  51. package/package.json +2 -9
  52. package/build/chunk-ANT2E3LT.js.map +0 -1
  53. package/build/chunk-B4Y3TNDI.js.map +0 -1
  54. package/build/chunk-HK7Z65DA.js +0 -19
  55. package/build/chunk-HK7Z65DA.js.map +0 -1
  56. package/build/chunk-SFAY2ZA4.js +0 -28
  57. package/build/chunk-SFAY2ZA4.js.map +0 -1
  58. package/build/chunk-SHH6U4CI.js.map +0 -1
  59. package/build/chunk-YAX5EHHB.js +0 -453
  60. package/build/chunk-YAX5EHHB.js.map +0 -1
  61. package/build/framework-CvxgHwbv.d.ts +0 -12
  62. package/build/src/client/svelte.d.ts +0 -22
  63. package/build/src/client/svelte.js +0 -82
  64. package/build/src/client/svelte.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/channel.ts","../../../src/client/socket_session.ts","../../../src/client/socket.ts"],"sourcesContent":["import type {\n SocketClientTransport,\n SubscribeOptions,\n SubscribeResult,\n UnsubscribeOptions,\n PresenceData,\n PresenceUser,\n EventHandler,\n ChannelMessage,\n ChannelAck,\n ChannelContract,\n} from './types.js'\nimport { callClientHandler } from './callback.js'\n\nconst CLIENT_EVENT_PREFIX = 'client:'\n\ntype Callable = (...args: never[]) => unknown\n\n/**\n * Represents a subscribed channel.\n * Chainable API inspired by Laravel Echo.\n *\n * @example\n * ```ts\n * socket.channel('chat/general')\n * .here((users) => setOnlineUsers(users))\n * .joining((user) => console.log(`${user.name} joined`))\n * .leaving((user) => console.log(`${user.name} left`))\n * .listen('chat:message', (msg) => addMessage(msg))\n * .subscribe()\n * ```\n */\ntype UnknownContract = ChannelContract<unknown, unknown>\ntype ClientMap<C> = C extends ChannelContract<infer E, unknown> ? E : unknown\ntype ServerMap<C> = C extends ChannelContract<unknown, infer E> ? E : unknown\ntype IsUnknown<T> = unknown extends T ? true : false\ntype StringKey<T> = Extract<keyof T, string>\ntype EventDataArgs<Payload> = undefined extends Payload ? [data?: Payload] : [data: Payload]\n\nexport class Channel<Contract = UnknownContract> {\n static #parsePresenceData(value: unknown): PresenceData | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return null\n }\n\n const data = value as Partial<PresenceData>\n if (\n typeof data.channel !== 'string' ||\n !Array.isArray(data.users) ||\n !data.users.every(\n (user) =>\n user !== null &&\n typeof user === 'object' &&\n typeof user.id === 'string' &&\n typeof user.joinedAt === 'string'\n )\n ) {\n return null\n }\n\n const usersById = new Map<string, PresenceUser>()\n for (const user of data.users) {\n if (!usersById.has(user.id)) {\n usersById.set(user.id, user)\n }\n }\n\n const users = [...usersById.values()]\n return { ...data, channel: data.channel, users, count: users.length }\n }\n\n /**\n * Channel name.\n */\n readonly name: string\n\n /**\n * Socket client transport.\n */\n #transport: SocketClientTransport\n\n /**\n * Whether the channel should stay subscribed.\n */\n #subscribed = false\n #active = false\n\n /**\n * Event handlers grouped by event type.\n */\n #eventHandlers = new Map<string, Set<Callable>>()\n #managedEventHandlers = new Map<string, Set<Callable>>()\n\n /**\n * Current presence data.\n */\n #presence: PresenceData | null = null\n\n /**\n * Present user IDs used to detect join and leave events.\n */\n #presentUserIds = new Set<string>()\n\n /**\n * Handler registered through .here().\n */\n #hereHandler: EventHandler<PresenceUser[]> | null = null\n\n /**\n * Handler registered through .joining().\n */\n #joiningHandler: EventHandler<PresenceUser> | null = null\n\n /**\n * Handler registered through .leaving().\n */\n #leavingHandler: EventHandler<PresenceUser> | null = null\n\n /**\n * Internal transport handlers to clean up on unsubscribe.\n */\n #boundPresenceHandler: ((data: unknown) => void) | null = null\n #boundEventHandler: ((data: unknown) => void) | null = null\n #boundDisconnectHandler: (() => void) | null = null\n #listenersAttached = false\n #pendingSubscribe: {\n promise: Promise<Channel<Contract>>\n resolve: (channel: Channel<Contract>) => void\n reject: (error: Error) => void\n token: number\n } | null = null\n #subscribeToken = 0\n #managedSubscriptions = 0\n #pendingUnsubscribe: Promise<void> | null = null\n\n constructor(name: string, transport: SocketClientTransport) {\n this.name = name\n this.#transport = transport\n }\n\n /**\n * Whether the channel should stay subscribed.\n */\n get subscribed(): boolean {\n return this.#subscribed || this.#managedSubscriptions > 0\n }\n\n /** Whether a framework lifecycle currently owns this channel. @internal */\n get $managed(): boolean {\n return this.#managedSubscriptions > 0\n }\n\n /**\n * Whether the channel is active on the server.\n */\n get active(): boolean {\n return this.#active\n }\n\n /**\n * List of present users.\n */\n get users(): PresenceUser[] {\n return this.#presence?.users ?? []\n }\n\n /**\n * Number of present users.\n */\n get count(): number {\n return this.#presence?.count ?? 0\n }\n\n /**\n * Registers a handler called with the present users.\n * Called immediately on subscribe and after each presence change.\n */\n here(handler: EventHandler<PresenceUser[]>): this {\n this.#hereHandler = handler\n return this\n }\n\n /**\n * Registers a handler called when a user joins.\n */\n joining(handler: EventHandler<PresenceUser>): this {\n this.#joiningHandler = handler\n return this\n }\n\n /**\n * Registers a handler called when a user leaves.\n */\n leaving(handler: EventHandler<PresenceUser>): this {\n this.#leavingHandler = handler\n return this\n }\n\n /**\n * Listens for an event on this channel.\n */\n listen<T = unknown>(\n this: IsUnknown<ServerMap<Contract>> extends true ? Channel<Contract> : never,\n event: string,\n handler: EventHandler<T>\n ): this\n listen<Event extends StringKey<ServerMap<Contract>>>(\n this: Channel<Contract>,\n event: Event,\n handler: EventHandler<ServerMap<Contract>[Event]>\n ): this\n listen(event: string, handler: EventHandler<any>): this {\n const handlers = this.#eventHandlers.get(event) ?? new Set<Callable>()\n handlers.add(handler)\n this.#eventHandlers.set(event, handlers)\n return this\n }\n\n /**\n * Removes an event listener.\n */\n stopListening<T = unknown>(\n this: IsUnknown<ServerMap<Contract>> extends true ? Channel<Contract> : never,\n event: string,\n handler?: EventHandler<T>\n ): this\n stopListening<Event extends StringKey<ServerMap<Contract>>>(\n this: Channel<Contract>,\n event: Event,\n handler?: EventHandler<ServerMap<Contract>[Event]>\n ): this\n stopListening(event: string, handler?: EventHandler<any>): this {\n if (handler) {\n this.#eventHandlers.get(event)?.delete(handler)\n } else {\n this.#eventHandlers.delete(event)\n }\n return this\n }\n\n /** Registers a lifecycle-owned event handler. @internal */\n $listen(event: string, handler: EventHandler<any>): void {\n const handlers = this.#managedEventHandlers.get(event) ?? new Set<Callable>()\n handlers.add(handler)\n this.#managedEventHandlers.set(event, handlers)\n }\n\n /** Removes a lifecycle-owned event handler. @internal */\n $stopListening(event: string, handler: EventHandler<any>): void {\n const handlers = this.#managedEventHandlers.get(event)\n handlers?.delete(handler)\n if (handlers?.size === 0) this.#managedEventHandlers.delete(event)\n }\n\n /**\n * Listens for a client event whispered by another channel member.\n */\n listenForWhisper<T = unknown>(event: string, handler: EventHandler<T>): this {\n const handlers =\n this.#eventHandlers.get(`${CLIENT_EVENT_PREFIX}${event}`) ?? new Set<Callable>()\n handlers.add(handler)\n this.#eventHandlers.set(`${CLIENT_EVENT_PREFIX}${event}`, handlers)\n return this\n }\n\n /**\n * Removes a whispered client event listener.\n */\n stopListeningForWhisper<T = unknown>(event: string, handler?: EventHandler<T>): this {\n const name = `${CLIENT_EVENT_PREFIX}${event}`\n if (handler) this.#eventHandlers.get(name)?.delete(handler)\n else this.#eventHandlers.delete(name)\n return this\n }\n\n /**\n * Subscribes to the channel.\n *\n * client listeners -> subscribe ack -> active channel\n * | | |\n * v v v\n * events ready presence sync send/listen\n */\n async subscribe(options: SubscribeOptions = {}): Promise<this> {\n this.#subscribed = true\n return this.#ensureSubscribed(options)\n }\n\n /** Acquires subscription intent without overriding a direct consumer. @internal */\n $acquire(options: SubscribeOptions = {}): {\n ready: Promise<Channel<Contract>>\n release: () => Promise<void>\n } {\n this.#managedSubscriptions++\n const ready = this.#transport.connected\n ? this.#ensureSubscribed(options)\n : Promise.resolve(this)\n let released = false\n\n return {\n ready,\n release: () => {\n if (released) return this.#pendingUnsubscribe ?? Promise.resolve()\n released = true\n this.#managedSubscriptions--\n return this.#unsubscribeIfUnused()\n },\n }\n }\n\n /** Restores desired subscriptions after the transport reconnects. @internal */\n $resubscribe(options: SubscribeOptions = {}): Promise<this> {\n return this.#ensureSubscribed(options)\n }\n\n async #ensureSubscribed(options: SubscribeOptions): Promise<this> {\n if (this.#pendingUnsubscribe) {\n await this.#pendingUnsubscribe\n }\n\n if (!this.subscribed) return this\n\n if (this.#pendingSubscribe) {\n await this.#pendingSubscribe.promise\n return this\n }\n\n if (this.#active) {\n return this\n }\n\n const timeout = options.timeout ?? 5000\n\n // Attach listeners before subscribing so the first server events are not missed.\n if (!this.#listenersAttached) {\n this.#setupSocketListeners()\n }\n\n const token = ++this.#subscribeToken\n\n const deferred = Promise.withResolvers<Channel<Contract>>()\n\n this.#pendingSubscribe = {\n promise: deferred.promise,\n resolve: deferred.resolve,\n reject: deferred.reject,\n token,\n }\n\n const { resolve, reject } = this.#pendingSubscribe\n\n const timer = setTimeout(() => {\n if (token !== this.#subscribeToken) return\n this.#subscribeToken++\n this.#pendingSubscribe = null\n this.#resetConnectionState()\n reject(new Error(`Subscribe timeout for channel: ${this.name}`))\n }, timeout)\n\n this.#transport\n .sendRequest<SubscribeResult>({ type: 'subscribe', channel: this.name }, timeout)\n .then((response) => {\n if (token !== this.#subscribeToken) return\n clearTimeout(timer)\n this.#pendingSubscribe = null\n\n if (response.ok) {\n this.#active = true\n\n const presenceData = Channel.#parsePresenceData(\n response.data?.presenceData ?? response.presenceData\n )\n\n // Apply the initial presence snapshot.\n if (presenceData) {\n this.#handleInitialPresence(presenceData)\n }\n\n resolve(this)\n } else {\n this.#resetConnectionState()\n reject(new Error(response.error ?? 'Subscribe failed'))\n }\n })\n .catch((error) => {\n if (token !== this.#subscribeToken) return\n clearTimeout(timer)\n this.#pendingSubscribe = null\n this.#resetConnectionState()\n reject(error instanceof Error ? error : new Error('Subscribe failed'))\n })\n\n await deferred.promise\n return this\n }\n\n /**\n * Unsubscribes from the channel.\n */\n async unsubscribe(options: UnsubscribeOptions = {}): Promise<void> {\n this.#subscribed = false\n this.#clearUserCallbacks()\n return this.#unsubscribeIfUnused(options)\n }\n\n #unsubscribeIfUnused(options: UnsubscribeOptions = {}): Promise<void> {\n if (this.subscribed) return Promise.resolve()\n if (this.#pendingUnsubscribe) return this.#pendingUnsubscribe\n\n const hadPendingSubscribe = this.#pendingSubscribe !== null\n this.#subscribeToken++\n if (this.#pendingSubscribe) {\n this.#pendingSubscribe.reject(new Error(`Unsubscribed from channel: ${this.name}`))\n this.#pendingSubscribe = null\n }\n\n if (!hadPendingSubscribe && !this.#active) {\n this.#cleanupTerminal()\n return Promise.resolve()\n }\n\n this.#active = false\n const pending = new Promise<void>((resolve) => {\n const timeout = options.timeout ?? 5000\n const timer = setTimeout(() => {\n resolve()\n }, timeout)\n\n this.#transport\n .sendRequest({ type: 'unsubscribe', channel: this.name }, timeout)\n .then(() => {\n clearTimeout(timer)\n resolve()\n })\n .catch(() => {\n clearTimeout(timer)\n resolve()\n })\n })\n this.#pendingUnsubscribe = pending\n void pending.finally(() => {\n if (this.#pendingUnsubscribe !== pending) return\n this.#pendingUnsubscribe = null\n this.#resetConnectionState()\n this.#detachTransportListeners()\n if (!this.subscribed) this.#clearCallbacks()\n })\n return pending\n }\n\n /**\n * Sends an event to the server.\n */\n send<T = unknown>(\n this: IsUnknown<ClientMap<Contract>> extends true ? Channel<Contract> : never,\n event: string,\n data?: T\n ): this\n send<Event extends StringKey<ClientMap<Contract>>>(\n this: Channel<Contract>,\n event: Event,\n ...[data]: ClientMap<Contract>[Event] extends { payload: infer Payload }\n ? EventDataArgs<Payload>\n : never\n ): this\n send(event: string, data?: unknown): this {\n if (!this.#active) {\n console.warn(`Cannot send to channel ${this.name}: not subscribed`)\n return this\n }\n const payload: ChannelMessage = {\n channel: this.name,\n event,\n data,\n }\n this.#transport.send({ type: 'message', ...payload })\n return this\n }\n\n /**\n * Relays a client event to other members of this channel.\n */\n whisper<T = unknown>(event: string, data?: T): this {\n if (!this.#active) {\n console.warn(`Cannot whisper to channel ${this.name}: not subscribed`)\n return this\n }\n const payload: ChannelMessage = {\n channel: this.name,\n event,\n data,\n }\n this.#transport.send({ type: 'whisper', ...payload })\n return this\n }\n\n /**\n * Sends an event and waits for a response.\n */\n sendWithAck<T = unknown, Result = unknown>(\n this: IsUnknown<ClientMap<Contract>> extends true ? Channel<Contract> : never,\n event: string,\n data?: T\n ): Promise<Result>\n sendWithAck<Event extends StringKey<ClientMap<Contract>>>(\n this: Channel<Contract>,\n event: Event,\n ...[data]: ClientMap<Contract>[Event] extends { payload: infer Payload }\n ? EventDataArgs<Payload>\n : never\n ): Promise<\n ClientMap<Contract>[Event] extends { ack: infer Acknowledgement } ? Acknowledgement : unknown\n >\n async sendWithAck(event: string, data?: unknown): Promise<unknown> {\n if (!this.#active) {\n throw new Error(`Cannot send to channel ${this.name}: not subscribed`)\n }\n const payload: ChannelMessage = {\n channel: this.name,\n event,\n data,\n }\n const response = await this.#transport.sendRequest<ChannelAck>({\n type: 'message',\n ...payload,\n })\n if (!response?.ok) {\n throw new Error(response?.error ?? `Channel handler failed: ${event}`)\n }\n return response.data\n }\n\n /**\n * Configures transport listeners.\n */\n #setupSocketListeners(): void {\n // Handler for presence:update.\n this.#boundPresenceHandler = (data: unknown) => {\n const presenceData = Channel.#parsePresenceData(data)\n if (!presenceData) return\n this.#handlePresenceUpdate(presenceData)\n }\n this.#transport.on(`channel:${this.name}:presence:update`, this.#boundPresenceHandler)\n\n this.#boundEventHandler = (data: unknown) => {\n if (!data || typeof data !== 'object') return\n\n const payload = data as { event?: string; data?: unknown }\n if (!payload.event) return\n\n const handlers = this.#eventHandlers.get(payload.event)\n handlers?.forEach((handler) => callClientHandler(handler, payload.data))\n const managedHandlers = this.#managedEventHandlers.get(payload.event)\n managedHandlers?.forEach((handler) => callClientHandler(handler, payload.data))\n }\n this.#transport.on(`channel:${this.name}:event`, this.#boundEventHandler)\n\n // Mark the channel inactive when the socket disconnects.\n this.#boundDisconnectHandler = () => {\n this.#resetConnectionState()\n }\n this.#transport.on('disconnect', this.#boundDisconnectHandler)\n\n this.#listenersAttached = true\n }\n\n /**\n * Handles the initial presence snapshot.\n */\n #handleInitialPresence(data: PresenceData): void {\n this.#presence = data\n this.#presentUserIds = new Set(data.users.map((u) => u.id))\n\n // Call here() with all users.\n if (this.#hereHandler) {\n callClientHandler(this.#hereHandler, data.users)\n }\n }\n\n /**\n * Handles a presence update.\n *\n * previous IDs current IDs\n * | |\n * +-- diff in -----+--> joining / leaving callbacks\n */\n #handlePresenceUpdate(data: PresenceData): void {\n const previousIds = this.#presentUserIds\n const currentIds = new Set(data.users.map((u) => u.id))\n const joiningUsers = data.users.filter((user) => !previousIds.has(user.id))\n const leavingUsers = (this.#presence?.users ?? []).filter((user) => !currentIds.has(user.id))\n\n // Commit the validated update before invoking user code.\n this.#presence = data\n this.#presentUserIds = currentIds\n\n // Detect new users.\n for (const user of joiningUsers) {\n if (this.#joiningHandler) {\n callClientHandler(this.#joiningHandler, user)\n }\n }\n\n // Detect users that left.\n for (const user of leavingUsers) {\n if (this.#leavingHandler) {\n callClientHandler(this.#leavingHandler, user)\n }\n }\n\n // Call here() with the updated list.\n if (this.#hereHandler) {\n callClientHandler(this.#hereHandler, data.users)\n }\n }\n\n #resetConnectionState(): void {\n this.#active = false\n this.#presence = null\n this.#presentUserIds.clear()\n }\n\n #detachTransportListeners(): void {\n if (this.#boundPresenceHandler) {\n this.#transport.off(`channel:${this.name}:presence:update`, this.#boundPresenceHandler)\n this.#boundPresenceHandler = null\n }\n\n if (this.#boundEventHandler) {\n this.#transport.off(`channel:${this.name}:event`, this.#boundEventHandler)\n this.#boundEventHandler = null\n }\n\n if (this.#boundDisconnectHandler) {\n this.#transport.off('disconnect', this.#boundDisconnectHandler)\n this.#boundDisconnectHandler = null\n }\n\n this.#listenersAttached = false\n }\n\n #clearUserCallbacks(): void {\n this.#eventHandlers.clear()\n this.#hereHandler = null\n this.#joiningHandler = null\n this.#leavingHandler = null\n }\n\n #clearCallbacks(): void {\n this.#clearUserCallbacks()\n this.#managedEventHandlers.clear()\n }\n\n /**\n * Performs terminal cleanup after the user leaves or the socket is disposed.\n */\n #cleanupTerminal(): void {\n this.#resetConnectionState()\n this.#detachTransportListeners()\n this.#clearCallbacks()\n }\n}\n","import type { ConnectionState, EventHandler } from './types.js'\nimport type { ServerProtocolMessage } from '../shared_types.js'\nimport { callClientHandler } from './callback.js'\n\ntype Callable = (...args: never[]) => unknown\ntype IncomingMessage = Extract<ServerProtocolMessage, { type: 'ack' | 'event' }>\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\ninterface ClientSocketSessionOptions {\n buildUrl: () => string\n createWebSocket?: (url: string) => WebSocket\n autoReconnect?: boolean\n reconnectDelay?: number\n reconnectMaxDelay?: number\n onConnected?: () => void\n}\n\nexport class ClientSocketSession {\n #ws: WebSocket | null = null\n #state: ConnectionState = 'disconnected'\n #connectPromise: Promise<void> | null = null\n #cancelConnect: ((error: Error) => void) | null = null\n #stateHandlers = new Set<Callable>()\n #eventHandlers = new Map<string, Set<Callable>>()\n #pendingRequests = new Map<string, PendingRequest>()\n #requestId = 0\n #reconnectAttempts = 0\n #reconnectTimer: ReturnType<typeof setTimeout> | null = null\n #manualDisconnect = false\n #buildUrl: () => string\n #createWebSocket: (url: string) => WebSocket\n #autoReconnect: boolean\n #reconnectDelay: number\n #reconnectMaxDelay: number\n #onConnected?: () => void\n\n constructor(options: ClientSocketSessionOptions) {\n this.#buildUrl = options.buildUrl\n this.#createWebSocket = options.createWebSocket ?? ((url) => new WebSocket(url))\n this.#autoReconnect = options.autoReconnect ?? true\n this.#reconnectDelay = Math.max(0, options.reconnectDelay ?? 250)\n this.#reconnectMaxDelay = Math.max(this.#reconnectDelay, options.reconnectMaxDelay ?? 5000)\n this.#onConnected = options.onConnected\n }\n\n get state(): ConnectionState {\n return this.#state\n }\n\n get connected(): boolean {\n return this.#state === 'connected'\n }\n\n connect(): Promise<void> {\n if (this.#state === 'connected') {\n return Promise.resolve()\n }\n\n if (this.#connectPromise) {\n return this.#connectPromise\n }\n\n this.#manualDisconnect = false\n this.#setState('connecting')\n\n let setupFailed = false\n const connectPromise = new Promise<void>((resolve, reject) => {\n let ws: WebSocket\n try {\n ws = this.#createWebSocket(this.#buildUrl())\n } catch (error) {\n setupFailed = true\n reject(error)\n return\n }\n\n this.#ws = ws\n let settled = false\n\n const cleanup = () => {\n ws.removeEventListener('open', handleOpen)\n ws.removeEventListener('error', handleError)\n if (this.#connectPromise === connectPromise) {\n this.#connectPromise = null\n }\n if (this.#cancelConnect === cancelConnect) {\n this.#cancelConnect = null\n }\n }\n\n const cancelConnect = (error: Error) => {\n if (settled) {\n return\n }\n\n settled = true\n cleanup()\n reject(error)\n }\n\n const handleOpen = () => {\n if (settled || this.#ws !== ws) {\n return\n }\n\n this.#setState('connected')\n if (settled || this.#ws !== ws || !this.connected) {\n return\n }\n\n settled = true\n cleanup()\n this.#reconnectAttempts = 0\n this.#emitLocal('connect')\n if (this.#onConnected) {\n this.#callHandler(this.#onConnected)\n }\n resolve()\n }\n\n const handleError = () => {\n cancelConnect(new Error('WebSocket connection failed'))\n if (this.#ws === ws) {\n this.#setState('disconnected')\n }\n }\n\n const handleClose = () => {\n cancelConnect(new Error('WebSocket connection failed'))\n\n if (this.#ws === ws) {\n this.#handleClose()\n }\n }\n\n this.#cancelConnect = cancelConnect\n ws.addEventListener('open', handleOpen)\n ws.addEventListener('error', handleError)\n ws.addEventListener('message', (event) => {\n if (this.#ws === ws) {\n this.#handleIncoming(event.data)\n }\n })\n ws.addEventListener('close', handleClose)\n })\n\n this.#connectPromise = connectPromise\n if (setupFailed) {\n this.#connectPromise = null\n this.#setState('disconnected')\n }\n\n return connectPromise\n }\n\n disconnect(): void {\n this.#manualDisconnect = true\n if (this.#reconnectTimer) {\n clearTimeout(this.#reconnectTimer)\n this.#reconnectTimer = null\n }\n\n this.#cancelConnect?.(new Error('Socket disconnected'))\n this.#reconnectAttempts = 0\n const ws = this.#ws\n const shouldEmitDisconnect = this.#state !== 'disconnected'\n this.#ws = null\n this.#setState('disconnected')\n if (shouldEmitDisconnect) {\n this.#emitLocal('disconnect')\n }\n ws?.close()\n this.#rejectPending(new Error('Socket disconnected'))\n }\n\n onStateChange(handler: EventHandler<ConnectionState>): () => void {\n this.#stateHandlers.add(handler)\n\n return () => {\n this.#stateHandlers.delete(handler)\n }\n }\n\n on<T = unknown>(event: string, handler: EventHandler<T>): () => void {\n if (!this.#eventHandlers.has(event)) {\n this.#eventHandlers.set(event, new Set())\n }\n\n this.#eventHandlers.get(event)!.add(handler)\n\n return () => {\n this.off(event, handler)\n }\n }\n\n off<T = unknown>(event: string, handler: EventHandler<T>): void {\n this.#eventHandlers.get(event)?.delete(handler)\n }\n\n send(message: Record<string, unknown>): void {\n const ws = this.#ws\n if (ws?.readyState !== WebSocket.OPEN) {\n return\n }\n\n ws.send(JSON.stringify(message))\n }\n\n sendRequest(message: Record<string, unknown>, timeout = 5000): Promise<unknown> {\n const ws = this.#ws\n if (ws?.readyState !== WebSocket.OPEN) {\n return Promise.reject(new Error('Socket is not connected'))\n }\n\n const id = String(++this.#requestId)\n const payload = { ...message, id }\n\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.#pendingRequests.delete(id)\n reject(new Error('Socket request timed out'))\n }, timeout)\n\n this.#pendingRequests.set(id, {\n resolve,\n reject,\n timer,\n })\n ws.send(JSON.stringify(payload))\n })\n }\n\n #handleIncoming(raw: unknown): void {\n const message = this.#parseMessage(raw)\n if (!message) {\n return\n }\n\n if (message.type === 'ack') {\n this.#resolveAck(message)\n return\n }\n\n if (message.type === 'event') {\n if (message.channel) {\n if (message.event === 'presence:update') {\n this.#emitLocal(`channel:${message.channel}:presence:update`, message.data)\n return\n }\n\n this.#emitLocal(`channel:${message.channel}:event`, {\n event: message.event,\n data: message.data,\n })\n return\n }\n\n this.#emitLocal(message.event, message.data)\n }\n }\n\n #parseMessage(raw: unknown): IncomingMessage | null {\n try {\n const data = typeof raw === 'string' ? raw : String(raw)\n const message = JSON.parse(data) as Record<string, unknown> | null\n\n if (!message || typeof message !== 'object' || Array.isArray(message)) {\n return null\n }\n\n if (\n message.type === 'ack' &&\n typeof message.id === 'string' &&\n typeof message.ok === 'boolean' &&\n (message.error === undefined || typeof message.error === 'string')\n ) {\n return message as IncomingMessage\n }\n\n if (\n message.type === 'event' &&\n typeof message.event === 'string' &&\n (message.channel === undefined || typeof message.channel === 'string')\n ) {\n return message as IncomingMessage\n }\n\n return null\n } catch {\n return null\n }\n }\n\n #resolveAck(message: Extract<ServerProtocolMessage, { type: 'ack' }>): void {\n if (!message.id) {\n return\n }\n\n const pending = this.#pendingRequests.get(message.id)\n if (!pending) {\n return\n }\n\n clearTimeout(pending.timer)\n this.#pendingRequests.delete(message.id)\n\n if (message.ok) {\n pending.resolve({ ok: true, data: message.data })\n } else {\n pending.resolve({ ok: false, error: message.error })\n }\n }\n\n #handleClose(): void {\n const shouldEmitDisconnect = this.#state !== 'disconnected'\n\n this.#ws = null\n this.#setState('disconnected')\n if (shouldEmitDisconnect) {\n this.#emitLocal('disconnect')\n }\n this.#rejectPending(new Error('Socket disconnected'))\n\n this.#scheduleReconnect()\n }\n\n #scheduleReconnect(): void {\n if (this.#manualDisconnect || !this.#autoReconnect || this.#reconnectTimer) {\n return\n }\n\n const delay = Math.min(\n this.#reconnectDelay * 2 ** this.#reconnectAttempts,\n this.#reconnectMaxDelay\n )\n this.#reconnectAttempts += 1\n\n this.#reconnectTimer = setTimeout(() => {\n this.#reconnectTimer = null\n this.connect().catch(() => {\n if (this.#state === 'disconnected') {\n this.#scheduleReconnect()\n }\n })\n }, delay)\n }\n\n #rejectPending(error: Error): void {\n for (const [id, pending] of this.#pendingRequests) {\n clearTimeout(pending.timer)\n pending.reject(error)\n this.#pendingRequests.delete(id)\n }\n }\n\n #emitLocal(event: string, data?: unknown): void {\n this.#eventHandlers.get(event)?.forEach((handler) => this.#callHandler(handler, data))\n }\n\n #setState(state: ConnectionState): void {\n if (this.#state === state) {\n return\n }\n\n this.#state = state\n this.#stateHandlers.forEach((handler) => this.#callHandler(handler, state))\n }\n\n #callHandler(handler: Callable, data?: unknown): void {\n callClientHandler(handler, data)\n }\n}\n","import { Channel } from './channel.js'\nimport { ClientSocketSession } from './socket_session.js'\nimport { reportClientError } from './callback.js'\nimport type {\n SocketOptions,\n ConnectionState,\n EventHandler,\n SocketClientTransport,\n ChannelContractFor,\n} from './types.js'\n\n/**\n * Main Socket client.\n */\ntype ChannelResult<Registry, Name extends string> = string extends Name\n ? Channel<unknown>\n : [Registry] extends [never]\n ? Channel\n : ChannelContractFor<Registry, Name> extends infer Contract\n ? [Contract] extends [never]\n ? never\n : Channel<Contract>\n : never\n\nexport class Socket<Registry = never> implements SocketClientTransport {\n #channels = new Map<string, Channel>()\n #url: string\n #path: string\n #session: ClientSocketSession\n\n constructor(options: SocketOptions = {}) {\n const browserWindow = globalThis as typeof globalThis & {\n window?: { location?: { origin?: string } }\n }\n const browserOrigin =\n typeof globalThis === 'object' && browserWindow.window?.location?.origin\n ? browserWindow.window.location.origin\n : ''\n\n this.#url = options.url ?? browserOrigin\n this.#path = options.path ?? '/socket'\n this.#session = new ClientSocketSession({\n buildUrl: () => this.#buildUrl(),\n autoReconnect: options.autoReconnect,\n reconnectDelay: options.reconnectDelay,\n reconnectMaxDelay: options.reconnectMaxDelay,\n onConnected: () => {\n void this.#resubscribeChannels()\n },\n })\n }\n\n get state(): ConnectionState {\n return this.#session.state\n }\n\n get connected(): boolean {\n return this.#session.connected\n }\n\n connect(): Promise<void> {\n return this.#session.connect()\n }\n\n disconnect(): void {\n for (const channel of this.#channels.values()) {\n channel.unsubscribe().catch(() => {})\n }\n\n this.#session.disconnect()\n }\n\n channel<const Name extends string>(\n name: Name & (ChannelResult<Registry, Name> extends never ? never : unknown)\n ): ChannelResult<Registry, Name> {\n if (!this.#channels.has(name)) {\n this.#channels.set(name, new Channel(name, this))\n }\n\n return this.#channels.get(name)! as ChannelResult<Registry, Name>\n }\n\n async leave(name: string): Promise<void> {\n const channel = this.#channels.get(name)\n if (channel) {\n await channel.unsubscribe()\n if (this.#channels.get(name) === channel && !channel.subscribed) {\n this.#channels.delete(name)\n }\n }\n }\n\n onStateChange(handler: EventHandler<ConnectionState>): () => void {\n return this.#session.onStateChange(handler)\n }\n\n on<T = unknown>(event: string, handler: EventHandler<T>): () => void {\n return this.#session.on(event, handler)\n }\n\n off<T = unknown>(event: string, handler: EventHandler<T>): void {\n this.#session.off(event, handler)\n }\n\n send(message: Record<string, unknown>): void {\n this.#session.send(message)\n }\n\n sendRequest<T = unknown>(message: Record<string, unknown>, timeout = 5000): Promise<T> {\n return this.#session.sendRequest(message, timeout) as Promise<T>\n }\n\n #buildUrl(): string {\n const browserGlobal = globalThis as typeof globalThis & {\n location?: { origin?: string }\n }\n const url = new URL(this.#url || browserGlobal.location?.origin || 'http://localhost')\n if (url.protocol === 'http:') {\n url.protocol = 'ws:'\n } else if (url.protocol === 'https:') {\n url.protocol = 'wss:'\n } else if (url.protocol !== 'ws:' && url.protocol !== 'wss:') {\n throw new Error(`Unsupported socket URL protocol: ${url.protocol}`)\n }\n url.pathname = this.#path\n\n return url.toString()\n }\n\n async #resubscribeChannels(): Promise<void> {\n for (const channel of this.#channels.values()) {\n if (channel.subscribed && !channel.active) {\n await channel.$resubscribe().catch(reportClientError)\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,15 +1,20 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { Socket } from './index.js';
3
+ import { S as Socket } from '../../index-Fg-tkHhP.js';
4
4
  import { ConnectionState, EventHandler } from './types.js';
5
- import { F as FrameworkChannelName, a as FrameworkChannel, b as FrameworkChannelEvent, c as FrameworkChannelEventPayload } from '../../framework-CvxgHwbv.js';
6
- import '../../types-C7Q36ryo.js';
5
+ import { F as FrameworkChannelCallArgs, a as FrameworkChannel, b as FrameworkChannelPattern, c as FrameworkChannelEvent, d as FrameworkChannelParameters, e as FrameworkChannelEventPayload } from '../../framework-B-4kGmAw.js';
6
+ import '../../base_channel-Dr40l7CW.js';
7
7
  import 'ws';
8
8
  import 'node:http';
9
9
  import '@adonisjs/core/types/http';
10
10
  import '@adonisjs/core/http';
11
11
  import '@boringnode/bus/types/main';
12
12
 
13
+ type ChannelEventArgs<Registry, Pattern extends FrameworkChannelPattern<Registry>, Event extends FrameworkChannelEvent<Registry, Pattern>> = FrameworkChannelParameters<Registry, Pattern> extends undefined ? [event: Event, handler: EventHandler<FrameworkChannelEventPayload<Registry, Pattern, Event>>] : [
14
+ parameters: FrameworkChannelParameters<Registry, Pattern>,
15
+ event: Event,
16
+ handler: EventHandler<FrameworkChannelEventPayload<Registry, Pattern, Event>>
17
+ ];
13
18
  interface SocketProviderProps<Registry> {
14
19
  socket: Socket<Registry>;
15
20
  children?: ReactNode;
@@ -20,8 +25,11 @@ declare function createSocketHooks<Registry = never>(): {
20
25
  SocketProvider: ({ socket, children, owned }: SocketProviderProps<Registry>) => react.FunctionComponentElement<react.ProviderProps<Socket<Registry> | null>>;
21
26
  useSocket: () => Socket<Registry>;
22
27
  useSocketState: () => ConnectionState;
23
- useChannel: <const Name extends string>(name: FrameworkChannelName<Registry, Name> | null) => FrameworkChannel<Registry, Name> | null;
24
- useChannelEvent: <const Name extends string, Event extends FrameworkChannelEvent<Registry, Name>>(name: FrameworkChannelName<Registry, Name> | null, event: Event, handler: EventHandler<FrameworkChannelEventPayload<Registry, Name, Event>>) => void;
28
+ useChannel: {
29
+ <const Args extends FrameworkChannelCallArgs<Registry>>(...args: Args): FrameworkChannel<Registry, Args[0]> | null;
30
+ (pattern: null): null;
31
+ };
32
+ useChannelEvent: <const Pattern extends FrameworkChannelPattern<Registry>, Event extends FrameworkChannelEvent<Registry, Pattern>>(pattern: Pattern | null, ...args: ChannelEventArgs<Registry, Pattern, Event>) => void;
25
33
  };
26
34
 
27
35
  export { type SocketProviderProps, createSocketHooks };
@@ -1,8 +1,14 @@
1
1
  import {
2
2
  acquireChannel,
3
- acquireSocketOwnership
4
- } from "../../chunk-ANT2E3LT.js";
5
- import "../../chunk-SFAY2ZA4.js";
3
+ acquireSocketOwnership,
4
+ createChannelCallArgs,
5
+ resolveChannelEventArgs
6
+ } from "../../chunk-YVC7IMDN.js";
7
+ import {
8
+ buildChannelName
9
+ } from "../../chunk-QNOOQXYY.js";
10
+ import "../../chunk-6PJ4ALJD.js";
11
+ import "../../chunk-E6ILCRL3.js";
6
12
 
7
13
  // src/client/react.ts
8
14
  import {
@@ -36,30 +42,40 @@ function createSocketHooks() {
36
42
  () => "disconnected"
37
43
  );
38
44
  }
39
- function useChannel(name) {
45
+ function useChannel(...args) {
46
+ const [pattern, parameters] = args;
40
47
  const socket = useSocket();
48
+ const name = pattern === null ? null : buildChannelName(pattern, parameters);
41
49
  const [acquired, setAcquired] = useState(null);
42
50
  useEffect(() => {
43
- if (name === null) {
51
+ if (pattern === null || name === null) {
44
52
  setAcquired(null);
45
53
  return;
46
54
  }
47
- const { channel, lease } = acquireChannel(socket, name);
55
+ const channelArgs = createChannelCallArgs(pattern, parameters);
56
+ const { channel, lease } = acquireChannel(socket, ...channelArgs);
48
57
  setAcquired({ socket, name, channel });
49
58
  return () => lease.release();
50
- }, [name, socket]);
59
+ }, [name, pattern, socket]);
51
60
  return acquired?.socket === socket && acquired.name === name ? acquired.channel : null;
52
61
  }
53
- function useChannelEvent(name, event, handler) {
62
+ function useChannelEvent(pattern, ...args) {
54
63
  const socket = useSocket();
64
+ const {
65
+ parameterInput: parameters,
66
+ event,
67
+ handler
68
+ } = resolveChannelEventArgs(args);
69
+ const name = pattern === null ? null : buildChannelName(pattern, parameters);
55
70
  const handlerRef = useRef(handler);
56
71
  handlerRef.current = handler;
57
72
  useEffect(() => {
58
- if (name === null) return;
59
- const { lease } = acquireChannel(socket, name);
73
+ if (pattern === null || name === null) return;
74
+ const channelArgs = createChannelCallArgs(pattern, parameters);
75
+ const { lease } = acquireChannel(socket, ...channelArgs);
60
76
  lease.listen(event, (data) => handlerRef.current(data));
61
77
  return () => lease.release();
62
- }, [event, name, socket]);
78
+ }, [event, name, pattern, socket]);
63
79
  }
64
80
  return { SocketProvider, useSocket, useSocketState, useChannel, useChannelEvent };
65
81
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/react.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useContext,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport type { Socket } from './socket.js'\nimport type { ConnectionState, EventHandler } from './types.js'\nimport {\n acquireChannel,\n acquireSocketOwnership,\n type FrameworkChannel,\n type FrameworkChannelEvent,\n type FrameworkChannelEventPayload,\n type FrameworkChannelName,\n} from './framework.js'\n\nexport interface SocketProviderProps<Registry> {\n socket: Socket<Registry>\n children?: ReactNode\n /** Connect on mount and disconnect on unmount. Use only for an exclusively owned socket. */\n owned?: boolean\n}\n\nexport function createSocketHooks<Registry = never>() {\n const SocketContext = createContext<Socket<Registry> | null>(null)\n\n function useSocket(): Socket<Registry> {\n const socket = useContext(SocketContext)\n if (!socket) throw new Error('SocketProvider is missing')\n return socket\n }\n\n function SocketProvider({ socket, children, owned = false }: SocketProviderProps<Registry>) {\n useEffect(() => {\n if (!owned) return\n return acquireSocketOwnership(socket)\n }, [owned, socket])\n\n return createElement(SocketContext.Provider, { value: socket }, children)\n }\n\n function useSocketState(): ConnectionState {\n const socket = useSocket()\n return useSyncExternalStore(\n (notify) => socket.onStateChange(notify),\n () => socket.state,\n () => 'disconnected'\n )\n }\n\n function useChannel<const Name extends string>(\n name: FrameworkChannelName<Registry, Name> | null\n ): FrameworkChannel<Registry, Name> | null {\n const socket = useSocket()\n const [acquired, setAcquired] = useState<{\n socket: Socket<Registry>\n name: string\n channel: FrameworkChannel<Registry, Name>\n } | null>(null)\n\n useEffect(() => {\n if (name === null) {\n setAcquired(null)\n return\n }\n const { channel, lease } = acquireChannel(socket, name)\n setAcquired({ socket, name, channel })\n return () => lease.release()\n }, [name, socket])\n\n return acquired?.socket === socket && acquired.name === name ? acquired.channel : null\n }\n\n function useChannelEvent<\n const Name extends string,\n Event extends FrameworkChannelEvent<Registry, Name>,\n >(\n name: FrameworkChannelName<Registry, Name> | null,\n event: Event,\n handler: EventHandler<FrameworkChannelEventPayload<Registry, Name, Event>>\n ): void {\n const socket = useSocket()\n const handlerRef = useRef(handler)\n handlerRef.current = handler\n\n useEffect(() => {\n if (name === null) return\n const { lease } = acquireChannel(socket, name)\n lease.listen(event, (data) => handlerRef.current(data))\n return () => lease.release()\n }, [event, name, socket])\n }\n\n return { SocketProvider, useSocket, useSocketState, useChannel, useChannelEvent }\n}\n"],"mappings":";;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAmBA,SAAS,oBAAsC;AACpD,QAAM,gBAAgB,cAAuC,IAAI;AAEjE,WAAS,YAA8B;AACrC,UAAM,SAAS,WAAW,aAAa;AACvC,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,2BAA2B;AACxD,WAAO;AAAA,EACT;AAEA,WAAS,eAAe,EAAE,QAAQ,UAAU,QAAQ,MAAM,GAAkC;AAC1F,cAAU,MAAM;AACd,UAAI,CAAC,MAAO;AACZ,aAAO,uBAAuB,MAAM;AAAA,IACtC,GAAG,CAAC,OAAO,MAAM,CAAC;AAElB,WAAO,cAAc,cAAc,UAAU,EAAE,OAAO,OAAO,GAAG,QAAQ;AAAA,EAC1E;AAEA,WAAS,iBAAkC;AACzC,UAAM,SAAS,UAAU;AACzB,WAAO;AAAA,MACL,CAAC,WAAW,OAAO,cAAc,MAAM;AAAA,MACvC,MAAM,OAAO;AAAA,MACb,MAAM;AAAA,IACR;AAAA,EACF;AAEA,WAAS,WACP,MACyC;AACzC,UAAM,SAAS,UAAU;AACzB,UAAM,CAAC,UAAU,WAAW,IAAI,SAItB,IAAI;AAEd,cAAU,MAAM;AACd,UAAI,SAAS,MAAM;AACjB,oBAAY,IAAI;AAChB;AAAA,MACF;AACA,YAAM,EAAE,SAAS,MAAM,IAAI,eAAe,QAAQ,IAAI;AACtD,kBAAY,EAAE,QAAQ,MAAM,QAAQ,CAAC;AACrC,aAAO,MAAM,MAAM,QAAQ;AAAA,IAC7B,GAAG,CAAC,MAAM,MAAM,CAAC;AAEjB,WAAO,UAAU,WAAW,UAAU,SAAS,SAAS,OAAO,SAAS,UAAU;AAAA,EACpF;AAEA,WAAS,gBAIP,MACA,OACA,SACM;AACN,UAAM,SAAS,UAAU;AACzB,UAAM,aAAa,OAAO,OAAO;AACjC,eAAW,UAAU;AAErB,cAAU,MAAM;AACd,UAAI,SAAS,KAAM;AACnB,YAAM,EAAE,MAAM,IAAI,eAAe,QAAQ,IAAI;AAC7C,YAAM,OAAO,OAAO,CAAC,SAAS,WAAW,QAAQ,IAAI,CAAC;AACtD,aAAO,MAAM,MAAM,QAAQ;AAAA,IAC7B,GAAG,CAAC,OAAO,MAAM,MAAM,CAAC;AAAA,EAC1B;AAEA,SAAO,EAAE,gBAAgB,WAAW,gBAAgB,YAAY,gBAAgB;AAClF;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/react.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useContext,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport type { Channel } from './channel.js'\nimport { buildChannelName, type Socket } from './socket.js'\nimport type { ConnectionState, EventHandler } from './types.js'\nimport {\n acquireChannel,\n acquireSocketOwnership,\n createChannelCallArgs,\n resolveChannelEventArgs,\n type FrameworkChannel,\n type FrameworkChannelCallArgs,\n type FrameworkChannelEvent,\n type FrameworkChannelEventPayload,\n type FrameworkChannelParameters,\n type FrameworkChannelPattern,\n} from './framework.js'\n\ntype ChannelEventArgs<\n Registry,\n Pattern extends FrameworkChannelPattern<Registry>,\n Event extends FrameworkChannelEvent<Registry, Pattern>,\n> =\n FrameworkChannelParameters<Registry, Pattern> extends undefined\n ? [event: Event, handler: EventHandler<FrameworkChannelEventPayload<Registry, Pattern, Event>>]\n : [\n parameters: FrameworkChannelParameters<Registry, Pattern>,\n event: Event,\n handler: EventHandler<FrameworkChannelEventPayload<Registry, Pattern, Event>>,\n ]\n\nexport interface SocketProviderProps<Registry> {\n socket: Socket<Registry>\n children?: ReactNode\n /** Connect on mount and disconnect on unmount. Use only for an exclusively owned socket. */\n owned?: boolean\n}\n\nexport function createSocketHooks<Registry = never>() {\n const SocketContext = createContext<Socket<Registry> | null>(null)\n\n function useSocket(): Socket<Registry> {\n const socket = useContext(SocketContext)\n if (!socket) throw new Error('SocketProvider is missing')\n return socket\n }\n\n function SocketProvider({ socket, children, owned = false }: SocketProviderProps<Registry>) {\n useEffect(() => {\n if (!owned) return\n return acquireSocketOwnership(socket)\n }, [owned, socket])\n\n return createElement(SocketContext.Provider, { value: socket }, children)\n }\n\n function useSocketState(): ConnectionState {\n const socket = useSocket()\n return useSyncExternalStore(\n (notify) => socket.onStateChange(notify),\n () => socket.state,\n () => 'disconnected'\n )\n }\n\n function useChannel<const Args extends FrameworkChannelCallArgs<Registry>>(\n ...args: Args\n ): FrameworkChannel<Registry, Args[0]> | null\n function useChannel(pattern: null): null\n function useChannel(\n ...args: [pattern: FrameworkChannelPattern<Registry> | null, parameters?: object]\n ): Channel<any> | null {\n const [pattern, parameters] = args\n const socket = useSocket()\n const name = pattern === null ? null : buildChannelName(pattern, parameters)\n const [acquired, setAcquired] = useState<{\n socket: Socket<Registry>\n name: string\n channel: Channel<any>\n } | null>(null)\n\n useEffect(() => {\n if (pattern === null || name === null) {\n setAcquired(null)\n return\n }\n const channelArgs = createChannelCallArgs<Registry>(pattern, parameters)\n const { channel, lease } = acquireChannel(socket, ...channelArgs)\n setAcquired({ socket, name, channel })\n return () => lease.release()\n }, [name, pattern, socket])\n\n return acquired?.socket === socket && acquired.name === name ? acquired.channel : null\n }\n\n function useChannelEvent<\n const Pattern extends FrameworkChannelPattern<Registry>,\n Event extends FrameworkChannelEvent<Registry, Pattern>,\n >(pattern: Pattern | null, ...args: ChannelEventArgs<Registry, Pattern, Event>): void {\n const socket = useSocket()\n const {\n parameterInput: parameters,\n event,\n handler,\n } = resolveChannelEventArgs<\n FrameworkChannelParameters<Registry, Pattern>,\n Event,\n FrameworkChannelEventPayload<Registry, Pattern, Event>\n >(args)\n const name = pattern === null ? null : buildChannelName(pattern, parameters)\n const handlerRef = useRef(handler)\n handlerRef.current = handler\n\n useEffect(() => {\n if (pattern === null || name === null) return\n const channelArgs = createChannelCallArgs<Registry>(pattern, parameters)\n const { lease } = acquireChannel(socket, ...channelArgs)\n lease.listen(event, (data) => handlerRef.current(data))\n return () => lease.release()\n }, [event, name, pattern, socket])\n }\n\n return { SocketProvider, useSocket, useSocketState, useChannel, useChannelEvent }\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAqCA,SAAS,oBAAsC;AACpD,QAAM,gBAAgB,cAAuC,IAAI;AAEjE,WAAS,YAA8B;AACrC,UAAM,SAAS,WAAW,aAAa;AACvC,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,2BAA2B;AACxD,WAAO;AAAA,EACT;AAEA,WAAS,eAAe,EAAE,QAAQ,UAAU,QAAQ,MAAM,GAAkC;AAC1F,cAAU,MAAM;AACd,UAAI,CAAC,MAAO;AACZ,aAAO,uBAAuB,MAAM;AAAA,IACtC,GAAG,CAAC,OAAO,MAAM,CAAC;AAElB,WAAO,cAAc,cAAc,UAAU,EAAE,OAAO,OAAO,GAAG,QAAQ;AAAA,EAC1E;AAEA,WAAS,iBAAkC;AACzC,UAAM,SAAS,UAAU;AACzB,WAAO;AAAA,MACL,CAAC,WAAW,OAAO,cAAc,MAAM;AAAA,MACvC,MAAM,OAAO;AAAA,MACb,MAAM;AAAA,IACR;AAAA,EACF;AAMA,WAAS,cACJ,MACkB;AACrB,UAAM,CAAC,SAAS,UAAU,IAAI;AAC9B,UAAM,SAAS,UAAU;AACzB,UAAM,OAAO,YAAY,OAAO,OAAO,iBAAiB,SAAS,UAAU;AAC3E,UAAM,CAAC,UAAU,WAAW,IAAI,SAItB,IAAI;AAEd,cAAU,MAAM;AACd,UAAI,YAAY,QAAQ,SAAS,MAAM;AACrC,oBAAY,IAAI;AAChB;AAAA,MACF;AACA,YAAM,cAAc,sBAAgC,SAAS,UAAU;AACvE,YAAM,EAAE,SAAS,MAAM,IAAI,eAAe,QAAQ,GAAG,WAAW;AAChE,kBAAY,EAAE,QAAQ,MAAM,QAAQ,CAAC;AACrC,aAAO,MAAM,MAAM,QAAQ;AAAA,IAC7B,GAAG,CAAC,MAAM,SAAS,MAAM,CAAC;AAE1B,WAAO,UAAU,WAAW,UAAU,SAAS,SAAS,OAAO,SAAS,UAAU;AAAA,EACpF;AAEA,WAAS,gBAGP,YAA4B,MAAwD;AACpF,UAAM,SAAS,UAAU;AACzB,UAAM;AAAA,MACJ,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,IACF,IAAI,wBAIF,IAAI;AACN,UAAM,OAAO,YAAY,OAAO,OAAO,iBAAiB,SAAS,UAAU;AAC3E,UAAM,aAAa,OAAO,OAAO;AACjC,eAAW,UAAU;AAErB,cAAU,MAAM;AACd,UAAI,YAAY,QAAQ,SAAS,KAAM;AACvC,YAAM,cAAc,sBAAgC,SAAS,UAAU;AACvE,YAAM,EAAE,MAAM,IAAI,eAAe,QAAQ,GAAG,WAAW;AACvD,YAAM,OAAO,OAAO,CAAC,SAAS,WAAW,QAAQ,IAAI,CAAC;AACtD,aAAO,MAAM,MAAM,QAAQ;AAAA,IAC7B,GAAG,CAAC,OAAO,MAAM,SAAS,MAAM,CAAC;AAAA,EACnC;AAEA,SAAO,EAAE,gBAAgB,WAAW,gBAAgB,YAAY,gBAAgB;AAClF;","names":[]}
@@ -1,5 +1,5 @@
1
- import { a as ChannelServerEventsOf } from '../../types-C7Q36ryo.js';
2
- export { b as ChannelAck, c as ChannelMessage } from '../../types-C7Q36ryo.js';
1
+ import { C as ChannelServerEventsOf } from '../../base_channel-Dr40l7CW.js';
2
+ export { a as ChannelAck, b as ChannelMessage } from '../../base_channel-Dr40l7CW.js';
3
3
  import 'ws';
4
4
  import 'node:http';
5
5
  import '@adonisjs/core/types/http';
@@ -30,38 +30,34 @@ type ClientContracts<Entry> = Entry extends {
30
30
  ack: HandlerAck<Entry, Event>;
31
31
  };
32
32
  } : unknown;
33
- type NormalizePath<Path extends string> = Path extends '/' ? '/' : Path extends `/${infer WithoutLeading}` ? WithoutLeading extends `${infer Normalized}/` ? Normalized : WithoutLeading : Path extends `${infer WithoutTrailing}/` ? WithoutTrailing : Path;
34
- type SupportedPattern<Pattern extends string> = string extends Pattern ? false : NormalizePath<Pattern> extends infer Normalized extends string ? Normalized extends '/' ? true : Normalized extends `${infer Segment}/${infer Rest}` ? Segment extends `:${infer Param}` ? Param extends `${string}?${string}` | `${string}.${string}` ? false : SupportedPattern<Rest> : Segment extends '' | '*' | `${string}:${string}` | `${string}*${string}` | `${string}?${string}` ? false : SupportedPattern<Rest> : Normalized extends '*' ? true : Normalized extends `:${infer Param}` ? Param extends `${string}.${string}` ? false : Param extends `${infer Name}?` ? Name extends '' | `${string}?${string}` ? false : true : Param extends '' | `${string}?${string}` ? false : true : Normalized extends '' | `${string}:${string}` | `${string}*${string}` | `${string}?${string}` ? false : true : false;
35
- type ReplaceNaN<Value extends string> = Value extends `${infer Prefix}NaN${infer Suffix}` ? `${Prefix}1.5${ReplaceNaN<Suffix>}` : Value;
36
- type ReplaceInfinity<Value extends string> = Value extends `${infer Prefix}-Infinity${infer Suffix}` ? `${Prefix}1.5${ReplaceInfinity<Suffix>}` | `${Prefix}-1.5${ReplaceInfinity<Suffix>}` : Value extends `${infer Prefix}Infinity${infer Suffix}` ? `${Prefix}1.5${ReplaceInfinity<Suffix>}` : Value;
37
- type ReplaceNonFiniteNumbers<Value extends string> = ReplaceInfinity<ReplaceNaN<Value>>;
38
- type FiniteNumberWitness<Value extends string> = ReplaceNonFiniteNumbers<Value> extends Value ? never : ReplaceNonFiniteNumbers<Value>;
39
- type PotentialStaticMatch<Pattern extends string, Name extends string> = Pattern extends Name ? true : [FiniteNumberWitness<Pattern>] extends [never] ? false : [Extract<FiniteNumberWitness<Pattern>, Name>] extends [never] ? false : true;
40
- type MatchesNormalizedPattern<Pattern extends string, Name extends string> = Pattern extends '*' ? true : Pattern extends `${infer PatternHead}/${infer PatternTail}` ? Name extends `${infer NameHead}/${infer NameTail}` ? PatternHead extends `:${string}` ? MatchesNormalizedPattern<PatternTail, NameTail> : PotentialStaticMatch<PatternHead, NameHead> extends true ? MatchesNormalizedPattern<PatternTail, NameTail> : false : PatternHead extends Name ? PatternTail extends `:${string}?` ? true : false : false : Pattern extends `:${string}?` ? Name extends '/' ? true : Name extends `${string}/${string}` ? false : true : Pattern extends `:${string}` ? Name extends `${string}/${string}` ? false : true : PotentialStaticMatch<Pattern, Name> extends true ? true : false;
41
- type MatchesChannelPattern<Pattern extends string, Name extends string> = SupportedPattern<Pattern> extends true ? MatchesNormalizedPattern<NormalizePath<Pattern>, NormalizePath<Name>> : false;
42
- type HasOpenString<Value extends string> = string extends Value ? true : Value extends '' ? false : Value extends `${infer _First}${infer Rest}` ? string extends Rest ? true : HasOpenString<Rest> : false;
43
- type DefinitelyMatchesNormalizedPattern<Pattern extends string, Name extends string> = Pattern extends '*' ? true : Pattern extends `${infer PatternHead}/${infer PatternTail}` ? Name extends `${infer NameHead}/${infer NameTail}` ? PatternHead extends `:${string}` ? HasOpenString<NameHead> extends true ? false : DefinitelyMatchesNormalizedPattern<PatternTail, NameTail> : NameHead extends PatternHead ? DefinitelyMatchesNormalizedPattern<PatternTail, NameTail> : false : PatternHead extends Name ? PatternTail extends `:${string}?` ? true : false : false : Pattern extends `:${string}?` ? HasOpenString<Name> extends true ? false : Name extends `${string}/${string}` ? Name extends '/' ? true : false : true : Pattern extends `:${string}` ? HasOpenString<Name> extends true ? false : Name extends `${string}/${string}` ? false : true : Name extends Pattern ? true : false;
44
- type DefinitelyMatchesChannelPattern<Pattern extends string, Name extends string> = SupportedPattern<Pattern> extends true ? DefinitelyMatchesNormalizedPattern<NormalizePath<Pattern>, NormalizePath<Name>> : false;
45
- type SegmentRank<Segment extends string> = Segment extends '*' ? 1 : Segment extends `:${string}?` ? 2 : Segment extends `:${string}` ? 3 : 4;
46
- type PatternScore<Pattern extends string> = NormalizePath<Pattern> extends `${infer Head}/${infer Tail}` ? [SegmentRank<Head>, ...PatternScore<Tail>] : [SegmentRank<NormalizePath<Pattern>>];
47
- type RankGreater<Left extends number, Right extends number> = Left extends 4 ? Right extends 4 ? false : true : Left extends 3 ? Right extends 1 | 2 ? true : false : Left extends 2 ? Right extends 1 ? true : false : false;
48
- type ScoreGreater<Left extends number[], Right extends number[]> = Left extends [
49
- infer LeftHead extends number,
50
- ...infer LeftTail extends number[]
51
- ] ? Right extends [infer RightHead extends number, ...infer RightTail extends number[]] ? LeftHead extends RightHead ? ScoreGreater<LeftTail, RightTail> : RankGreater<LeftHead, RightHead> : true : false;
52
- type PatternOf<Entry> = Entry extends {
53
- readonly pattern: infer Pattern extends string;
54
- } ? Pattern : never;
55
- type MoreSpecific<Left, Right> = ScoreGreater<PatternScore<PatternOf<Left>>, PatternScore<PatternOf<Right>>>;
56
- type ResolveRegistryEntry<Entries extends readonly unknown[], Name extends string, Best = never, Ambiguous extends boolean = false> = Entries extends readonly [infer Current, ...infer Rest] ? true extends MatchesChannelPattern<PatternOf<Current>, Name> ? [Best] extends [never] ? ResolveRegistryEntry<Rest, Name, Current, false> : MoreSpecific<Current, Best> extends true ? ResolveRegistryEntry<Rest, Name, Current, false> : MoreSpecific<Best, Current> extends true ? ResolveRegistryEntry<Rest, Name, Best, Ambiguous> : ResolveRegistryEntry<Rest, Name, Best, true> : ResolveRegistryEntry<Rest, Name, Best, Ambiguous> : Ambiguous extends true ? unknown : Best;
57
- type RegistryEntries<Registry> = Registry extends {
58
- readonly channels: infer Entries extends readonly unknown[];
59
- } ? Entries : [];
60
33
  type ContractOfEntry<Entry> = ChannelContract<ClientContracts<Entry>, ChannelServerEventsOf<ChannelInstance<Entry>>>;
61
- /** Resolves a literal channel name to its unique most-specific generated contract. */
62
- type ChannelContractFor<Registry, Name extends string> = string extends Name ? unknown : Registry extends {
63
- readonly uncertain: true;
64
- } ? unknown : ResolveRegistryEntry<RegistryEntries<Registry>, Name> extends infer Entry ? unknown extends Entry ? unknown : [Entry] extends [never] ? never : DefinitelyMatchesChannelPattern<PatternOf<Entry>, Name> extends true ? ContractOfEntry<Entry> : unknown : never;
34
+ type RegistryChannels<Registry> = Registry extends {
35
+ readonly channels: infer Channels;
36
+ } ? Channels : never;
37
+ type RegistryChannelEntry<Registry, Pattern extends ChannelPattern<Registry>> = RegistryChannels<Registry>[Pattern];
38
+ /** Channel patterns explicitly declared in a generated registry. */
39
+ type ChannelPattern<Registry> = Extract<keyof RegistryChannels<Registry>, string>;
40
+ /** Resolves an explicit generated channel pattern to its contract. */
41
+ type ChannelContractFor<Registry, Pattern extends string> = string extends Pattern ? never : Pattern extends ChannelPattern<Registry> ? ContractOfEntry<RegistryChannelEntry<Registry, Pattern>> : never;
42
+ type ChannelParameterValue = string | number;
43
+ /** Parameters generated for an explicit channel pattern. Static channels use `undefined`. */
44
+ type ChannelParameters<Registry, Pattern extends ChannelPattern<Registry>> = RegistryChannelEntry<Registry, Pattern> extends {
45
+ readonly params: infer Parameters;
46
+ } ? Parameters extends object | undefined ? Parameters : never : never;
47
+ /** A correlated client call for one generated channel pattern. */
48
+ type ChannelCallArgs<Registry, Pattern extends ChannelPattern<Registry> = ChannelPattern<Registry>> = Pattern extends ChannelPattern<Registry> ? ChannelParameters<Registry, Pattern> extends undefined ? [pattern: Pattern] : [pattern: Pattern, parameters: ChannelParameters<Registry, Pattern>] : never;
49
+ type ClientEvents<Contract> = Contract extends ChannelContract<infer Events, unknown> ? Events : never;
50
+ type ServerEvents<Contract> = Contract extends ChannelContract<unknown, infer Events> ? Events : never;
51
+ /** Client events accepted by a generated channel. */
52
+ type ChannelClientEvent<Registry, Pattern extends ChannelPattern<Registry>> = Extract<keyof ClientEvents<ChannelContractFor<Registry, Pattern>>, string>;
53
+ /** Payload sent from the client for a generated channel event. */
54
+ type ChannelClientEventPayload<Registry, Pattern extends ChannelPattern<Registry>, Event extends ChannelClientEvent<Registry, Pattern>> = ClientEvents<ChannelContractFor<Registry, Pattern>>[Event] extends {
55
+ payload: infer Payload;
56
+ } ? Payload : never;
57
+ /** Server broadcast events received by a generated channel. */
58
+ type ChannelBroadcastEvent<Registry, Pattern extends ChannelPattern<Registry>> = Extract<keyof ServerEvents<ChannelContractFor<Registry, Pattern>>, string>;
59
+ /** Payload received from a server broadcast on a generated channel. */
60
+ type ChannelBroadcastPayload<Registry, Pattern extends ChannelPattern<Registry>, Event extends ChannelBroadcastEvent<Registry, Pattern>> = ServerEvents<ChannelContractFor<Registry, Pattern>>[Event];
65
61
  /**
66
62
  * Connection options.
67
63
  */
@@ -118,7 +114,6 @@ interface SubscribeResult {
118
114
  ok: boolean;
119
115
  error?: string;
120
116
  data?: SubscribeAckData;
121
- presenceData?: PresenceData | null;
122
117
  }
123
118
  /**
124
119
  * Presence data.
@@ -156,4 +151,4 @@ interface SocketClientTransport {
156
151
  off<T = unknown>(event: string, handler: EventHandler<T>): void;
157
152
  }
158
153
 
159
- export { type ChannelContract, type ChannelContractFor, ChannelServerEventsOf, type ConnectionState, type EventHandler, type PresenceData, type PresenceUser, type SocketClientTransport, type SocketOptions, type SubscribeAckData, type SubscribeOptions, type SubscribeResult, type UnsubscribeOptions };
154
+ export { type ChannelBroadcastEvent, type ChannelBroadcastPayload, type ChannelCallArgs, type ChannelClientEvent, type ChannelClientEventPayload, type ChannelContract, type ChannelContractFor, type ChannelParameterValue, type ChannelParameters, type ChannelPattern, ChannelServerEventsOf, type ConnectionState, type EventHandler, type PresenceData, type PresenceUser, type SocketClientTransport, type SocketOptions, type SubscribeAckData, type SubscribeOptions, type SubscribeResult, type UnsubscribeOptions };
@@ -1,14 +1,23 @@
1
1
  import { ShallowRef, ComputedRef, MaybeRefOrGetter } from 'vue';
2
- import { Socket } from './index.js';
2
+ import { S as Socket } from '../../index-Fg-tkHhP.js';
3
3
  import { ConnectionState, EventHandler } from './types.js';
4
- import { F as FrameworkChannelName, a as FrameworkChannel, b as FrameworkChannelEvent, c as FrameworkChannelEventPayload } from '../../framework-CvxgHwbv.js';
5
- import '../../types-C7Q36ryo.js';
4
+ import { b as FrameworkChannelPattern, d as FrameworkChannelParameters, a as FrameworkChannel, c as FrameworkChannelEvent, e as FrameworkChannelEventPayload } from '../../framework-B-4kGmAw.js';
5
+ import '../../base_channel-Dr40l7CW.js';
6
6
  import 'ws';
7
7
  import 'node:http';
8
8
  import '@adonisjs/core/types/http';
9
9
  import '@adonisjs/core/http';
10
10
  import '@boringnode/bus/types/main';
11
11
 
12
+ type ChannelParameterInput<Registry, Pattern extends FrameworkChannelPattern<Registry>> = MaybeRefOrGetter<FrameworkChannelParameters<Registry, Pattern>>;
13
+ type VueChannelCallArgs<Registry> = {
14
+ [Pattern in FrameworkChannelPattern<Registry>]: FrameworkChannelParameters<Registry, Pattern> extends undefined ? [pattern: Pattern] : [pattern: Pattern, parameters: ChannelParameterInput<Registry, Pattern>];
15
+ }[FrameworkChannelPattern<Registry>];
16
+ type VueChannelEventArgs<Registry, Pattern extends FrameworkChannelPattern<Registry>, Event extends FrameworkChannelEvent<Registry, Pattern>> = FrameworkChannelParameters<Registry, Pattern> extends undefined ? [event: Event, handler: EventHandler<FrameworkChannelEventPayload<Registry, Pattern, Event>>] : [
17
+ parameters: ChannelParameterInput<Registry, Pattern>,
18
+ event: Event,
19
+ handler: EventHandler<FrameworkChannelEventPayload<Registry, Pattern, Event>>
20
+ ];
12
21
  declare function createSocketComposables<Registry = never>(): {
13
22
  provideSocket: (socket: Socket<Registry>, options?: {
14
23
  owned?: boolean;
@@ -18,8 +27,11 @@ declare function createSocketComposables<Registry = never>(): {
18
27
  state: Readonly<ShallowRef<ConnectionState>>;
19
28
  connected: ComputedRef<boolean>;
20
29
  };
21
- useChannel: <const Name extends string>(name: MaybeRefOrGetter<FrameworkChannelName<Registry, Name> | null>) => Readonly<ShallowRef<FrameworkChannel<Registry, Name> | null>>;
22
- useChannelEvent: <const Name extends string, Event extends FrameworkChannelEvent<Registry, Name>>(name: MaybeRefOrGetter<FrameworkChannelName<Registry, Name> | null>, event: Event, handler: EventHandler<FrameworkChannelEventPayload<Registry, Name, Event>>) => void;
30
+ useChannel: {
31
+ <const Args extends VueChannelCallArgs<Registry>>(...args: Args): Readonly<ShallowRef<FrameworkChannel<Registry, Args[0]> | null>>;
32
+ (pattern: null): Readonly<ShallowRef<null>>;
33
+ };
34
+ useChannelEvent: <const Pattern extends FrameworkChannelPattern<Registry>, Event extends FrameworkChannelEvent<Registry, Pattern>>(pattern: Pattern | null, ...args: VueChannelEventArgs<Registry, Pattern, Event>) => void;
23
35
  };
24
36
 
25
37
  export { createSocketComposables };
@@ -1,8 +1,14 @@
1
1
  import {
2
2
  acquireChannel,
3
- acquireSocketOwnership
4
- } from "../../chunk-ANT2E3LT.js";
5
- import "../../chunk-SFAY2ZA4.js";
3
+ acquireSocketOwnership,
4
+ createChannelCallArgs,
5
+ resolveChannelEventArgs
6
+ } from "../../chunk-YVC7IMDN.js";
7
+ import {
8
+ buildChannelName
9
+ } from "../../chunk-QNOOQXYY.js";
10
+ import "../../chunk-6PJ4ALJD.js";
11
+ import "../../chunk-E6ILCRL3.js";
6
12
 
7
13
  // src/client/vue.ts
8
14
  import {
@@ -42,17 +48,23 @@ function createSocketComposables() {
42
48
  const state = useContext().state;
43
49
  return { state, connected: computed(() => state.value === "connected") };
44
50
  }
45
- function useChannel(name) {
51
+ function useChannel(...args) {
52
+ const [pattern, parameterInput] = args;
46
53
  const socket = useSocket();
47
54
  const channel = shallowRef(null);
48
55
  watch(
49
- () => toValue(name),
50
- (nextName, _previousName, onCleanup) => {
51
- if (nextName === null) {
56
+ () => pattern === null ? null : toValue(parameterInput),
57
+ (parameters, _previousParameters, onCleanup) => {
58
+ const nextName = pattern === null ? null : buildChannelName(pattern, parameters);
59
+ if (nextName === null || pattern === null) {
52
60
  channel.value = null;
53
61
  return;
54
62
  }
55
- const acquired = acquireChannel(socket, nextName);
63
+ const channelArgs = createChannelCallArgs(
64
+ pattern,
65
+ parameters
66
+ );
67
+ const acquired = acquireChannel(socket, ...channelArgs);
56
68
  channel.value = acquired.channel;
57
69
  onCleanup(() => acquired.lease.release());
58
70
  },
@@ -60,13 +72,19 @@ function createSocketComposables() {
60
72
  );
61
73
  return channel;
62
74
  }
63
- function useChannelEvent(name, event, handler) {
75
+ function useChannelEvent(pattern, ...args) {
64
76
  const socket = useSocket();
77
+ const { parameterInput, event, handler } = resolveChannelEventArgs(args);
65
78
  watch(
66
- () => toValue(name),
67
- (nextName, _previousName, onCleanup) => {
68
- if (nextName === null) return;
69
- const { lease } = acquireChannel(socket, nextName);
79
+ () => pattern === null ? null : toValue(parameterInput),
80
+ (parameters, _previousParameters, onCleanup) => {
81
+ const nextName = pattern === null ? null : buildChannelName(pattern, parameters);
82
+ if (nextName === null || pattern === null) return;
83
+ const channelArgs = createChannelCallArgs(
84
+ pattern,
85
+ parameters
86
+ );
87
+ const { lease } = acquireChannel(socket, ...channelArgs);
70
88
  lease.listen(event, handler);
71
89
  onCleanup(() => lease.release());
72
90
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/vue.ts"],"sourcesContent":["import {\n computed,\n inject,\n onMounted,\n onScopeDispose,\n provide,\n shallowRef,\n toValue,\n watch,\n type ComputedRef,\n type InjectionKey,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from 'vue'\nimport type { Socket } from './socket.js'\nimport type { ConnectionState, EventHandler } from './types.js'\nimport {\n acquireChannel,\n acquireSocketOwnership,\n type FrameworkChannel,\n type FrameworkChannelEvent,\n type FrameworkChannelEventPayload,\n type FrameworkChannelName,\n} from './framework.js'\n\ninterface VueSocketContext<Registry> {\n socket: Socket<Registry>\n state: ShallowRef<ConnectionState>\n}\n\nexport function createSocketComposables<Registry = never>() {\n const key = Symbol('socket') as InjectionKey<VueSocketContext<Registry>>\n\n function provideSocket(socket: Socket<Registry>, options: { owned?: boolean } = {}): void {\n const state = shallowRef(socket.state)\n const stopStateListener = socket.onStateChange((nextState) => {\n state.value = nextState\n })\n provide(key, { socket, state })\n\n let releaseOwnership: (() => void) | undefined\n if (options.owned) onMounted(() => (releaseOwnership = acquireSocketOwnership(socket)))\n onScopeDispose(() => {\n stopStateListener()\n releaseOwnership?.()\n })\n }\n\n function useContext(): VueSocketContext<Registry> {\n const context = inject(key)\n if (!context) throw new Error('provideSocket must be called by an ancestor')\n return context\n }\n\n function useSocket(): Socket<Registry> {\n return useContext().socket\n }\n\n function useSocketState(): {\n state: Readonly<ShallowRef<ConnectionState>>\n connected: ComputedRef<boolean>\n } {\n const state = useContext().state\n return { state, connected: computed(() => state.value === 'connected') }\n }\n\n function useChannel<const Name extends string>(\n name: MaybeRefOrGetter<FrameworkChannelName<Registry, Name> | null>\n ): Readonly<ShallowRef<FrameworkChannel<Registry, Name> | null>> {\n const socket = useSocket()\n const channel = shallowRef(null) as ShallowRef<FrameworkChannel<Registry, Name> | null>\n\n watch(\n () => toValue(name),\n (nextName, _previousName, onCleanup) => {\n if (nextName === null) {\n channel.value = null\n return\n }\n const acquired = acquireChannel(socket, nextName)\n channel.value = acquired.channel\n onCleanup(() => acquired.lease.release())\n },\n { immediate: true }\n )\n\n return channel\n }\n\n function useChannelEvent<\n const Name extends string,\n Event extends FrameworkChannelEvent<Registry, Name>,\n >(\n name: MaybeRefOrGetter<FrameworkChannelName<Registry, Name> | null>,\n event: Event,\n handler: EventHandler<FrameworkChannelEventPayload<Registry, Name, Event>>\n ): void {\n const socket = useSocket()\n watch(\n () => toValue(name),\n (nextName, _previousName, onCleanup) => {\n if (nextName === null) return\n const { lease } = acquireChannel(socket, nextName)\n lease.listen(event, handler)\n onCleanup(() => lease.release())\n },\n { immediate: true }\n )\n }\n\n return { provideSocket, useSocket, useSocketState, useChannel, useChannelEvent }\n}\n"],"mappings":";;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AAiBA,SAAS,0BAA4C;AAC1D,QAAM,MAAM,uBAAO,QAAQ;AAE3B,WAAS,cAAc,QAA0B,UAA+B,CAAC,GAAS;AACxF,UAAM,QAAQ,WAAW,OAAO,KAAK;AACrC,UAAM,oBAAoB,OAAO,cAAc,CAAC,cAAc;AAC5D,YAAM,QAAQ;AAAA,IAChB,CAAC;AACD,YAAQ,KAAK,EAAE,QAAQ,MAAM,CAAC;AAE9B,QAAI;AACJ,QAAI,QAAQ,MAAO,WAAU,MAAO,mBAAmB,uBAAuB,MAAM,CAAE;AACtF,mBAAe,MAAM;AACnB,wBAAkB;AAClB,yBAAmB;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,WAAS,aAAyC;AAChD,UAAM,UAAU,OAAO,GAAG;AAC1B,QAAI,CAAC,QAAS,OAAM,IAAI,MAAM,6CAA6C;AAC3E,WAAO;AAAA,EACT;AAEA,WAAS,YAA8B;AACrC,WAAO,WAAW,EAAE;AAAA,EACtB;AAEA,WAAS,iBAGP;AACA,UAAM,QAAQ,WAAW,EAAE;AAC3B,WAAO,EAAE,OAAO,WAAW,SAAS,MAAM,MAAM,UAAU,WAAW,EAAE;AAAA,EACzE;AAEA,WAAS,WACP,MAC+D;AAC/D,UAAM,SAAS,UAAU;AACzB,UAAM,UAAU,WAAW,IAAI;AAE/B;AAAA,MACE,MAAM,QAAQ,IAAI;AAAA,MAClB,CAAC,UAAU,eAAe,cAAc;AACtC,YAAI,aAAa,MAAM;AACrB,kBAAQ,QAAQ;AAChB;AAAA,QACF;AACA,cAAM,WAAW,eAAe,QAAQ,QAAQ;AAChD,gBAAQ,QAAQ,SAAS;AACzB,kBAAU,MAAM,SAAS,MAAM,QAAQ,CAAC;AAAA,MAC1C;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACpB;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,gBAIP,MACA,OACA,SACM;AACN,UAAM,SAAS,UAAU;AACzB;AAAA,MACE,MAAM,QAAQ,IAAI;AAAA,MAClB,CAAC,UAAU,eAAe,cAAc;AACtC,YAAI,aAAa,KAAM;AACvB,cAAM,EAAE,MAAM,IAAI,eAAe,QAAQ,QAAQ;AACjD,cAAM,OAAO,OAAO,OAAO;AAC3B,kBAAU,MAAM,MAAM,QAAQ,CAAC;AAAA,MACjC;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SAAO,EAAE,eAAe,WAAW,gBAAgB,YAAY,gBAAgB;AACjF;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/vue.ts"],"sourcesContent":["import {\n computed,\n inject,\n onMounted,\n onScopeDispose,\n provide,\n shallowRef,\n toValue,\n watch,\n type ComputedRef,\n type InjectionKey,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from 'vue'\nimport type { Channel } from './channel.js'\nimport { buildChannelName, type Socket } from './socket.js'\nimport type { ConnectionState, EventHandler } from './types.js'\nimport {\n acquireChannel,\n acquireSocketOwnership,\n createChannelCallArgs,\n resolveChannelEventArgs,\n type FrameworkChannel,\n type FrameworkChannelEvent,\n type FrameworkChannelEventPayload,\n type FrameworkChannelParameters,\n type FrameworkChannelPattern,\n} from './framework.js'\n\ninterface VueSocketContext<Registry> {\n socket: Socket<Registry>\n state: ShallowRef<ConnectionState>\n}\n\ntype ChannelParameterInput<\n Registry,\n Pattern extends FrameworkChannelPattern<Registry>,\n> = MaybeRefOrGetter<FrameworkChannelParameters<Registry, Pattern>>\n\ntype VueChannelCallArgs<Registry> = {\n [Pattern in FrameworkChannelPattern<Registry>]: FrameworkChannelParameters<\n Registry,\n Pattern\n > extends undefined\n ? [pattern: Pattern]\n : [pattern: Pattern, parameters: ChannelParameterInput<Registry, Pattern>]\n}[FrameworkChannelPattern<Registry>]\n\ntype VueChannelEventArgs<\n Registry,\n Pattern extends FrameworkChannelPattern<Registry>,\n Event extends FrameworkChannelEvent<Registry, Pattern>,\n> =\n FrameworkChannelParameters<Registry, Pattern> extends undefined\n ? [event: Event, handler: EventHandler<FrameworkChannelEventPayload<Registry, Pattern, Event>>]\n : [\n parameters: ChannelParameterInput<Registry, Pattern>,\n event: Event,\n handler: EventHandler<FrameworkChannelEventPayload<Registry, Pattern, Event>>,\n ]\n\nexport function createSocketComposables<Registry = never>() {\n const key = Symbol('socket') as InjectionKey<VueSocketContext<Registry>>\n\n function provideSocket(socket: Socket<Registry>, options: { owned?: boolean } = {}): void {\n const state = shallowRef(socket.state)\n const stopStateListener = socket.onStateChange((nextState) => {\n state.value = nextState\n })\n provide(key, { socket, state })\n\n let releaseOwnership: (() => void) | undefined\n if (options.owned) onMounted(() => (releaseOwnership = acquireSocketOwnership(socket)))\n onScopeDispose(() => {\n stopStateListener()\n releaseOwnership?.()\n })\n }\n\n function useContext(): VueSocketContext<Registry> {\n const context = inject(key)\n if (!context) throw new Error('provideSocket must be called by an ancestor')\n return context\n }\n\n function useSocket(): Socket<Registry> {\n return useContext().socket\n }\n\n function useSocketState(): {\n state: Readonly<ShallowRef<ConnectionState>>\n connected: ComputedRef<boolean>\n } {\n const state = useContext().state\n return { state, connected: computed(() => state.value === 'connected') }\n }\n\n function useChannel<const Args extends VueChannelCallArgs<Registry>>(\n ...args: Args\n ): Readonly<ShallowRef<FrameworkChannel<Registry, Args[0]> | null>>\n function useChannel(pattern: null): Readonly<ShallowRef<null>>\n function useChannel(\n ...args: [\n pattern: FrameworkChannelPattern<Registry> | null,\n parameterInput?: MaybeRefOrGetter<object | undefined>,\n ]\n ): Readonly<ShallowRef<Channel<any> | null>> {\n const [pattern, parameterInput] = args\n const socket = useSocket()\n const channel = shallowRef(null) as ShallowRef<Channel<any> | null>\n\n watch(\n () => (pattern === null ? null : toValue(parameterInput)),\n (parameters, _previousParameters, onCleanup) => {\n const nextName =\n pattern === null ? null : buildChannelName(pattern, parameters as object | undefined)\n if (nextName === null || pattern === null) {\n channel.value = null\n return\n }\n const channelArgs = createChannelCallArgs<Registry>(\n pattern,\n parameters as object | undefined\n )\n const acquired = acquireChannel(socket, ...channelArgs)\n channel.value = acquired.channel\n onCleanup(() => acquired.lease.release())\n },\n { immediate: true }\n )\n\n return channel\n }\n\n function useChannelEvent<\n const Pattern extends FrameworkChannelPattern<Registry>,\n Event extends FrameworkChannelEvent<Registry, Pattern>,\n >(pattern: Pattern | null, ...args: VueChannelEventArgs<Registry, Pattern, Event>): void {\n const socket = useSocket()\n const { parameterInput, event, handler } = resolveChannelEventArgs<\n ChannelParameterInput<Registry, Pattern>,\n Event,\n FrameworkChannelEventPayload<Registry, Pattern, Event>\n >(args)\n watch(\n () => (pattern === null ? null : toValue(parameterInput)),\n (parameters, _previousParameters, onCleanup) => {\n const nextName =\n pattern === null ? null : buildChannelName(pattern, parameters as object | undefined)\n if (nextName === null || pattern === null) return\n const channelArgs = createChannelCallArgs<Registry>(\n pattern,\n parameters as object | undefined\n )\n const { lease } = acquireChannel(socket, ...channelArgs)\n lease.listen(event, handler)\n onCleanup(() => lease.release())\n },\n { immediate: true }\n )\n }\n\n return { provideSocket, useSocket, useSocketState, useChannel, useChannelEvent }\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AAgDA,SAAS,0BAA4C;AAC1D,QAAM,MAAM,uBAAO,QAAQ;AAE3B,WAAS,cAAc,QAA0B,UAA+B,CAAC,GAAS;AACxF,UAAM,QAAQ,WAAW,OAAO,KAAK;AACrC,UAAM,oBAAoB,OAAO,cAAc,CAAC,cAAc;AAC5D,YAAM,QAAQ;AAAA,IAChB,CAAC;AACD,YAAQ,KAAK,EAAE,QAAQ,MAAM,CAAC;AAE9B,QAAI;AACJ,QAAI,QAAQ,MAAO,WAAU,MAAO,mBAAmB,uBAAuB,MAAM,CAAE;AACtF,mBAAe,MAAM;AACnB,wBAAkB;AAClB,yBAAmB;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,WAAS,aAAyC;AAChD,UAAM,UAAU,OAAO,GAAG;AAC1B,QAAI,CAAC,QAAS,OAAM,IAAI,MAAM,6CAA6C;AAC3E,WAAO;AAAA,EACT;AAEA,WAAS,YAA8B;AACrC,WAAO,WAAW,EAAE;AAAA,EACtB;AAEA,WAAS,iBAGP;AACA,UAAM,QAAQ,WAAW,EAAE;AAC3B,WAAO,EAAE,OAAO,WAAW,SAAS,MAAM,MAAM,UAAU,WAAW,EAAE;AAAA,EACzE;AAMA,WAAS,cACJ,MAIwC;AAC3C,UAAM,CAAC,SAAS,cAAc,IAAI;AAClC,UAAM,SAAS,UAAU;AACzB,UAAM,UAAU,WAAW,IAAI;AAE/B;AAAA,MACE,MAAO,YAAY,OAAO,OAAO,QAAQ,cAAc;AAAA,MACvD,CAAC,YAAY,qBAAqB,cAAc;AAC9C,cAAM,WACJ,YAAY,OAAO,OAAO,iBAAiB,SAAS,UAAgC;AACtF,YAAI,aAAa,QAAQ,YAAY,MAAM;AACzC,kBAAQ,QAAQ;AAChB;AAAA,QACF;AACA,cAAM,cAAc;AAAA,UAClB;AAAA,UACA;AAAA,QACF;AACA,cAAM,WAAW,eAAe,QAAQ,GAAG,WAAW;AACtD,gBAAQ,QAAQ,SAAS;AACzB,kBAAU,MAAM,SAAS,MAAM,QAAQ,CAAC;AAAA,MAC1C;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACpB;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,gBAGP,YAA4B,MAA2D;AACvF,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,gBAAgB,OAAO,QAAQ,IAAI,wBAIzC,IAAI;AACN;AAAA,MACE,MAAO,YAAY,OAAO,OAAO,QAAQ,cAAc;AAAA,MACvD,CAAC,YAAY,qBAAqB,cAAc;AAC9C,cAAM,WACJ,YAAY,OAAO,OAAO,iBAAiB,SAAS,UAAgC;AACtF,YAAI,aAAa,QAAQ,YAAY,KAAM;AAC3C,cAAM,cAAc;AAAA,UAClB;AAAA,UACA;AAAA,QACF;AACA,cAAM,EAAE,MAAM,IAAI,eAAe,QAAQ,GAAG,WAAW;AACvD,cAAM,OAAO,OAAO,OAAO;AAC3B,kBAAU,MAAM,MAAM,QAAQ,CAAC;AAAA,MACjC;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SAAO,EAAE,eAAe,WAAW,gBAAgB,YAAY,gBAAgB;AACjF;","names":[]}
@@ -1,10 +1,11 @@
1
- import { C as ChannelHandlerMap } from '../types-C7Q36ryo.js';
1
+ import { A as AuthenticatedSocket } from '../base_channel-Dr40l7CW.js';
2
2
  import 'ws';
3
3
  import 'node:http';
4
4
  import '@adonisjs/core/types/http';
5
5
  import '@adonisjs/core/http';
6
6
  import '@boringnode/bus/types/main';
7
7
 
8
+ type DecoratedChannelHandler<User> = (socket: AuthenticatedSocket<User>, data: unknown) => unknown;
8
9
  /**
9
10
  * Method decorator used to bind an incoming channel event to a method.
10
11
  */
@@ -13,6 +14,6 @@ declare function onMessage<EventName extends string>(event: EventName): MethodDe
13
14
  * Resolve decorated handlers for a channel instance, including inherited ones.
14
15
  * Child classes override parent handlers when the event name is the same.
15
16
  */
16
- declare function getDecoratedChannelHandlers<User = unknown>(instance: object): ChannelHandlerMap<User>;
17
+ declare function getDecoratedChannelHandlers<User = unknown>(instance: object): Record<string, DecoratedChannelHandler<User>>;
17
18
 
18
19
  export { getDecoratedChannelHandlers, onMessage };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getDecoratedChannelHandlers,
3
3
  onMessage
4
- } from "../chunk-SHH6U4CI.js";
4
+ } from "../chunk-G75J233Z.js";
5
5
  export {
6
6
  getDecoratedChannelHandlers,
7
7
  onMessage
@@ -1,10 +1,10 @@
1
1
  import { BaseCheck, Result } from '@adonisjs/core/health';
2
- import { S as SocketService } from '../socket_service-mybqv1hj.js';
2
+ import { S as SocketService } from '../socket_service-BYEB8LIN.js';
3
3
  import 'node:http';
4
4
  import '@adonisjs/logger';
5
5
  import 'emittery';
6
6
  import 'ws';
7
- import '../types-C7Q36ryo.js';
7
+ import '../base_channel-Dr40l7CW.js';
8
8
  import '@adonisjs/core/types/http';
9
9
  import '@adonisjs/core/http';
10
10
  import '@boringnode/bus/types/main';
@@ -1,6 +1,17 @@
1
- import {
2
- SocketHealthCheck
3
- } from "../chunk-HK7Z65DA.js";
1
+ // src/health_check.ts
2
+ import { BaseCheck, Result } from "@adonisjs/core/health";
3
+ var SocketHealthCheck = class extends BaseCheck {
4
+ constructor(socket) {
5
+ super();
6
+ this.socket = socket;
7
+ }
8
+ name = "Socket health check";
9
+ async run() {
10
+ const snapshot = this.socket.health();
11
+ const result = snapshot.ready ? Result.ok("Socket service is ready") : Result.failed(`Socket service is ${snapshot.status}`);
12
+ return result.setMetaData(snapshot);
13
+ }
14
+ };
4
15
  export {
5
16
  SocketHealthCheck
6
17
  };
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../../src/health_check.ts"],"sourcesContent":["import { BaseCheck, Result } from '@adonisjs/core/health'\nimport type { SocketService } from './socket_service.js'\n\nexport class SocketHealthCheck extends BaseCheck {\n name = 'Socket health check'\n\n constructor(private socket: SocketService) {\n super()\n }\n\n async run() {\n const snapshot = this.socket.health()\n const result = snapshot.ready\n ? Result.ok('Socket service is ready')\n : Result.failed(`Socket service is ${snapshot.status}`)\n\n return result.setMetaData(snapshot)\n }\n}\n"],"mappings":";AAAA,SAAS,WAAW,cAAc;AAG3B,IAAM,oBAAN,cAAgC,UAAU;AAAA,EAG/C,YAAoB,QAAuB;AACzC,UAAM;AADY;AAAA,EAEpB;AAAA,EAJA,OAAO;AAAA,EAMP,MAAM,MAAM;AACV,UAAM,WAAW,KAAK,OAAO,OAAO;AACpC,UAAM,SAAS,SAAS,QACpB,OAAO,GAAG,yBAAyB,IACnC,OAAO,OAAO,qBAAqB,SAAS,MAAM,EAAE;AAExD,WAAO,OAAO,YAAY,QAAQ;AAAA,EACpC;AACF;","names":[]}
package/build/src/otel.js CHANGED
@@ -264,7 +264,6 @@ var SocketInstrumentation = class extends InstrumentationBase {
264
264
  "socket.broadcast.via": message.via
265
265
  };
266
266
  if (message.channel) attributes["messaging.destination.name"] = message.channel;
267
- if (message.room) attributes["socket.user.room"] = message.room;
268
267
  if (message.except) attributes["socket.broadcast.except_count"] = message.except.length;
269
268
  return attributes;
270
269
  }