@triformine/nexis-sdk 0.1.0-next.6d96464

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client.ts"],"sourcesContent":["import {\n applyPatch,\n computeStateChecksum,\n parsePatchPayload,\n parseSnapshotPayload,\n} from \"./patch\";\nimport { JsonCodec, MsgpackCodec, codecFor, type Codec } from \"./codec\";\nimport { RpcClient, UnknownRidError } from \"./rpc\";\nimport type {\n ConnectOptions,\n Envelope,\n HandshakeRequest,\n MatchFound,\n MatchmakingDequeueResponse,\n MatchmakingQueueResponse,\n RoomListResponse,\n RoomMessagePayload,\n RoomMessageType,\n} from \"./types\";\n\nconst DEFAULT_VERSION = 1;\nconst DEFAULT_RECONNECT_INITIAL_DELAY_MS = 250;\nconst DEFAULT_RECONNECT_MAX_DELAY_MS = 3_000;\nconst DEFAULT_RECONNECT_MAX_ATTEMPTS = 20;\n\ntype EventHandler = (message: Envelope) => void;\ntype StateHandler = (state: Record<string, unknown>) => void;\ntype MatchFoundHandler = (match: MatchFound, message: Envelope) => void;\ntype RoomMessageHandler = (data: unknown, envelope: Envelope) => void;\ntype SelectorHandler = (value: unknown, state: Record<string, unknown>) => void;\ntype SupportedCodec = \"json\" | \"msgpack\";\n\ntype SelectorRegistration = {\n path: string;\n callback: SelectorHandler;\n lastValue: unknown;\n};\n\ntype ResolvedConnectOptions = ConnectOptions & {\n codecs: Array<\"msgpack\" | \"json\">;\n autoJoinMatchedRoom: boolean;\n autoReconnect: boolean;\n reconnectInitialDelayMs: number;\n reconnectMaxDelayMs: number;\n reconnectMaxAttempts: number;\n};\n\nexport type RoomStateChangeSubscription = {\n (callback: StateHandler): () => void;\n once(callback: StateHandler): () => void;\n select(path: string, callback: SelectorHandler): () => void;\n};\n\nfunction normalizeConnectOptions(\n options: ConnectOptions,\n): ResolvedConnectOptions {\n const reconnectInitialDelayMs = Math.max(\n 50,\n options.reconnectInitialDelayMs ?? DEFAULT_RECONNECT_INITIAL_DELAY_MS,\n );\n const reconnectMaxDelayMs = Math.max(\n reconnectInitialDelayMs,\n options.reconnectMaxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS,\n );\n const reconnectMaxAttempts = Math.max(\n 1,\n options.reconnectMaxAttempts ?? DEFAULT_RECONNECT_MAX_ATTEMPTS,\n );\n return {\n ...options,\n codecs: options.codecs ?? [\"msgpack\", \"json\"],\n autoJoinMatchedRoom: options.autoJoinMatchedRoom ?? false,\n autoReconnect: options.autoReconnect ?? true,\n reconnectInitialDelayMs,\n reconnectMaxDelayMs,\n reconnectMaxAttempts,\n };\n}\n\nfunction readCodecName(message: Envelope): SupportedCodec {\n const payload = message.p;\n if (\n payload &&\n typeof payload === \"object\" &&\n \"codec\" in payload &&\n (payload as { codec?: unknown }).codec === \"msgpack\"\n ) {\n return \"msgpack\";\n }\n return \"json\";\n}\n\nfunction readSessionId(message: Envelope): string | undefined {\n const payload = message.p;\n if (\n payload &&\n typeof payload === \"object\" &&\n \"session_id\" in payload &&\n typeof (payload as { session_id?: unknown }).session_id === \"string\"\n ) {\n return (payload as { session_id: string }).session_id;\n }\n return undefined;\n}\n\nfunction readErrorReason(message: Envelope): string {\n const payload = message.p;\n if (\n payload &&\n typeof payload === \"object\" &&\n \"reason\" in payload &&\n typeof (payload as { reason?: unknown }).reason === \"string\"\n ) {\n return (payload as { reason: string }).reason;\n }\n return \"server returned error\";\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n return (\n Array.isArray(value) && value.every((item) => typeof item === \"string\")\n );\n}\n\nfunction deepEqual(left: unknown, right: unknown): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\nfunction toJsonValue(bytes: Uint8Array): string {\n let binary = \"\";\n for (const value of bytes) {\n binary += String.fromCharCode(value);\n }\n return btoa(binary);\n}\n\nfunction fromJsonValue(value: unknown): Uint8Array | null {\n if (typeof value !== \"string\") {\n return null;\n }\n\n try {\n const decoded = atob(value);\n const bytes = new Uint8Array(decoded.length);\n for (let i = 0; i < decoded.length; i += 1) {\n bytes[i] = decoded.charCodeAt(i);\n }\n return bytes;\n } catch {\n return null;\n }\n}\n\nfunction readRoomMessagePayload(payload: unknown): RoomMessagePayload | null {\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n const type = (payload as { type?: unknown }).type;\n if (typeof type !== \"string\" && typeof type !== \"number\") {\n return null;\n }\n const data = (payload as { data?: unknown }).data;\n return { type, data };\n}\n\nexport function parseMatchFoundPayload(payload: unknown): MatchFound | null {\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n\n const room = (payload as { room?: unknown }).room;\n const roomType = (payload as { room_type?: unknown }).room_type;\n const size = (payload as { size?: unknown }).size;\n const participants = (payload as { participants?: unknown }).participants;\n if (\n typeof room !== \"string\" ||\n typeof roomType !== \"string\" ||\n typeof size !== \"number\" ||\n !Number.isFinite(size) ||\n !isStringArray(participants)\n ) {\n return null;\n }\n\n return {\n room,\n roomType,\n size,\n participants,\n };\n}\n\nexport class NexisRoom {\n readonly id: string;\n readonly onStateChange: RoomStateChangeSubscription;\n\n constructor(\n private readonly client: NexisClient,\n roomId: string,\n ) {\n this.id = roomId;\n this.onStateChange = this.buildStateChangeSubscription();\n }\n\n get state(): Record<string, unknown> {\n return this.client.getRoomState(this.id);\n }\n\n send(type: RoomMessageType, message: unknown): void {\n this.client.sendRoomMessage(this.id, type, message);\n }\n\n sendBytes(type: RoomMessageType, bytes: Uint8Array | number[]): void {\n const normalized =\n bytes instanceof Uint8Array ? bytes : Uint8Array.from(bytes);\n this.client.sendRoomMessageBytes(this.id, type, normalized);\n }\n\n onMessage(type: RoomMessageType, callback: RoomMessageHandler): () => void {\n return this.client.onRoomMessage(this.id, type, callback);\n }\n\n private buildStateChangeSubscription(): RoomStateChangeSubscription {\n const subscribe = (callback: StateHandler): (() => void) =>\n this.client.onRoomState(this.id, callback);\n\n subscribe.once = (callback: StateHandler): (() => void) =>\n this.client.onRoomStateOnce(this.id, callback);\n\n subscribe.select = (\n path: string,\n callback: SelectorHandler,\n ): (() => void) => this.client.onRoomStateSelect(this.id, path, callback);\n\n return subscribe;\n }\n}\n\nexport class NexisClient {\n private socket: WebSocket;\n private readonly url: string;\n private readonly connectOptions: ResolvedConnectOptions;\n private readonly rpc = new RpcClient();\n private codec: Codec;\n private readonly eventHandlers = new Map<string, Set<EventHandler>>();\n private readonly stateHandlers = new Set<StateHandler>();\n private readonly roomStateHandlers = new Map<string, Set<StateHandler>>();\n private readonly roomStateSelectors = new Map<\n string,\n Set<SelectorRegistration>\n >();\n private readonly roomMessageHandlers = new Map<\n string,\n Map<string, Set<RoomMessageHandler>>\n >();\n private readonly roomStates = new Map<string, Record<string, unknown>>();\n private readonly roomSeq = new Map<string, number>();\n private readonly roomChecksum = new Map<string, string>();\n private sessionId: string | undefined;\n private readonly autoJoinMatchedRoom: boolean;\n private reconnecting = false;\n private disposed = false;\n\n private constructor(\n url: string,\n socket: WebSocket,\n codec: Codec,\n sessionId: string | undefined,\n options: ResolvedConnectOptions,\n ) {\n this.url = url;\n this.socket = socket;\n this.codec = codec;\n this.sessionId = sessionId;\n this.connectOptions = options;\n this.autoJoinMatchedRoom = options.autoJoinMatchedRoom;\n this.attachSocket(socket);\n }\n\n static connect(url: string, options: ConnectOptions): Promise<NexisClient> {\n const resolved = normalizeConnectOptions(options);\n return NexisClient.openSocketAndHandshake(\n url,\n resolved,\n resolved.sessionId,\n ).then(\n ({ socket, codec, sessionId }) =>\n new NexisClient(url, socket, codec, sessionId, resolved),\n );\n }\n\n close(): void {\n this.disposed = true;\n this.socket.close();\n }\n\n private attachSocket(socket: WebSocket): void {\n this.socket = socket;\n this.socket.addEventListener(\"message\", (event) => {\n void this.onRawMessage(event.data);\n });\n this.socket.addEventListener(\"close\", () => {\n this.rpc.rejectAll(new Error(\"socket closed\"));\n if (!this.disposed && this.connectOptions.autoReconnect) {\n void this.tryReconnect();\n }\n });\n }\n\n private async tryReconnect(): Promise<void> {\n if (this.reconnecting || this.disposed) {\n return;\n }\n this.reconnecting = true;\n this.dispatchEvent({\n v: DEFAULT_VERSION,\n t: \"reconnect.start\",\n p: { session_id: this.sessionId },\n });\n\n let attempt = 0;\n let delayMs = this.connectOptions.reconnectInitialDelayMs;\n while (\n !this.disposed &&\n attempt < this.connectOptions.reconnectMaxAttempts\n ) {\n attempt += 1;\n await NexisClient.wait(delayMs);\n try {\n const reconnect = await NexisClient.openSocketAndHandshake(\n this.url,\n this.connectOptions,\n this.sessionId,\n );\n this.codec = reconnect.codec;\n this.sessionId = reconnect.sessionId ?? this.sessionId;\n this.attachSocket(reconnect.socket);\n this.dispatchEvent({\n v: DEFAULT_VERSION,\n t: \"reconnect.ok\",\n p: { attempt, session_id: this.sessionId },\n });\n this.reconnecting = false;\n return;\n } catch {\n this.dispatchEvent({\n v: DEFAULT_VERSION,\n t: \"reconnect.retry\",\n p: { attempt },\n });\n }\n delayMs = Math.min(delayMs * 2, this.connectOptions.reconnectMaxDelayMs);\n }\n\n this.reconnecting = false;\n this.dispatchEvent({\n v: DEFAULT_VERSION,\n t: \"reconnect.failed\",\n p: { session_id: this.sessionId },\n });\n }\n\n getSessionId(): string | undefined {\n return this.sessionId;\n }\n\n room(roomId: string): NexisRoom {\n return new NexisRoom(this, roomId);\n }\n\n async joinOrCreate(\n roomType: string,\n options?: { roomId?: string } & Record<string, unknown>,\n ): Promise<NexisRoom> {\n const roomId =\n typeof options?.roomId === \"string\" ? options.roomId : undefined;\n const response = await this.sendRPC(\n \"room.join_or_create\",\n {\n roomType,\n roomId,\n options,\n },\n roomId,\n );\n if (\n response &&\n typeof response === \"object\" &&\n typeof (response as { room?: unknown }).room === \"string\"\n ) {\n return this.room((response as { room: string }).room);\n }\n if (roomId) {\n return this.room(roomId);\n }\n return this.room(`${roomType}:default`);\n }\n\n listRooms(roomType?: string): Promise<RoomListResponse> {\n return this.sendRPC(\n \"room.list\",\n roomType ? { roomType } : {},\n ) as Promise<RoomListResponse>;\n }\n\n enqueueMatchmaking(\n roomType: string,\n size = 2,\n ): Promise<MatchmakingQueueResponse> {\n return this.sendRPC(\"matchmaking.enqueue\", {\n roomType,\n size,\n }) as Promise<MatchmakingQueueResponse>;\n }\n\n dequeueMatchmaking(): Promise<MatchmakingDequeueResponse> {\n return this.sendRPC(\n \"matchmaking.dequeue\",\n {},\n ) as Promise<MatchmakingDequeueResponse>;\n }\n\n onStateChange(callback: StateHandler): () => void {\n this.stateHandlers.add(callback);\n return () => this.stateHandlers.delete(callback);\n }\n\n onEvent(type: string, callback: EventHandler): () => void {\n const handlers = this.eventHandlers.get(type) ?? new Set<EventHandler>();\n handlers.add(callback);\n this.eventHandlers.set(type, handlers);\n return () => {\n const current = this.eventHandlers.get(type);\n if (!current) {\n return;\n }\n current.delete(callback);\n if (current.size === 0) {\n this.eventHandlers.delete(type);\n }\n };\n }\n\n onMatchFound(callback: MatchFoundHandler): () => void {\n return this.onEvent(\"match.found\", (message) => {\n const parsed = parseMatchFoundPayload(message.p);\n if (!parsed) {\n return;\n }\n callback(parsed, message);\n });\n }\n\n sendRPC(type: string, payload: unknown, room?: string): Promise<unknown> {\n const { message, promise } = this.rpc.createRequest(type, payload, room);\n this.sendEnvelope(message);\n return promise;\n }\n\n getRoomState(roomId: string): Record<string, unknown> {\n return this.roomStates.get(roomId) ?? {};\n }\n\n sendRoomMessage(roomId: string, type: RoomMessageType, data: unknown): void {\n this.sendEnvelope({\n v: DEFAULT_VERSION,\n t: \"room.message\",\n room: roomId,\n p: { type: String(type), data },\n });\n }\n\n sendRoomMessageBytes(\n roomId: string,\n type: RoomMessageType,\n data: Uint8Array,\n ): void {\n this.sendEnvelope({\n v: DEFAULT_VERSION,\n t: \"room.message.bytes\",\n room: roomId,\n p: { type: String(type), data_b64: toJsonValue(data) },\n });\n }\n\n onRoomMessage(\n roomId: string,\n type: RoomMessageType,\n callback: RoomMessageHandler,\n ): () => void {\n const key = String(type);\n const byType = this.roomMessageHandlers.get(roomId) ?? new Map();\n const handlers = byType.get(key) ?? new Set<RoomMessageHandler>();\n handlers.add(callback);\n byType.set(key, handlers);\n this.roomMessageHandlers.set(roomId, byType);\n\n return () => {\n const roomHandlers = this.roomMessageHandlers.get(roomId);\n if (!roomHandlers) {\n return;\n }\n const typeHandlers = roomHandlers.get(key);\n if (!typeHandlers) {\n return;\n }\n typeHandlers.delete(callback);\n if (typeHandlers.size === 0) {\n roomHandlers.delete(key);\n }\n if (roomHandlers.size === 0) {\n this.roomMessageHandlers.delete(roomId);\n }\n };\n }\n\n onRoomState(roomId: string, callback: StateHandler): () => void {\n const handlers =\n this.roomStateHandlers.get(roomId) ?? new Set<StateHandler>();\n handlers.add(callback);\n this.roomStateHandlers.set(roomId, handlers);\n if (this.roomStates.has(roomId)) {\n callback(this.roomStates.get(roomId) ?? {});\n }\n return () => {\n const current = this.roomStateHandlers.get(roomId);\n if (!current) {\n return;\n }\n current.delete(callback);\n if (current.size === 0) {\n this.roomStateHandlers.delete(roomId);\n }\n };\n }\n\n onRoomStateOnce(roomId: string, callback: StateHandler): () => void {\n let disposed = false;\n const off = this.onRoomState(roomId, (state) => {\n if (disposed) {\n return;\n }\n disposed = true;\n off();\n callback(state);\n });\n return () => {\n disposed = true;\n off();\n };\n }\n\n onRoomStateSelect(\n roomId: string,\n path: string,\n callback: SelectorHandler,\n ): () => void {\n const normalizedPath = path.startsWith(\"/\") ? path.slice(1) : path;\n const currentState = this.getRoomState(roomId);\n const registration: SelectorRegistration = {\n path: normalizedPath,\n callback,\n lastValue: currentState[normalizedPath],\n };\n const selectors = this.roomStateSelectors.get(roomId) ?? new Set();\n selectors.add(registration);\n this.roomStateSelectors.set(roomId, selectors);\n\n return () => {\n const current = this.roomStateSelectors.get(roomId);\n if (!current) {\n return;\n }\n current.delete(registration);\n if (current.size === 0) {\n this.roomStateSelectors.delete(roomId);\n }\n };\n }\n\n private sendEnvelope(message: Envelope): void {\n const bytes = this.codec.encode(message);\n this.socket.send(bytes);\n }\n\n private dispatchEvent(message: Envelope): void {\n const handlers = this.eventHandlers.get(message.t);\n if (!handlers) {\n return;\n }\n\n for (const handler of handlers) {\n handler(message);\n }\n }\n\n private dispatchState(\n roomId: string,\n nextState: Record<string, unknown>,\n prevState: Record<string, unknown>,\n ): void {\n for (const handler of this.stateHandlers) {\n handler(nextState);\n }\n\n const roomHandlers = this.roomStateHandlers.get(roomId);\n if (roomHandlers) {\n for (const handler of roomHandlers) {\n handler(nextState);\n }\n }\n\n const selectors = this.roomStateSelectors.get(roomId);\n if (selectors) {\n for (const registration of selectors) {\n const nextValue = nextState[registration.path];\n const prevValue = prevState[registration.path];\n if (!deepEqual(nextValue, prevValue)) {\n registration.lastValue = nextValue;\n registration.callback(nextValue, nextState);\n }\n }\n }\n }\n\n private dispatchRoomMessage(message: Envelope): void {\n if (!message.room) {\n return;\n }\n\n const payload = readRoomMessagePayload(message.p);\n if (!payload) {\n return;\n }\n\n const byType = this.roomMessageHandlers.get(message.room);\n if (!byType) {\n return;\n }\n\n const handlers = byType.get(String(payload.type));\n if (!handlers) {\n return;\n }\n for (const handler of handlers) {\n handler(payload.data, message);\n }\n }\n\n private async onRawMessage(raw: unknown): Promise<void> {\n const bytes = await NexisClient.toBytes(raw);\n if (!bytes) {\n return;\n }\n\n let message: Envelope;\n try {\n message = this.codec.decode(bytes);\n } catch {\n return;\n }\n\n if (message.t === \"rpc.response\") {\n try {\n this.rpc.resolveResponse(message);\n } catch (error) {\n if (error instanceof UnknownRidError) {\n this.dispatchEvent({\n v: DEFAULT_VERSION,\n t: \"error\",\n p: { reason: error.message },\n });\n return;\n }\n throw error;\n }\n return;\n }\n\n if (message.t === \"state.snapshot\") {\n if (!message.room) {\n return;\n }\n const snapshot = parseSnapshotPayload(message.p);\n if (!snapshot) {\n return;\n }\n const computedChecksum = await computeStateChecksum(snapshot.state);\n if (snapshot.checksum && snapshot.checksum !== computedChecksum) {\n this.sendEnvelope({\n v: DEFAULT_VERSION,\n t: \"state.resync\",\n room: message.room,\n p: { since: this.roomSeq.get(message.room) ?? 0 },\n });\n return;\n }\n const checksum = snapshot.checksum ?? computedChecksum;\n\n const prevState = this.roomStates.get(message.room) ?? {};\n this.roomStates.set(message.room, snapshot.state);\n this.roomSeq.set(message.room, snapshot.seq);\n this.roomChecksum.set(message.room, checksum);\n this.dispatchState(message.room, snapshot.state, prevState);\n this.sendEnvelope({\n v: DEFAULT_VERSION,\n t: \"state.ack\",\n room: message.room,\n p: { seq: snapshot.seq, checksum },\n });\n return;\n }\n\n if (message.t === \"state.patch\") {\n if (!message.room) {\n return;\n }\n const parsedPatch = parsePatchPayload(message.p);\n if (!parsedPatch) {\n return;\n }\n\n const currentSeq = this.roomSeq.get(message.room) ?? 0;\n const patchSeq = parsedPatch.seq > 0 ? parsedPatch.seq : currentSeq + 1;\n\n if (patchSeq <= currentSeq) {\n return;\n }\n\n if (patchSeq > currentSeq + 1) {\n this.sendEnvelope({\n v: DEFAULT_VERSION,\n t: \"state.resync\",\n room: message.room,\n p: { since: currentSeq },\n });\n return;\n }\n\n const currentState = this.roomStates.get(message.room) ?? {};\n const nextState = applyPatch(currentState, parsedPatch.ops);\n let localChecksum: string | undefined;\n if (parsedPatch.checksum) {\n localChecksum = await computeStateChecksum(nextState);\n if (parsedPatch.checksum !== localChecksum) {\n this.sendEnvelope({\n v: DEFAULT_VERSION,\n t: \"state.resync\",\n room: message.room,\n p: {\n since: currentSeq,\n checksum: this.roomChecksum.get(message.room),\n },\n });\n return;\n }\n }\n\n this.roomStates.set(message.room, nextState);\n this.roomSeq.set(message.room, patchSeq);\n if (parsedPatch.checksum) {\n this.roomChecksum.set(message.room, parsedPatch.checksum);\n } else if (localChecksum) {\n this.roomChecksum.set(message.room, localChecksum);\n }\n this.dispatchState(message.room, nextState, currentState);\n this.sendEnvelope({\n v: DEFAULT_VERSION,\n t: \"state.ack\",\n room: message.room,\n p: parsedPatch.checksum\n ? { seq: patchSeq, checksum: this.roomChecksum.get(message.room) }\n : { seq: patchSeq },\n });\n return;\n }\n\n if (this.autoJoinMatchedRoom && message.t === \"match.found\") {\n const parsed = parseMatchFoundPayload(message.p);\n if (parsed) {\n void this.joinOrCreate(parsed.roomType, { roomId: parsed.room }).catch(\n () => undefined,\n );\n }\n }\n\n if (message.t === \"room.message\" && message.room) {\n this.dispatchRoomMessage(message);\n }\n\n this.dispatchEvent(message);\n }\n\n private static openSocketAndHandshake(\n url: string,\n options: ResolvedConnectOptions,\n sessionIdOverride?: string,\n ): Promise<{\n socket: WebSocket;\n codec: Codec;\n sessionId: string | undefined;\n }> {\n const socket = new WebSocket(url);\n const jsonCodec = new JsonCodec();\n const msgpackCodec = new MsgpackCodec();\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const handshakeSessionId = sessionIdOverride ?? options.sessionId;\n\n const onOpen = () => {\n const handshake: HandshakeRequest = {\n v: DEFAULT_VERSION,\n codecs: options.codecs,\n project_id: options.projectId?.trim() || \"anonymous\",\n token: options.token?.trim() || \"\",\n session_id: handshakeSessionId,\n };\n socket.send(JSON.stringify(handshake));\n };\n\n const onError = () => {\n finishReject(new Error(\"socket connection failed\"));\n };\n\n const onClose = () => {\n finishReject(new Error(\"socket closed before handshake\"));\n };\n\n const onMessage = async (event: MessageEvent) => {\n try {\n const message = await NexisClient.decodeHandshakeMessage(\n event.data,\n jsonCodec,\n msgpackCodec,\n );\n if (!message) {\n return;\n }\n\n if (message.t === \"error\") {\n finishReject(new Error(readErrorReason(message)));\n return;\n }\n\n if (message.t !== \"handshake.ok\") {\n return;\n }\n\n const negotiatedCodec = readCodecName(message);\n const sessionId = readSessionId(message) ?? handshakeSessionId;\n finishResolve({\n socket,\n codec: codecFor(negotiatedCodec),\n sessionId,\n });\n } catch (error) {\n finishReject(new Error(`handshake decode failed: ${String(error)}`));\n }\n };\n\n const cleanup = () => {\n socket.removeEventListener(\"open\", onOpen);\n socket.removeEventListener(\"error\", onError);\n socket.removeEventListener(\"close\", onClose);\n socket.removeEventListener(\"message\", onMessage);\n };\n\n const finishResolve = (result: {\n socket: WebSocket;\n codec: Codec;\n sessionId: string | undefined;\n }) => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n resolve(result);\n };\n\n const finishReject = (error: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n reject(error);\n };\n\n socket.addEventListener(\"open\", onOpen);\n socket.addEventListener(\"error\", onError);\n socket.addEventListener(\"close\", onClose);\n socket.addEventListener(\"message\", onMessage);\n });\n }\n\n private static wait(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private static async decodeHandshakeMessage(\n raw: unknown,\n jsonCodec: JsonCodec,\n msgpackCodec: MsgpackCodec,\n ): Promise<Envelope | null> {\n if (typeof raw === \"string\") {\n return JSON.parse(raw) as Envelope;\n }\n\n const bytes = await NexisClient.toBytes(raw);\n if (!bytes) {\n return null;\n }\n\n try {\n return msgpackCodec.decode(bytes);\n } catch {\n return jsonCodec.decode(bytes);\n }\n }\n\n private static async toBytes(raw: unknown): Promise<Uint8Array | null> {\n if (raw instanceof Uint8Array) {\n return raw;\n }\n if (raw instanceof ArrayBuffer) {\n return new Uint8Array(raw);\n }\n if (raw instanceof Blob) {\n return new Uint8Array(await raw.arrayBuffer());\n }\n if (typeof raw === \"string\") {\n return new TextEncoder().encode(raw);\n }\n return null;\n }\n}\n\nexport async function connect(\n url: string,\n options: ConnectOptions,\n): Promise<NexisClient> {\n return NexisClient.connect(url, options);\n}\n\nexport function decodeRoomBytes(payload: unknown): Uint8Array | null {\n return fromJsonValue(payload);\n}\n"],"names":["NexisClient","NexisRoom","connect","decodeRoomBytes","parseMatchFoundPayload","DEFAULT_VERSION","DEFAULT_RECONNECT_INITIAL_DELAY_MS","DEFAULT_RECONNECT_MAX_DELAY_MS","DEFAULT_RECONNECT_MAX_ATTEMPTS","normalizeConnectOptions","options","reconnectInitialDelayMs","Math","max","reconnectMaxDelayMs","reconnectMaxAttempts","codecs","autoJoinMatchedRoom","autoReconnect","readCodecName","message","payload","p","codec","readSessionId","session_id","undefined","readErrorReason","reason","isStringArray","value","Array","isArray","every","item","deepEqual","left","right","JSON","stringify","toJsonValue","bytes","binary","String","fromCharCode","btoa","fromJsonValue","decoded","atob","Uint8Array","length","i","charCodeAt","readRoomMessagePayload","type","data","room","roomType","room_type","size","participants","Number","isFinite","id","onStateChange","constructor","client","roomId","buildStateChangeSubscription","state","getRoomState","send","sendRoomMessage","sendBytes","normalized","from","sendRoomMessageBytes","onMessage","callback","onRoomMessage","subscribe","onRoomState","once","onRoomStateOnce","select","path","onRoomStateSelect","socket","url","connectOptions","rpc","RpcClient","eventHandlers","Map","stateHandlers","Set","roomStateHandlers","roomStateSelectors","roomMessageHandlers","roomStates","roomSeq","roomChecksum","sessionId","reconnecting","disposed","attachSocket","resolved","openSocketAndHandshake","then","close","addEventListener","event","onRawMessage","rejectAll","Error","tryReconnect","dispatchEvent","v","t","attempt","delayMs","wait","reconnect","min","getSessionId","joinOrCreate","response","sendRPC","listRooms","enqueueMatchmaking","dequeueMatchmaking","add","delete","onEvent","handlers","get","set","current","onMatchFound","parsed","promise","createRequest","sendEnvelope","data_b64","key","byType","roomHandlers","typeHandlers","has","off","normalizedPath","startsWith","slice","currentState","registration","lastValue","selectors","encode","handler","dispatchState","nextState","prevState","nextValue","prevValue","dispatchRoomMessage","raw","toBytes","decode","resolveResponse","error","UnknownRidError","snapshot","parseSnapshotPayload","computedChecksum","computeStateChecksum","checksum","since","seq","parsedPatch","parsePatchPayload","currentSeq","patchSeq","applyPatch","ops","localChecksum","catch","sessionIdOverride","WebSocket","jsonCodec","JsonCodec","msgpackCodec","MsgpackCodec","Promise","resolve","reject","settled","handshakeSessionId","onOpen","handshake","project_id","projectId","trim","token","onError","finishReject","onClose","decodeHandshakeMessage","negotiatedCodec","finishResolve","codecFor","cleanup","removeEventListener","result","ms","setTimeout","parse","ArrayBuffer","Blob","arrayBuffer","TextEncoder"],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ JsonCodec: function() {
13
+ return JsonCodec;
14
+ },
15
+ MsgpackCodec: function() {
16
+ return MsgpackCodec;
17
+ },
18
+ codecFor: function() {
19
+ return codecFor;
20
+ }
21
+ });
22
+ const _msgpackr = require("msgpackr");
23
+ class JsonCodec {
24
+ name = "json";
25
+ encode(message) {
26
+ return new TextEncoder().encode(JSON.stringify(message));
27
+ }
28
+ decode(bytes) {
29
+ const text = new TextDecoder().decode(bytes);
30
+ const parsed = JSON.parse(text);
31
+ return parsed;
32
+ }
33
+ }
34
+ class MsgpackCodec {
35
+ name = "msgpack";
36
+ packr = new _msgpackr.Packr({
37
+ useRecords: false,
38
+ structuredClone: false,
39
+ bundleStrings: false,
40
+ maxSharedStructures: 0
41
+ });
42
+ unpackr = new _msgpackr.Unpackr({
43
+ useRecords: false
44
+ });
45
+ encode(message) {
46
+ return this.packr.pack(message);
47
+ }
48
+ decode(bytes) {
49
+ const decoded = this.unpackr.unpack(bytes);
50
+ return decoded;
51
+ }
52
+ }
53
+ function codecFor(name) {
54
+ return name === "msgpack" ? new MsgpackCodec() : new JsonCodec();
55
+ }
56
+
57
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/codec.ts"],"sourcesContent":["import { Packr, Unpackr } from \"msgpackr\";\nimport type { Envelope } from \"./types\";\n\nexport interface Codec {\n readonly name: \"json\" | \"msgpack\";\n encode(message: Envelope): Uint8Array;\n decode(bytes: Uint8Array): Envelope;\n}\n\nexport class JsonCodec implements Codec {\n readonly name = \"json\" as const;\n\n encode(message: Envelope): Uint8Array {\n return new TextEncoder().encode(JSON.stringify(message));\n }\n\n decode(bytes: Uint8Array): Envelope {\n const text = new TextDecoder().decode(bytes);\n const parsed = JSON.parse(text);\n return parsed as Envelope;\n }\n}\n\nexport class MsgpackCodec implements Codec {\n readonly name = \"msgpack\" as const;\n private readonly packr = new Packr({\n useRecords: false,\n structuredClone: false,\n bundleStrings: false,\n maxSharedStructures: 0,\n });\n private readonly unpackr = new Unpackr({\n useRecords: false,\n });\n\n encode(message: Envelope): Uint8Array {\n return this.packr.pack(message);\n }\n\n decode(bytes: Uint8Array): Envelope {\n const decoded = this.unpackr.unpack(bytes);\n return decoded as Envelope;\n }\n}\n\nexport function codecFor(name: \"json\" | \"msgpack\"): Codec {\n return name === \"msgpack\" ? new MsgpackCodec() : new JsonCodec();\n}\n"],"names":["JsonCodec","MsgpackCodec","codecFor","name","encode","message","TextEncoder","JSON","stringify","decode","bytes","text","TextDecoder","parsed","parse","packr","Packr","useRecords","structuredClone","bundleStrings","maxSharedStructures","unpackr","Unpackr","pack","decoded","unpack"],"mappings":";;;;;;;;;;;IASaA,SAAS;eAATA;;IAcAC,YAAY;eAAZA;;IAsBGC,QAAQ;eAARA;;;0BA7Ce;AASxB,MAAMF;IACFG,OAAO,OAAgB;IAEhCC,OAAOC,OAAiB,EAAc;QACpC,OAAO,IAAIC,cAAcF,MAAM,CAACG,KAAKC,SAAS,CAACH;IACjD;IAEAI,OAAOC,KAAiB,EAAY;QAClC,MAAMC,OAAO,IAAIC,cAAcH,MAAM,CAACC;QACtC,MAAMG,SAASN,KAAKO,KAAK,CAACH;QAC1B,OAAOE;IACT;AACF;AAEO,MAAMZ;IACFE,OAAO,UAAmB;IAClBY,QAAQ,IAAIC,eAAK,CAAC;QACjCC,YAAY;QACZC,iBAAiB;QACjBC,eAAe;QACfC,qBAAqB;IACvB,GAAG;IACcC,UAAU,IAAIC,iBAAO,CAAC;QACrCL,YAAY;IACd,GAAG;IAEHb,OAAOC,OAAiB,EAAc;QACpC,OAAO,IAAI,CAACU,KAAK,CAACQ,IAAI,CAAClB;IACzB;IAEAI,OAAOC,KAAiB,EAAY;QAClC,MAAMc,UAAU,IAAI,CAACH,OAAO,CAACI,MAAM,CAACf;QACpC,OAAOc;IACT;AACF;AAEO,SAAStB,SAASC,IAAwB;IAC/C,OAAOA,SAAS,YAAY,IAAIF,iBAAiB,IAAID;AACvD"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./types"), exports);
6
+ _export_star(require("./codec"), exports);
7
+ _export_star(require("./patch"), exports);
8
+ _export_star(require("./rpc"), exports);
9
+ _export_star(require("./client"), exports);
10
+ function _export_star(from, to) {
11
+ Object.keys(from).forEach(function(k) {
12
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
13
+ Object.defineProperty(to, k, {
14
+ enumerable: true,
15
+ get: function() {
16
+ return from[k];
17
+ }
18
+ });
19
+ }
20
+ });
21
+ return from;
22
+ }
23
+
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export * from \"./types\";\nexport * from \"./codec\";\nexport * from \"./patch\";\nexport * from \"./rpc\";\nexport * from \"./client\";\n"],"names":[],"mappings":";;;;qBAAc;qBACA;qBACA;qBACA;qBACA"}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ applyPatch: function() {
13
+ return applyPatch;
14
+ },
15
+ computeStateChecksum: function() {
16
+ return computeStateChecksum;
17
+ },
18
+ parsePatchPayload: function() {
19
+ return parsePatchPayload;
20
+ },
21
+ parseSnapshotPayload: function() {
22
+ return parseSnapshotPayload;
23
+ }
24
+ });
25
+ function keyFromPath(path) {
26
+ if (!path.startsWith("/")) {
27
+ throw new Error(`Invalid patch path: ${path}`);
28
+ }
29
+ const key = path.slice(1);
30
+ if (!key || key.includes("/")) {
31
+ throw new Error(`Invalid patch path: ${path}`);
32
+ }
33
+ return key.replace(/~1/g, "/").replace(/~0/g, "~");
34
+ }
35
+ function applyPatch(state, patch) {
36
+ const next = {
37
+ ...state
38
+ };
39
+ for (const op of patch){
40
+ const key = keyFromPath(op.path);
41
+ if (op.op === "set") {
42
+ next[key] = op.value;
43
+ continue;
44
+ }
45
+ delete next[key];
46
+ }
47
+ return next;
48
+ }
49
+ function canonicalize(value) {
50
+ if (Array.isArray(value)) {
51
+ return value.map((item)=>canonicalize(item));
52
+ }
53
+ if (value && typeof value === "object") {
54
+ const sortedEntries = Object.entries(value).sort(([left], [right])=>left.localeCompare(right));
55
+ const normalized = {};
56
+ for (const [key, item] of sortedEntries){
57
+ normalized[key] = canonicalize(item);
58
+ }
59
+ return normalized;
60
+ }
61
+ return value;
62
+ }
63
+ async function computeStateChecksum(state) {
64
+ const cryptoApi = globalThis.crypto?.subtle;
65
+ if (!cryptoApi) {
66
+ throw new Error("crypto.subtle is unavailable");
67
+ }
68
+ const canonicalJson = JSON.stringify(canonicalize(state));
69
+ const bytes = new TextEncoder().encode(canonicalJson);
70
+ const digest = await cryptoApi.digest("SHA-256", bytes);
71
+ const hashBytes = new Uint8Array(digest);
72
+ return Array.from(hashBytes).map((value)=>value.toString(16).padStart(2, "0")).join("");
73
+ }
74
+ function parsePatchPayload(payload) {
75
+ if (Array.isArray(payload)) {
76
+ return {
77
+ seq: 0,
78
+ checksum: undefined,
79
+ ops: payload
80
+ };
81
+ }
82
+ if (!payload || typeof payload !== "object") {
83
+ return null;
84
+ }
85
+ const candidate = payload;
86
+ if (typeof candidate.seq !== "number" || !Array.isArray(candidate.ops) || candidate.checksum !== undefined && typeof candidate.checksum !== "string") {
87
+ return null;
88
+ }
89
+ return {
90
+ seq: candidate.seq,
91
+ checksum: candidate.checksum,
92
+ ops: candidate.ops
93
+ };
94
+ }
95
+ function parseSnapshotPayload(payload) {
96
+ if (!payload || typeof payload !== "object") {
97
+ return null;
98
+ }
99
+ const candidate = payload;
100
+ if (typeof candidate.seq !== "number" || candidate.checksum !== undefined && typeof candidate.checksum !== "string" || !candidate.state || typeof candidate.state !== "object" || Array.isArray(candidate.state)) {
101
+ return null;
102
+ }
103
+ return {
104
+ seq: candidate.seq,
105
+ checksum: candidate.checksum,
106
+ state: candidate.state
107
+ };
108
+ }
109
+
110
+ //# sourceMappingURL=patch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/patch.ts"],"sourcesContent":["import type { PatchOp, StatePatchPayload, StateSnapshotPayload } from \"./types\";\n\nfunction keyFromPath(path: string): string {\n if (!path.startsWith(\"/\")) {\n throw new Error(`Invalid patch path: ${path}`);\n }\n const key = path.slice(1);\n if (!key || key.includes(\"/\")) {\n throw new Error(`Invalid patch path: ${path}`);\n }\n return key.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\n\nexport function applyPatch<T extends Record<string, unknown>>(\n state: T,\n patch: PatchOp[],\n): T {\n const next: Record<string, unknown> = { ...state };\n\n for (const op of patch) {\n const key = keyFromPath(op.path);\n if (op.op === \"set\") {\n next[key] = op.value;\n continue;\n }\n delete next[key];\n }\n\n return next as T;\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => canonicalize(item));\n }\n\n if (value && typeof value === \"object\") {\n const sortedEntries = Object.entries(value as Record<string, unknown>).sort(\n ([left], [right]) => left.localeCompare(right),\n );\n const normalized: Record<string, unknown> = {};\n for (const [key, item] of sortedEntries) {\n normalized[key] = canonicalize(item);\n }\n return normalized;\n }\n\n return value;\n}\n\nexport async function computeStateChecksum(state: unknown): Promise<string> {\n const cryptoApi = globalThis.crypto?.subtle;\n if (!cryptoApi) {\n throw new Error(\"crypto.subtle is unavailable\");\n }\n\n const canonicalJson = JSON.stringify(canonicalize(state));\n const bytes = new TextEncoder().encode(canonicalJson);\n const digest = await cryptoApi.digest(\"SHA-256\", bytes);\n const hashBytes = new Uint8Array(digest);\n\n return Array.from(hashBytes)\n .map((value) => value.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nexport function parsePatchPayload(payload: unknown): StatePatchPayload | null {\n if (Array.isArray(payload)) {\n return {\n seq: 0,\n checksum: undefined,\n ops: payload as PatchOp[],\n };\n }\n\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n\n const candidate = payload as {\n seq?: unknown;\n checksum?: unknown;\n ops?: unknown;\n };\n if (\n typeof candidate.seq !== \"number\" ||\n !Array.isArray(candidate.ops) ||\n (candidate.checksum !== undefined && typeof candidate.checksum !== \"string\")\n ) {\n return null;\n }\n\n return {\n seq: candidate.seq,\n checksum: candidate.checksum as string | undefined,\n ops: candidate.ops as PatchOp[],\n };\n}\n\nexport function parseSnapshotPayload(\n payload: unknown,\n): StateSnapshotPayload | null {\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n\n const candidate = payload as {\n seq?: unknown;\n checksum?: unknown;\n state?: unknown;\n };\n if (\n typeof candidate.seq !== \"number\" ||\n (candidate.checksum !== undefined &&\n typeof candidate.checksum !== \"string\") ||\n !candidate.state ||\n typeof candidate.state !== \"object\" ||\n Array.isArray(candidate.state)\n ) {\n return null;\n }\n\n return {\n seq: candidate.seq,\n checksum: candidate.checksum as string | undefined,\n state: candidate.state as Record<string, unknown>,\n };\n}\n"],"names":["applyPatch","computeStateChecksum","parsePatchPayload","parseSnapshotPayload","keyFromPath","path","startsWith","Error","key","slice","includes","replace","state","patch","next","op","value","canonicalize","Array","isArray","map","item","sortedEntries","Object","entries","sort","left","right","localeCompare","normalized","cryptoApi","globalThis","crypto","subtle","canonicalJson","JSON","stringify","bytes","TextEncoder","encode","digest","hashBytes","Uint8Array","from","toString","padStart","join","payload","seq","checksum","undefined","ops","candidate"],"mappings":";;;;;;;;;;;IAagBA,UAAU;eAAVA;;IAqCMC,oBAAoB;eAApBA;;IAgBNC,iBAAiB;eAAjBA;;IAiCAC,oBAAoB;eAApBA;;;AAjGhB,SAASC,YAAYC,IAAY;IAC/B,IAAI,CAACA,KAAKC,UAAU,CAAC,MAAM;QACzB,MAAM,IAAIC,MAAM,CAAC,oBAAoB,EAAEF,MAAM;IAC/C;IACA,MAAMG,MAAMH,KAAKI,KAAK,CAAC;IACvB,IAAI,CAACD,OAAOA,IAAIE,QAAQ,CAAC,MAAM;QAC7B,MAAM,IAAIH,MAAM,CAAC,oBAAoB,EAAEF,MAAM;IAC/C;IACA,OAAOG,IAAIG,OAAO,CAAC,OAAO,KAAKA,OAAO,CAAC,OAAO;AAChD;AAEO,SAASX,WACdY,KAAQ,EACRC,KAAgB;IAEhB,MAAMC,OAAgC;QAAE,GAAGF,KAAK;IAAC;IAEjD,KAAK,MAAMG,MAAMF,MAAO;QACtB,MAAML,MAAMJ,YAAYW,GAAGV,IAAI;QAC/B,IAAIU,GAAGA,EAAE,KAAK,OAAO;YACnBD,IAAI,CAACN,IAAI,GAAGO,GAAGC,KAAK;YACpB;QACF;QACA,OAAOF,IAAI,CAACN,IAAI;IAClB;IAEA,OAAOM;AACT;AAEA,SAASG,aAAaD,KAAc;IAClC,IAAIE,MAAMC,OAAO,CAACH,QAAQ;QACxB,OAAOA,MAAMI,GAAG,CAAC,CAACC,OAASJ,aAAaI;IAC1C;IAEA,IAAIL,SAAS,OAAOA,UAAU,UAAU;QACtC,MAAMM,gBAAgBC,OAAOC,OAAO,CAACR,OAAkCS,IAAI,CACzE,CAAC,CAACC,KAAK,EAAE,CAACC,MAAM,GAAKD,KAAKE,aAAa,CAACD;QAE1C,MAAME,aAAsC,CAAC;QAC7C,KAAK,MAAM,CAACrB,KAAKa,KAAK,IAAIC,cAAe;YACvCO,UAAU,CAACrB,IAAI,GAAGS,aAAaI;QACjC;QACA,OAAOQ;IACT;IAEA,OAAOb;AACT;AAEO,eAAef,qBAAqBW,KAAc;IACvD,MAAMkB,YAAYC,WAAWC,MAAM,EAAEC;IACrC,IAAI,CAACH,WAAW;QACd,MAAM,IAAIvB,MAAM;IAClB;IAEA,MAAM2B,gBAAgBC,KAAKC,SAAS,CAACnB,aAAaL;IAClD,MAAMyB,QAAQ,IAAIC,cAAcC,MAAM,CAACL;IACvC,MAAMM,SAAS,MAAMV,UAAUU,MAAM,CAAC,WAAWH;IACjD,MAAMI,YAAY,IAAIC,WAAWF;IAEjC,OAAOtB,MAAMyB,IAAI,CAACF,WACfrB,GAAG,CAAC,CAACJ,QAAUA,MAAM4B,QAAQ,CAAC,IAAIC,QAAQ,CAAC,GAAG,MAC9CC,IAAI,CAAC;AACV;AAEO,SAAS5C,kBAAkB6C,OAAgB;IAChD,IAAI7B,MAAMC,OAAO,CAAC4B,UAAU;QAC1B,OAAO;YACLC,KAAK;YACLC,UAAUC;YACVC,KAAKJ;QACP;IACF;IAEA,IAAI,CAACA,WAAW,OAAOA,YAAY,UAAU;QAC3C,OAAO;IACT;IAEA,MAAMK,YAAYL;IAKlB,IACE,OAAOK,UAAUJ,GAAG,KAAK,YACzB,CAAC9B,MAAMC,OAAO,CAACiC,UAAUD,GAAG,KAC3BC,UAAUH,QAAQ,KAAKC,aAAa,OAAOE,UAAUH,QAAQ,KAAK,UACnE;QACA,OAAO;IACT;IAEA,OAAO;QACLD,KAAKI,UAAUJ,GAAG;QAClBC,UAAUG,UAAUH,QAAQ;QAC5BE,KAAKC,UAAUD,GAAG;IACpB;AACF;AAEO,SAAShD,qBACd4C,OAAgB;IAEhB,IAAI,CAACA,WAAW,OAAOA,YAAY,UAAU;QAC3C,OAAO;IACT;IAEA,MAAMK,YAAYL;IAKlB,IACE,OAAOK,UAAUJ,GAAG,KAAK,YACxBI,UAAUH,QAAQ,KAAKC,aACtB,OAAOE,UAAUH,QAAQ,KAAK,YAChC,CAACG,UAAUxC,KAAK,IAChB,OAAOwC,UAAUxC,KAAK,KAAK,YAC3BM,MAAMC,OAAO,CAACiC,UAAUxC,KAAK,GAC7B;QACA,OAAO;IACT;IAEA,OAAO;QACLoC,KAAKI,UAAUJ,GAAG;QAClBC,UAAUG,UAAUH,QAAQ;QAC5BrC,OAAOwC,UAAUxC,KAAK;IACxB;AACF"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ RpcClient: function() {
13
+ return RpcClient;
14
+ },
15
+ UnknownRidError: function() {
16
+ return UnknownRidError;
17
+ }
18
+ });
19
+ class UnknownRidError extends Error {
20
+ constructor(rid){
21
+ super(`Unknown RPC rid: ${rid}`);
22
+ }
23
+ }
24
+ class RpcClient {
25
+ nextId = 1;
26
+ pending = new Map();
27
+ createRequest(type, payload, room) {
28
+ const rid = `rpc-${this.nextId++}`;
29
+ const message = {
30
+ v: 1,
31
+ t: type,
32
+ rid,
33
+ p: payload
34
+ };
35
+ if (room !== undefined) {
36
+ message.room = room;
37
+ }
38
+ const promise = new Promise((resolve, reject)=>{
39
+ this.pending.set(rid, {
40
+ resolve,
41
+ reject
42
+ });
43
+ });
44
+ return {
45
+ message,
46
+ promise
47
+ };
48
+ }
49
+ resolveResponse(response) {
50
+ const rid = response.rid;
51
+ if (!rid) {
52
+ throw new UnknownRidError("missing");
53
+ }
54
+ const pending = this.pending.get(rid);
55
+ if (!pending) {
56
+ throw new UnknownRidError(rid);
57
+ }
58
+ this.pending.delete(rid);
59
+ pending.resolve(response.p);
60
+ }
61
+ rejectAll(error) {
62
+ for (const pending of this.pending.values()){
63
+ pending.reject(error);
64
+ }
65
+ this.pending.clear();
66
+ }
67
+ }
68
+
69
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/rpc.ts"],"sourcesContent":["import type { Envelope } from \"./types\";\n\nexport class UnknownRidError extends Error {\n constructor(rid: string) {\n super(`Unknown RPC rid: ${rid}`);\n }\n}\n\nexport class RpcClient {\n private nextId = 1;\n private pending = new Map<\n string,\n { resolve: (payload: unknown) => void; reject: (error: Error) => void }\n >();\n\n createRequest(\n type: string,\n payload: unknown,\n room?: string,\n ): { message: Envelope; promise: Promise<unknown> } {\n const rid = `rpc-${this.nextId++}`;\n const message: Envelope = { v: 1, t: type, rid, p: payload };\n if (room !== undefined) {\n message.room = room;\n }\n const promise = new Promise<unknown>((resolve, reject) => {\n this.pending.set(rid, { resolve, reject });\n });\n\n return { message, promise };\n }\n\n resolveResponse(response: Envelope): void {\n const rid = response.rid;\n if (!rid) {\n throw new UnknownRidError(\"missing\");\n }\n\n const pending = this.pending.get(rid);\n if (!pending) {\n throw new UnknownRidError(rid);\n }\n\n this.pending.delete(rid);\n pending.resolve(response.p);\n }\n\n rejectAll(error: Error): void {\n for (const pending of this.pending.values()) {\n pending.reject(error);\n }\n this.pending.clear();\n }\n}\n"],"names":["RpcClient","UnknownRidError","Error","constructor","rid","nextId","pending","Map","createRequest","type","payload","room","message","v","t","p","undefined","promise","Promise","resolve","reject","set","resolveResponse","response","get","delete","rejectAll","error","values","clear"],"mappings":";;;;;;;;;;;IAQaA,SAAS;eAATA;;IANAC,eAAe;eAAfA;;;AAAN,MAAMA,wBAAwBC;IACnCC,YAAYC,GAAW,CAAE;QACvB,KAAK,CAAC,CAAC,iBAAiB,EAAEA,KAAK;IACjC;AACF;AAEO,MAAMJ;IACHK,SAAS,EAAE;IACXC,UAAU,IAAIC,MAGlB;IAEJC,cACEC,IAAY,EACZC,OAAgB,EAChBC,IAAa,EACqC;QAClD,MAAMP,MAAM,CAAC,IAAI,EAAE,IAAI,CAACC,MAAM,IAAI;QAClC,MAAMO,UAAoB;YAAEC,GAAG;YAAGC,GAAGL;YAAML;YAAKW,GAAGL;QAAQ;QAC3D,IAAIC,SAASK,WAAW;YACtBJ,QAAQD,IAAI,GAAGA;QACjB;QACA,MAAMM,UAAU,IAAIC,QAAiB,CAACC,SAASC;YAC7C,IAAI,CAACd,OAAO,CAACe,GAAG,CAACjB,KAAK;gBAAEe;gBAASC;YAAO;QAC1C;QAEA,OAAO;YAAER;YAASK;QAAQ;IAC5B;IAEAK,gBAAgBC,QAAkB,EAAQ;QACxC,MAAMnB,MAAMmB,SAASnB,GAAG;QACxB,IAAI,CAACA,KAAK;YACR,MAAM,IAAIH,gBAAgB;QAC5B;QAEA,MAAMK,UAAU,IAAI,CAACA,OAAO,CAACkB,GAAG,CAACpB;QACjC,IAAI,CAACE,SAAS;YACZ,MAAM,IAAIL,gBAAgBG;QAC5B;QAEA,IAAI,CAACE,OAAO,CAACmB,MAAM,CAACrB;QACpBE,QAAQa,OAAO,CAACI,SAASR,CAAC;IAC5B;IAEAW,UAAUC,KAAY,EAAQ;QAC5B,KAAK,MAAMrB,WAAW,IAAI,CAACA,OAAO,CAACsB,MAAM,GAAI;YAC3CtB,QAAQc,MAAM,CAACO;QACjB;QACA,IAAI,CAACrB,OAAO,CAACuB,KAAK;IACpB;AACF"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types.ts"],"names":[],"mappings":""}