query-optimistic 0.9.0 → 0.11.0

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.
@@ -108,8 +108,7 @@ var QueryRegistry = class {
108
108
  /** Apply update directly to query cache (used when scope is provided) */
109
109
  applyDirectCacheUpdate(name, action, payload, scope) {
110
110
  if (!this.queryClient) return [];
111
- const def = this.collectionDefs.get(name);
112
- if (!def) return [];
111
+ const collectionDef = this.collectionDefs.get(name);
113
112
  const rollbacks = [];
114
113
  const queries = this.queryClient.getQueriesData({
115
114
  queryKey: [name]
@@ -118,28 +117,40 @@ var QueryRegistry = class {
118
117
  if (!data) continue;
119
118
  const params = queryKey[1];
120
119
  if (!this.matchesScope(params, scope)) continue;
121
- const isPaginated = data && typeof data === "object" && "pages" in data;
122
- if (isPaginated) {
123
- const paginatedData = data;
124
- const previous = paginatedData;
125
- rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
126
- this.queryClient.setQueryData(queryKey, (prev) => {
127
- if (!prev) return prev;
128
- return {
129
- ...prev,
130
- pages: prev.pages.map(
131
- (page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, def.id) : page
132
- )
133
- };
134
- });
120
+ if (collectionDef) {
121
+ const isPaginated = data && typeof data === "object" && "pages" in data;
122
+ if (isPaginated) {
123
+ const paginatedData = data;
124
+ const previous = paginatedData;
125
+ rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
126
+ this.queryClient.setQueryData(queryKey, (prev) => {
127
+ if (!prev) return prev;
128
+ return {
129
+ ...prev,
130
+ pages: prev.pages.map(
131
+ (page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, collectionDef.id) : page
132
+ )
133
+ };
134
+ });
135
+ } else {
136
+ const previous = data;
137
+ rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
138
+ this.queryClient.setQueryData(queryKey, (prev) => {
139
+ if (!prev) return prev;
140
+ return this.applyCollectionUpdate(prev, action, payload, collectionDef.id);
141
+ });
142
+ }
135
143
  } else {
136
- const arrayData = data;
137
- const previous = arrayData;
144
+ const previous = data;
138
145
  rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
139
- this.queryClient.setQueryData(queryKey, (prev) => {
140
- if (!prev) return prev;
141
- return this.applyCollectionUpdate(prev, action, payload, def.id);
142
- });
146
+ if (action === "update" && payload.update) {
147
+ this.queryClient.setQueryData(
148
+ queryKey,
149
+ (prev) => prev ? payload.update(prev) : prev
150
+ );
151
+ } else if (action === "replace" && payload.data) {
152
+ this.queryClient.setQueryData(queryKey, payload.data);
153
+ }
143
154
  }
144
155
  }
145
156
  return rollbacks;
@@ -180,22 +191,35 @@ var QueryRegistry = class {
180
191
  var registry = new QueryRegistry();
181
192
 
182
193
  // src/react/use-query.ts
194
+ function useStableValue(value) {
195
+ const serializedRef = react.useRef();
196
+ const valueRef = react.useRef(value);
197
+ const serialized = JSON.stringify(value);
198
+ if (serializedRef.current !== serialized) {
199
+ serializedRef.current = serialized;
200
+ valueRef.current = value;
201
+ }
202
+ return valueRef.current;
203
+ }
183
204
  function useQuery(def, options) {
184
205
  const queryClient = reactQuery.useQueryClient();
185
206
  const { params, paginated, getPageParams, getNextPageParam, select, queryKey: customQueryKey, syncInBackground, disableOptimistic, ...queryOptions } = options ?? {};
186
207
  registry.setQueryClient(queryClient);
208
+ const stableParams = useStableValue(params);
209
+ const stableCustomQueryKey = useStableValue(customQueryKey);
187
210
  const queryKey = react.useMemo(
188
- () => customQueryKey ?? [def.name, params].filter(Boolean),
189
- [customQueryKey, def.name, params]
211
+ () => stableCustomQueryKey ?? [def.name, stableParams].filter(Boolean),
212
+ [stableCustomQueryKey, def.name, stableParams]
190
213
  );
191
214
  if (def._type === "entity") {
192
215
  const entityDef = def;
193
216
  const query2 = reactQuery.useQuery({
194
217
  queryKey,
195
- queryFn: () => entityDef.fetch(params),
218
+ queryFn: () => entityDef.fetch(stableParams),
196
219
  enabled: queryOptions.enabled,
197
220
  staleTime: queryOptions.staleTime,
198
221
  gcTime: queryOptions.cacheTime,
222
+ placeholderData: queryOptions.placeholderData,
199
223
  refetchOnMount: queryOptions.refetchOnMount,
200
224
  refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,
201
225
  refetchInterval: queryOptions.refetchInterval
@@ -220,7 +244,7 @@ function useQuery(def, options) {
220
244
  const ensuredQuery2 = Object.assign(query2, {
221
245
  ensureQueryData: (opts) => queryClient.ensureQueryData({
222
246
  queryKey,
223
- queryFn: () => entityDef.fetch(params),
247
+ queryFn: () => entityDef.fetch(stableParams),
224
248
  staleTime: opts?.staleTime ?? queryOptions.staleTime
225
249
  })
226
250
  });
@@ -275,10 +299,11 @@ function useQuery(def, options) {
275
299
  }
276
300
  const query = reactQuery.useQuery({
277
301
  queryKey,
278
- queryFn: () => collectionDef.fetch(params),
302
+ queryFn: () => collectionDef.fetch(stableParams),
279
303
  enabled: queryOptions.enabled,
280
304
  staleTime: queryOptions.staleTime,
281
305
  gcTime: queryOptions.cacheTime,
306
+ placeholderData: queryOptions.placeholderData,
282
307
  refetchOnMount: queryOptions.refetchOnMount,
283
308
  refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,
284
309
  refetchInterval: queryOptions.refetchInterval
@@ -301,7 +326,7 @@ function useQuery(def, options) {
301
326
  const ensuredQuery = Object.assign(query, {
302
327
  ensureQueryData: (opts) => queryClient.ensureQueryData({
303
328
  queryKey,
304
- queryFn: () => collectionDef.fetch(params),
329
+ queryFn: () => collectionDef.fetch(stableParams),
305
330
  staleTime: opts?.staleTime ?? queryOptions.staleTime
306
331
  })
307
332
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/registry.ts","../../src/react/use-query.ts","../../src/react/use-queries.ts","../../src/react/provider.tsx","../../src/react/use-mutation.ts"],"names":["useQueryClient","useMemo","query","useTanstackQuery","useEffect","ensuredQuery","data","useInfiniteQuery","useTanstackQueries","useRef","createContext","jsx","useContext","useTanstackMutation","nanoid","context"],"mappings":"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","file":"index.js","sourcesContent":["import type { QueryClient } from '@tanstack/react-query';\nimport type { CollectionDef, EntityDef, Optimistic } from './types';\n\n/** Registered collection entry */\nexport interface RegisteredCollection<T = any> {\n kind: 'collection';\n name: string;\n queryKey: readonly unknown[];\n def: CollectionDef<T, any>;\n getData: () => T[] | undefined;\n setData: (updater: (prev: T[] | undefined) => T[] | undefined) => void;\n}\n\n/** Registered entity entry */\nexport interface RegisteredEntity<T = any> {\n kind: 'entity';\n name: string;\n queryKey: readonly unknown[];\n def: EntityDef<T, any>;\n getData: () => T | undefined;\n setData: (updater: (prev: T | undefined) => T | undefined) => void;\n}\n\n/** Registered paginated collection entry */\nexport interface RegisteredPaginatedCollection<T = any> {\n kind: 'paginated';\n name: string;\n queryKey: readonly unknown[];\n def: CollectionDef<T, any>;\n getData: () => { pages: T[][]; pageParams: unknown[] } | undefined;\n setData: (\n updater: (\n prev: { pages: T[][]; pageParams: unknown[] } | undefined\n ) => { pages: T[][]; pageParams: unknown[] } | undefined\n ) => void;\n}\n\nexport type RegisteredEntry =\n | RegisteredCollection\n | RegisteredEntity\n | RegisteredPaginatedCollection;\n\n/**\n * Internal registry for tracking active queries\n * Used by optimistic updates to broadcast changes\n */\nclass QueryRegistry {\n private entries = new Map<string, Set<RegisteredEntry>>();\n private queryClient: QueryClient | null = null;\n private collectionDefs = new Map<string, CollectionDef<any, any>>();\n\n /** Set the query client for direct cache access */\n setQueryClient(client: QueryClient): void {\n this.queryClient = client;\n }\n\n /** Register a collection definition for direct cache updates */\n registerDef(def: CollectionDef<any, any>): void {\n this.collectionDefs.set(def.name, def);\n }\n\n /** Register an active query */\n register(entry: RegisteredEntry): void {\n if (!this.entries.has(entry.name)) {\n this.entries.set(entry.name, new Set());\n }\n this.entries.get(entry.name)!.add(entry);\n\n // Also store the def for direct cache access\n if (entry.kind === 'collection' || entry.kind === 'paginated') {\n this.collectionDefs.set(entry.name, entry.def);\n }\n }\n\n /** Unregister a query when component unmounts */\n unregister(entry: RegisteredEntry): void {\n const set = this.entries.get(entry.name);\n if (set) {\n set.delete(entry);\n if (set.size === 0) {\n this.entries.delete(entry.name);\n }\n }\n }\n\n /** Get all registered entries for a query name */\n getByName(name: string): RegisteredEntry[] {\n return Array.from(this.entries.get(name) ?? []);\n }\n\n /**\n * Check if params partially match the given scope object.\n * Returns true if all key-value pairs in scope exist in params.\n */\n private matchesScope(params: Record<string, unknown> | undefined, scope?: Record<string, unknown>): boolean {\n if (!scope) return true;\n if (!params) return false;\n\n // Check if all scope keys exist in params with same value\n return Object.entries(scope).every(([key, value]) => params[key] === value);\n }\n\n /** Apply an optimistic update to all queries with given name */\n applyUpdate<T>(\n name: string,\n action: 'prepend' | 'append' | 'update' | 'delete' | 'replace',\n payload: {\n data?: Partial<Optimistic<T>>;\n id?: string;\n where?: (item: T) => boolean;\n update?: (item: T) => T;\n },\n scope?: Record<string, unknown>\n ): (() => void)[] {\n // When scope is provided and we have a queryClient, update cache directly\n if (scope && this.queryClient) {\n return this.applyDirectCacheUpdate(name, action, payload, scope);\n }\n\n // Otherwise, use registry-based updates\n const entries = this.getByName(name);\n const rollbacks: (() => void)[] = [];\n\n // Deduplicate by queryKey to avoid updating the same cache entry multiple times\n const seenKeys = new Set<string>();\n const uniqueEntries = entries.filter((entry) => {\n const key = JSON.stringify(entry.queryKey);\n if (seenKeys.has(key)) return false;\n seenKeys.add(key);\n // Also filter by scope if provided\n const params = entry.queryKey[1] as Record<string, unknown> | undefined;\n return this.matchesScope(params, scope);\n });\n\n for (const entry of uniqueEntries) {\n if (entry.kind === 'collection') {\n const previous = entry.getData();\n const rollback = () => entry.setData(() => previous);\n rollbacks.push(rollback);\n\n entry.setData((prev) => {\n if (!prev) return prev;\n return this.applyCollectionUpdate(prev, action, payload, entry.def.id);\n });\n } else if (entry.kind === 'paginated') {\n const previous = entry.getData();\n const rollback = () => entry.setData(() => previous);\n rollbacks.push(rollback);\n\n entry.setData((prev) => {\n if (!prev) return prev;\n return {\n ...prev,\n pages: prev.pages.map((page, i) =>\n i === 0\n ? this.applyCollectionUpdate(page, action, payload, entry.def.id)\n : page\n ),\n };\n });\n } else if (entry.kind === 'entity') {\n const previous = entry.getData();\n const rollback = () => entry.setData(() => previous);\n rollbacks.push(rollback);\n\n if (action === 'update' && payload.update) {\n entry.setData((prev) => (prev ? payload.update!(prev as T) : prev));\n } else if (action === 'replace' && payload.data) {\n entry.setData(() => payload.data as T);\n }\n }\n }\n\n return rollbacks;\n }\n\n /** Apply update directly to query cache (used when scope is provided) */\n private applyDirectCacheUpdate<T>(\n name: string,\n action: 'prepend' | 'append' | 'update' | 'delete' | 'replace',\n payload: {\n data?: Partial<Optimistic<T>>;\n id?: string;\n where?: (item: T) => boolean;\n update?: (item: T) => T;\n },\n scope: Record<string, unknown>\n ): (() => void)[] {\n if (!this.queryClient) return [];\n\n const def = this.collectionDefs.get(name);\n if (!def) return [];\n\n const rollbacks: (() => void)[] = [];\n\n // Get all queries with this name from the cache\n const queries = this.queryClient.getQueriesData<T[] | { pages: T[][]; pageParams: unknown[] }>({\n queryKey: [name],\n });\n\n for (const [queryKey, data] of queries) {\n if (!data) continue;\n\n // Extract params from queryKey [name, params]\n const params = queryKey[1] as Record<string, unknown> | undefined;\n if (!this.matchesScope(params, scope)) continue;\n\n // Check if this is a paginated query\n const isPaginated = data && typeof data === 'object' && 'pages' in data;\n\n if (isPaginated) {\n const paginatedData = data as { pages: T[][]; pageParams: unknown[] };\n const previous = paginatedData;\n rollbacks.push(() => this.queryClient!.setQueryData(queryKey, previous));\n\n this.queryClient.setQueryData<{ pages: T[][]; pageParams: unknown[] }>(queryKey, (prev) => {\n if (!prev) return prev;\n return {\n ...prev,\n pages: prev.pages.map((page, i) =>\n i === 0\n ? this.applyCollectionUpdate(page, action, payload, def.id)\n : page\n ),\n };\n });\n } else {\n const arrayData = data as T[];\n const previous = arrayData;\n rollbacks.push(() => this.queryClient!.setQueryData(queryKey, previous));\n\n this.queryClient.setQueryData<T[]>(queryKey, (prev) => {\n if (!prev) return prev;\n return this.applyCollectionUpdate(prev, action, payload, def.id);\n });\n }\n }\n\n return rollbacks;\n }\n\n private applyCollectionUpdate<T>(\n items: T[],\n action: string,\n payload: {\n data?: Partial<Optimistic<T>>;\n id?: string;\n where?: (item: T) => boolean;\n update?: (item: T) => T;\n },\n getId: (item: T) => string\n ): T[] {\n switch (action) {\n case 'prepend':\n return payload.data ? [payload.data as T, ...items] : items;\n\n case 'append':\n return payload.data ? [...items, payload.data as T] : items;\n\n case 'update':\n return items.map((item) => {\n const matches = payload.id\n ? getId(item) === payload.id\n : payload.where?.(item);\n if (matches && payload.update) {\n return payload.update(item);\n }\n if (matches && payload.data) {\n return { ...item, ...payload.data };\n }\n return item;\n });\n\n case 'delete':\n return items.filter((item) => {\n if (payload.id) return getId(item) !== payload.id;\n if (payload.where) return !payload.where(item);\n return true;\n });\n\n case 'replace':\n return items.map((item) => {\n const matches = payload.id\n ? getId(item) === payload.id\n : payload.where?.(item);\n return matches && payload.data ? (payload.data as T) : item;\n });\n\n default:\n return items;\n }\n }\n}\n\n/** Singleton registry instance */\nexport const registry = new QueryRegistry();\n","import { useEffect, useMemo } from 'react';\nimport {\n useQuery as useTanstackQuery,\n useInfiniteQuery,\n useQueryClient,\n type UseQueryResult,\n type UseInfiniteQueryResult,\n} from '@tanstack/react-query';\nimport type {\n CollectionDef,\n EntityDef,\n Optimistic,\n QueryOptions,\n} from '../core/types';\nimport { registry } from '../core/registry';\n\n/** Options for useQuery hook */\nexport interface UseQueryHookOptions<TParams, TData = unknown> extends QueryOptions {\n /** Parameters to pass to the fetch function */\n params?: TParams;\n /** Enable pagination mode (infinite query) */\n paginated?: boolean;\n /** For paginated: get params for each page */\n getPageParams?: (context: { pageParam: number }) => TParams;\n /** For paginated: custom logic to determine the next page param. Return undefined to stop. */\n getNextPageParam?: (lastPage: TData[], allPages: TData[][]) => number | undefined;\n /** Custom query key (defaults to [def.name, params]) */\n queryKey?: readonly unknown[];\n /** Transform the query data. Useful for deriving different views from the same cache. */\n select?: (data: Optimistic<TData>[] | Optimistic<TData>) => unknown;\n /**\n * Keep this query registered for optimistic updates even when unmounted.\n * Useful when you want updates from other pages to sync to this query's cache.\n */\n syncInBackground?: boolean;\n /**\n * Disable optimistic update registration for this query.\n * Useful for queries that don't need optimistic updates (e.g. analytics, logs).\n */\n disableOptimistic?: boolean;\n}\n\n/** Adds ensureQueryData capability to a query result */\nexport type WithEnsureData<TData> = {\n ensureQueryData: (options?: { staleTime?: number }) => Promise<TData>;\n};\n\n/** Return type for collection queries: [data, queryResult] */\nexport type QueryResult<T> = [\n Optimistic<T>[] | undefined,\n UseQueryResult<T[], Error> & WithEnsureData<T[]>\n];\n\n/** Return type for paginated queries: [data, infiniteQueryResult] */\nexport type PaginatedQueryResult<T> = [\n Optimistic<T>[] | undefined,\n UseInfiniteQueryResult<{ pages: T[][]; pageParams: unknown[] }, Error>\n];\n\n/** Return type for entity queries: [data, queryResult] */\nexport type EntityResult<T> = [\n Optimistic<T> | undefined,\n UseQueryResult<T, Error> & WithEnsureData<T>\n];\n\n/**\n * Unified query hook for fetching data\n *\n * Returns a tuple of [data, queryResult] where queryResult is the full\n * TanStack Query result object with all properties (isLoading, isError,\n * refetch, etc.)\n *\n * @example\n * // Simple collection query\n * const [data, query] = useQuery(postsQuery, { params: { limit: 10 } })\n * // query.isLoading, query.isError, query.refetch(), etc.\n *\n * @example\n * // Paginated query - returns full infinite query result\n * const [data, query] = useQuery(postsQuery, {\n * paginated: true,\n * getPageParams: ({ pageParam }) => ({ page: pageParam, limit: 10 })\n * })\n * // query.fetchNextPage(), query.hasNextPage, query.isFetchingNextPage\n *\n * @example\n * // Entity query\n * const [user, query] = useQuery(userEntity, { params: userId })\n */\nexport function useQuery<TData, TParams, TSelected>(\n def: CollectionDef<TData, TParams>,\n options: Omit<UseQueryHookOptions<TParams, TData>, 'select'> & { paginated: true; select: (data: Optimistic<TData>[]) => TSelected }\n): [TSelected | undefined, UseInfiniteQueryResult<{ pages: TData[][]; pageParams: unknown[] }, Error>];\n\nexport function useQuery<TData, TParams>(\n def: CollectionDef<TData, TParams>,\n options: UseQueryHookOptions<TParams, TData> & { paginated: true }\n): PaginatedQueryResult<TData>;\n\nexport function useQuery<TData, TParams, TSelected>(\n def: CollectionDef<TData, TParams>,\n options: Omit<UseQueryHookOptions<TParams, TData>, 'select'> & { select: (data: Optimistic<TData>[]) => TSelected }\n): [TSelected | undefined, UseQueryResult<TData[], Error> & WithEnsureData<TData[]>];\n\nexport function useQuery<TData, TParams>(\n def: CollectionDef<TData, TParams>,\n options?: UseQueryHookOptions<TParams, TData>\n): QueryResult<TData>;\n\nexport function useQuery<TData, TParams, TSelected>(\n def: EntityDef<TData, TParams>,\n options: Omit<UseQueryHookOptions<TParams, TData>, 'select'> & { select: (data: Optimistic<TData>) => TSelected }\n): [TSelected | undefined, UseQueryResult<TData, Error> & WithEnsureData<TData>];\n\nexport function useQuery<TData, TParams>(\n def: EntityDef<TData, TParams>,\n options?: UseQueryHookOptions<TParams, TData>\n): EntityResult<TData>;\n\nexport function useQuery<TData, TParams>(\n def: CollectionDef<TData, TParams> | EntityDef<TData, TParams>,\n options?: UseQueryHookOptions<TParams, TData>\n): QueryResult<TData> | PaginatedQueryResult<TData> | EntityResult<TData> {\n const queryClient = useQueryClient();\n const { params, paginated, getPageParams, getNextPageParam, select, queryKey: customQueryKey, syncInBackground, disableOptimistic, ...queryOptions } = options ?? {};\n\n // Set queryClient on registry for direct cache access\n registry.setQueryClient(queryClient);\n\n // Build query key\n const queryKey = useMemo(\n () => customQueryKey ?? [def.name, params].filter(Boolean),\n [customQueryKey, def.name, params]\n );\n\n // Entity query\n if (def._type === 'entity') {\n const entityDef = def as EntityDef<TData, TParams>;\n const query = useTanstackQuery({\n queryKey,\n queryFn: () => entityDef.fetch(params as TParams),\n enabled: queryOptions.enabled,\n staleTime: queryOptions.staleTime,\n gcTime: queryOptions.cacheTime,\n refetchOnMount: queryOptions.refetchOnMount,\n refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,\n refetchInterval: queryOptions.refetchInterval,\n });\n\n // Register for optimistic updates\n useEffect(() => {\n if (disableOptimistic || query.status !== 'success' || !query.data) {\n return;\n }\n\n const entry = {\n kind: 'entity' as const,\n name: def.name,\n queryKey,\n def: entityDef,\n getData: () => queryClient.getQueryData<TData>(queryKey),\n setData: (updater: (prev: TData | undefined) => TData | undefined) =>\n queryClient.setQueryData<TData>(queryKey, updater),\n };\n\n registry.register(entry);\n\n // If syncInBackground is enabled, don't unregister on unmount\n if (!syncInBackground) {\n return () => registry.unregister(entry);\n }\n }, [def.name, queryKey, query.status, query.data, queryClient, syncInBackground, disableOptimistic]);\n\n const ensuredQuery = Object.assign(query, {\n ensureQueryData: (opts?: { staleTime?: number }) =>\n queryClient.ensureQueryData<TData>({\n queryKey,\n queryFn: () => entityDef.fetch(params as TParams),\n staleTime: opts?.staleTime ?? queryOptions.staleTime,\n }),\n });\n\n const data = ensuredQuery.data as Optimistic<TData> | undefined;\n return [\n (data !== undefined && select ? select(data) : data) as any,\n ensuredQuery,\n ];\n }\n\n const collectionDef = def as CollectionDef<TData, TParams>;\n\n // Paginated collection\n if (paginated) {\n const infiniteQuery = useInfiniteQuery({\n queryKey,\n queryFn: ({ pageParam }) => {\n const pageParams = getPageParams\n ? getPageParams({ pageParam: pageParam as number })\n : ({ pageParam } as TParams);\n return collectionDef.fetch(pageParams);\n },\n initialPageParam: 1,\n getNextPageParam: getNextPageParam\n ?? ((lastPage, allPages) =>\n lastPage.length > 0 ? allPages.length + 1 : undefined),\n enabled: queryOptions.enabled,\n staleTime: queryOptions.staleTime,\n gcTime: queryOptions.cacheTime,\n refetchOnMount: queryOptions.refetchOnMount,\n refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,\n refetchInterval: queryOptions.refetchInterval,\n });\n\n const flatData = useMemo(() => {\n const flat = infiniteQuery.data?.pages.flat() as Optimistic<TData>[] | undefined;\n return flat !== undefined && select ? select(flat) : flat;\n }, [infiniteQuery.data]);\n\n // Register for optimistic updates\n useEffect(() => {\n if (disableOptimistic || infiniteQuery.status !== 'success' || !infiniteQuery.data) return;\n\n const entry = {\n kind: 'paginated' as const,\n name: def.name,\n queryKey,\n def: collectionDef,\n getData: () =>\n queryClient.getQueryData<{ pages: TData[][]; pageParams: unknown[] }>(\n queryKey\n ),\n setData: (\n updater: (\n prev: { pages: TData[][]; pageParams: unknown[] } | undefined\n ) => { pages: TData[][]; pageParams: unknown[] } | undefined\n ) =>\n queryClient.setQueryData<{\n pages: TData[][];\n pageParams: unknown[];\n }>(queryKey, updater),\n };\n\n registry.register(entry);\n\n // If syncInBackground is enabled, don't unregister on unmount\n if (!syncInBackground) {\n return () => registry.unregister(entry);\n }\n }, [def.name, queryKey, infiniteQuery.status, infiniteQuery.data, queryClient, syncInBackground, disableOptimistic]);\n\n return [\n flatData as any,\n infiniteQuery as UseInfiniteQueryResult<{ pages: TData[][]; pageParams: unknown[] }, Error>,\n ];\n }\n\n // Simple collection query\n const query = useTanstackQuery({\n queryKey,\n queryFn: () => collectionDef.fetch(params as TParams),\n enabled: queryOptions.enabled,\n staleTime: queryOptions.staleTime,\n gcTime: queryOptions.cacheTime,\n refetchOnMount: queryOptions.refetchOnMount,\n refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,\n refetchInterval: queryOptions.refetchInterval,\n });\n\n // Register for optimistic updates\n useEffect(() => {\n if (disableOptimistic || query.status !== 'success' || !query.data) return;\n\n const entry = {\n kind: 'collection' as const,\n name: def.name,\n queryKey,\n def: collectionDef,\n getData: () => queryClient.getQueryData<TData[]>(queryKey),\n setData: (updater: (prev: TData[] | undefined) => TData[] | undefined) =>\n queryClient.setQueryData<TData[]>(queryKey, updater),\n };\n\n registry.register(entry);\n\n // If syncInBackground is enabled, don't unregister on unmount\n if (!syncInBackground) {\n return () => registry.unregister(entry);\n }\n }, [def.name, queryKey, query.status, query.data, queryClient, syncInBackground, disableOptimistic]);\n\n const ensuredQuery = Object.assign(query, {\n ensureQueryData: (opts?: { staleTime?: number }) =>\n queryClient.ensureQueryData<TData[]>({\n queryKey,\n queryFn: () => collectionDef.fetch(params as TParams),\n staleTime: opts?.staleTime ?? queryOptions.staleTime,\n }),\n });\n\n const data = ensuredQuery.data as Optimistic<TData>[] | undefined;\n return [\n (data !== undefined && select ? select(data) : data) as any,\n ensuredQuery,\n ];\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport {\n useQueries as useTanstackQueries,\n useQueryClient,\n type UseQueryResult,\n} from '@tanstack/react-query';\nimport type {\n CollectionDef,\n EntityDef,\n Optimistic,\n} from '../core/types';\nimport { registry } from '../core/registry';\nimport type { UseQueryHookOptions, QueryResult, EntityResult } from './use-query';\n\n/**\n * Fetch multiple queries of the same entity/collection type in parallel.\n *\n * @example\n * const results = useQueries(tokenInfoEntity, positions.map(p => ({\n * params: { address: p.tokenAddress, chainName },\n * })))\n * // results[i] = [data, queryResult]\n */\nexport function useQueries<TData, TParams>(\n def: EntityDef<TData, TParams>,\n optionsArray: UseQueryHookOptions<TParams, TData>[]\n): EntityResult<TData>[];\n\nexport function useQueries<TData, TParams>(\n def: CollectionDef<TData, TParams>,\n optionsArray: UseQueryHookOptions<TParams, TData>[]\n): QueryResult<TData>[];\n\nexport function useQueries<TData, TParams>(\n def: EntityDef<TData, TParams> | CollectionDef<TData, TParams>,\n optionsArray: UseQueryHookOptions<TParams, TData>[]\n): (EntityResult<TData> | QueryResult<TData>)[] {\n const queryClient = useQueryClient();\n\n registry.setQueryClient(queryClient);\n\n const queries = useMemo(\n () =>\n optionsArray.map((opts) => {\n const { params, queryKey: customQueryKey, ...queryOptions } = opts;\n const queryKey = customQueryKey ?? [def.name, params].filter(Boolean);\n\n return {\n queryKey,\n queryFn: () => def.fetch(params as TParams),\n enabled: queryOptions.enabled,\n staleTime: queryOptions.staleTime,\n gcTime: queryOptions.cacheTime,\n refetchOnMount: queryOptions.refetchOnMount,\n refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,\n refetchInterval: queryOptions.refetchInterval,\n };\n }),\n [def, optionsArray]\n );\n\n const results = useTanstackQueries({ queries });\n\n // Track registered entries for cleanup\n const registeredRef = useRef<Set<any>>(new Set());\n\n useEffect(() => {\n const currentEntries = new Set<any>();\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (optionsArray[i]?.disableOptimistic || result.status !== 'success' || !result.data) continue;\n\n const queryKey = queries[i].queryKey;\n\n if (def._type === 'entity') {\n const entry = {\n kind: 'entity' as const,\n name: def.name,\n queryKey,\n def: def as EntityDef<TData, TParams>,\n getData: () => queryClient.getQueryData<TData>(queryKey),\n setData: (updater: (prev: TData | undefined) => TData | undefined) =>\n queryClient.setQueryData<TData>(queryKey, updater),\n };\n registry.register(entry);\n currentEntries.add(entry);\n } else {\n const collDef = def as CollectionDef<TData, TParams>;\n const entry = {\n kind: 'collection' as const,\n name: def.name,\n queryKey,\n def: collDef,\n getData: () => queryClient.getQueryData<TData[]>(queryKey),\n setData: (updater: (prev: TData[] | undefined) => TData[] | undefined) =>\n queryClient.setQueryData<TData[]>(queryKey, updater),\n };\n registry.register(entry);\n currentEntries.add(entry);\n }\n }\n\n // Unregister previous entries that are no longer active\n for (const entry of registeredRef.current) {\n if (!currentEntries.has(entry)) {\n registry.unregister(entry);\n }\n }\n\n registeredRef.current = currentEntries;\n\n return () => {\n for (const entry of currentEntries) {\n registry.unregister(entry);\n }\n registeredRef.current = new Set();\n };\n }, [def, results, queries, queryClient, optionsArray]);\n\n // Map to tuples\n return results.map((result) => {\n if (def._type === 'entity') {\n return [\n result.data as Optimistic<TData> | undefined,\n result as UseQueryResult<TData, Error>,\n ] as EntityResult<TData>;\n }\n return [\n result.data as Optimistic<TData>[] | undefined,\n result as UseQueryResult<TData[], Error>,\n ] as QueryResult<TData>;\n });\n}\n","import { createContext, useContext, type ReactNode } from 'react';\n\nexport interface OptimisticQueryProviderProps {\n /** Default error handler called when no local onError is provided */\n onError?: (error: Error) => void;\n children: ReactNode;\n}\n\ninterface OptimisticQueryContextValue {\n onError?: (error: Error) => void;\n}\n\nconst OptimisticQueryContext = createContext<OptimisticQueryContextValue>({});\n\nexport function OptimisticQueryProvider({ onError, children }: OptimisticQueryProviderProps) {\n return (\n <OptimisticQueryContext.Provider value={{ onError }}>\n {children}\n </OptimisticQueryContext.Provider>\n );\n}\n\nexport function useOptimisticQueryContext(): OptimisticQueryContextValue {\n return useContext(OptimisticQueryContext);\n}\n","import {\n useMutation as useTanstackMutation,\n type UseMutationResult,\n} from '@tanstack/react-query';\nimport { nanoid } from 'nanoid';\nimport { useOptimisticQueryContext } from './provider';\nimport type {\n MutationDef,\n CollectionDef,\n EntityDef,\n} from '../core/types';\nimport { registry } from '../core/registry';\nimport {\n channel as coreChannel,\n type Channel,\n type ChannelOptions,\n type CollectionChannel,\n type EntityChannel,\n} from '../core/channel';\n\n/** Extract entity type from a collection or entity definition */\ntype InferEntity<T> = T extends CollectionDef<infer TData, any>\n ? TData & {}\n : T extends EntityDef<infer TData, any>\n ? TData & {}\n : never;\n\n/** Base optimistic config with shared properties */\ninterface OptimisticConfigBase<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> {\n /** Target collection/entity to update */\n target: TTarget;\n /** Whether to reconcile with server response (replace optimistic with real data) */\n reconcile?: boolean;\n}\n\n/** Config for prepend/append actions - requires full entity */\ninterface OptimisticPrependAppendConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> extends OptimisticConfigBase<TTarget, TParams> {\n action: 'prepend' | 'append';\n /** Data to prepend/append - must be a full entity */\n data: (params: TParams) => NoInfer<InferEntity<TTarget>>;\n}\n\n/** Config for replace action */\ninterface OptimisticReplaceConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> extends OptimisticConfigBase<TTarget, TParams> {\n action: 'replace';\n /** Data for replacement */\n data: (params: TParams) => NoInfer<InferEntity<TTarget>>;\n /** ID of item to replace */\n id?: string | ((params: TParams) => string);\n /** Filter function to find items to replace */\n where?: (item: NoInfer<InferEntity<TTarget>>) => boolean;\n}\n\n/** Config for update action */\ninterface OptimisticUpdateConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> extends OptimisticConfigBase<TTarget, TParams> {\n action: 'update';\n /** Partial data for update */\n data?: (params: TParams) => Partial<NoInfer<InferEntity<TTarget>>>;\n /** ID of item to update */\n id?: string | ((params: TParams) => string);\n /** Filter function to find items to update */\n where?: (item: NoInfer<InferEntity<TTarget>>) => boolean;\n /** Update function */\n update?: (item: NoInfer<InferEntity<TTarget>>, params: TParams) => NoInfer<InferEntity<TTarget>>;\n}\n\n/** Config for delete action */\ninterface OptimisticDeleteConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> extends OptimisticConfigBase<TTarget, TParams> {\n action: 'delete';\n /** ID of item to delete */\n id?: string | ((params: TParams) => string);\n /** Filter function to find items to delete */\n where?: (item: NoInfer<InferEntity<TTarget>>) => boolean;\n}\n\n/** Optimistic update configuration - type inferred from target */\nexport type OptimisticConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> =\n | OptimisticPrependAppendConfig<TTarget, TParams>\n | OptimisticReplaceConfig<TTarget, TParams>\n | OptimisticUpdateConfig<TTarget, TParams>\n | OptimisticDeleteConfig<TTarget, TParams>;\n\n/** Internal transaction type for batched mutations */\ninterface MutationTransaction {\n target: CollectionDef<any, any> | EntityDef<any, any>;\n action: 'prepend' | 'append' | 'update' | 'delete' | 'replace';\n data?: any;\n id?: string;\n where?: (item: any) => boolean;\n update?: (item: any) => any;\n reconcile?: boolean;\n scope?: Record<string, unknown>;\n}\n\n/** Internal collection channel for batched mutations */\nclass BatchedCollectionChannel<TEntity> {\n constructor(\n private readonly target: CollectionDef<TEntity, any>,\n private readonly transactions: MutationTransaction[],\n private readonly options?: ChannelOptions\n ) {}\n\n prepend(data: TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'prepend',\n data,\n reconcile: options?.reconcile,\n scope: this.options?.scope,\n });\n return this;\n }\n\n append(data: TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'append',\n data,\n reconcile: options?.reconcile,\n scope: this.options?.scope,\n });\n return this;\n }\n\n update(id: string, updateFn: (item: TEntity) => TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'update',\n id,\n update: updateFn,\n reconcile: options?.reconcile,\n scope: this.options?.scope,\n });\n return this;\n }\n\n delete(id: string): this {\n this.transactions.push({\n target: this.target,\n action: 'delete',\n id,\n scope: this.options?.scope,\n });\n return this;\n }\n}\n\n/** Internal entity channel for batched mutations */\nclass BatchedEntityChannel<TEntity> {\n constructor(\n private readonly target: EntityDef<TEntity, any>,\n private readonly transactions: MutationTransaction[]\n ) {}\n\n update(updateFn: (item: TEntity) => TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'update',\n update: updateFn,\n reconcile: options?.reconcile,\n });\n return this;\n }\n\n replace(data: TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'replace',\n data,\n reconcile: options?.reconcile,\n });\n return this;\n }\n}\n\n/** Internal batched channel type */\ninterface BatchedChannel {\n <TEntity>(target: CollectionDef<TEntity, any>, options?: ChannelOptions): BatchedCollectionChannel<TEntity>;\n <TEntity>(target: EntityDef<TEntity, any>): BatchedEntityChannel<TEntity>;\n}\n\n/** Creates a batched channel for collecting mutations */\nfunction createBatchedChannel(transactions: MutationTransaction[]): BatchedChannel {\n function channel<TEntity>(target: CollectionDef<TEntity, any>, options?: ChannelOptions): BatchedCollectionChannel<TEntity>;\n function channel<TEntity>(target: EntityDef<TEntity, any>): BatchedEntityChannel<TEntity>;\n function channel<TEntity>(\n target: CollectionDef<TEntity, any> | EntityDef<TEntity, any>,\n options?: ChannelOptions\n ): BatchedCollectionChannel<TEntity> | BatchedEntityChannel<TEntity> {\n if (target._type === 'collection') {\n return new BatchedCollectionChannel(target, transactions, options);\n } else {\n return new BatchedEntityChannel(target, transactions);\n }\n }\n return channel;\n}\n\n\n/** Options for useMutation hook */\nexport interface UseMutationOptions<TParams, TResponse> {\n /** Called when mutation starts */\n onMutate?: (params: TParams) => void;\n /** Called on success */\n onSuccess?: (data: TResponse, params: TParams) => void;\n /** Called on error */\n onError?: (error: Error, params: TParams) => void;\n}\n\n/**\n * Mutation hook with simplified optimistic updates\n *\n * @example\n * // Simple mutation\n * const { mutate } = useMutation(createPost)\n *\n * @example\n * // With optimistic update\n * const { mutate } = useMutation(createPost, {\n * optimistic: {\n * target: postsQuery,\n * action: 'prepend',\n * data: (params) => ({ ...params, _id: 'temp-id' })\n * }\n * })\n *\n * @example\n * // Multiple optimistic updates\n * const { mutate } = useMutation(deletePost, {\n * optimistic: [\n * { target: postsQuery, action: 'delete', id: (p) => p.postId },\n * { target: userStatsEntity, action: 'update', update: (stats) => ({ ...stats, postCount: stats.postCount - 1 }) }\n * ]\n * })\n */\nexport function useMutation<\n TParams,\n TResponse,\n>(\n def: MutationDef<TParams, TResponse>,\n options?: UseMutationOptions<TParams, TResponse> & {\n /** Optimistic update configuration - receives channel and params */\n optimistic?: (channel: BatchedChannel, params: TParams) => void;\n }\n): UseMutationResult<TResponse, Error, TParams> {\n const context = useOptimisticQueryContext();\n const mutation = useTanstackMutation<\n TResponse,\n Error,\n TParams,\n { rollbacks: (() => void)[]; optimisticId: string; transactions: MutationTransaction[] }\n >({\n mutationKey: def.name ? [def.name] : undefined,\n mutationFn: def.mutate,\n\n onMutate: async (params) => {\n const rollbacks: (() => void)[] = [];\n const optimisticId = nanoid();\n const transactions: MutationTransaction[] = [];\n\n // Apply optimistic updates via channel\n if (options?.optimistic) {\n const channel = createBatchedChannel(transactions);\n options.optimistic(channel, params);\n\n for (const tx of transactions) {\n const { target, action, data, id, where, update, scope } = tx;\n\n // Add optimistic metadata to data\n const optimisticData = data\n ? {\n ...data,\n _optimistic: { id: optimisticId, status: 'pending' as const },\n }\n : undefined;\n\n const updateRollbacks = registry.applyUpdate(target.name, action, {\n data: optimisticData,\n id,\n where,\n update: update\n ? (item: any) => update(item)\n : optimisticData\n ? (item: any) => ({ ...item, ...optimisticData })\n : undefined,\n }, scope);\n\n rollbacks.push(...updateRollbacks);\n }\n }\n\n options?.onMutate?.(params);\n return { rollbacks, optimisticId, transactions };\n },\n\n onSuccess: (data, params, context) => {\n // If reconcile is enabled, replace optimistic data with server response\n if (context?.transactions) {\n for (const tx of context.transactions) {\n if (tx.reconcile && data) {\n // Replace optimistic item with real server data\n registry.applyUpdate(tx.target.name, 'update', {\n where: (item: any) =>\n item._optimistic?.id === context?.optimisticId,\n update: () => data as any,\n });\n }\n }\n }\n\n options?.onSuccess?.(data, params);\n },\n\n onError: (error, params, mutationContext) => {\n // Rollback all optimistic updates\n mutationContext?.rollbacks.forEach((rollback) => rollback());\n if (options?.onError) {\n options.onError(error, params);\n } else {\n context.onError?.(error);\n }\n },\n });\n\n return mutation;\n}\n"]}
1
+ {"version":3,"sources":["../../src/core/registry.ts","../../src/react/use-query.ts","../../src/react/use-queries.ts","../../src/react/provider.tsx","../../src/react/use-mutation.ts"],"names":["useRef","useQueryClient","useMemo","query","useTanstackQuery","useEffect","ensuredQuery","data","useInfiniteQuery","useTanstackQueries","createContext","jsx","useContext","useTanstackMutation","nanoid","context"],"mappings":"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","file":"index.js","sourcesContent":["import type { QueryClient } from '@tanstack/react-query';\nimport type { CollectionDef, EntityDef, Optimistic } from './types';\n\n/** Registered collection entry */\nexport interface RegisteredCollection<T = any> {\n kind: 'collection';\n name: string;\n queryKey: readonly unknown[];\n def: CollectionDef<T, any>;\n getData: () => T[] | undefined;\n setData: (updater: (prev: T[] | undefined) => T[] | undefined) => void;\n}\n\n/** Registered entity entry */\nexport interface RegisteredEntity<T = any> {\n kind: 'entity';\n name: string;\n queryKey: readonly unknown[];\n def: EntityDef<T, any>;\n getData: () => T | undefined;\n setData: (updater: (prev: T | undefined) => T | undefined) => void;\n}\n\n/** Registered paginated collection entry */\nexport interface RegisteredPaginatedCollection<T = any> {\n kind: 'paginated';\n name: string;\n queryKey: readonly unknown[];\n def: CollectionDef<T, any>;\n getData: () => { pages: T[][]; pageParams: unknown[] } | undefined;\n setData: (\n updater: (\n prev: { pages: T[][]; pageParams: unknown[] } | undefined\n ) => { pages: T[][]; pageParams: unknown[] } | undefined\n ) => void;\n}\n\nexport type RegisteredEntry =\n | RegisteredCollection\n | RegisteredEntity\n | RegisteredPaginatedCollection;\n\n/**\n * Internal registry for tracking active queries\n * Used by optimistic updates to broadcast changes\n */\nclass QueryRegistry {\n private entries = new Map<string, Set<RegisteredEntry>>();\n private queryClient: QueryClient | null = null;\n private collectionDefs = new Map<string, CollectionDef<any, any>>();\n\n /** Set the query client for direct cache access */\n setQueryClient(client: QueryClient): void {\n this.queryClient = client;\n }\n\n /** Register a collection definition for direct cache updates */\n registerDef(def: CollectionDef<any, any>): void {\n this.collectionDefs.set(def.name, def);\n }\n\n /** Register an active query */\n register(entry: RegisteredEntry): void {\n if (!this.entries.has(entry.name)) {\n this.entries.set(entry.name, new Set());\n }\n this.entries.get(entry.name)!.add(entry);\n\n // Also store the def for direct cache access\n if (entry.kind === 'collection' || entry.kind === 'paginated') {\n this.collectionDefs.set(entry.name, entry.def);\n }\n }\n\n /** Unregister a query when component unmounts */\n unregister(entry: RegisteredEntry): void {\n const set = this.entries.get(entry.name);\n if (set) {\n set.delete(entry);\n if (set.size === 0) {\n this.entries.delete(entry.name);\n }\n }\n }\n\n /** Get all registered entries for a query name */\n getByName(name: string): RegisteredEntry[] {\n return Array.from(this.entries.get(name) ?? []);\n }\n\n /**\n * Check if params partially match the given scope object.\n * Returns true if all key-value pairs in scope exist in params.\n */\n private matchesScope(params: Record<string, unknown> | undefined, scope?: Record<string, unknown>): boolean {\n if (!scope) return true;\n if (!params) return false;\n\n // Check if all scope keys exist in params with same value\n return Object.entries(scope).every(([key, value]) => params[key] === value);\n }\n\n /** Apply an optimistic update to all queries with given name */\n applyUpdate<T>(\n name: string,\n action: 'prepend' | 'append' | 'update' | 'delete' | 'replace',\n payload: {\n data?: Partial<Optimistic<T>>;\n id?: string;\n where?: (item: T) => boolean;\n update?: (item: T) => T;\n },\n scope?: Record<string, unknown>\n ): (() => void)[] {\n // When scope is provided and we have a queryClient, update cache directly\n if (scope && this.queryClient) {\n return this.applyDirectCacheUpdate(name, action, payload, scope);\n }\n\n // Otherwise, use registry-based updates\n const entries = this.getByName(name);\n const rollbacks: (() => void)[] = [];\n\n // Deduplicate by queryKey to avoid updating the same cache entry multiple times\n const seenKeys = new Set<string>();\n const uniqueEntries = entries.filter((entry) => {\n const key = JSON.stringify(entry.queryKey);\n if (seenKeys.has(key)) return false;\n seenKeys.add(key);\n // Also filter by scope if provided\n const params = entry.queryKey[1] as Record<string, unknown> | undefined;\n return this.matchesScope(params, scope);\n });\n\n for (const entry of uniqueEntries) {\n if (entry.kind === 'collection') {\n const previous = entry.getData();\n const rollback = () => entry.setData(() => previous);\n rollbacks.push(rollback);\n\n entry.setData((prev) => {\n if (!prev) return prev;\n return this.applyCollectionUpdate(prev, action, payload, entry.def.id);\n });\n } else if (entry.kind === 'paginated') {\n const previous = entry.getData();\n const rollback = () => entry.setData(() => previous);\n rollbacks.push(rollback);\n\n entry.setData((prev) => {\n if (!prev) return prev;\n return {\n ...prev,\n pages: prev.pages.map((page, i) =>\n i === 0\n ? this.applyCollectionUpdate(page, action, payload, entry.def.id)\n : page\n ),\n };\n });\n } else if (entry.kind === 'entity') {\n const previous = entry.getData();\n const rollback = () => entry.setData(() => previous);\n rollbacks.push(rollback);\n\n if (action === 'update' && payload.update) {\n entry.setData((prev) => (prev ? payload.update!(prev as T) : prev));\n } else if (action === 'replace' && payload.data) {\n entry.setData(() => payload.data as T);\n }\n }\n }\n\n return rollbacks;\n }\n\n /** Apply update directly to query cache (used when scope is provided) */\n private applyDirectCacheUpdate<T>(\n name: string,\n action: 'prepend' | 'append' | 'update' | 'delete' | 'replace',\n payload: {\n data?: Partial<Optimistic<T>>;\n id?: string;\n where?: (item: T) => boolean;\n update?: (item: T) => T;\n },\n scope: Record<string, unknown>\n ): (() => void)[] {\n if (!this.queryClient) return [];\n\n const collectionDef = this.collectionDefs.get(name);\n const rollbacks: (() => void)[] = [];\n\n // Get all queries with this name from the cache\n const queries = this.queryClient.getQueriesData<any>({\n queryKey: [name],\n });\n\n for (const [queryKey, data] of queries) {\n if (!data) continue;\n\n // Extract params from queryKey [name, params]\n const params = queryKey[1] as Record<string, unknown> | undefined;\n if (!this.matchesScope(params, scope)) continue;\n\n if (collectionDef) {\n // Check if this is a paginated query\n const isPaginated = data && typeof data === 'object' && 'pages' in data;\n\n if (isPaginated) {\n const paginatedData = data as { pages: T[][]; pageParams: unknown[] };\n const previous = paginatedData;\n rollbacks.push(() => this.queryClient!.setQueryData(queryKey, previous));\n\n this.queryClient.setQueryData<{ pages: T[][]; pageParams: unknown[] }>(queryKey, (prev) => {\n if (!prev) return prev;\n return {\n ...prev,\n pages: prev.pages.map((page, i) =>\n i === 0\n ? this.applyCollectionUpdate(page, action, payload, collectionDef.id)\n : page\n ),\n };\n });\n } else {\n const previous = data as T[];\n rollbacks.push(() => this.queryClient!.setQueryData(queryKey, previous));\n\n this.queryClient.setQueryData<T[]>(queryKey, (prev) => {\n if (!prev) return prev;\n return this.applyCollectionUpdate(prev, action, payload, collectionDef.id);\n });\n }\n } else {\n // Entity: apply update/replace directly\n const previous = data as T;\n rollbacks.push(() => this.queryClient!.setQueryData(queryKey, previous));\n\n if (action === 'update' && payload.update) {\n this.queryClient.setQueryData<T>(queryKey, (prev) =>\n prev ? payload.update!(prev) : prev\n );\n } else if (action === 'replace' && payload.data) {\n this.queryClient.setQueryData(queryKey, payload.data);\n }\n }\n }\n\n return rollbacks;\n }\n\n private applyCollectionUpdate<T>(\n items: T[],\n action: string,\n payload: {\n data?: Partial<Optimistic<T>>;\n id?: string;\n where?: (item: T) => boolean;\n update?: (item: T) => T;\n },\n getId: (item: T) => string\n ): T[] {\n switch (action) {\n case 'prepend':\n return payload.data ? [payload.data as T, ...items] : items;\n\n case 'append':\n return payload.data ? [...items, payload.data as T] : items;\n\n case 'update':\n return items.map((item) => {\n const matches = payload.id\n ? getId(item) === payload.id\n : payload.where?.(item);\n if (matches && payload.update) {\n return payload.update(item);\n }\n if (matches && payload.data) {\n return { ...item, ...payload.data };\n }\n return item;\n });\n\n case 'delete':\n return items.filter((item) => {\n if (payload.id) return getId(item) !== payload.id;\n if (payload.where) return !payload.where(item);\n return true;\n });\n\n case 'replace':\n return items.map((item) => {\n const matches = payload.id\n ? getId(item) === payload.id\n : payload.where?.(item);\n return matches && payload.data ? (payload.data as T) : item;\n });\n\n default:\n return items;\n }\n }\n}\n\n/** Singleton registry instance */\nexport const registry = new QueryRegistry();\n","import { useEffect, useMemo, useRef } from 'react';\nimport {\n useQuery as useTanstackQuery,\n useInfiniteQuery,\n useQueryClient,\n type UseQueryResult,\n type UseInfiniteQueryResult,\n} from '@tanstack/react-query';\nimport type {\n CollectionDef,\n EntityDef,\n Optimistic,\n QueryOptions,\n} from '../core/types';\nimport { registry } from '../core/registry';\n\n/**\n * Returns a referentially stable version of `value`.\n * Only updates the reference when the JSON-serialized form changes.\n * Prevents unnecessary queryKey recalculations from inline objects.\n */\nfunction useStableValue<T>(value: T): T {\n const serializedRef = useRef<string>();\n const valueRef = useRef(value);\n\n const serialized = JSON.stringify(value);\n if (serializedRef.current !== serialized) {\n serializedRef.current = serialized;\n valueRef.current = value;\n }\n\n return valueRef.current;\n}\n\n/** Options for useQuery hook */\nexport interface UseQueryHookOptions<TParams, TData = unknown> extends QueryOptions {\n /** Parameters to pass to the fetch function */\n params?: TParams;\n /** Enable pagination mode (infinite query) */\n paginated?: boolean;\n /** For paginated: get params for each page */\n getPageParams?: (context: { pageParam: number }) => TParams;\n /** For paginated: custom logic to determine the next page param. Return undefined to stop. */\n getNextPageParam?: (lastPage: TData[], allPages: TData[][]) => number | undefined;\n /** Custom query key (defaults to [def.name, params]) */\n queryKey?: readonly unknown[];\n /** Transform the query data. Useful for deriving different views from the same cache. */\n select?: (data: Optimistic<TData>[] | Optimistic<TData>) => unknown;\n /**\n * Keep this query registered for optimistic updates even when unmounted.\n * Useful when you want updates from other pages to sync to this query's cache.\n */\n syncInBackground?: boolean;\n /**\n * Disable optimistic update registration for this query.\n * Useful for queries that don't need optimistic updates (e.g. analytics, logs).\n */\n disableOptimistic?: boolean;\n}\n\n/** Adds ensureQueryData capability to a query result */\nexport type WithEnsureData<TData> = {\n ensureQueryData: (options?: { staleTime?: number }) => Promise<TData>;\n};\n\n/** Return type for collection queries: [data, queryResult] */\nexport type QueryResult<T> = [\n Optimistic<T>[] | undefined,\n UseQueryResult<T[], Error> & WithEnsureData<T[]>\n];\n\n/** Return type for paginated queries: [data, infiniteQueryResult] */\nexport type PaginatedQueryResult<T> = [\n Optimistic<T>[] | undefined,\n UseInfiniteQueryResult<{ pages: T[][]; pageParams: unknown[] }, Error>\n];\n\n/** Return type for entity queries: [data, queryResult] */\nexport type EntityResult<T> = [\n Optimistic<T> | undefined,\n UseQueryResult<T, Error> & WithEnsureData<T>\n];\n\n/**\n * Unified query hook for fetching data\n *\n * Returns a tuple of [data, queryResult] where queryResult is the full\n * TanStack Query result object with all properties (isLoading, isError,\n * refetch, etc.)\n *\n * @example\n * // Simple collection query\n * const [data, query] = useQuery(postsQuery, { params: { limit: 10 } })\n * // query.isLoading, query.isError, query.refetch(), etc.\n *\n * @example\n * // Paginated query - returns full infinite query result\n * const [data, query] = useQuery(postsQuery, {\n * paginated: true,\n * getPageParams: ({ pageParam }) => ({ page: pageParam, limit: 10 })\n * })\n * // query.fetchNextPage(), query.hasNextPage, query.isFetchingNextPage\n *\n * @example\n * // Entity query\n * const [user, query] = useQuery(userEntity, { params: userId })\n */\nexport function useQuery<TData, TParams, TSelected>(\n def: CollectionDef<TData, TParams>,\n options: Omit<UseQueryHookOptions<TParams, TData>, 'select'> & { paginated: true; select: (data: Optimistic<TData>[]) => TSelected }\n): [TSelected | undefined, UseInfiniteQueryResult<{ pages: TData[][]; pageParams: unknown[] }, Error>];\n\nexport function useQuery<TData, TParams>(\n def: CollectionDef<TData, TParams>,\n options: UseQueryHookOptions<TParams, TData> & { paginated: true }\n): PaginatedQueryResult<TData>;\n\nexport function useQuery<TData, TParams, TSelected>(\n def: CollectionDef<TData, TParams>,\n options: Omit<UseQueryHookOptions<TParams, TData>, 'select'> & { select: (data: Optimistic<TData>[]) => TSelected }\n): [TSelected | undefined, UseQueryResult<TData[], Error> & WithEnsureData<TData[]>];\n\nexport function useQuery<TData, TParams>(\n def: CollectionDef<TData, TParams>,\n options?: UseQueryHookOptions<TParams, TData>\n): QueryResult<TData>;\n\nexport function useQuery<TData, TParams, TSelected>(\n def: EntityDef<TData, TParams>,\n options: Omit<UseQueryHookOptions<TParams, TData>, 'select'> & { select: (data: Optimistic<TData>) => TSelected }\n): [TSelected | undefined, UseQueryResult<TData, Error> & WithEnsureData<TData>];\n\nexport function useQuery<TData, TParams>(\n def: EntityDef<TData, TParams>,\n options?: UseQueryHookOptions<TParams, TData>\n): EntityResult<TData>;\n\nexport function useQuery<TData, TParams>(\n def: CollectionDef<TData, TParams> | EntityDef<TData, TParams>,\n options?: UseQueryHookOptions<TParams, TData>\n): QueryResult<TData> | PaginatedQueryResult<TData> | EntityResult<TData> {\n const queryClient = useQueryClient();\n const { params, paginated, getPageParams, getNextPageParam, select, queryKey: customQueryKey, syncInBackground, disableOptimistic, ...queryOptions } = options ?? {};\n\n // Set queryClient on registry for direct cache access\n registry.setQueryClient(queryClient);\n\n // Stabilize params and customQueryKey to prevent unnecessary queryKey recalculations\n const stableParams = useStableValue(params);\n const stableCustomQueryKey = useStableValue(customQueryKey);\n\n // Build query key\n const queryKey = useMemo(\n () => stableCustomQueryKey ?? [def.name, stableParams].filter(Boolean),\n [stableCustomQueryKey, def.name, stableParams]\n );\n\n // Entity query\n if (def._type === 'entity') {\n const entityDef = def as EntityDef<TData, TParams>;\n const query = useTanstackQuery({\n queryKey,\n queryFn: () => entityDef.fetch(stableParams as TParams),\n enabled: queryOptions.enabled,\n staleTime: queryOptions.staleTime,\n gcTime: queryOptions.cacheTime,\n placeholderData: queryOptions.placeholderData as any,\n refetchOnMount: queryOptions.refetchOnMount,\n refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,\n refetchInterval: queryOptions.refetchInterval,\n });\n\n // Register for optimistic updates\n useEffect(() => {\n if (disableOptimistic || query.status !== 'success' || !query.data) {\n return;\n }\n\n const entry = {\n kind: 'entity' as const,\n name: def.name,\n queryKey,\n def: entityDef,\n getData: () => queryClient.getQueryData<TData>(queryKey),\n setData: (updater: (prev: TData | undefined) => TData | undefined) =>\n queryClient.setQueryData<TData>(queryKey, updater),\n };\n\n registry.register(entry);\n\n // If syncInBackground is enabled, don't unregister on unmount\n if (!syncInBackground) {\n return () => registry.unregister(entry);\n }\n }, [def.name, queryKey, query.status, query.data, queryClient, syncInBackground, disableOptimistic]);\n\n const ensuredQuery = Object.assign(query, {\n ensureQueryData: (opts?: { staleTime?: number }) =>\n queryClient.ensureQueryData<TData>({\n queryKey,\n queryFn: () => entityDef.fetch(stableParams as TParams),\n staleTime: opts?.staleTime ?? queryOptions.staleTime,\n }),\n });\n\n const data = ensuredQuery.data as Optimistic<TData> | undefined;\n return [\n (data !== undefined && select ? select(data) : data) as any,\n ensuredQuery,\n ];\n }\n\n const collectionDef = def as CollectionDef<TData, TParams>;\n\n // Paginated collection\n if (paginated) {\n const infiniteQuery = useInfiniteQuery({\n queryKey,\n queryFn: ({ pageParam }) => {\n const pageParams = getPageParams\n ? getPageParams({ pageParam: pageParam as number })\n : ({ pageParam } as TParams);\n return collectionDef.fetch(pageParams);\n },\n initialPageParam: 1,\n getNextPageParam: getNextPageParam\n ?? ((lastPage, allPages) =>\n lastPage.length > 0 ? allPages.length + 1 : undefined),\n enabled: queryOptions.enabled,\n staleTime: queryOptions.staleTime,\n gcTime: queryOptions.cacheTime,\n refetchOnMount: queryOptions.refetchOnMount,\n refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,\n refetchInterval: queryOptions.refetchInterval,\n });\n\n const flatData = useMemo(() => {\n const flat = infiniteQuery.data?.pages.flat() as Optimistic<TData>[] | undefined;\n return flat !== undefined && select ? select(flat) : flat;\n }, [infiniteQuery.data]);\n\n // Register for optimistic updates\n useEffect(() => {\n if (disableOptimistic || infiniteQuery.status !== 'success' || !infiniteQuery.data) return;\n\n const entry = {\n kind: 'paginated' as const,\n name: def.name,\n queryKey,\n def: collectionDef,\n getData: () =>\n queryClient.getQueryData<{ pages: TData[][]; pageParams: unknown[] }>(\n queryKey\n ),\n setData: (\n updater: (\n prev: { pages: TData[][]; pageParams: unknown[] } | undefined\n ) => { pages: TData[][]; pageParams: unknown[] } | undefined\n ) =>\n queryClient.setQueryData<{\n pages: TData[][];\n pageParams: unknown[];\n }>(queryKey, updater),\n };\n\n registry.register(entry);\n\n // If syncInBackground is enabled, don't unregister on unmount\n if (!syncInBackground) {\n return () => registry.unregister(entry);\n }\n }, [def.name, queryKey, infiniteQuery.status, infiniteQuery.data, queryClient, syncInBackground, disableOptimistic]);\n\n return [\n flatData as any,\n infiniteQuery as UseInfiniteQueryResult<{ pages: TData[][]; pageParams: unknown[] }, Error>,\n ];\n }\n\n // Simple collection query\n const query = useTanstackQuery({\n queryKey,\n queryFn: () => collectionDef.fetch(stableParams as TParams),\n enabled: queryOptions.enabled,\n staleTime: queryOptions.staleTime,\n gcTime: queryOptions.cacheTime,\n placeholderData: queryOptions.placeholderData as any,\n refetchOnMount: queryOptions.refetchOnMount,\n refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,\n refetchInterval: queryOptions.refetchInterval,\n });\n\n // Register for optimistic updates\n useEffect(() => {\n if (disableOptimistic || query.status !== 'success' || !query.data) return;\n\n const entry = {\n kind: 'collection' as const,\n name: def.name,\n queryKey,\n def: collectionDef,\n getData: () => queryClient.getQueryData<TData[]>(queryKey),\n setData: (updater: (prev: TData[] | undefined) => TData[] | undefined) =>\n queryClient.setQueryData<TData[]>(queryKey, updater),\n };\n\n registry.register(entry);\n\n // If syncInBackground is enabled, don't unregister on unmount\n if (!syncInBackground) {\n return () => registry.unregister(entry);\n }\n }, [def.name, queryKey, query.status, query.data, queryClient, syncInBackground, disableOptimistic]);\n\n const ensuredQuery = Object.assign(query, {\n ensureQueryData: (opts?: { staleTime?: number }) =>\n queryClient.ensureQueryData<TData[]>({\n queryKey,\n queryFn: () => collectionDef.fetch(stableParams as TParams),\n staleTime: opts?.staleTime ?? queryOptions.staleTime,\n }),\n });\n\n const data = ensuredQuery.data as Optimistic<TData>[] | undefined;\n return [\n (data !== undefined && select ? select(data) : data) as any,\n ensuredQuery,\n ];\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport {\n useQueries as useTanstackQueries,\n useQueryClient,\n type UseQueryResult,\n} from '@tanstack/react-query';\nimport type {\n CollectionDef,\n EntityDef,\n Optimistic,\n} from '../core/types';\nimport { registry } from '../core/registry';\nimport type { UseQueryHookOptions, QueryResult, EntityResult } from './use-query';\n\n/**\n * Fetch multiple queries of the same entity/collection type in parallel.\n *\n * @example\n * const results = useQueries(tokenInfoEntity, positions.map(p => ({\n * params: { address: p.tokenAddress, chainName },\n * })))\n * // results[i] = [data, queryResult]\n */\nexport function useQueries<TData, TParams>(\n def: EntityDef<TData, TParams>,\n optionsArray: UseQueryHookOptions<TParams, TData>[]\n): EntityResult<TData>[];\n\nexport function useQueries<TData, TParams>(\n def: CollectionDef<TData, TParams>,\n optionsArray: UseQueryHookOptions<TParams, TData>[]\n): QueryResult<TData>[];\n\nexport function useQueries<TData, TParams>(\n def: EntityDef<TData, TParams> | CollectionDef<TData, TParams>,\n optionsArray: UseQueryHookOptions<TParams, TData>[]\n): (EntityResult<TData> | QueryResult<TData>)[] {\n const queryClient = useQueryClient();\n\n registry.setQueryClient(queryClient);\n\n const queries = useMemo(\n () =>\n optionsArray.map((opts) => {\n const { params, queryKey: customQueryKey, ...queryOptions } = opts;\n const queryKey = customQueryKey ?? [def.name, params].filter(Boolean);\n\n return {\n queryKey,\n queryFn: () => def.fetch(params as TParams),\n enabled: queryOptions.enabled,\n staleTime: queryOptions.staleTime,\n gcTime: queryOptions.cacheTime,\n refetchOnMount: queryOptions.refetchOnMount,\n refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,\n refetchInterval: queryOptions.refetchInterval,\n };\n }),\n [def, optionsArray]\n );\n\n const results = useTanstackQueries({ queries });\n\n // Track registered entries for cleanup\n const registeredRef = useRef<Set<any>>(new Set());\n\n useEffect(() => {\n const currentEntries = new Set<any>();\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (optionsArray[i]?.disableOptimistic || result.status !== 'success' || !result.data) continue;\n\n const queryKey = queries[i].queryKey;\n\n if (def._type === 'entity') {\n const entry = {\n kind: 'entity' as const,\n name: def.name,\n queryKey,\n def: def as EntityDef<TData, TParams>,\n getData: () => queryClient.getQueryData<TData>(queryKey),\n setData: (updater: (prev: TData | undefined) => TData | undefined) =>\n queryClient.setQueryData<TData>(queryKey, updater),\n };\n registry.register(entry);\n currentEntries.add(entry);\n } else {\n const collDef = def as CollectionDef<TData, TParams>;\n const entry = {\n kind: 'collection' as const,\n name: def.name,\n queryKey,\n def: collDef,\n getData: () => queryClient.getQueryData<TData[]>(queryKey),\n setData: (updater: (prev: TData[] | undefined) => TData[] | undefined) =>\n queryClient.setQueryData<TData[]>(queryKey, updater),\n };\n registry.register(entry);\n currentEntries.add(entry);\n }\n }\n\n // Unregister previous entries that are no longer active\n for (const entry of registeredRef.current) {\n if (!currentEntries.has(entry)) {\n registry.unregister(entry);\n }\n }\n\n registeredRef.current = currentEntries;\n\n return () => {\n for (const entry of currentEntries) {\n registry.unregister(entry);\n }\n registeredRef.current = new Set();\n };\n }, [def, results, queries, queryClient, optionsArray]);\n\n // Map to tuples\n return results.map((result) => {\n if (def._type === 'entity') {\n return [\n result.data as Optimistic<TData> | undefined,\n result as UseQueryResult<TData, Error>,\n ] as EntityResult<TData>;\n }\n return [\n result.data as Optimistic<TData>[] | undefined,\n result as UseQueryResult<TData[], Error>,\n ] as QueryResult<TData>;\n });\n}\n","import { createContext, useContext, type ReactNode } from 'react';\n\nexport interface OptimisticQueryProviderProps {\n /** Default error handler called when no local onError is provided */\n onError?: (error: Error) => void;\n children: ReactNode;\n}\n\ninterface OptimisticQueryContextValue {\n onError?: (error: Error) => void;\n}\n\nconst OptimisticQueryContext = createContext<OptimisticQueryContextValue>({});\n\nexport function OptimisticQueryProvider({ onError, children }: OptimisticQueryProviderProps) {\n return (\n <OptimisticQueryContext.Provider value={{ onError }}>\n {children}\n </OptimisticQueryContext.Provider>\n );\n}\n\nexport function useOptimisticQueryContext(): OptimisticQueryContextValue {\n return useContext(OptimisticQueryContext);\n}\n","import {\n useMutation as useTanstackMutation,\n type UseMutationResult,\n} from '@tanstack/react-query';\nimport { nanoid } from 'nanoid';\nimport { useOptimisticQueryContext } from './provider';\nimport type {\n MutationDef,\n CollectionDef,\n EntityDef,\n} from '../core/types';\nimport { registry } from '../core/registry';\nimport {\n channel as coreChannel,\n type Channel,\n type ChannelOptions,\n type CollectionChannel,\n type EntityChannel,\n} from '../core/channel';\n\n/** Extract entity type from a collection or entity definition */\ntype InferEntity<T> = T extends CollectionDef<infer TData, any>\n ? TData & {}\n : T extends EntityDef<infer TData, any>\n ? TData & {}\n : never;\n\n/** Base optimistic config with shared properties */\ninterface OptimisticConfigBase<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> {\n /** Target collection/entity to update */\n target: TTarget;\n /** Whether to reconcile with server response (replace optimistic with real data) */\n reconcile?: boolean;\n}\n\n/** Config for prepend/append actions - requires full entity */\ninterface OptimisticPrependAppendConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> extends OptimisticConfigBase<TTarget, TParams> {\n action: 'prepend' | 'append';\n /** Data to prepend/append - must be a full entity */\n data: (params: TParams) => NoInfer<InferEntity<TTarget>>;\n}\n\n/** Config for replace action */\ninterface OptimisticReplaceConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> extends OptimisticConfigBase<TTarget, TParams> {\n action: 'replace';\n /** Data for replacement */\n data: (params: TParams) => NoInfer<InferEntity<TTarget>>;\n /** ID of item to replace */\n id?: string | ((params: TParams) => string);\n /** Filter function to find items to replace */\n where?: (item: NoInfer<InferEntity<TTarget>>) => boolean;\n}\n\n/** Config for update action */\ninterface OptimisticUpdateConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> extends OptimisticConfigBase<TTarget, TParams> {\n action: 'update';\n /** Partial data for update */\n data?: (params: TParams) => Partial<NoInfer<InferEntity<TTarget>>>;\n /** ID of item to update */\n id?: string | ((params: TParams) => string);\n /** Filter function to find items to update */\n where?: (item: NoInfer<InferEntity<TTarget>>) => boolean;\n /** Update function */\n update?: (item: NoInfer<InferEntity<TTarget>>, params: TParams) => NoInfer<InferEntity<TTarget>>;\n}\n\n/** Config for delete action */\ninterface OptimisticDeleteConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> extends OptimisticConfigBase<TTarget, TParams> {\n action: 'delete';\n /** ID of item to delete */\n id?: string | ((params: TParams) => string);\n /** Filter function to find items to delete */\n where?: (item: NoInfer<InferEntity<TTarget>>) => boolean;\n}\n\n/** Optimistic update configuration - type inferred from target */\nexport type OptimisticConfig<\n TTarget extends CollectionDef<any, any> | EntityDef<any, any>,\n TParams\n> =\n | OptimisticPrependAppendConfig<TTarget, TParams>\n | OptimisticReplaceConfig<TTarget, TParams>\n | OptimisticUpdateConfig<TTarget, TParams>\n | OptimisticDeleteConfig<TTarget, TParams>;\n\n/** Internal transaction type for batched mutations */\ninterface MutationTransaction {\n target: CollectionDef<any, any> | EntityDef<any, any>;\n action: 'prepend' | 'append' | 'update' | 'delete' | 'replace';\n data?: any;\n id?: string;\n where?: (item: any) => boolean;\n update?: (item: any) => any;\n reconcile?: boolean;\n scope?: Record<string, unknown>;\n}\n\n/** Internal collection channel for batched mutations */\nclass BatchedCollectionChannel<TEntity> {\n constructor(\n private readonly target: CollectionDef<TEntity, any>,\n private readonly transactions: MutationTransaction[],\n private readonly options?: ChannelOptions\n ) {}\n\n prepend(data: TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'prepend',\n data,\n reconcile: options?.reconcile,\n scope: this.options?.scope,\n });\n return this;\n }\n\n append(data: TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'append',\n data,\n reconcile: options?.reconcile,\n scope: this.options?.scope,\n });\n return this;\n }\n\n update(id: string, updateFn: (item: TEntity) => TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'update',\n id,\n update: updateFn,\n reconcile: options?.reconcile,\n scope: this.options?.scope,\n });\n return this;\n }\n\n delete(id: string): this {\n this.transactions.push({\n target: this.target,\n action: 'delete',\n id,\n scope: this.options?.scope,\n });\n return this;\n }\n}\n\n/** Internal entity channel for batched mutations */\nclass BatchedEntityChannel<TEntity> {\n constructor(\n private readonly target: EntityDef<TEntity, any>,\n private readonly transactions: MutationTransaction[]\n ) {}\n\n update(updateFn: (item: TEntity) => TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'update',\n update: updateFn,\n reconcile: options?.reconcile,\n });\n return this;\n }\n\n replace(data: TEntity, options?: { reconcile?: boolean }): this {\n this.transactions.push({\n target: this.target,\n action: 'replace',\n data,\n reconcile: options?.reconcile,\n });\n return this;\n }\n}\n\n/** Internal batched channel type */\ninterface BatchedChannel {\n <TEntity>(target: CollectionDef<TEntity, any>, options?: ChannelOptions): BatchedCollectionChannel<TEntity>;\n <TEntity>(target: EntityDef<TEntity, any>): BatchedEntityChannel<TEntity>;\n}\n\n/** Creates a batched channel for collecting mutations */\nfunction createBatchedChannel(transactions: MutationTransaction[]): BatchedChannel {\n function channel<TEntity>(target: CollectionDef<TEntity, any>, options?: ChannelOptions): BatchedCollectionChannel<TEntity>;\n function channel<TEntity>(target: EntityDef<TEntity, any>): BatchedEntityChannel<TEntity>;\n function channel<TEntity>(\n target: CollectionDef<TEntity, any> | EntityDef<TEntity, any>,\n options?: ChannelOptions\n ): BatchedCollectionChannel<TEntity> | BatchedEntityChannel<TEntity> {\n if (target._type === 'collection') {\n return new BatchedCollectionChannel(target, transactions, options);\n } else {\n return new BatchedEntityChannel(target, transactions);\n }\n }\n return channel;\n}\n\n\n/** Options for useMutation hook */\nexport interface UseMutationOptions<TParams, TResponse> {\n /** Called when mutation starts */\n onMutate?: (params: TParams) => void;\n /** Called on success */\n onSuccess?: (data: TResponse, params: TParams) => void;\n /** Called on error */\n onError?: (error: Error, params: TParams) => void;\n}\n\n/**\n * Mutation hook with simplified optimistic updates\n *\n * @example\n * // Simple mutation\n * const { mutate } = useMutation(createPost)\n *\n * @example\n * // With optimistic update\n * const { mutate } = useMutation(createPost, {\n * optimistic: {\n * target: postsQuery,\n * action: 'prepend',\n * data: (params) => ({ ...params, _id: 'temp-id' })\n * }\n * })\n *\n * @example\n * // Multiple optimistic updates\n * const { mutate } = useMutation(deletePost, {\n * optimistic: [\n * { target: postsQuery, action: 'delete', id: (p) => p.postId },\n * { target: userStatsEntity, action: 'update', update: (stats) => ({ ...stats, postCount: stats.postCount - 1 }) }\n * ]\n * })\n */\nexport function useMutation<\n TParams,\n TResponse,\n>(\n def: MutationDef<TParams, TResponse>,\n options?: UseMutationOptions<TParams, TResponse> & {\n /** Optimistic update configuration - receives channel and params */\n optimistic?: (channel: BatchedChannel, params: TParams) => void;\n }\n): UseMutationResult<TResponse, Error, TParams> {\n const context = useOptimisticQueryContext();\n const mutation = useTanstackMutation<\n TResponse,\n Error,\n TParams,\n { rollbacks: (() => void)[]; optimisticId: string; transactions: MutationTransaction[] }\n >({\n mutationKey: def.name ? [def.name] : undefined,\n mutationFn: def.mutate,\n\n onMutate: async (params) => {\n const rollbacks: (() => void)[] = [];\n const optimisticId = nanoid();\n const transactions: MutationTransaction[] = [];\n\n // Apply optimistic updates via channel\n if (options?.optimistic) {\n const channel = createBatchedChannel(transactions);\n options.optimistic(channel, params);\n\n for (const tx of transactions) {\n const { target, action, data, id, where, update, scope } = tx;\n\n // Add optimistic metadata to data\n const optimisticData = data\n ? {\n ...data,\n _optimistic: { id: optimisticId, status: 'pending' as const },\n }\n : undefined;\n\n const updateRollbacks = registry.applyUpdate(target.name, action, {\n data: optimisticData,\n id,\n where,\n update: update\n ? (item: any) => update(item)\n : optimisticData\n ? (item: any) => ({ ...item, ...optimisticData })\n : undefined,\n }, scope);\n\n rollbacks.push(...updateRollbacks);\n }\n }\n\n options?.onMutate?.(params);\n return { rollbacks, optimisticId, transactions };\n },\n\n onSuccess: (data, params, context) => {\n // If reconcile is enabled, replace optimistic data with server response\n if (context?.transactions) {\n for (const tx of context.transactions) {\n if (tx.reconcile && data) {\n // Replace optimistic item with real server data\n registry.applyUpdate(tx.target.name, 'update', {\n where: (item: any) =>\n item._optimistic?.id === context?.optimisticId,\n update: () => data as any,\n });\n }\n }\n }\n\n options?.onSuccess?.(data, params);\n },\n\n onError: (error, params, mutationContext) => {\n // Rollback all optimistic updates\n mutationContext?.rollbacks.forEach((rollback) => rollback());\n if (options?.onError) {\n options.onError(error, params);\n } else {\n context.onError?.(error);\n }\n },\n });\n\n return mutation;\n}\n"]}
@@ -106,8 +106,7 @@ var QueryRegistry = class {
106
106
  /** Apply update directly to query cache (used when scope is provided) */
107
107
  applyDirectCacheUpdate(name, action, payload, scope) {
108
108
  if (!this.queryClient) return [];
109
- const def = this.collectionDefs.get(name);
110
- if (!def) return [];
109
+ const collectionDef = this.collectionDefs.get(name);
111
110
  const rollbacks = [];
112
111
  const queries = this.queryClient.getQueriesData({
113
112
  queryKey: [name]
@@ -116,28 +115,40 @@ var QueryRegistry = class {
116
115
  if (!data) continue;
117
116
  const params = queryKey[1];
118
117
  if (!this.matchesScope(params, scope)) continue;
119
- const isPaginated = data && typeof data === "object" && "pages" in data;
120
- if (isPaginated) {
121
- const paginatedData = data;
122
- const previous = paginatedData;
123
- rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
124
- this.queryClient.setQueryData(queryKey, (prev) => {
125
- if (!prev) return prev;
126
- return {
127
- ...prev,
128
- pages: prev.pages.map(
129
- (page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, def.id) : page
130
- )
131
- };
132
- });
118
+ if (collectionDef) {
119
+ const isPaginated = data && typeof data === "object" && "pages" in data;
120
+ if (isPaginated) {
121
+ const paginatedData = data;
122
+ const previous = paginatedData;
123
+ rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
124
+ this.queryClient.setQueryData(queryKey, (prev) => {
125
+ if (!prev) return prev;
126
+ return {
127
+ ...prev,
128
+ pages: prev.pages.map(
129
+ (page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, collectionDef.id) : page
130
+ )
131
+ };
132
+ });
133
+ } else {
134
+ const previous = data;
135
+ rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
136
+ this.queryClient.setQueryData(queryKey, (prev) => {
137
+ if (!prev) return prev;
138
+ return this.applyCollectionUpdate(prev, action, payload, collectionDef.id);
139
+ });
140
+ }
133
141
  } else {
134
- const arrayData = data;
135
- const previous = arrayData;
142
+ const previous = data;
136
143
  rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
137
- this.queryClient.setQueryData(queryKey, (prev) => {
138
- if (!prev) return prev;
139
- return this.applyCollectionUpdate(prev, action, payload, def.id);
140
- });
144
+ if (action === "update" && payload.update) {
145
+ this.queryClient.setQueryData(
146
+ queryKey,
147
+ (prev) => prev ? payload.update(prev) : prev
148
+ );
149
+ } else if (action === "replace" && payload.data) {
150
+ this.queryClient.setQueryData(queryKey, payload.data);
151
+ }
141
152
  }
142
153
  }
143
154
  return rollbacks;
@@ -178,22 +189,35 @@ var QueryRegistry = class {
178
189
  var registry = new QueryRegistry();
179
190
 
180
191
  // src/react/use-query.ts
192
+ function useStableValue(value) {
193
+ const serializedRef = useRef();
194
+ const valueRef = useRef(value);
195
+ const serialized = JSON.stringify(value);
196
+ if (serializedRef.current !== serialized) {
197
+ serializedRef.current = serialized;
198
+ valueRef.current = value;
199
+ }
200
+ return valueRef.current;
201
+ }
181
202
  function useQuery(def, options) {
182
203
  const queryClient = useQueryClient();
183
204
  const { params, paginated, getPageParams, getNextPageParam, select, queryKey: customQueryKey, syncInBackground, disableOptimistic, ...queryOptions } = options ?? {};
184
205
  registry.setQueryClient(queryClient);
206
+ const stableParams = useStableValue(params);
207
+ const stableCustomQueryKey = useStableValue(customQueryKey);
185
208
  const queryKey = useMemo(
186
- () => customQueryKey ?? [def.name, params].filter(Boolean),
187
- [customQueryKey, def.name, params]
209
+ () => stableCustomQueryKey ?? [def.name, stableParams].filter(Boolean),
210
+ [stableCustomQueryKey, def.name, stableParams]
188
211
  );
189
212
  if (def._type === "entity") {
190
213
  const entityDef = def;
191
214
  const query2 = useQuery$1({
192
215
  queryKey,
193
- queryFn: () => entityDef.fetch(params),
216
+ queryFn: () => entityDef.fetch(stableParams),
194
217
  enabled: queryOptions.enabled,
195
218
  staleTime: queryOptions.staleTime,
196
219
  gcTime: queryOptions.cacheTime,
220
+ placeholderData: queryOptions.placeholderData,
197
221
  refetchOnMount: queryOptions.refetchOnMount,
198
222
  refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,
199
223
  refetchInterval: queryOptions.refetchInterval
@@ -218,7 +242,7 @@ function useQuery(def, options) {
218
242
  const ensuredQuery2 = Object.assign(query2, {
219
243
  ensureQueryData: (opts) => queryClient.ensureQueryData({
220
244
  queryKey,
221
- queryFn: () => entityDef.fetch(params),
245
+ queryFn: () => entityDef.fetch(stableParams),
222
246
  staleTime: opts?.staleTime ?? queryOptions.staleTime
223
247
  })
224
248
  });
@@ -273,10 +297,11 @@ function useQuery(def, options) {
273
297
  }
274
298
  const query = useQuery$1({
275
299
  queryKey,
276
- queryFn: () => collectionDef.fetch(params),
300
+ queryFn: () => collectionDef.fetch(stableParams),
277
301
  enabled: queryOptions.enabled,
278
302
  staleTime: queryOptions.staleTime,
279
303
  gcTime: queryOptions.cacheTime,
304
+ placeholderData: queryOptions.placeholderData,
280
305
  refetchOnMount: queryOptions.refetchOnMount,
281
306
  refetchOnWindowFocus: queryOptions.refetchOnWindowFocus,
282
307
  refetchInterval: queryOptions.refetchInterval
@@ -299,7 +324,7 @@ function useQuery(def, options) {
299
324
  const ensuredQuery = Object.assign(query, {
300
325
  ensureQueryData: (opts) => queryClient.ensureQueryData({
301
326
  queryKey,
302
- queryFn: () => collectionDef.fetch(params),
327
+ queryFn: () => collectionDef.fetch(stableParams),
303
328
  staleTime: opts?.staleTime ?? queryOptions.staleTime
304
329
  })
305
330
  });