dynamodb-reactive 0.1.20 → 0.1.22

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.
@@ -1,13 +1,13 @@
1
1
  import jsonpatch from 'fast-json-patch';
2
2
  import { error, debug, warn } from 'ag-common/dist/common/helpers/log.js';
3
- import { createContext, useState, useEffect, useContext, useSyncExternalStore, useRef } from 'react';
3
+ import { createContext, useState, useEffect, useContext, useSyncExternalStore, useRef, useCallback } from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
 
6
6
  // ../client/src/patcher.ts
7
7
  var { applyPatch } = jsonpatch;
8
- function applyPatches(document, patches) {
8
+ function applyPatches(document2, patches) {
9
9
  if (patches.length === 0) {
10
- return document;
10
+ return document2;
11
11
  }
12
12
  const operations = patches.map((patch) => {
13
13
  const op = {
@@ -24,7 +24,7 @@ function applyPatches(document, patches) {
24
24
  });
25
25
  try {
26
26
  const result = applyPatch(
27
- structuredClone(document),
27
+ structuredClone(document2),
28
28
  operations,
29
29
  true,
30
30
  // Validate operations
@@ -47,6 +47,8 @@ var WebSocketManager = class {
47
47
  stateHandlers = /* @__PURE__ */ new Set();
48
48
  _connectionId = null;
49
49
  connectionIdResolvers = [];
50
+ /** Flag to indicate intentional disconnect (skip auto-reconnect) */
51
+ intentionalDisconnect = false;
50
52
  constructor(config) {
51
53
  this.config = {
52
54
  autoReconnect: true,
@@ -93,14 +95,15 @@ var WebSocketManager = class {
93
95
  this.reconnectAttempts = 0;
94
96
  this.ws?.send(JSON.stringify({ type: "init" }));
95
97
  };
96
- this.ws.onclose = (event) => {
98
+ this.ws.onclose = () => {
97
99
  this.ws = null;
98
100
  this._connectionId = null;
99
101
  this.setState("disconnected");
100
102
  this.config.onDisconnect?.();
101
- if (this.config.autoReconnect && !event.wasClean) {
103
+ if (this.config.autoReconnect && !this.intentionalDisconnect) {
102
104
  this.scheduleReconnect();
103
105
  }
106
+ this.intentionalDisconnect = false;
104
107
  };
105
108
  this.ws.onerror = () => {
106
109
  const error2 = new Error("WebSocket error");
@@ -141,6 +144,7 @@ var WebSocketManager = class {
141
144
  * Disconnect from the WebSocket server
142
145
  */
143
146
  disconnect() {
147
+ this.intentionalDisconnect = true;
144
148
  if (this.reconnectTimer) {
145
149
  clearTimeout(this.reconnectTimer);
146
150
  this.reconnectTimer = null;
@@ -152,6 +156,24 @@ var WebSocketManager = class {
152
156
  this._connectionId = null;
153
157
  this.setState("disconnected");
154
158
  }
159
+ /**
160
+ * Force reconnect - closes existing connection and reconnects
161
+ * Useful for recovering from stale connections
162
+ */
163
+ forceReconnect() {
164
+ if (this.reconnectTimer) {
165
+ clearTimeout(this.reconnectTimer);
166
+ this.reconnectTimer = null;
167
+ }
168
+ if (this.ws) {
169
+ this.ws.close(1e3, "Force reconnect");
170
+ this.ws = null;
171
+ }
172
+ this._connectionId = null;
173
+ this.reconnectAttempts = 0;
174
+ this.setState("disconnected");
175
+ void this.connect();
176
+ }
155
177
  /**
156
178
  * Send a message to the server
157
179
  */
@@ -270,6 +292,13 @@ var ReactiveClient = class {
270
292
  disconnect() {
271
293
  this.wsManager.disconnect();
272
294
  }
295
+ /**
296
+ * Force reconnect - closes existing connection and reconnects
297
+ * Useful for recovering from stale connections
298
+ */
299
+ forceReconnect() {
300
+ this.wsManager.forceReconnect();
301
+ }
273
302
  /**
274
303
  * Update the headers getter for HTTP requests.
275
304
  * Useful for dynamically setting auth or user context headers.
@@ -698,7 +727,10 @@ var ReactiveClient = class {
698
727
  return void 0;
699
728
  }
700
729
  /**
701
- * Apply an optimistic update to a subscription's data
730
+ * Apply an optimistic update to a subscription's data.
731
+ * Stores the original data for rollback (on mutation error) or as base for
732
+ * incoming server patches. Safe to call after external API calls — the next
733
+ * server snapshot/patch will reconcile automatically.
702
734
  */
703
735
  applyOptimisticUpdate(subscriptionId, updater) {
704
736
  const state = this.subscriptions.get(subscriptionId);
@@ -810,6 +842,46 @@ function ReactiveClientProvider({
810
842
  client.disconnect();
811
843
  };
812
844
  }, [client]);
845
+ useEffect(() => {
846
+ if (typeof window === "undefined" || typeof document === "undefined") {
847
+ return;
848
+ }
849
+ if (!client) return;
850
+ const attemptReconnect = () => {
851
+ const state = client.getConnectionState();
852
+ if (state === "connected") {
853
+ return;
854
+ }
855
+ if (state === "connecting") {
856
+ return;
857
+ }
858
+ if (state === "reconnecting") {
859
+ debug(
860
+ "[dynamodb-reactive] Tab became active during reconnect backoff, forcing reconnect..."
861
+ );
862
+ client.forceReconnect();
863
+ } else {
864
+ debug(
865
+ "[dynamodb-reactive] Tab became active while disconnected, reconnecting..."
866
+ );
867
+ void client.connect();
868
+ }
869
+ };
870
+ const handleVisibilityChange = () => {
871
+ if (document.visibilityState === "visible") {
872
+ attemptReconnect();
873
+ }
874
+ };
875
+ const handleFocus = () => {
876
+ attemptReconnect();
877
+ };
878
+ document.addEventListener("visibilitychange", handleVisibilityChange);
879
+ window.addEventListener("focus", handleFocus);
880
+ return () => {
881
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
882
+ window.removeEventListener("focus", handleFocus);
883
+ };
884
+ }, [client]);
813
885
  useEffect(() => {
814
886
  if (!hasUrl && process.env.NODE_ENV === "development") {
815
887
  warn(
@@ -913,10 +985,22 @@ function useSubscription(path, options = {}) {
913
985
  await subscriptionRef.current.refetch();
914
986
  }
915
987
  };
988
+ const setData = useCallback(
989
+ (updater) => {
990
+ if (client && subscriptionRef.current) {
991
+ client.applyOptimisticUpdate(
992
+ subscriptionRef.current.id,
993
+ updater
994
+ );
995
+ }
996
+ },
997
+ [client]
998
+ );
916
999
  return {
917
1000
  ...state,
918
1001
  disabled: !client,
919
- refetch
1002
+ refetch,
1003
+ setData
920
1004
  };
921
1005
  }
922
1006
  function useMutation(path, options) {
@@ -1015,5 +1099,5 @@ function createProcedureHooks(path) {
1015
1099
  }
1016
1100
 
1017
1101
  export { ReactiveClient, ReactiveClientProvider, WebSocketManager, applyPatches, createProcedureHooks, createReactiveClient, createReactiveHooks, useClient, useConnectionState, useMutation, useReactiveClient, useReactiveClientOrThrow, useSubscription };
1018
- //# sourceMappingURL=chunk-7RHIKRY7.js.map
1019
- //# sourceMappingURL=chunk-7RHIKRY7.js.map
1102
+ //# sourceMappingURL=chunk-2KC44Q5I.js.map
1103
+ //# sourceMappingURL=chunk-2KC44Q5I.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../client/src/patcher.ts","../../client/src/websocket.ts","../../client/src/client.ts","../../client/src/react.tsx"],"names":["document","error","debug"],"mappings":"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","file":"chunk-2KC44Q5I.js","sourcesContent":["import jsonpatch, { type Operation } from 'fast-json-patch';\n\nimport type { JsonPatch } from './types.js';\n\nconst { applyPatch } = jsonpatch;\n\n/**\n * Apply JSON patches to a document\n */\nexport function applyPatches<T>(document: T, patches: JsonPatch[]): T {\n if (patches.length === 0) {\n return document;\n }\n\n const operations: Operation[] = patches.map((patch) => {\n const op: Operation = {\n op: patch.op,\n path: patch.path,\n } as Operation;\n\n if ('value' in patch && patch.value !== undefined) {\n (op as { value: unknown }).value = patch.value;\n }\n if ('from' in patch && patch.from !== undefined) {\n (op as { from: string }).from = patch.from;\n }\n\n return op;\n });\n\n try {\n const result = applyPatch(\n structuredClone(document),\n operations,\n true, // Validate operations\n false, // Don't mutate the original\n );\n\n return result.newDocument as T;\n } catch (error) {\n throw new Error('Failed to apply patches', { cause: error });\n }\n}\n","/* eslint-disable no-console */\nimport { error } from 'ag-common/dist/common/helpers/log.js';\n\nimport type {\n ClientMessage,\n ConnectionState,\n ReactiveClientConfig,\n ServerMessage,\n} from './types.js';\n\n/**\n * WebSocket manager with automatic reconnection\n */\nexport class WebSocketManager {\n private config: Required<\n Omit<\n ReactiveClientConfig,\n 'auth' | 'httpUrl' | 'headers' | 'onConnect' | 'onDisconnect' | 'onError'\n >\n > &\n ReactiveClientConfig;\n private ws: WebSocket | null = null;\n private state: ConnectionState = 'disconnected';\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private messageQueue: ClientMessage[] = [];\n private messageHandlers = new Set<(message: ServerMessage) => void>();\n private stateHandlers = new Set<(state: ConnectionState) => void>();\n private _connectionId: string | null = null;\n private connectionIdResolvers: Array<(id: string) => void> = [];\n /** Flag to indicate intentional disconnect (skip auto-reconnect) */\n private intentionalDisconnect = false;\n\n constructor(config: ReactiveClientConfig) {\n this.config = {\n autoReconnect: true,\n reconnectDelay: 1000,\n maxReconnectAttempts: 10,\n ...config,\n };\n }\n\n /**\n * Get the current connection ID (null if not connected)\n */\n get connectionId(): string | null {\n return this._connectionId;\n }\n\n /**\n * Wait for the connection ID to be available\n */\n waitForConnectionId(): Promise<string> {\n if (this._connectionId) {\n return Promise.resolve(this._connectionId);\n }\n return new Promise((resolve) => {\n this.connectionIdResolvers.push(resolve);\n });\n }\n\n /**\n * Get current connection state\n */\n getState(): ConnectionState {\n return this.state;\n }\n\n /**\n * Connect to the WebSocket server\n */\n async connect(): Promise<void> {\n if (this.state === 'connected' || this.state === 'connecting') {\n return;\n }\n\n this.setState('connecting');\n\n try {\n const url = await this.buildUrl();\n this.ws = new WebSocket(url);\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n // Send init message to get connectionId from server\n // Don't set state to 'connected' until we receive connectionId\n this.ws?.send(JSON.stringify({ type: 'init' }));\n };\n\n this.ws.onclose = () => {\n this.ws = null;\n this._connectionId = null;\n this.setState('disconnected');\n this.config.onDisconnect?.();\n\n // Always attempt reconnect unless intentionally disconnected\n // This handles server timeouts (which may close \"cleanly\") and network issues\n if (this.config.autoReconnect && !this.intentionalDisconnect) {\n this.scheduleReconnect();\n }\n this.intentionalDisconnect = false;\n };\n\n this.ws.onerror = () => {\n const error = new Error('WebSocket error');\n this.config.onError?.(error);\n };\n\n this.ws.onmessage = (event) => {\n try {\n const message = JSON.parse(event.data) as ServerMessage;\n\n // Handle 'connected' message - we got connectionId, now verify with ping/pong\n if (message.type === 'connected') {\n this._connectionId = message.connectionId;\n // Send ping to verify the connection is fully working\n this.ws?.send(JSON.stringify({ type: 'ping' }));\n return;\n }\n\n // Handle 'pong' message - connection is verified, now we're truly connected\n if (message.type === 'pong') {\n this.setState('connected');\n this.flushMessageQueue();\n this.config.onConnect?.();\n\n // Resolve any pending waitForConnectionId promises\n for (const resolve of this.connectionIdResolvers) {\n resolve(this._connectionId!);\n }\n this.connectionIdResolvers = [];\n return;\n }\n\n this.handleMessage(message);\n } catch (e) {\n error('Failed to parse WebSocket message:', e);\n }\n };\n } catch (e) {\n this.setState('disconnected');\n this.config.onError?.(e instanceof Error ? e : new Error(String(e)));\n\n if (this.config.autoReconnect) {\n this.scheduleReconnect();\n }\n }\n }\n\n /**\n * Disconnect from the WebSocket server\n */\n disconnect(): void {\n this.intentionalDisconnect = true;\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n this.ws.close(1000, 'Client disconnect');\n this.ws = null;\n }\n\n this._connectionId = null;\n this.setState('disconnected');\n }\n\n /**\n * Force reconnect - closes existing connection and reconnects\n * Useful for recovering from stale connections\n */\n forceReconnect(): void {\n // Close existing connection without setting intentionalDisconnect\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n this.ws.close(1000, 'Force reconnect');\n this.ws = null;\n }\n\n this._connectionId = null;\n this.reconnectAttempts = 0;\n this.setState('disconnected');\n\n // Immediately reconnect\n void this.connect();\n }\n\n /**\n * Send a message to the server\n */\n send(message: ClientMessage): void {\n // Check both our state and the actual WebSocket readyState\n if (this.state === 'connected' && this.ws?.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(message));\n } else {\n // Queue message for when we reconnect\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Subscribe to incoming messages\n */\n onMessage(handler: (message: ServerMessage) => void): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n /**\n * Subscribe to connection state changes\n */\n onStateChange(handler: (state: ConnectionState) => void): () => void {\n this.stateHandlers.add(handler);\n return () => this.stateHandlers.delete(handler);\n }\n\n private async buildUrl(): Promise<string> {\n let url = this.config.url;\n\n if (this.config.auth) {\n const token =\n typeof this.config.auth === 'function'\n ? await this.config.auth()\n : this.config.auth;\n\n const separator = url.includes('?') ? '&' : '?';\n url = `${url}${separator}token=${encodeURIComponent(token)}`;\n }\n\n return url;\n }\n\n private setState(state: ConnectionState): void {\n this.state = state;\n for (const handler of this.stateHandlers) {\n handler(state);\n }\n }\n\n private handleMessage(message: ServerMessage): void {\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {\n error('Max reconnection attempts reached');\n return;\n }\n\n this.setState('reconnecting');\n this.reconnectAttempts++;\n\n // Exponential backoff with jitter\n const delay =\n Math.min(\n this.config.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000, // Max 30 seconds\n ) *\n (0.5 + Math.random() * 0.5);\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n void this.connect();\n }, delay);\n }\n\n private flushMessageQueue(): void {\n const queue = this.messageQueue;\n this.messageQueue = [];\n\n for (const message of queue) {\n this.send(message);\n }\n }\n}\n","import { debug } from 'ag-common/dist/common/helpers/log.js';\n\nimport { applyPatches } from './patcher.js';\nimport type {\n ConnectionState,\n JsonPatch,\n MutationOptions,\n ReactiveClientConfig,\n ServerMessage,\n Subscription,\n SubscriptionOptions,\n} from './types.js';\nimport { WebSocketManager } from './websocket.js';\n\n/**\n * Default HTTP URL for subscribe/call requests (Next.js API route)\n */\nconst DEFAULT_HTTP_URL = '/api/reactive';\n\n/**\n * Generate a unique subscription ID\n */\nfunction generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Internal subscription state\n */\ninterface SubscriptionState<TData> {\n id: string;\n path: string;\n input: unknown;\n data: TData | undefined;\n loading: boolean;\n error: Error | undefined;\n listeners: Set<() => void>;\n options: SubscriptionOptions<unknown>;\n}\n\n/**\n * Pending call state\n */\ninterface PendingCall {\n resolve: (data: unknown) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Reactive client for type-safe subscriptions\n */\nexport class ReactiveClient {\n private wsManager: WebSocketManager;\n private httpUrl: string;\n private authGetter?: () => string | Promise<string>;\n private headersGetter?: () =>\n | Record<string, string>\n | Promise<Record<string, string>>;\n private subscriptions = new Map<string, SubscriptionState<unknown>>();\n private pendingCalls = new Map<string, PendingCall>();\n private connectionState: ConnectionState = 'disconnected';\n private stateListeners = new Set<(state: ConnectionState) => void>();\n // Stores original data for rollback when optimistic updates fail\n private optimisticUpdates = new Map<string, unknown>();\n\n constructor(config: ReactiveClientConfig) {\n this.wsManager = new WebSocketManager(config);\n this.httpUrl = config.httpUrl ?? DEFAULT_HTTP_URL;\n\n // Store auth getter for HTTP requests\n if (typeof config.auth === 'function') {\n this.authGetter = config.auth;\n } else if (config.auth) {\n this.authGetter = () => config.auth as string;\n }\n\n // Store headers getter for HTTP requests\n if (typeof config.headers === 'function') {\n this.headersGetter = config.headers;\n } else if (config.headers) {\n this.headersGetter = () => config.headers as Record<string, string>;\n }\n\n // Handle incoming messages (patches come via WebSocket)\n this.wsManager.onMessage((message) => this.handleMessage(message));\n\n // Handle connection state changes\n this.wsManager.onStateChange((state) => {\n this.connectionState = state;\n this.notifyStateListeners();\n\n if (state === 'connected') {\n this.resubscribeAll();\n }\n });\n }\n\n /**\n * Connect to the server\n */\n async connect(): Promise<void> {\n await this.wsManager.connect();\n }\n\n /**\n * Disconnect from the server\n */\n disconnect(): void {\n this.wsManager.disconnect();\n }\n\n /**\n * Force reconnect - closes existing connection and reconnects\n * Useful for recovering from stale connections\n */\n forceReconnect(): void {\n this.wsManager.forceReconnect();\n }\n\n /**\n * Update the headers getter for HTTP requests.\n * Useful for dynamically setting auth or user context headers.\n */\n setHeaders(\n headers:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>),\n ): void {\n if (typeof headers === 'function') {\n this.headersGetter = headers;\n } else {\n this.headersGetter = () => headers;\n }\n }\n\n /**\n * Get current connection state\n */\n getConnectionState(): ConnectionState {\n return this.connectionState;\n }\n\n /**\n * Subscribe to connection state changes\n */\n onConnectionStateChange(\n listener: (state: ConnectionState) => void,\n ): () => void {\n this.stateListeners.add(listener);\n return () => this.stateListeners.delete(listener);\n }\n\n /**\n * Subscribe to a procedure via HTTP.\n * Snapshot is returned via HTTP, patches come via WebSocket.\n */\n subscribe<TData>(\n path: string,\n options: SubscriptionOptions<unknown> = {},\n ): Subscription<TData> {\n const id = generateId();\n\n const state: SubscriptionState<TData> = {\n id,\n path,\n input: options.input,\n data: undefined,\n loading: true,\n error: undefined,\n listeners: new Set(),\n options,\n };\n\n this.subscriptions.set(id, state as SubscriptionState<unknown>);\n\n // Send subscribe request via HTTP (async)\n this.sendSubscribeRequest(id, path, options.input).catch((error) => {\n state.error = error instanceof Error ? error : new Error(String(error));\n state.loading = false;\n this.notifySubscriptionListeners(id);\n options.onError?.(state.error);\n });\n\n const subscription: Subscription<TData> = {\n id,\n get data() {\n return state.data;\n },\n get loading() {\n return state.loading;\n },\n get error() {\n return state.error;\n },\n unsubscribe: () => this.unsubscribe(id),\n refetch: () => this.refetch(id),\n };\n\n return subscription;\n }\n\n /**\n * Send subscribe request via HTTP\n */\n private async sendSubscribeRequest(\n subscriptionId: string,\n path: string,\n input: unknown,\n ): Promise<void> {\n // Wait for connectionId to be available\n const connectionId = await this.wsManager.waitForConnectionId();\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n // Add custom headers if configured\n if (this.headersGetter) {\n const customHeaders = await this.headersGetter();\n Object.assign(headers, customHeaders);\n }\n\n // Add auth header if configured\n if (this.authGetter) {\n const token = await this.authGetter();\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(this.httpUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n type: 'subscribe',\n connectionId,\n subscriptionId,\n path,\n input,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `Subscribe failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const result = (await response.json()) as {\n type: string;\n message?: string;\n data?: unknown;\n };\n\n if (result.type === 'error') {\n throw new Error(result.message ?? 'Unknown error');\n }\n\n if (result.type === 'snapshot') {\n this.handleSnapshot(subscriptionId, result.data);\n }\n }\n\n /**\n * Call a mutation procedure via HTTP with optimistic update support.\n * All optimistic updates are applied INSTANTLY (before HTTP request).\n */\n async call<TInput, TOutput>(\n path: string,\n input: TInput,\n options?: MutationOptions<TInput, TOutput>,\n ): Promise<TOutput> {\n const invalidatesPath = options?.invalidates;\n const updateType = options?.optimisticUpdate;\n let targetSubscriptionId: string | undefined;\n\n // Find subscription to optimistically update\n if (invalidatesPath) {\n targetSubscriptionId = this.findSubscriptionByPath(invalidatesPath);\n debug(\n '[optimistic] Looking for subscription:',\n invalidatesPath,\n '-> found:',\n targetSubscriptionId ?? 'NONE',\n );\n }\n\n // Apply INSTANT optimistic update (before HTTP request)\n if (targetSubscriptionId) {\n debug(\n '[optimistic] Applying update type:',\n updateType,\n 'to subscription:',\n targetSubscriptionId,\n );\n const state = this.subscriptions.get(targetSubscriptionId);\n const currentData = state?.data;\n\n if (updateType === 'remove') {\n // Remove: filter out item by id\n const inputId = (input as { id?: string }).id;\n if (inputId) {\n this.applyOptimisticUpdate(targetSubscriptionId, (data) => {\n if (!Array.isArray(data)) return data;\n return data.filter((item: { id?: string }) => item.id !== inputId);\n });\n }\n } else if (updateType === 'merge') {\n // Merge: find item by id and merge input fields into it\n const inputWithId = input as { id?: string };\n if (inputWithId.id) {\n this.applyOptimisticUpdate(targetSubscriptionId, (data) => {\n if (!Array.isArray(data)) return data;\n const idx = data.findIndex(\n (item: { id?: string }) => item.id === inputWithId.id,\n );\n if (idx >= 0) {\n // Merge input into existing item\n return [\n ...data.slice(0, idx),\n { ...data[idx], ...input },\n ...data.slice(idx + 1),\n ];\n }\n return data;\n });\n } else if (options?.optimisticData) {\n // For creates without id, use provided optimisticData\n const optimistic =\n typeof options.optimisticData === 'function'\n ? (\n options.optimisticData as (\n input: TInput,\n data: unknown[],\n ) => TOutput\n )(input, Array.isArray(currentData) ? currentData : [])\n : options.optimisticData;\n if (optimistic) {\n this.applyOptimisticUpdate(targetSubscriptionId, (data) => {\n if (!Array.isArray(data)) return data;\n return [optimistic, ...data];\n });\n }\n }\n } else if (typeof updateType === 'function') {\n // Custom update function - apply instantly\n this.applyOptimisticUpdate(targetSubscriptionId, (data) => {\n if (!Array.isArray(data)) return data;\n return updateType(data, input, undefined);\n });\n }\n }\n\n // Wait for connectionId to be available\n const connectionId = await this.wsManager.waitForConnectionId();\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n // Add custom headers if configured\n if (this.headersGetter) {\n const customHeaders = await this.headersGetter();\n Object.assign(headers, customHeaders);\n }\n\n // Add auth header if configured\n if (this.authGetter) {\n const token = await this.authGetter();\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n try {\n const response = await fetch(this.httpUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n type: 'call',\n connectionId,\n path,\n input,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `Call failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const result = (await response.json()) as {\n type: string;\n message?: string;\n data?: unknown;\n };\n\n if (result.type === 'error') {\n throw new Error(result.message ?? 'Unknown error');\n }\n\n const data = result.data as TOutput;\n\n // After HTTP success, reconcile with real server data\n if (targetSubscriptionId && updateType === 'merge') {\n const resultWithId = data as { id?: string };\n if (resultWithId.id) {\n this.applyOptimisticUpdate(targetSubscriptionId, (currentData) => {\n if (!Array.isArray(currentData)) return currentData;\n const idx = currentData.findIndex(\n (item: { id?: string }) => item.id === resultWithId.id,\n );\n if (idx >= 0) {\n // Update with real server data\n return [\n ...currentData.slice(0, idx),\n data,\n ...currentData.slice(idx + 1),\n ];\n } else {\n // New item - add it (and remove any temp items)\n return [\n data,\n ...currentData.filter(\n (item: { id?: string }) =>\n item.id && !item.id.startsWith('temp-'),\n ),\n ];\n }\n });\n }\n }\n\n return data;\n } catch (error) {\n // Rollback on error\n if (targetSubscriptionId) {\n this.rollbackOptimisticUpdate(targetSubscriptionId);\n }\n throw error;\n }\n }\n\n /**\n * Unsubscribe from a subscription\n */\n private unsubscribe(id: string): void {\n const state = this.subscriptions.get(id);\n if (!state) return;\n\n this.subscriptions.delete(id);\n\n this.wsManager.send({\n type: 'unsubscribe',\n subscriptionId: id,\n });\n }\n\n /**\n * Refetch a subscription via HTTP\n */\n private async refetch(id: string): Promise<void> {\n const state = this.subscriptions.get(id);\n if (!state) return;\n\n state.loading = true;\n this.notifySubscriptionListeners(id);\n\n try {\n await this.sendSubscribeRequest(id, state.path, state.input);\n } catch (error) {\n state.error = error instanceof Error ? error : new Error(String(error));\n state.loading = false;\n this.notifySubscriptionListeners(id);\n state.options.onError?.(state.error);\n }\n }\n\n /**\n * Handle incoming server messages.\n * Note: 'connected' messages are handled by WebSocketManager before reaching here.\n */\n private handleMessage(message: ServerMessage): void {\n switch (message.type) {\n case 'connected':\n // Handled by WebSocketManager - should not reach here\n break;\n\n case 'pong':\n // Heartbeat response - no action needed\n break;\n\n case 'snapshot':\n this.handleSnapshot(message.subscriptionId, message.data);\n break;\n\n case 'patch':\n this.handlePatch(message.subscriptionId, message.patches);\n break;\n\n case 'result':\n this.handleResult(message.callId, message.data);\n break;\n\n case 'error':\n this.handleError(message);\n break;\n }\n }\n\n /**\n * Handle a snapshot message\n */\n private handleSnapshot(subscriptionId: string, data: unknown): void {\n const state = this.subscriptions.get(subscriptionId);\n if (!state) return;\n\n // Clear optimistic state since we have authoritative data\n this.clearOptimisticUpdate(subscriptionId);\n\n state.data = data;\n state.loading = false;\n state.error = undefined;\n\n this.notifySubscriptionListeners(subscriptionId);\n state.options.onData?.(data);\n }\n\n /**\n * Handle a patch message\n */\n private handlePatch(subscriptionId: string, patches: JsonPatch[]): void {\n const state = this.subscriptions.get(subscriptionId);\n if (!state || state.data === undefined) return;\n\n // If we have optimistic state, apply patch to the ORIGINAL data\n // This prevents conflicts when patch tries to modify already-modified data\n const originalData = this.optimisticUpdates.get(subscriptionId);\n const baseData = originalData !== undefined ? originalData : state.data;\n\n // Clear optimistic state since we have authoritative patch data\n this.clearOptimisticUpdate(subscriptionId);\n\n try {\n state.data = applyPatches(baseData, patches);\n this.notifySubscriptionListeners(subscriptionId);\n state.options.onData?.(state.data);\n } catch (error) {\n state.error = error instanceof Error ? error : new Error(String(error));\n this.notifySubscriptionListeners(subscriptionId);\n state.options.onError?.(state.error);\n }\n }\n\n /**\n * Handle a result message\n */\n private handleResult(callId: string, data: unknown): void {\n const pending = this.pendingCalls.get(callId);\n if (!pending) return;\n\n this.pendingCalls.delete(callId);\n pending.resolve(data);\n }\n\n /**\n * Handle an error message\n */\n private handleError(message: {\n message: string;\n subscriptionId?: string;\n callId?: string;\n }): void {\n const error = new Error(message.message);\n\n if (message.subscriptionId) {\n const state = this.subscriptions.get(message.subscriptionId);\n if (state) {\n state.error = error;\n state.loading = false;\n this.notifySubscriptionListeners(message.subscriptionId);\n state.options.onError?.(error);\n }\n }\n\n if (message.callId) {\n const pending = this.pendingCalls.get(message.callId);\n if (pending) {\n this.pendingCalls.delete(message.callId);\n pending.reject(error);\n }\n }\n }\n\n /**\n * Resubscribe to all subscriptions after reconnect via HTTP\n */\n private resubscribeAll(): void {\n for (const [id, state] of this.subscriptions) {\n if (state.options.resubscribeOnReconnect !== false) {\n state.loading = true;\n this.notifySubscriptionListeners(id);\n\n // Re-subscribe via HTTP\n this.sendSubscribeRequest(id, state.path, state.input).catch(\n (error) => {\n state.error =\n error instanceof Error ? error : new Error(String(error));\n state.loading = false;\n this.notifySubscriptionListeners(id);\n state.options.onError?.(state.error);\n },\n );\n }\n }\n }\n\n /**\n * Notify subscription listeners of state changes\n */\n private notifySubscriptionListeners(id: string): void {\n const state = this.subscriptions.get(id);\n if (!state) return;\n\n for (const listener of state.listeners) {\n listener();\n }\n }\n\n /**\n * Notify connection state listeners\n */\n private notifyStateListeners(): void {\n for (const listener of this.stateListeners) {\n listener(this.connectionState);\n }\n }\n\n /**\n * Add a listener for subscription state changes\n * Used internally by React hooks\n */\n addSubscriptionListener(id: string, listener: () => void): () => void {\n const state = this.subscriptions.get(id);\n if (!state) return () => {};\n\n state.listeners.add(listener);\n return () => state.listeners.delete(listener);\n }\n\n /**\n * Get subscription state\n * Used internally by React hooks\n */\n getSubscriptionState<TData>(\n id: string,\n ): SubscriptionState<TData> | undefined {\n return this.subscriptions.get(id) as SubscriptionState<TData> | undefined;\n }\n\n /**\n * Find subscription by path\n */\n private findSubscriptionByPath(path: string): string | undefined {\n debug(\n '[optimistic] Searching for path:',\n path,\n 'in subscriptions:',\n Array.from(this.subscriptions.entries()).map(([id, s]) => ({\n id,\n path: s.path,\n })),\n );\n for (const [id, state] of this.subscriptions) {\n if (state.path === path) {\n return id;\n }\n }\n return undefined;\n }\n\n /**\n * Apply an optimistic update to a subscription's data.\n * Stores the original data for rollback (on mutation error) or as base for\n * incoming server patches. Safe to call after external API calls — the next\n * server snapshot/patch will reconcile automatically.\n */\n applyOptimisticUpdate(\n subscriptionId: string,\n updater: (data: unknown) => unknown,\n ): void {\n const state = this.subscriptions.get(subscriptionId);\n if (!state) {\n debug(\n '[optimistic] applyOptimisticUpdate: subscription not found:',\n subscriptionId,\n );\n return;\n }\n if (state.data === undefined) {\n debug(\n '[optimistic] applyOptimisticUpdate: subscription data is undefined (still loading?):',\n subscriptionId,\n );\n return;\n }\n debug(\n '[optimistic] applyOptimisticUpdate: applying update, current data length:',\n Array.isArray(state.data) ? state.data.length : 'not array',\n );\n\n // Store original data for rollback (only if not already stored)\n if (!this.optimisticUpdates.has(subscriptionId)) {\n this.optimisticUpdates.set(\n subscriptionId,\n JSON.parse(JSON.stringify(state.data)),\n );\n }\n\n // Apply the update\n state.data = updater(state.data);\n this.notifySubscriptionListeners(subscriptionId);\n }\n\n /**\n * Rollback an optimistic update\n */\n private rollbackOptimisticUpdate(subscriptionId: string): void {\n const original = this.optimisticUpdates.get(subscriptionId);\n if (original === undefined) return;\n\n const state = this.subscriptions.get(subscriptionId);\n if (state) {\n state.data = original;\n this.notifySubscriptionListeners(subscriptionId);\n }\n this.optimisticUpdates.delete(subscriptionId);\n }\n\n /**\n * Clear optimistic state (called when real data arrives)\n */\n private clearOptimisticUpdate(subscriptionId: string): void {\n this.optimisticUpdates.delete(subscriptionId);\n }\n}\n\n/**\n * Create a type-safe reactive client\n */\nexport function createReactiveClient<TRouter>(\n config: ReactiveClientConfig,\n): TypedReactiveClient<TRouter> {\n const client = new ReactiveClient(config);\n return createTypedProxy(client, []) as TypedReactiveClient<TRouter>;\n}\n\n/**\n * Type-safe client proxy type\n */\nexport type TypedReactiveClient<TRouter> = {\n [K in keyof TRouter]: TRouter[K] extends { query: unknown }\n ? {\n useSubscription: <TData = unknown>(\n input?: unknown,\n options?: Omit<SubscriptionOptions<unknown>, 'input'>,\n ) => Subscription<TData>;\n }\n : TRouter[K] extends { mutation: unknown }\n ? {\n mutate: <TInput, TOutput>(input: TInput) => Promise<TOutput>;\n }\n : TypedReactiveClient<TRouter[K]>;\n} & {\n _client: ReactiveClient;\n connect: () => Promise<void>;\n disconnect: () => void;\n};\n\n/**\n * Create a typed proxy for path-based access\n */\nfunction createTypedProxy(client: ReactiveClient, path: string[]): unknown {\n return new Proxy(\n {},\n {\n get(_target, prop) {\n if (prop === '_client') return client;\n if (prop === 'connect') return () => client.connect();\n if (prop === 'disconnect') return () => client.disconnect();\n\n if (typeof prop !== 'string') return undefined;\n\n const newPath = [...path, prop];\n\n // Check if this is a subscription or mutation\n if (prop === 'useSubscription') {\n return (input?: unknown, options?: SubscriptionOptions<unknown>) => {\n const parentPath = path.join('.');\n return client.subscribe(parentPath, { ...options, input });\n };\n }\n\n if (prop === 'mutate') {\n return async (input: unknown) => {\n const parentPath = path.join('.');\n // Auto-detect invalidates path: 'todos.toggle' → 'todos.list'\n const invalidatesPath =\n path.length >= 2\n ? `${path.slice(0, -1).join('.')}.list`\n : undefined;\n // Auto-detect update type: '*.delete' → 'remove', others → 'merge'\n const updateType = parentPath.endsWith('.delete')\n ? ('remove' as const)\n : ('merge' as const);\n return client.call(parentPath, input, {\n invalidates: invalidatesPath,\n optimisticUpdate: updateType,\n });\n };\n }\n\n return createTypedProxy(client, newPath);\n },\n },\n );\n}\n","import { debug, warn } from 'ag-common/dist/common/helpers/log.js';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\n\nimport { ReactiveClient } from './client.js';\nimport type {\n ConnectionState,\n MutationOptions,\n ReactiveClientConfig,\n Subscription,\n SubscriptionOptions,\n} from './types.js';\n\n/**\n * Context for the reactive client\n */\nconst ReactiveClientContext = createContext<ReactiveClient | null>(null);\n\n/**\n * Provider component for the reactive client\n *\n * If no config.url or client is provided, WebSocket features are disabled\n * and children are rendered without the reactive context.\n */\nexport function ReactiveClientProvider({\n children,\n config,\n client: externalClient,\n}: {\n children: ReactNode;\n config?: ReactiveClientConfig;\n client?: ReactiveClient;\n}) {\n // Extract URL for stable dependency\n const url = config?.url;\n const hasUrl = Boolean(url);\n\n // Always start with null to avoid hydration mismatch\n // Client will be created in useEffect after hydration\n const [client, setClient] = useState<ReactiveClient | null>(\n externalClient ?? null,\n );\n\n // Create client after mount (avoids hydration mismatch)\n useEffect(() => {\n // Skip if we have an external client or no URL\n if (externalClient || !url) return;\n\n // Create client if we don't have one\n if (!client) {\n const newClient = new ReactiveClient({ ...config, url });\n setClient(newClient);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, externalClient]);\n\n // Connect/disconnect effect\n useEffect(() => {\n if (!client) return;\n\n void client.connect();\n\n return () => {\n client.disconnect();\n };\n }, [client]);\n\n // Visibility change and focus handlers - reconnect when tab becomes active\n useEffect(() => {\n // Skip if not in browser environment or no client\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n if (!client) return;\n\n const attemptReconnect = () => {\n const state = client.getConnectionState();\n if (state === 'connected') {\n // Already connected, nothing to do\n return;\n }\n if (state === 'connecting') {\n // Already connecting, give it a moment\n return;\n }\n if (state === 'reconnecting') {\n // Stuck in backoff, force immediate reconnect\n debug(\n '[dynamodb-reactive] Tab became active during reconnect backoff, forcing reconnect...',\n );\n client.forceReconnect();\n } else {\n // Disconnected, connect normally\n debug(\n '[dynamodb-reactive] Tab became active while disconnected, reconnecting...',\n );\n void client.connect();\n }\n };\n\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'visible') {\n attemptReconnect();\n }\n };\n\n const handleFocus = () => {\n attemptReconnect();\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n window.addEventListener('focus', handleFocus);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n window.removeEventListener('focus', handleFocus);\n };\n }, [client]);\n\n // Log warning if no URL configured (only once in dev)\n useEffect(() => {\n if (!hasUrl && process.env.NODE_ENV === 'development') {\n warn(\n '[dynamodb-reactive] WebSocket URL not configured, real-time features disabled',\n );\n }\n }, [hasUrl]);\n\n // Always render with context provider - hooks will handle null client\n return (\n <ReactiveClientContext.Provider value={client}>\n {children}\n </ReactiveClientContext.Provider>\n );\n}\n\n/**\n * Hook to get the reactive client\n * Returns null if WebSocket is not configured\n */\nexport function useReactiveClient(): ReactiveClient | null {\n return useContext(ReactiveClientContext);\n}\n\n/**\n * Hook to get the reactive client, throwing if not available\n */\nexport function useReactiveClientOrThrow(): ReactiveClient {\n const client = useContext(ReactiveClientContext);\n if (!client) {\n throw new Error(\n 'useReactiveClientOrThrow must be used within a ReactiveClientProvider with a configured URL',\n );\n }\n return client;\n}\n\n/**\n * Hook to get the connection state\n * Returns 'disabled' if WebSocket is not configured\n */\nexport function useConnectionState(): ConnectionState | 'disabled' {\n const client = useReactiveClient();\n\n return useSyncExternalStore(\n (callback) => {\n if (!client) return () => {};\n return client.onConnectionStateChange(callback);\n },\n () => (client ? client.getConnectionState() : 'disabled'),\n () => 'disabled' as const,\n );\n}\n\n/**\n * Hook for reactive subscriptions\n * Returns disabled state if WebSocket is not configured\n */\nexport function useSubscription<TData>(\n path: string,\n options: SubscriptionOptions<unknown> = {},\n): {\n data: TData | undefined;\n loading: boolean;\n error: Error | undefined;\n disabled: boolean;\n refetch: () => Promise<void>;\n setData: (updater: (data: TData) => TData) => void;\n} {\n const client = useReactiveClient();\n const subscriptionRef = useRef<Subscription<TData> | null>(null);\n const [state, setState] = useState<{\n data: TData | undefined;\n loading: boolean;\n error: Error | undefined;\n }>({\n data: undefined,\n loading: !client ? false : true,\n error: undefined,\n });\n\n // Serialize options for dependency comparison\n const inputKey = JSON.stringify(options.input);\n // Store callbacks in refs to avoid re-subscribing when they change\n const onDataRef = useRef(options.onData);\n const onErrorRef = useRef(options.onError);\n onDataRef.current = options.onData;\n onErrorRef.current = options.onError;\n\n useEffect(() => {\n if (!client) return;\n\n // Parse input from inputKey to ensure we use the serialized value\n const input = inputKey ? JSON.parse(inputKey) : undefined;\n\n const subscription = client.subscribe<TData>(path, {\n input,\n onData: (data) => {\n setState((prev) => ({\n ...prev,\n data: data as TData,\n loading: false,\n error: undefined,\n }));\n onDataRef.current?.(data);\n },\n onError: (error) => {\n setState((prev) => ({\n ...prev,\n error,\n loading: false,\n }));\n onErrorRef.current?.(error);\n },\n });\n\n subscriptionRef.current = subscription;\n\n // Register a listener for optimistic updates (notifySubscriptionListeners)\n // This ensures React state updates when optimistic changes happen\n const unregisterListener = client.addSubscriptionListener(\n subscription.id,\n () => {\n // Re-read current state from subscription\n debug(\n '[optimistic] useSubscription listener fired for:',\n path,\n 'data length:',\n Array.isArray(subscription.data)\n ? subscription.data.length\n : 'not array',\n );\n setState({\n data: subscription.data,\n loading: subscription.loading,\n error: subscription.error,\n });\n },\n );\n\n // Update state from subscription\n setState({\n data: subscription.data,\n loading: subscription.loading,\n error: subscription.error,\n });\n\n return () => {\n unregisterListener();\n subscription.unsubscribe();\n subscriptionRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, path, inputKey]);\n\n const refetch = async () => {\n if (subscriptionRef.current) {\n setState((prev) => ({ ...prev, loading: true }));\n await subscriptionRef.current.refetch();\n }\n };\n\n const setData = useCallback(\n (updater: (data: TData) => TData) => {\n if (client && subscriptionRef.current) {\n client.applyOptimisticUpdate(\n subscriptionRef.current.id,\n updater as (data: unknown) => unknown,\n );\n }\n },\n [client],\n );\n\n return {\n ...state,\n disabled: !client,\n refetch,\n setData,\n };\n}\n\n/**\n * Hook for mutations with automatic optimistic updates\n *\n * Auto-detection:\n * - `invalidates`: Auto-detected from path (e.g., 'todos.toggle' -> 'todos.list')\n * - `optimisticUpdate`: Auto-detected from path ('*.delete' -> 'remove', others -> 'merge')\n *\n * You can override these with explicit options.\n */\nexport function useMutation<TInput, TOutput>(\n path: string,\n options?: MutationOptions<TInput, TOutput>,\n): {\n mutate: (input: TInput) => Promise<TOutput>;\n data: TOutput | undefined;\n loading: boolean;\n error: Error | undefined;\n disabled: boolean;\n reset: () => void;\n} {\n const client = useReactiveClient();\n const [state, setState] = useState<{\n data: TOutput | undefined;\n loading: boolean;\n error: Error | undefined;\n }>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n // Auto-detect invalidates path from mutation path\n // e.g., 'todos.toggle' -> 'todos.list', 'todos.create' -> 'todos.list'\n const autoInvalidates =\n options?.invalidates ??\n (() => {\n const parts = path.split('.');\n if (parts.length >= 2) {\n return `${parts.slice(0, -1).join('.')}.list`;\n }\n return undefined;\n })();\n\n // Auto-detect update type from path\n // '*.delete' -> 'remove', others -> 'merge'\n const autoUpdateType =\n options?.optimisticUpdate ??\n (path.endsWith('.delete') ? 'remove' : 'merge');\n\n const mutate = async (input: TInput): Promise<TOutput> => {\n if (!client) {\n throw new Error('WebSocket not configured - mutations are disabled');\n }\n\n debug('[optimistic] useMutation.mutate called:', {\n path,\n autoInvalidates,\n autoUpdateType,\n input,\n });\n\n setState((prev) => ({ ...prev, loading: true, error: undefined }));\n\n try {\n const result = await client.call<TInput, TOutput>(path, input, {\n invalidates: autoInvalidates,\n optimisticUpdate: autoUpdateType,\n });\n setState({ data: result, loading: false, error: undefined });\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n setState((prev) => ({ ...prev, loading: false, error: err }));\n throw err;\n }\n };\n\n const reset = () => {\n setState({ data: undefined, loading: false, error: undefined });\n };\n\n return {\n mutate,\n ...state,\n disabled: !client,\n reset,\n };\n}\n\n/**\n * Type helper for extracting procedure input type from ProcedureDefinition\n * Uses Zod's internal _output property to extract the parsed type\n * (Zod schemas have _input/_output as actual properties for type inference)\n */\ntype ProcedureInput<T> = T extends { inputSchema?: { _output: infer I } }\n ? I\n : undefined;\n\n/**\n * Type helper for extracting procedure output type from ProcedureDefinition\n * Extracts from resolver return type using any[] for flexible argument matching\n */\ntype ProcedureOutput<T> = T extends {\n resolver: (...args: any[]) => infer TReturn; // eslint-disable-line @typescript-eslint/no-explicit-any -- contravariance requires `any`\n}\n ? Awaited<TReturn>\n : unknown;\n\n/**\n * Typed client hooks for a router procedure\n * Provides both useQuery and useMutation - use whichever matches your procedure type\n */\ntype TypedProcedureHooks<TInput, TOutput> = {\n useQuery: (\n input: TInput,\n options?: Omit<SubscriptionOptions<TInput>, 'input'>,\n ) => {\n data: TOutput | undefined;\n loading: boolean;\n error: Error | undefined;\n disabled: boolean;\n refetch: () => Promise<void>;\n setData: (updater: (data: TOutput) => TOutput) => void;\n };\n useMutation: (options?: MutationOptions<TInput, TOutput>) => {\n mutate: (input: TInput) => Promise<TOutput>;\n data: TOutput | undefined;\n loading: boolean;\n error: Error | undefined;\n disabled: boolean;\n reset: () => void;\n };\n};\n\n/**\n * Extract router definition from Router class or use T directly\n */\ntype ExtractRouterDefinition<T> = T extends { definition: infer TDef }\n ? TDef\n : T;\n\n/**\n * Recursive type for typed client proxy\n * Checks for 'resolver' property to identify procedures (all procedures have it)\n */\ntype TypedClientProxyRecursive<T> = T extends { resolver: unknown }\n ? TypedProcedureHooks<ProcedureInput<T>, ProcedureOutput<T>>\n : { [K in keyof T]: TypedClientProxyRecursive<T[K]> };\n\n/**\n * Client utilities available at the root level\n */\ninterface ClientUtilities {\n /**\n * Set custom headers to be sent with HTTP requests.\n * Useful for auth context (e.g., user tokens, session info).\n */\n setHeaders: (\n headers:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>),\n ) => void;\n}\n\n/**\n * Typed client proxy combining router procedures and client utilities\n */\ntype TypedClientProxy<T> = TypedClientProxyRecursive<\n ExtractRouterDefinition<T>\n> &\n ClientUtilities;\n\n/**\n * Create a typed client proxy for use in React components.\n *\n * @example\n * ```tsx\n * const client = useClient<AppRouter>();\n *\n * // Queries (subscriptions)\n * const { data, loading } = client.todos.list.useQuery({});\n *\n * // Mutations\n * const { mutate, loading } = client.todos.toggle.useMutation();\n * await mutate({ id: '123' });\n *\n * // Set custom headers for HTTP requests (e.g., for auth context)\n * client.setHeaders({ 'Authorization': 'Bearer token' });\n * ```\n */\nexport function useClient<TRouter>(): TypedClientProxy<TRouter> {\n const client = useReactiveClient();\n\n function buildProxy(path: string[]): unknown {\n return new Proxy(\n {},\n {\n get(_target, prop: string) {\n if (prop === 'useQuery') {\n // Return a hook function for subscriptions\n return function useQueryHook(\n input?: unknown,\n options?: SubscriptionOptions<unknown>,\n ) {\n const pathStr = path.join('.');\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useSubscription(pathStr, { ...options, input });\n };\n }\n\n if (prop === 'useMutation') {\n // Return a hook function for mutations\n return function useMutationHook(\n options?: MutationOptions<unknown, unknown>,\n ) {\n const pathStr = path.join('.');\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useMutation(pathStr, options);\n };\n }\n\n // Expose setHeaders from the underlying client\n if (prop === 'setHeaders') {\n return (\n headers:\n | Record<string, string>\n | (() =>\n | Record<string, string>\n | Promise<Record<string, string>>),\n ) => {\n client?.setHeaders(headers);\n };\n }\n\n return buildProxy([...path, prop]);\n },\n },\n );\n }\n\n return buildProxy([]) as TypedClientProxy<TRouter>;\n}\n\n/**\n * @deprecated Use useClient<TRouter>() instead for typed proxy access\n */\nexport function createReactiveHooks() {\n return {\n useSubscription: <TPath extends string, TData = unknown>(\n path: TPath,\n options?: SubscriptionOptions<unknown>,\n ) => useSubscription<TData>(path, options),\n\n useMutation: <TPath extends string, TInput = unknown, TOutput = unknown>(\n path: TPath,\n options?: MutationOptions<TInput, TOutput>,\n ) => useMutation<TInput, TOutput>(path, options),\n\n useConnectionState,\n useReactiveClient,\n };\n}\n\n/**\n * @deprecated Use useClient<TRouter>() instead for typed proxy access\n */\nexport function createProcedureHooks<TInput, TOutput>(path: string) {\n return {\n useSubscription: (\n input?: TInput,\n options?: Omit<SubscriptionOptions<TInput>, 'input'>,\n ) => useSubscription<TOutput>(path, { ...options, input }),\n\n useMutation: (options?: MutationOptions<TInput, TOutput>) =>\n useMutation<TInput, TOutput>(path, options),\n };\n}\n"]}
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as ReactiveClientConfig, C as ConnectionState, a as ClientMessage, S as ServerMessage, J as JsonPatch } from './react-DJzw1_9P.js';
2
- export { d as CallMessage, E as ErrorMessage, I as InferInput, e as InferOutput, M as MutationOptions, P as PatchMessage, b as ReactiveClient, m as ReactiveClientProvider, f as ResultMessage, g as SnapshotMessage, h as SubscribeMessage, i as Subscription, j as SubscriptionOptions, T as TypedReactiveClient, U as UnsubscribeMessage, k as createProcedureHooks, c as createReactiveClient, l as createReactiveHooks, u as useClient, n as useConnectionState, o as useMutation, p as useReactiveClient, q as useReactiveClientOrThrow, r as useSubscription } from './react-DJzw1_9P.js';
1
+ import { R as ReactiveClientConfig, C as ConnectionState, a as ClientMessage, S as ServerMessage, J as JsonPatch } from './react-D_NLHuuO.js';
2
+ export { d as CallMessage, E as ErrorMessage, I as InferInput, e as InferOutput, M as MutationOptions, P as PatchMessage, b as ReactiveClient, m as ReactiveClientProvider, f as ResultMessage, g as SnapshotMessage, h as SubscribeMessage, i as Subscription, j as SubscriptionOptions, T as TypedReactiveClient, U as UnsubscribeMessage, k as createProcedureHooks, c as createReactiveClient, l as createReactiveHooks, u as useClient, n as useConnectionState, o as useMutation, p as useReactiveClient, q as useReactiveClientOrThrow, r as useSubscription } from './react-D_NLHuuO.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
5
5
 
@@ -17,6 +17,8 @@ declare class WebSocketManager {
17
17
  private stateHandlers;
18
18
  private _connectionId;
19
19
  private connectionIdResolvers;
20
+ /** Flag to indicate intentional disconnect (skip auto-reconnect) */
21
+ private intentionalDisconnect;
20
22
  constructor(config: ReactiveClientConfig);
21
23
  /**
22
24
  * Get the current connection ID (null if not connected)
@@ -38,6 +40,11 @@ declare class WebSocketManager {
38
40
  * Disconnect from the WebSocket server
39
41
  */
40
42
  disconnect(): void;
43
+ /**
44
+ * Force reconnect - closes existing connection and reconnects
45
+ * Useful for recovering from stale connections
46
+ */
47
+ forceReconnect(): void;
41
48
  /**
42
49
  * Send a message to the server
43
50
  */
package/dist/client.js CHANGED
@@ -1,3 +1,3 @@
1
- export { ReactiveClient, ReactiveClientProvider, WebSocketManager, applyPatches, createProcedureHooks, createReactiveClient, createReactiveHooks, useClient, useConnectionState, useMutation, useReactiveClient, useReactiveClientOrThrow, useSubscription } from './chunk-7RHIKRY7.js';
1
+ export { ReactiveClient, ReactiveClientProvider, WebSocketManager, applyPatches, createProcedureHooks, createReactiveClient, createReactiveHooks, useClient, useConnectionState, useMutation, useReactiveClient, useReactiveClientOrThrow, useSubscription } from './chunk-2KC44Q5I.js';
2
2
  //# sourceMappingURL=client.js.map
3
3
  //# sourceMappingURL=client.js.map
@@ -241,6 +241,11 @@ declare class ReactiveClient {
241
241
  * Disconnect from the server
242
242
  */
243
243
  disconnect(): void;
244
+ /**
245
+ * Force reconnect - closes existing connection and reconnects
246
+ * Useful for recovering from stale connections
247
+ */
248
+ forceReconnect(): void;
244
249
  /**
245
250
  * Update the headers getter for HTTP requests.
246
251
  * Useful for dynamically setting auth or user context headers.
@@ -324,9 +329,12 @@ declare class ReactiveClient {
324
329
  */
325
330
  private findSubscriptionByPath;
326
331
  /**
327
- * Apply an optimistic update to a subscription's data
332
+ * Apply an optimistic update to a subscription's data.
333
+ * Stores the original data for rollback (on mutation error) or as base for
334
+ * incoming server patches. Safe to call after external API calls — the next
335
+ * server snapshot/patch will reconcile automatically.
328
336
  */
329
- private applyOptimisticUpdate;
337
+ applyOptimisticUpdate(subscriptionId: string, updater: (data: unknown) => unknown): void;
330
338
  /**
331
339
  * Rollback an optimistic update
332
340
  */
@@ -394,6 +402,7 @@ declare function useSubscription<TData>(path: string, options?: SubscriptionOpti
394
402
  error: Error | undefined;
395
403
  disabled: boolean;
396
404
  refetch: () => Promise<void>;
405
+ setData: (updater: (data: TData) => TData) => void;
397
406
  };
398
407
  /**
399
408
  * Hook for mutations with automatic optimistic updates
@@ -440,6 +449,7 @@ type TypedProcedureHooks<TInput, TOutput> = {
440
449
  error: Error | undefined;
441
450
  disabled: boolean;
442
451
  refetch: () => Promise<void>;
452
+ setData: (updater: (data: TOutput) => TOutput) => void;
443
453
  };
444
454
  useMutation: (options?: MutationOptions<TInput, TOutput>) => {
445
455
  mutate: (input: TInput) => Promise<TOutput>;
@@ -508,6 +518,7 @@ declare function createReactiveHooks(): {
508
518
  error: Error | undefined;
509
519
  disabled: boolean;
510
520
  refetch: () => Promise<void>;
521
+ setData: (updater: (data: TData) => TData) => void;
511
522
  };
512
523
  useMutation: <TPath extends string, TInput = unknown, TOutput = unknown>(path: TPath, options?: MutationOptions<TInput, TOutput>) => {
513
524
  mutate: (input: TInput) => Promise<TOutput>;
@@ -530,6 +541,7 @@ declare function createProcedureHooks<TInput, TOutput>(path: string): {
530
541
  error: Error | undefined;
531
542
  disabled: boolean;
532
543
  refetch: () => Promise<void>;
544
+ setData: (updater: (data: TOutput) => TOutput) => void;
533
545
  };
534
546
  useMutation: (options?: MutationOptions<TInput, TOutput>) => {
535
547
  mutate: (input: TInput) => Promise<TOutput>;
package/dist/react.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { m as ReactiveClientProvider, k as createProcedureHooks, l as createReactiveHooks, u as useClient, n as useConnectionState, o as useMutation, p as useReactiveClient, q as useReactiveClientOrThrow, r as useSubscription } from './react-DJzw1_9P.js';
1
+ export { m as ReactiveClientProvider, k as createProcedureHooks, l as createReactiveHooks, u as useClient, n as useConnectionState, o as useMutation, p as useReactiveClient, q as useReactiveClientOrThrow, r as useSubscription } from './react-D_NLHuuO.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
package/dist/react.js CHANGED
@@ -1,3 +1,3 @@
1
- export { ReactiveClientProvider, createProcedureHooks, createReactiveHooks, useClient, useConnectionState, useMutation, useReactiveClient, useReactiveClientOrThrow, useSubscription } from './chunk-7RHIKRY7.js';
1
+ export { ReactiveClientProvider, createProcedureHooks, createReactiveHooks, useClient, useConnectionState, useMutation, useReactiveClient, useReactiveClientOrThrow, useSubscription } from './chunk-2KC44Q5I.js';
2
2
  //# sourceMappingURL=react.js.map
3
3
  //# sourceMappingURL=react.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynamodb-reactive",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "type": "module",
5
5
  "description": "A Serverless, Reactive tRPC replacement for AWS DynamoDB",
6
6
  "keywords": [
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../client/src/patcher.ts","../../client/src/websocket.ts","../../client/src/client.ts","../../client/src/react.tsx"],"names":["error","debug"],"mappings":"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","file":"chunk-7RHIKRY7.js","sourcesContent":["import jsonpatch, { type Operation } from 'fast-json-patch';\n\nimport type { JsonPatch } from './types.js';\n\nconst { applyPatch } = jsonpatch;\n\n/**\n * Apply JSON patches to a document\n */\nexport function applyPatches<T>(document: T, patches: JsonPatch[]): T {\n if (patches.length === 0) {\n return document;\n }\n\n const operations: Operation[] = patches.map((patch) => {\n const op: Operation = {\n op: patch.op,\n path: patch.path,\n } as Operation;\n\n if ('value' in patch && patch.value !== undefined) {\n (op as { value: unknown }).value = patch.value;\n }\n if ('from' in patch && patch.from !== undefined) {\n (op as { from: string }).from = patch.from;\n }\n\n return op;\n });\n\n try {\n const result = applyPatch(\n structuredClone(document),\n operations,\n true, // Validate operations\n false, // Don't mutate the original\n );\n\n return result.newDocument as T;\n } catch (error) {\n throw new Error('Failed to apply patches', { cause: error });\n }\n}\n","/* eslint-disable no-console */\nimport { error } from 'ag-common/dist/common/helpers/log.js';\n\nimport type {\n ClientMessage,\n ConnectionState,\n ReactiveClientConfig,\n ServerMessage,\n} from './types.js';\n\n/**\n * WebSocket manager with automatic reconnection\n */\nexport class WebSocketManager {\n private config: Required<\n Omit<\n ReactiveClientConfig,\n 'auth' | 'httpUrl' | 'headers' | 'onConnect' | 'onDisconnect' | 'onError'\n >\n > &\n ReactiveClientConfig;\n private ws: WebSocket | null = null;\n private state: ConnectionState = 'disconnected';\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private messageQueue: ClientMessage[] = [];\n private messageHandlers = new Set<(message: ServerMessage) => void>();\n private stateHandlers = new Set<(state: ConnectionState) => void>();\n private _connectionId: string | null = null;\n private connectionIdResolvers: Array<(id: string) => void> = [];\n\n constructor(config: ReactiveClientConfig) {\n this.config = {\n autoReconnect: true,\n reconnectDelay: 1000,\n maxReconnectAttempts: 10,\n ...config,\n };\n }\n\n /**\n * Get the current connection ID (null if not connected)\n */\n get connectionId(): string | null {\n return this._connectionId;\n }\n\n /**\n * Wait for the connection ID to be available\n */\n waitForConnectionId(): Promise<string> {\n if (this._connectionId) {\n return Promise.resolve(this._connectionId);\n }\n return new Promise((resolve) => {\n this.connectionIdResolvers.push(resolve);\n });\n }\n\n /**\n * Get current connection state\n */\n getState(): ConnectionState {\n return this.state;\n }\n\n /**\n * Connect to the WebSocket server\n */\n async connect(): Promise<void> {\n if (this.state === 'connected' || this.state === 'connecting') {\n return;\n }\n\n this.setState('connecting');\n\n try {\n const url = await this.buildUrl();\n this.ws = new WebSocket(url);\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n // Send init message to get connectionId from server\n // Don't set state to 'connected' until we receive connectionId\n this.ws?.send(JSON.stringify({ type: 'init' }));\n };\n\n this.ws.onclose = (event) => {\n this.ws = null;\n this._connectionId = null;\n this.setState('disconnected');\n this.config.onDisconnect?.();\n\n if (this.config.autoReconnect && !event.wasClean) {\n this.scheduleReconnect();\n }\n };\n\n this.ws.onerror = () => {\n const error = new Error('WebSocket error');\n this.config.onError?.(error);\n };\n\n this.ws.onmessage = (event) => {\n try {\n const message = JSON.parse(event.data) as ServerMessage;\n\n // Handle 'connected' message - we got connectionId, now verify with ping/pong\n if (message.type === 'connected') {\n this._connectionId = message.connectionId;\n // Send ping to verify the connection is fully working\n this.ws?.send(JSON.stringify({ type: 'ping' }));\n return;\n }\n\n // Handle 'pong' message - connection is verified, now we're truly connected\n if (message.type === 'pong') {\n this.setState('connected');\n this.flushMessageQueue();\n this.config.onConnect?.();\n\n // Resolve any pending waitForConnectionId promises\n for (const resolve of this.connectionIdResolvers) {\n resolve(this._connectionId!);\n }\n this.connectionIdResolvers = [];\n return;\n }\n\n this.handleMessage(message);\n } catch (e) {\n error('Failed to parse WebSocket message:', e);\n }\n };\n } catch (e) {\n this.setState('disconnected');\n this.config.onError?.(e instanceof Error ? e : new Error(String(e)));\n\n if (this.config.autoReconnect) {\n this.scheduleReconnect();\n }\n }\n }\n\n /**\n * Disconnect from the WebSocket server\n */\n disconnect(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n this.ws.close(1000, 'Client disconnect');\n this.ws = null;\n }\n\n this._connectionId = null;\n this.setState('disconnected');\n }\n\n /**\n * Send a message to the server\n */\n send(message: ClientMessage): void {\n // Check both our state and the actual WebSocket readyState\n if (this.state === 'connected' && this.ws?.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(message));\n } else {\n // Queue message for when we reconnect\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Subscribe to incoming messages\n */\n onMessage(handler: (message: ServerMessage) => void): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n /**\n * Subscribe to connection state changes\n */\n onStateChange(handler: (state: ConnectionState) => void): () => void {\n this.stateHandlers.add(handler);\n return () => this.stateHandlers.delete(handler);\n }\n\n private async buildUrl(): Promise<string> {\n let url = this.config.url;\n\n if (this.config.auth) {\n const token =\n typeof this.config.auth === 'function'\n ? await this.config.auth()\n : this.config.auth;\n\n const separator = url.includes('?') ? '&' : '?';\n url = `${url}${separator}token=${encodeURIComponent(token)}`;\n }\n\n return url;\n }\n\n private setState(state: ConnectionState): void {\n this.state = state;\n for (const handler of this.stateHandlers) {\n handler(state);\n }\n }\n\n private handleMessage(message: ServerMessage): void {\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {\n error('Max reconnection attempts reached');\n return;\n }\n\n this.setState('reconnecting');\n this.reconnectAttempts++;\n\n // Exponential backoff with jitter\n const delay =\n Math.min(\n this.config.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000, // Max 30 seconds\n ) *\n (0.5 + Math.random() * 0.5);\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n void this.connect();\n }, delay);\n }\n\n private flushMessageQueue(): void {\n const queue = this.messageQueue;\n this.messageQueue = [];\n\n for (const message of queue) {\n this.send(message);\n }\n }\n}\n","import { debug } from 'ag-common/dist/common/helpers/log.js';\n\nimport { applyPatches } from './patcher.js';\nimport type {\n ConnectionState,\n JsonPatch,\n MutationOptions,\n ReactiveClientConfig,\n ServerMessage,\n Subscription,\n SubscriptionOptions,\n} from './types.js';\nimport { WebSocketManager } from './websocket.js';\n\n/**\n * Default HTTP URL for subscribe/call requests (Next.js API route)\n */\nconst DEFAULT_HTTP_URL = '/api/reactive';\n\n/**\n * Generate a unique subscription ID\n */\nfunction generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Internal subscription state\n */\ninterface SubscriptionState<TData> {\n id: string;\n path: string;\n input: unknown;\n data: TData | undefined;\n loading: boolean;\n error: Error | undefined;\n listeners: Set<() => void>;\n options: SubscriptionOptions<unknown>;\n}\n\n/**\n * Pending call state\n */\ninterface PendingCall {\n resolve: (data: unknown) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Reactive client for type-safe subscriptions\n */\nexport class ReactiveClient {\n private wsManager: WebSocketManager;\n private httpUrl: string;\n private authGetter?: () => string | Promise<string>;\n private headersGetter?: () =>\n | Record<string, string>\n | Promise<Record<string, string>>;\n private subscriptions = new Map<string, SubscriptionState<unknown>>();\n private pendingCalls = new Map<string, PendingCall>();\n private connectionState: ConnectionState = 'disconnected';\n private stateListeners = new Set<(state: ConnectionState) => void>();\n // Stores original data for rollback when optimistic updates fail\n private optimisticUpdates = new Map<string, unknown>();\n\n constructor(config: ReactiveClientConfig) {\n this.wsManager = new WebSocketManager(config);\n this.httpUrl = config.httpUrl ?? DEFAULT_HTTP_URL;\n\n // Store auth getter for HTTP requests\n if (typeof config.auth === 'function') {\n this.authGetter = config.auth;\n } else if (config.auth) {\n this.authGetter = () => config.auth as string;\n }\n\n // Store headers getter for HTTP requests\n if (typeof config.headers === 'function') {\n this.headersGetter = config.headers;\n } else if (config.headers) {\n this.headersGetter = () => config.headers as Record<string, string>;\n }\n\n // Handle incoming messages (patches come via WebSocket)\n this.wsManager.onMessage((message) => this.handleMessage(message));\n\n // Handle connection state changes\n this.wsManager.onStateChange((state) => {\n this.connectionState = state;\n this.notifyStateListeners();\n\n if (state === 'connected') {\n this.resubscribeAll();\n }\n });\n }\n\n /**\n * Connect to the server\n */\n async connect(): Promise<void> {\n await this.wsManager.connect();\n }\n\n /**\n * Disconnect from the server\n */\n disconnect(): void {\n this.wsManager.disconnect();\n }\n\n /**\n * Update the headers getter for HTTP requests.\n * Useful for dynamically setting auth or user context headers.\n */\n setHeaders(\n headers:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>),\n ): void {\n if (typeof headers === 'function') {\n this.headersGetter = headers;\n } else {\n this.headersGetter = () => headers;\n }\n }\n\n /**\n * Get current connection state\n */\n getConnectionState(): ConnectionState {\n return this.connectionState;\n }\n\n /**\n * Subscribe to connection state changes\n */\n onConnectionStateChange(\n listener: (state: ConnectionState) => void,\n ): () => void {\n this.stateListeners.add(listener);\n return () => this.stateListeners.delete(listener);\n }\n\n /**\n * Subscribe to a procedure via HTTP.\n * Snapshot is returned via HTTP, patches come via WebSocket.\n */\n subscribe<TData>(\n path: string,\n options: SubscriptionOptions<unknown> = {},\n ): Subscription<TData> {\n const id = generateId();\n\n const state: SubscriptionState<TData> = {\n id,\n path,\n input: options.input,\n data: undefined,\n loading: true,\n error: undefined,\n listeners: new Set(),\n options,\n };\n\n this.subscriptions.set(id, state as SubscriptionState<unknown>);\n\n // Send subscribe request via HTTP (async)\n this.sendSubscribeRequest(id, path, options.input).catch((error) => {\n state.error = error instanceof Error ? error : new Error(String(error));\n state.loading = false;\n this.notifySubscriptionListeners(id);\n options.onError?.(state.error);\n });\n\n const subscription: Subscription<TData> = {\n id,\n get data() {\n return state.data;\n },\n get loading() {\n return state.loading;\n },\n get error() {\n return state.error;\n },\n unsubscribe: () => this.unsubscribe(id),\n refetch: () => this.refetch(id),\n };\n\n return subscription;\n }\n\n /**\n * Send subscribe request via HTTP\n */\n private async sendSubscribeRequest(\n subscriptionId: string,\n path: string,\n input: unknown,\n ): Promise<void> {\n // Wait for connectionId to be available\n const connectionId = await this.wsManager.waitForConnectionId();\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n // Add custom headers if configured\n if (this.headersGetter) {\n const customHeaders = await this.headersGetter();\n Object.assign(headers, customHeaders);\n }\n\n // Add auth header if configured\n if (this.authGetter) {\n const token = await this.authGetter();\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(this.httpUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n type: 'subscribe',\n connectionId,\n subscriptionId,\n path,\n input,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `Subscribe failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const result = (await response.json()) as {\n type: string;\n message?: string;\n data?: unknown;\n };\n\n if (result.type === 'error') {\n throw new Error(result.message ?? 'Unknown error');\n }\n\n if (result.type === 'snapshot') {\n this.handleSnapshot(subscriptionId, result.data);\n }\n }\n\n /**\n * Call a mutation procedure via HTTP with optimistic update support.\n * All optimistic updates are applied INSTANTLY (before HTTP request).\n */\n async call<TInput, TOutput>(\n path: string,\n input: TInput,\n options?: MutationOptions<TInput, TOutput>,\n ): Promise<TOutput> {\n const invalidatesPath = options?.invalidates;\n const updateType = options?.optimisticUpdate;\n let targetSubscriptionId: string | undefined;\n\n // Find subscription to optimistically update\n if (invalidatesPath) {\n targetSubscriptionId = this.findSubscriptionByPath(invalidatesPath);\n debug(\n '[optimistic] Looking for subscription:',\n invalidatesPath,\n '-> found:',\n targetSubscriptionId ?? 'NONE',\n );\n }\n\n // Apply INSTANT optimistic update (before HTTP request)\n if (targetSubscriptionId) {\n debug(\n '[optimistic] Applying update type:',\n updateType,\n 'to subscription:',\n targetSubscriptionId,\n );\n const state = this.subscriptions.get(targetSubscriptionId);\n const currentData = state?.data;\n\n if (updateType === 'remove') {\n // Remove: filter out item by id\n const inputId = (input as { id?: string }).id;\n if (inputId) {\n this.applyOptimisticUpdate(targetSubscriptionId, (data) => {\n if (!Array.isArray(data)) return data;\n return data.filter((item: { id?: string }) => item.id !== inputId);\n });\n }\n } else if (updateType === 'merge') {\n // Merge: find item by id and merge input fields into it\n const inputWithId = input as { id?: string };\n if (inputWithId.id) {\n this.applyOptimisticUpdate(targetSubscriptionId, (data) => {\n if (!Array.isArray(data)) return data;\n const idx = data.findIndex(\n (item: { id?: string }) => item.id === inputWithId.id,\n );\n if (idx >= 0) {\n // Merge input into existing item\n return [\n ...data.slice(0, idx),\n { ...data[idx], ...input },\n ...data.slice(idx + 1),\n ];\n }\n return data;\n });\n } else if (options?.optimisticData) {\n // For creates without id, use provided optimisticData\n const optimistic =\n typeof options.optimisticData === 'function'\n ? (\n options.optimisticData as (\n input: TInput,\n data: unknown[],\n ) => TOutput\n )(input, Array.isArray(currentData) ? currentData : [])\n : options.optimisticData;\n if (optimistic) {\n this.applyOptimisticUpdate(targetSubscriptionId, (data) => {\n if (!Array.isArray(data)) return data;\n return [optimistic, ...data];\n });\n }\n }\n } else if (typeof updateType === 'function') {\n // Custom update function - apply instantly\n this.applyOptimisticUpdate(targetSubscriptionId, (data) => {\n if (!Array.isArray(data)) return data;\n return updateType(data, input, undefined);\n });\n }\n }\n\n // Wait for connectionId to be available\n const connectionId = await this.wsManager.waitForConnectionId();\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n // Add custom headers if configured\n if (this.headersGetter) {\n const customHeaders = await this.headersGetter();\n Object.assign(headers, customHeaders);\n }\n\n // Add auth header if configured\n if (this.authGetter) {\n const token = await this.authGetter();\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n try {\n const response = await fetch(this.httpUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n type: 'call',\n connectionId,\n path,\n input,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `Call failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const result = (await response.json()) as {\n type: string;\n message?: string;\n data?: unknown;\n };\n\n if (result.type === 'error') {\n throw new Error(result.message ?? 'Unknown error');\n }\n\n const data = result.data as TOutput;\n\n // After HTTP success, reconcile with real server data\n if (targetSubscriptionId && updateType === 'merge') {\n const resultWithId = data as { id?: string };\n if (resultWithId.id) {\n this.applyOptimisticUpdate(targetSubscriptionId, (currentData) => {\n if (!Array.isArray(currentData)) return currentData;\n const idx = currentData.findIndex(\n (item: { id?: string }) => item.id === resultWithId.id,\n );\n if (idx >= 0) {\n // Update with real server data\n return [\n ...currentData.slice(0, idx),\n data,\n ...currentData.slice(idx + 1),\n ];\n } else {\n // New item - add it (and remove any temp items)\n return [\n data,\n ...currentData.filter(\n (item: { id?: string }) =>\n item.id && !item.id.startsWith('temp-'),\n ),\n ];\n }\n });\n }\n }\n\n return data;\n } catch (error) {\n // Rollback on error\n if (targetSubscriptionId) {\n this.rollbackOptimisticUpdate(targetSubscriptionId);\n }\n throw error;\n }\n }\n\n /**\n * Unsubscribe from a subscription\n */\n private unsubscribe(id: string): void {\n const state = this.subscriptions.get(id);\n if (!state) return;\n\n this.subscriptions.delete(id);\n\n this.wsManager.send({\n type: 'unsubscribe',\n subscriptionId: id,\n });\n }\n\n /**\n * Refetch a subscription via HTTP\n */\n private async refetch(id: string): Promise<void> {\n const state = this.subscriptions.get(id);\n if (!state) return;\n\n state.loading = true;\n this.notifySubscriptionListeners(id);\n\n try {\n await this.sendSubscribeRequest(id, state.path, state.input);\n } catch (error) {\n state.error = error instanceof Error ? error : new Error(String(error));\n state.loading = false;\n this.notifySubscriptionListeners(id);\n state.options.onError?.(state.error);\n }\n }\n\n /**\n * Handle incoming server messages.\n * Note: 'connected' messages are handled by WebSocketManager before reaching here.\n */\n private handleMessage(message: ServerMessage): void {\n switch (message.type) {\n case 'connected':\n // Handled by WebSocketManager - should not reach here\n break;\n\n case 'pong':\n // Heartbeat response - no action needed\n break;\n\n case 'snapshot':\n this.handleSnapshot(message.subscriptionId, message.data);\n break;\n\n case 'patch':\n this.handlePatch(message.subscriptionId, message.patches);\n break;\n\n case 'result':\n this.handleResult(message.callId, message.data);\n break;\n\n case 'error':\n this.handleError(message);\n break;\n }\n }\n\n /**\n * Handle a snapshot message\n */\n private handleSnapshot(subscriptionId: string, data: unknown): void {\n const state = this.subscriptions.get(subscriptionId);\n if (!state) return;\n\n // Clear optimistic state since we have authoritative data\n this.clearOptimisticUpdate(subscriptionId);\n\n state.data = data;\n state.loading = false;\n state.error = undefined;\n\n this.notifySubscriptionListeners(subscriptionId);\n state.options.onData?.(data);\n }\n\n /**\n * Handle a patch message\n */\n private handlePatch(subscriptionId: string, patches: JsonPatch[]): void {\n const state = this.subscriptions.get(subscriptionId);\n if (!state || state.data === undefined) return;\n\n // If we have optimistic state, apply patch to the ORIGINAL data\n // This prevents conflicts when patch tries to modify already-modified data\n const originalData = this.optimisticUpdates.get(subscriptionId);\n const baseData = originalData !== undefined ? originalData : state.data;\n\n // Clear optimistic state since we have authoritative patch data\n this.clearOptimisticUpdate(subscriptionId);\n\n try {\n state.data = applyPatches(baseData, patches);\n this.notifySubscriptionListeners(subscriptionId);\n state.options.onData?.(state.data);\n } catch (error) {\n state.error = error instanceof Error ? error : new Error(String(error));\n this.notifySubscriptionListeners(subscriptionId);\n state.options.onError?.(state.error);\n }\n }\n\n /**\n * Handle a result message\n */\n private handleResult(callId: string, data: unknown): void {\n const pending = this.pendingCalls.get(callId);\n if (!pending) return;\n\n this.pendingCalls.delete(callId);\n pending.resolve(data);\n }\n\n /**\n * Handle an error message\n */\n private handleError(message: {\n message: string;\n subscriptionId?: string;\n callId?: string;\n }): void {\n const error = new Error(message.message);\n\n if (message.subscriptionId) {\n const state = this.subscriptions.get(message.subscriptionId);\n if (state) {\n state.error = error;\n state.loading = false;\n this.notifySubscriptionListeners(message.subscriptionId);\n state.options.onError?.(error);\n }\n }\n\n if (message.callId) {\n const pending = this.pendingCalls.get(message.callId);\n if (pending) {\n this.pendingCalls.delete(message.callId);\n pending.reject(error);\n }\n }\n }\n\n /**\n * Resubscribe to all subscriptions after reconnect via HTTP\n */\n private resubscribeAll(): void {\n for (const [id, state] of this.subscriptions) {\n if (state.options.resubscribeOnReconnect !== false) {\n state.loading = true;\n this.notifySubscriptionListeners(id);\n\n // Re-subscribe via HTTP\n this.sendSubscribeRequest(id, state.path, state.input).catch(\n (error) => {\n state.error =\n error instanceof Error ? error : new Error(String(error));\n state.loading = false;\n this.notifySubscriptionListeners(id);\n state.options.onError?.(state.error);\n },\n );\n }\n }\n }\n\n /**\n * Notify subscription listeners of state changes\n */\n private notifySubscriptionListeners(id: string): void {\n const state = this.subscriptions.get(id);\n if (!state) return;\n\n for (const listener of state.listeners) {\n listener();\n }\n }\n\n /**\n * Notify connection state listeners\n */\n private notifyStateListeners(): void {\n for (const listener of this.stateListeners) {\n listener(this.connectionState);\n }\n }\n\n /**\n * Add a listener for subscription state changes\n * Used internally by React hooks\n */\n addSubscriptionListener(id: string, listener: () => void): () => void {\n const state = this.subscriptions.get(id);\n if (!state) return () => {};\n\n state.listeners.add(listener);\n return () => state.listeners.delete(listener);\n }\n\n /**\n * Get subscription state\n * Used internally by React hooks\n */\n getSubscriptionState<TData>(\n id: string,\n ): SubscriptionState<TData> | undefined {\n return this.subscriptions.get(id) as SubscriptionState<TData> | undefined;\n }\n\n /**\n * Find subscription by path\n */\n private findSubscriptionByPath(path: string): string | undefined {\n debug(\n '[optimistic] Searching for path:',\n path,\n 'in subscriptions:',\n Array.from(this.subscriptions.entries()).map(([id, s]) => ({\n id,\n path: s.path,\n })),\n );\n for (const [id, state] of this.subscriptions) {\n if (state.path === path) {\n return id;\n }\n }\n return undefined;\n }\n\n /**\n * Apply an optimistic update to a subscription's data\n */\n private applyOptimisticUpdate(\n subscriptionId: string,\n updater: (data: unknown) => unknown,\n ): void {\n const state = this.subscriptions.get(subscriptionId);\n if (!state) {\n debug(\n '[optimistic] applyOptimisticUpdate: subscription not found:',\n subscriptionId,\n );\n return;\n }\n if (state.data === undefined) {\n debug(\n '[optimistic] applyOptimisticUpdate: subscription data is undefined (still loading?):',\n subscriptionId,\n );\n return;\n }\n debug(\n '[optimistic] applyOptimisticUpdate: applying update, current data length:',\n Array.isArray(state.data) ? state.data.length : 'not array',\n );\n\n // Store original data for rollback (only if not already stored)\n if (!this.optimisticUpdates.has(subscriptionId)) {\n this.optimisticUpdates.set(\n subscriptionId,\n JSON.parse(JSON.stringify(state.data)),\n );\n }\n\n // Apply the update\n state.data = updater(state.data);\n this.notifySubscriptionListeners(subscriptionId);\n }\n\n /**\n * Rollback an optimistic update\n */\n private rollbackOptimisticUpdate(subscriptionId: string): void {\n const original = this.optimisticUpdates.get(subscriptionId);\n if (original === undefined) return;\n\n const state = this.subscriptions.get(subscriptionId);\n if (state) {\n state.data = original;\n this.notifySubscriptionListeners(subscriptionId);\n }\n this.optimisticUpdates.delete(subscriptionId);\n }\n\n /**\n * Clear optimistic state (called when real data arrives)\n */\n private clearOptimisticUpdate(subscriptionId: string): void {\n this.optimisticUpdates.delete(subscriptionId);\n }\n}\n\n/**\n * Create a type-safe reactive client\n */\nexport function createReactiveClient<TRouter>(\n config: ReactiveClientConfig,\n): TypedReactiveClient<TRouter> {\n const client = new ReactiveClient(config);\n return createTypedProxy(client, []) as TypedReactiveClient<TRouter>;\n}\n\n/**\n * Type-safe client proxy type\n */\nexport type TypedReactiveClient<TRouter> = {\n [K in keyof TRouter]: TRouter[K] extends { query: unknown }\n ? {\n useSubscription: <TData = unknown>(\n input?: unknown,\n options?: Omit<SubscriptionOptions<unknown>, 'input'>,\n ) => Subscription<TData>;\n }\n : TRouter[K] extends { mutation: unknown }\n ? {\n mutate: <TInput, TOutput>(input: TInput) => Promise<TOutput>;\n }\n : TypedReactiveClient<TRouter[K]>;\n} & {\n _client: ReactiveClient;\n connect: () => Promise<void>;\n disconnect: () => void;\n};\n\n/**\n * Create a typed proxy for path-based access\n */\nfunction createTypedProxy(client: ReactiveClient, path: string[]): unknown {\n return new Proxy(\n {},\n {\n get(_target, prop) {\n if (prop === '_client') return client;\n if (prop === 'connect') return () => client.connect();\n if (prop === 'disconnect') return () => client.disconnect();\n\n if (typeof prop !== 'string') return undefined;\n\n const newPath = [...path, prop];\n\n // Check if this is a subscription or mutation\n if (prop === 'useSubscription') {\n return (input?: unknown, options?: SubscriptionOptions<unknown>) => {\n const parentPath = path.join('.');\n return client.subscribe(parentPath, { ...options, input });\n };\n }\n\n if (prop === 'mutate') {\n return async (input: unknown) => {\n const parentPath = path.join('.');\n // Auto-detect invalidates path: 'todos.toggle' → 'todos.list'\n const invalidatesPath =\n path.length >= 2\n ? `${path.slice(0, -1).join('.')}.list`\n : undefined;\n // Auto-detect update type: '*.delete' → 'remove', others → 'merge'\n const updateType = parentPath.endsWith('.delete')\n ? ('remove' as const)\n : ('merge' as const);\n return client.call(parentPath, input, {\n invalidates: invalidatesPath,\n optimisticUpdate: updateType,\n });\n };\n }\n\n return createTypedProxy(client, newPath);\n },\n },\n );\n}\n","import { debug, warn } from 'ag-common/dist/common/helpers/log.js';\nimport {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\n\nimport { ReactiveClient } from './client.js';\nimport type {\n ConnectionState,\n MutationOptions,\n ReactiveClientConfig,\n Subscription,\n SubscriptionOptions,\n} from './types.js';\n\n/**\n * Context for the reactive client\n */\nconst ReactiveClientContext = createContext<ReactiveClient | null>(null);\n\n/**\n * Provider component for the reactive client\n *\n * If no config.url or client is provided, WebSocket features are disabled\n * and children are rendered without the reactive context.\n */\nexport function ReactiveClientProvider({\n children,\n config,\n client: externalClient,\n}: {\n children: ReactNode;\n config?: ReactiveClientConfig;\n client?: ReactiveClient;\n}) {\n // Extract URL for stable dependency\n const url = config?.url;\n const hasUrl = Boolean(url);\n\n // Always start with null to avoid hydration mismatch\n // Client will be created in useEffect after hydration\n const [client, setClient] = useState<ReactiveClient | null>(\n externalClient ?? null,\n );\n\n // Create client after mount (avoids hydration mismatch)\n useEffect(() => {\n // Skip if we have an external client or no URL\n if (externalClient || !url) return;\n\n // Create client if we don't have one\n if (!client) {\n const newClient = new ReactiveClient({ ...config, url });\n setClient(newClient);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, externalClient]);\n\n // Connect/disconnect effect\n useEffect(() => {\n if (!client) return;\n\n void client.connect();\n\n return () => {\n client.disconnect();\n };\n }, [client]);\n\n // Log warning if no URL configured (only once in dev)\n useEffect(() => {\n if (!hasUrl && process.env.NODE_ENV === 'development') {\n warn(\n '[dynamodb-reactive] WebSocket URL not configured, real-time features disabled',\n );\n }\n }, [hasUrl]);\n\n // Always render with context provider - hooks will handle null client\n return (\n <ReactiveClientContext.Provider value={client}>\n {children}\n </ReactiveClientContext.Provider>\n );\n}\n\n/**\n * Hook to get the reactive client\n * Returns null if WebSocket is not configured\n */\nexport function useReactiveClient(): ReactiveClient | null {\n return useContext(ReactiveClientContext);\n}\n\n/**\n * Hook to get the reactive client, throwing if not available\n */\nexport function useReactiveClientOrThrow(): ReactiveClient {\n const client = useContext(ReactiveClientContext);\n if (!client) {\n throw new Error(\n 'useReactiveClientOrThrow must be used within a ReactiveClientProvider with a configured URL',\n );\n }\n return client;\n}\n\n/**\n * Hook to get the connection state\n * Returns 'disabled' if WebSocket is not configured\n */\nexport function useConnectionState(): ConnectionState | 'disabled' {\n const client = useReactiveClient();\n\n return useSyncExternalStore(\n (callback) => {\n if (!client) return () => {};\n return client.onConnectionStateChange(callback);\n },\n () => (client ? client.getConnectionState() : 'disabled'),\n () => 'disabled' as const,\n );\n}\n\n/**\n * Hook for reactive subscriptions\n * Returns disabled state if WebSocket is not configured\n */\nexport function useSubscription<TData>(\n path: string,\n options: SubscriptionOptions<unknown> = {},\n): {\n data: TData | undefined;\n loading: boolean;\n error: Error | undefined;\n disabled: boolean;\n refetch: () => Promise<void>;\n} {\n const client = useReactiveClient();\n const subscriptionRef = useRef<Subscription<TData> | null>(null);\n const [state, setState] = useState<{\n data: TData | undefined;\n loading: boolean;\n error: Error | undefined;\n }>({\n data: undefined,\n loading: !client ? false : true,\n error: undefined,\n });\n\n // Serialize options for dependency comparison\n const inputKey = JSON.stringify(options.input);\n // Store callbacks in refs to avoid re-subscribing when they change\n const onDataRef = useRef(options.onData);\n const onErrorRef = useRef(options.onError);\n onDataRef.current = options.onData;\n onErrorRef.current = options.onError;\n\n useEffect(() => {\n if (!client) return;\n\n // Parse input from inputKey to ensure we use the serialized value\n const input = inputKey ? JSON.parse(inputKey) : undefined;\n\n const subscription = client.subscribe<TData>(path, {\n input,\n onData: (data) => {\n setState((prev) => ({\n ...prev,\n data: data as TData,\n loading: false,\n error: undefined,\n }));\n onDataRef.current?.(data);\n },\n onError: (error) => {\n setState((prev) => ({\n ...prev,\n error,\n loading: false,\n }));\n onErrorRef.current?.(error);\n },\n });\n\n subscriptionRef.current = subscription;\n\n // Register a listener for optimistic updates (notifySubscriptionListeners)\n // This ensures React state updates when optimistic changes happen\n const unregisterListener = client.addSubscriptionListener(\n subscription.id,\n () => {\n // Re-read current state from subscription\n debug(\n '[optimistic] useSubscription listener fired for:',\n path,\n 'data length:',\n Array.isArray(subscription.data) ? subscription.data.length : 'not array',\n );\n setState({\n data: subscription.data,\n loading: subscription.loading,\n error: subscription.error,\n });\n },\n );\n\n // Update state from subscription\n setState({\n data: subscription.data,\n loading: subscription.loading,\n error: subscription.error,\n });\n\n return () => {\n unregisterListener();\n subscription.unsubscribe();\n subscriptionRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, path, inputKey]);\n\n const refetch = async () => {\n if (subscriptionRef.current) {\n setState((prev) => ({ ...prev, loading: true }));\n await subscriptionRef.current.refetch();\n }\n };\n\n return {\n ...state,\n disabled: !client,\n refetch,\n };\n}\n\n/**\n * Hook for mutations with automatic optimistic updates\n *\n * Auto-detection:\n * - `invalidates`: Auto-detected from path (e.g., 'todos.toggle' -> 'todos.list')\n * - `optimisticUpdate`: Auto-detected from path ('*.delete' -> 'remove', others -> 'merge')\n *\n * You can override these with explicit options.\n */\nexport function useMutation<TInput, TOutput>(\n path: string,\n options?: MutationOptions<TInput, TOutput>,\n): {\n mutate: (input: TInput) => Promise<TOutput>;\n data: TOutput | undefined;\n loading: boolean;\n error: Error | undefined;\n disabled: boolean;\n reset: () => void;\n} {\n const client = useReactiveClient();\n const [state, setState] = useState<{\n data: TOutput | undefined;\n loading: boolean;\n error: Error | undefined;\n }>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n // Auto-detect invalidates path from mutation path\n // e.g., 'todos.toggle' -> 'todos.list', 'todos.create' -> 'todos.list'\n const autoInvalidates =\n options?.invalidates ??\n (() => {\n const parts = path.split('.');\n if (parts.length >= 2) {\n return `${parts.slice(0, -1).join('.')}.list`;\n }\n return undefined;\n })();\n\n // Auto-detect update type from path\n // '*.delete' -> 'remove', others -> 'merge'\n const autoUpdateType =\n options?.optimisticUpdate ??\n (path.endsWith('.delete') ? 'remove' : 'merge');\n\n const mutate = async (input: TInput): Promise<TOutput> => {\n if (!client) {\n throw new Error('WebSocket not configured - mutations are disabled');\n }\n\n debug('[optimistic] useMutation.mutate called:', {\n path,\n autoInvalidates,\n autoUpdateType,\n input,\n });\n\n setState((prev) => ({ ...prev, loading: true, error: undefined }));\n\n try {\n const result = await client.call<TInput, TOutput>(path, input, {\n invalidates: autoInvalidates,\n optimisticUpdate: autoUpdateType,\n });\n setState({ data: result, loading: false, error: undefined });\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n setState((prev) => ({ ...prev, loading: false, error: err }));\n throw err;\n }\n };\n\n const reset = () => {\n setState({ data: undefined, loading: false, error: undefined });\n };\n\n return {\n mutate,\n ...state,\n disabled: !client,\n reset,\n };\n}\n\n/**\n * Type helper for extracting procedure input type from ProcedureDefinition\n * Uses Zod's internal _output property to extract the parsed type\n * (Zod schemas have _input/_output as actual properties for type inference)\n */\ntype ProcedureInput<T> = T extends { inputSchema?: { _output: infer I } }\n ? I\n : undefined;\n\n/**\n * Type helper for extracting procedure output type from ProcedureDefinition\n * Extracts from resolver return type using any[] for flexible argument matching\n */\ntype ProcedureOutput<T> = T extends {\n resolver: (...args: any[]) => infer TReturn; // eslint-disable-line @typescript-eslint/no-explicit-any -- contravariance requires `any`\n}\n ? Awaited<TReturn>\n : unknown;\n\n/**\n * Typed client hooks for a router procedure\n * Provides both useQuery and useMutation - use whichever matches your procedure type\n */\ntype TypedProcedureHooks<TInput, TOutput> = {\n useQuery: (\n input: TInput,\n options?: Omit<SubscriptionOptions<TInput>, 'input'>,\n ) => {\n data: TOutput | undefined;\n loading: boolean;\n error: Error | undefined;\n disabled: boolean;\n refetch: () => Promise<void>;\n };\n useMutation: (options?: MutationOptions<TInput, TOutput>) => {\n mutate: (input: TInput) => Promise<TOutput>;\n data: TOutput | undefined;\n loading: boolean;\n error: Error | undefined;\n disabled: boolean;\n reset: () => void;\n };\n};\n\n/**\n * Extract router definition from Router class or use T directly\n */\ntype ExtractRouterDefinition<T> = T extends { definition: infer TDef }\n ? TDef\n : T;\n\n/**\n * Recursive type for typed client proxy\n * Checks for 'resolver' property to identify procedures (all procedures have it)\n */\ntype TypedClientProxyRecursive<T> = T extends { resolver: unknown }\n ? TypedProcedureHooks<ProcedureInput<T>, ProcedureOutput<T>>\n : { [K in keyof T]: TypedClientProxyRecursive<T[K]> };\n\n/**\n * Client utilities available at the root level\n */\ninterface ClientUtilities {\n /**\n * Set custom headers to be sent with HTTP requests.\n * Useful for auth context (e.g., user tokens, session info).\n */\n setHeaders: (\n headers:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>),\n ) => void;\n}\n\n/**\n * Typed client proxy combining router procedures and client utilities\n */\ntype TypedClientProxy<T> = TypedClientProxyRecursive<\n ExtractRouterDefinition<T>\n> &\n ClientUtilities;\n\n/**\n * Create a typed client proxy for use in React components.\n *\n * @example\n * ```tsx\n * const client = useClient<AppRouter>();\n *\n * // Queries (subscriptions)\n * const { data, loading } = client.todos.list.useQuery({});\n *\n * // Mutations\n * const { mutate, loading } = client.todos.toggle.useMutation();\n * await mutate({ id: '123' });\n *\n * // Set custom headers for HTTP requests (e.g., for auth context)\n * client.setHeaders({ 'Authorization': 'Bearer token' });\n * ```\n */\nexport function useClient<TRouter>(): TypedClientProxy<TRouter> {\n const client = useReactiveClient();\n\n function buildProxy(path: string[]): unknown {\n return new Proxy(\n {},\n {\n get(_target, prop: string) {\n if (prop === 'useQuery') {\n // Return a hook function for subscriptions\n return function useQueryHook(\n input?: unknown,\n options?: SubscriptionOptions<unknown>,\n ) {\n const pathStr = path.join('.');\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useSubscription(pathStr, { ...options, input });\n };\n }\n\n if (prop === 'useMutation') {\n // Return a hook function for mutations\n return function useMutationHook(\n options?: MutationOptions<unknown, unknown>,\n ) {\n const pathStr = path.join('.');\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useMutation(pathStr, options);\n };\n }\n\n // Expose setHeaders from the underlying client\n if (prop === 'setHeaders') {\n return (\n headers:\n | Record<string, string>\n | (() =>\n | Record<string, string>\n | Promise<Record<string, string>>),\n ) => {\n client?.setHeaders(headers);\n };\n }\n\n return buildProxy([...path, prop]);\n },\n },\n );\n }\n\n return buildProxy([]) as TypedClientProxy<TRouter>;\n}\n\n/**\n * @deprecated Use useClient<TRouter>() instead for typed proxy access\n */\nexport function createReactiveHooks() {\n return {\n useSubscription: <TPath extends string, TData = unknown>(\n path: TPath,\n options?: SubscriptionOptions<unknown>,\n ) => useSubscription<TData>(path, options),\n\n useMutation: <TPath extends string, TInput = unknown, TOutput = unknown>(\n path: TPath,\n options?: MutationOptions<TInput, TOutput>,\n ) => useMutation<TInput, TOutput>(path, options),\n\n useConnectionState,\n useReactiveClient,\n };\n}\n\n/**\n * @deprecated Use useClient<TRouter>() instead for typed proxy access\n */\nexport function createProcedureHooks<TInput, TOutput>(path: string) {\n return {\n useSubscription: (\n input?: TInput,\n options?: Omit<SubscriptionOptions<TInput>, 'input'>,\n ) => useSubscription<TOutput>(path, { ...options, input }),\n\n useMutation: (options?: MutationOptions<TInput, TOutput>) =>\n useMutation<TInput, TOutput>(path, options),\n };\n}\n"]}