query-optimistic 0.9.0 → 0.10.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.
- package/dist/{channel-OFFEKFI1.d.mts → channel-BtO4F29s.d.mts} +3 -2
- package/dist/{channel-OFFEKFI1.d.ts → channel-BtO4F29s.d.ts} +3 -2
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +38 -26
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +38 -26
- package/dist/core/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +38 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +38 -26
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +33 -22
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +33 -22
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -130,8 +130,7 @@ var QueryRegistry = class {
|
|
|
130
130
|
/** Apply update directly to query cache (used when scope is provided) */
|
|
131
131
|
applyDirectCacheUpdate(name, action, payload, scope) {
|
|
132
132
|
if (!this.queryClient) return [];
|
|
133
|
-
const
|
|
134
|
-
if (!def) return [];
|
|
133
|
+
const collectionDef = this.collectionDefs.get(name);
|
|
135
134
|
const rollbacks = [];
|
|
136
135
|
const queries = this.queryClient.getQueriesData({
|
|
137
136
|
queryKey: [name]
|
|
@@ -140,28 +139,40 @@ var QueryRegistry = class {
|
|
|
140
139
|
if (!data) continue;
|
|
141
140
|
const params = queryKey[1];
|
|
142
141
|
if (!this.matchesScope(params, scope)) continue;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
142
|
+
if (collectionDef) {
|
|
143
|
+
const isPaginated = data && typeof data === "object" && "pages" in data;
|
|
144
|
+
if (isPaginated) {
|
|
145
|
+
const paginatedData = data;
|
|
146
|
+
const previous = paginatedData;
|
|
147
|
+
rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
|
|
148
|
+
this.queryClient.setQueryData(queryKey, (prev) => {
|
|
149
|
+
if (!prev) return prev;
|
|
150
|
+
return {
|
|
151
|
+
...prev,
|
|
152
|
+
pages: prev.pages.map(
|
|
153
|
+
(page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, collectionDef.id) : page
|
|
154
|
+
)
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
} else {
|
|
158
|
+
const previous = data;
|
|
159
|
+
rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
|
|
160
|
+
this.queryClient.setQueryData(queryKey, (prev) => {
|
|
161
|
+
if (!prev) return prev;
|
|
162
|
+
return this.applyCollectionUpdate(prev, action, payload, collectionDef.id);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
157
165
|
} else {
|
|
158
|
-
const
|
|
159
|
-
const previous = arrayData;
|
|
166
|
+
const previous = data;
|
|
160
167
|
rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
168
|
+
if (action === "update" && payload.update) {
|
|
169
|
+
this.queryClient.setQueryData(
|
|
170
|
+
queryKey,
|
|
171
|
+
(prev) => prev ? payload.update(prev) : prev
|
|
172
|
+
);
|
|
173
|
+
} else if (action === "replace" && payload.data) {
|
|
174
|
+
this.queryClient.setQueryData(queryKey, payload.data);
|
|
175
|
+
}
|
|
165
176
|
}
|
|
166
177
|
}
|
|
167
178
|
return rollbacks;
|
|
@@ -278,8 +289,9 @@ var CollectionChannel = class {
|
|
|
278
289
|
}
|
|
279
290
|
};
|
|
280
291
|
var EntityChannel = class {
|
|
281
|
-
constructor(target) {
|
|
292
|
+
constructor(target, options) {
|
|
282
293
|
this.target = target;
|
|
294
|
+
this.options = options;
|
|
283
295
|
}
|
|
284
296
|
/**
|
|
285
297
|
* Update the entity
|
|
@@ -288,7 +300,7 @@ var EntityChannel = class {
|
|
|
288
300
|
update(updateFn, options) {
|
|
289
301
|
const rollbacks = registry.applyUpdate(this.target.name, "update", {
|
|
290
302
|
update: updateFn
|
|
291
|
-
});
|
|
303
|
+
}, this.options?.scope);
|
|
292
304
|
return () => rollbacks.forEach((rb) => rb());
|
|
293
305
|
}
|
|
294
306
|
/**
|
|
@@ -298,7 +310,7 @@ var EntityChannel = class {
|
|
|
298
310
|
replace(data, options) {
|
|
299
311
|
const rollbacks = registry.applyUpdate(this.target.name, "replace", {
|
|
300
312
|
data
|
|
301
|
-
});
|
|
313
|
+
}, this.options?.scope);
|
|
302
314
|
return () => rollbacks.forEach((rb) => rb());
|
|
303
315
|
}
|
|
304
316
|
};
|
|
@@ -306,7 +318,7 @@ var channel = ((target, options) => {
|
|
|
306
318
|
if (target._type === "collection") {
|
|
307
319
|
return new CollectionChannel(target, options);
|
|
308
320
|
} else {
|
|
309
|
-
return new EntityChannel(target);
|
|
321
|
+
return new EntityChannel(target, options);
|
|
310
322
|
}
|
|
311
323
|
});
|
|
312
324
|
function useQuery(def, options) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/define.ts","../src/core/registry.ts","../src/core/channel.ts","../src/react/use-query.ts","../src/react/use-queries.ts","../src/react/provider.tsx","../src/react/use-mutation.ts"],"names":["nanoid","useQueryClient","useMemo","query","useTanstackQuery","useEffect","ensuredQuery","data","useInfiniteQuery","useTanstackQueries","useRef","createContext","jsx","useContext","channel","useTanstackMutation","context"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n CollectionDef,\n EntityDef,\n MutationDef,\n IdGetter,\n} from './types';\n\n/**\n * Define a collection query for fetching arrays of items\n *\n * @example\n * const postsQuery = defineCollection({\n * name: 'posts',\n * id: (post) => post._id,\n * fetch: ({ page }) => api.get(`/posts?page=${page}`).json()\n * })\n */\nexport function defineCollection<TData, TParams = void>(config: {\n name: string;\n id: IdGetter<TData>;\n fetch: (params: TParams) => Promise<TData[]>;\n}): CollectionDef<TData, TParams> {\n return {\n _type: 'collection',\n name: config.name,\n id: config.id,\n fetch: config.fetch,\n };\n}\n\n/**\n * Define an entity for fetching single items\n *\n * @example\n * const userEntity = defineEntity({\n * name: 'user',\n * fetch: (userId) => api.get(`/users/${userId}`).json()\n * })\n */\nexport function defineEntity<TData, TParams = void>(config: {\n name: string;\n fetch: (params: TParams) => Promise<TData>;\n}): EntityDef<TData, TParams> {\n return {\n _type: 'entity',\n name: config.name,\n fetch: config.fetch,\n };\n}\n\n/**\n * Define a mutation for writing data\n *\n * @example\n * const createPost = defineMutation({\n * name: 'createPost',\n * mutate: (data) => api.post('/posts', { json: data }).json()\n * })\n */\nexport function defineMutation<TParams, TResponse = void>(config: {\n name?: string;\n mutate: (params: TParams) => Promise<TResponse>;\n}): MutationDef<TParams, TResponse> {\n return {\n _type: 'mutation',\n name: config.name,\n mutate: config.mutate,\n };\n}\n","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 { nanoid } from 'nanoid';\nimport type { CollectionDef, EntityDef, Optimistic } from './types';\nimport { registry } from './registry';\n\n/** Transaction returned from channel methods */\nexport interface OptimisticTransaction {\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 sync?: boolean;\n rollback: () => void;\n}\n\n/** Options for channel operations */\nexport interface ChannelOptions {\n /**\n * Only apply updates to queries whose params partially match this object.\n * All key-value pairs in scope must exist in the query's params.\n * @example\n * channel(ordersCollection, { scope: { chain: 'solana' } }).delete(id)\n * // Only affects queries with params containing chain: 'solana'\n */\n scope?: Record<string, unknown>;\n}\n\n/** Channel for a collection - provides typed optimistic mutation methods */\nexport class CollectionChannel<TEntity> {\n private readonly optimisticId = nanoid();\n\n constructor(\n private readonly target: CollectionDef<TEntity, any>,\n private readonly options?: ChannelOptions\n ) {}\n\n /**\n * Prepend an item to the collection\n * @returns Rollback function to undo the change\n */\n prepend(data: TEntity, options?: { sync?: boolean }): () => void {\n const optimisticData = {\n ...data,\n _optimistic: { id: this.optimisticId, status: 'pending' as const },\n };\n\n const rollbacks = registry.applyUpdate(this.target.name, 'prepend', {\n data: optimisticData,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Append an item to the collection\n * @returns Rollback function to undo the change\n */\n append(data: TEntity, options?: { sync?: boolean }): () => void {\n const optimisticData = {\n ...data,\n _optimistic: { id: this.optimisticId, status: 'pending' as const },\n };\n\n const rollbacks = registry.applyUpdate(this.target.name, 'append', {\n data: optimisticData,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Update an item in the collection by ID\n * @returns Rollback function to undo the change\n */\n update(\n id: string,\n updateFn: (item: TEntity) => TEntity,\n options?: { sync?: boolean }\n ): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'update', {\n id,\n update: updateFn,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Update items matching a predicate\n * @returns Rollback function to undo the change\n */\n updateWhere(\n where: (item: TEntity) => boolean,\n updateFn: (item: TEntity) => TEntity\n ): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'update', {\n where,\n update: updateFn,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Delete an item from the collection by ID\n * @returns Rollback function to undo the change\n */\n delete(id: string): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'delete', {\n id,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Delete items matching a predicate\n * @returns Rollback function to undo the change\n */\n deleteWhere(where: (item: TEntity) => boolean): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'delete', {\n where,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n}\n\n/** Channel for an entity - provides typed optimistic mutation methods */\nexport class EntityChannel<TEntity> {\n constructor(private readonly target: EntityDef<TEntity, any>) {}\n\n /**\n * Update the entity\n * @returns Rollback function to undo the change\n */\n update(updateFn: (item: TEntity) => TEntity, options?: { sync?: boolean }): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'update', {\n update: updateFn,\n });\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Replace the entity with new data\n * @returns Rollback function to undo the change\n */\n replace(data: TEntity, options?: { sync?: boolean }): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'replace', {\n data: data as any,\n });\n\n return () => rollbacks.forEach((rb) => rb());\n }\n}\n\n/**\n * Channel function for optimistic mutations.\n * Call with a collection or entity to get typed mutation methods.\n *\n * @example\n * // Standalone usage\n * const rollback = channel(usersCollection).prepend({ id: '1', name: 'John' });\n * // Later, to undo:\n * rollback();\n *\n * @example\n * // Update an entity\n * channel(userEntity).update(user => ({ ...user, name: 'Jane' }));\n *\n * @example\n * // Scoped update\n * channel(ordersCollection, { scope: { chain: 'solana' } }).delete(id);\n * // Only affects queries with params containing chain: 'solana'\n */\nexport interface Channel {\n <TEntity>(target: CollectionDef<TEntity, any>, options?: ChannelOptions): CollectionChannel<TEntity>;\n <TEntity>(target: EntityDef<TEntity, any>): EntityChannel<TEntity>;\n}\n\n/**\n * Create a channel for optimistic mutations.\n * Use this to apply immediate UI updates that can be rolled back.\n *\n * @example\n * const rollback = channel(usersCollection).prepend(newUser);\n * try {\n * await api.createUser(newUser);\n * } catch (error) {\n * rollback(); // Undo the optimistic update\n * }\n *\n * @example\n * // Scoped update - only affects queries with matching params\n * channel(ordersCollection, { scope: { chain: 'solana', status: 'pending' } }).delete(id);\n */\nexport const channel: Channel = (<TEntity>(\n target: CollectionDef<TEntity, any> | EntityDef<TEntity, any>,\n options?: ChannelOptions\n): CollectionChannel<TEntity> | EntityChannel<TEntity> => {\n if (target._type === 'collection') {\n return new CollectionChannel(target, options);\n } else {\n return new EntityChannel(target);\n }\n}) as Channel;\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/define.ts","../src/core/registry.ts","../src/core/channel.ts","../src/react/use-query.ts","../src/react/use-queries.ts","../src/react/provider.tsx","../src/react/use-mutation.ts"],"names":["nanoid","useQueryClient","useMemo","query","useTanstackQuery","useEffect","ensuredQuery","data","useInfiniteQuery","useTanstackQueries","useRef","createContext","jsx","useContext","channel","useTanstackMutation","context"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n CollectionDef,\n EntityDef,\n MutationDef,\n IdGetter,\n} from './types';\n\n/**\n * Define a collection query for fetching arrays of items\n *\n * @example\n * const postsQuery = defineCollection({\n * name: 'posts',\n * id: (post) => post._id,\n * fetch: ({ page }) => api.get(`/posts?page=${page}`).json()\n * })\n */\nexport function defineCollection<TData, TParams = void>(config: {\n name: string;\n id: IdGetter<TData>;\n fetch: (params: TParams) => Promise<TData[]>;\n}): CollectionDef<TData, TParams> {\n return {\n _type: 'collection',\n name: config.name,\n id: config.id,\n fetch: config.fetch,\n };\n}\n\n/**\n * Define an entity for fetching single items\n *\n * @example\n * const userEntity = defineEntity({\n * name: 'user',\n * fetch: (userId) => api.get(`/users/${userId}`).json()\n * })\n */\nexport function defineEntity<TData, TParams = void>(config: {\n name: string;\n fetch: (params: TParams) => Promise<TData>;\n}): EntityDef<TData, TParams> {\n return {\n _type: 'entity',\n name: config.name,\n fetch: config.fetch,\n };\n}\n\n/**\n * Define a mutation for writing data\n *\n * @example\n * const createPost = defineMutation({\n * name: 'createPost',\n * mutate: (data) => api.post('/posts', { json: data }).json()\n * })\n */\nexport function defineMutation<TParams, TResponse = void>(config: {\n name?: string;\n mutate: (params: TParams) => Promise<TResponse>;\n}): MutationDef<TParams, TResponse> {\n return {\n _type: 'mutation',\n name: config.name,\n mutate: config.mutate,\n };\n}\n","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 { nanoid } from 'nanoid';\nimport type { CollectionDef, EntityDef, Optimistic } from './types';\nimport { registry } from './registry';\n\n/** Transaction returned from channel methods */\nexport interface OptimisticTransaction {\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 sync?: boolean;\n rollback: () => void;\n}\n\n/** Options for channel operations */\nexport interface ChannelOptions {\n /**\n * Only apply updates to queries whose params partially match this object.\n * All key-value pairs in scope must exist in the query's params.\n * @example\n * channel(ordersCollection, { scope: { chain: 'solana' } }).delete(id)\n * // Only affects queries with params containing chain: 'solana'\n */\n scope?: Record<string, unknown>;\n}\n\n/** Channel for a collection - provides typed optimistic mutation methods */\nexport class CollectionChannel<TEntity> {\n private readonly optimisticId = nanoid();\n\n constructor(\n private readonly target: CollectionDef<TEntity, any>,\n private readonly options?: ChannelOptions\n ) {}\n\n /**\n * Prepend an item to the collection\n * @returns Rollback function to undo the change\n */\n prepend(data: TEntity, options?: { sync?: boolean }): () => void {\n const optimisticData = {\n ...data,\n _optimistic: { id: this.optimisticId, status: 'pending' as const },\n };\n\n const rollbacks = registry.applyUpdate(this.target.name, 'prepend', {\n data: optimisticData,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Append an item to the collection\n * @returns Rollback function to undo the change\n */\n append(data: TEntity, options?: { sync?: boolean }): () => void {\n const optimisticData = {\n ...data,\n _optimistic: { id: this.optimisticId, status: 'pending' as const },\n };\n\n const rollbacks = registry.applyUpdate(this.target.name, 'append', {\n data: optimisticData,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Update an item in the collection by ID\n * @returns Rollback function to undo the change\n */\n update(\n id: string,\n updateFn: (item: TEntity) => TEntity,\n options?: { sync?: boolean }\n ): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'update', {\n id,\n update: updateFn,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Update items matching a predicate\n * @returns Rollback function to undo the change\n */\n updateWhere(\n where: (item: TEntity) => boolean,\n updateFn: (item: TEntity) => TEntity\n ): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'update', {\n where,\n update: updateFn,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Delete an item from the collection by ID\n * @returns Rollback function to undo the change\n */\n delete(id: string): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'delete', {\n id,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Delete items matching a predicate\n * @returns Rollback function to undo the change\n */\n deleteWhere(where: (item: TEntity) => boolean): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'delete', {\n where,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n}\n\n/** Channel for an entity - provides typed optimistic mutation methods */\nexport class EntityChannel<TEntity> {\n constructor(\n private readonly target: EntityDef<TEntity, any>,\n private readonly options?: ChannelOptions\n ) {}\n\n /**\n * Update the entity\n * @returns Rollback function to undo the change\n */\n update(updateFn: (item: TEntity) => TEntity, options?: { sync?: boolean }): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'update', {\n update: updateFn,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n\n /**\n * Replace the entity with new data\n * @returns Rollback function to undo the change\n */\n replace(data: TEntity, options?: { sync?: boolean }): () => void {\n const rollbacks = registry.applyUpdate(this.target.name, 'replace', {\n data: data as any,\n }, this.options?.scope);\n\n return () => rollbacks.forEach((rb) => rb());\n }\n}\n\n/**\n * Channel function for optimistic mutations.\n * Call with a collection or entity to get typed mutation methods.\n *\n * @example\n * // Standalone usage\n * const rollback = channel(usersCollection).prepend({ id: '1', name: 'John' });\n * // Later, to undo:\n * rollback();\n *\n * @example\n * // Update an entity\n * channel(userEntity).update(user => ({ ...user, name: 'Jane' }));\n *\n * @example\n * // Scoped update\n * channel(ordersCollection, { scope: { chain: 'solana' } }).delete(id);\n * // Only affects queries with params containing chain: 'solana'\n */\nexport interface Channel {\n <TEntity>(target: CollectionDef<TEntity, any>, options?: ChannelOptions): CollectionChannel<TEntity>;\n <TEntity>(target: EntityDef<TEntity, any>, options?: ChannelOptions): EntityChannel<TEntity>;\n}\n\n/**\n * Create a channel for optimistic mutations.\n * Use this to apply immediate UI updates that can be rolled back.\n *\n * @example\n * const rollback = channel(usersCollection).prepend(newUser);\n * try {\n * await api.createUser(newUser);\n * } catch (error) {\n * rollback(); // Undo the optimistic update\n * }\n *\n * @example\n * // Scoped update - only affects queries with matching params\n * channel(ordersCollection, { scope: { chain: 'solana', status: 'pending' } }).delete(id);\n */\nexport const channel: Channel = (<TEntity>(\n target: CollectionDef<TEntity, any> | EntityDef<TEntity, any>,\n options?: ChannelOptions\n): CollectionChannel<TEntity> | EntityChannel<TEntity> => {\n if (target._type === 'collection') {\n return new CollectionChannel(target, options);\n } else {\n return new EntityChannel(target, options);\n }\n}) as Channel;\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"]}
|
package/dist/index.mjs
CHANGED
|
@@ -128,8 +128,7 @@ var QueryRegistry = class {
|
|
|
128
128
|
/** Apply update directly to query cache (used when scope is provided) */
|
|
129
129
|
applyDirectCacheUpdate(name, action, payload, scope) {
|
|
130
130
|
if (!this.queryClient) return [];
|
|
131
|
-
const
|
|
132
|
-
if (!def) return [];
|
|
131
|
+
const collectionDef = this.collectionDefs.get(name);
|
|
133
132
|
const rollbacks = [];
|
|
134
133
|
const queries = this.queryClient.getQueriesData({
|
|
135
134
|
queryKey: [name]
|
|
@@ -138,28 +137,40 @@ var QueryRegistry = class {
|
|
|
138
137
|
if (!data) continue;
|
|
139
138
|
const params = queryKey[1];
|
|
140
139
|
if (!this.matchesScope(params, scope)) continue;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
140
|
+
if (collectionDef) {
|
|
141
|
+
const isPaginated = data && typeof data === "object" && "pages" in data;
|
|
142
|
+
if (isPaginated) {
|
|
143
|
+
const paginatedData = data;
|
|
144
|
+
const previous = paginatedData;
|
|
145
|
+
rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
|
|
146
|
+
this.queryClient.setQueryData(queryKey, (prev) => {
|
|
147
|
+
if (!prev) return prev;
|
|
148
|
+
return {
|
|
149
|
+
...prev,
|
|
150
|
+
pages: prev.pages.map(
|
|
151
|
+
(page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, collectionDef.id) : page
|
|
152
|
+
)
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
} else {
|
|
156
|
+
const previous = data;
|
|
157
|
+
rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
|
|
158
|
+
this.queryClient.setQueryData(queryKey, (prev) => {
|
|
159
|
+
if (!prev) return prev;
|
|
160
|
+
return this.applyCollectionUpdate(prev, action, payload, collectionDef.id);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
155
163
|
} else {
|
|
156
|
-
const
|
|
157
|
-
const previous = arrayData;
|
|
164
|
+
const previous = data;
|
|
158
165
|
rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
if (action === "update" && payload.update) {
|
|
167
|
+
this.queryClient.setQueryData(
|
|
168
|
+
queryKey,
|
|
169
|
+
(prev) => prev ? payload.update(prev) : prev
|
|
170
|
+
);
|
|
171
|
+
} else if (action === "replace" && payload.data) {
|
|
172
|
+
this.queryClient.setQueryData(queryKey, payload.data);
|
|
173
|
+
}
|
|
163
174
|
}
|
|
164
175
|
}
|
|
165
176
|
return rollbacks;
|
|
@@ -276,8 +287,9 @@ var CollectionChannel = class {
|
|
|
276
287
|
}
|
|
277
288
|
};
|
|
278
289
|
var EntityChannel = class {
|
|
279
|
-
constructor(target) {
|
|
290
|
+
constructor(target, options) {
|
|
280
291
|
this.target = target;
|
|
292
|
+
this.options = options;
|
|
281
293
|
}
|
|
282
294
|
/**
|
|
283
295
|
* Update the entity
|
|
@@ -286,7 +298,7 @@ var EntityChannel = class {
|
|
|
286
298
|
update(updateFn, options) {
|
|
287
299
|
const rollbacks = registry.applyUpdate(this.target.name, "update", {
|
|
288
300
|
update: updateFn
|
|
289
|
-
});
|
|
301
|
+
}, this.options?.scope);
|
|
290
302
|
return () => rollbacks.forEach((rb) => rb());
|
|
291
303
|
}
|
|
292
304
|
/**
|
|
@@ -296,7 +308,7 @@ var EntityChannel = class {
|
|
|
296
308
|
replace(data, options) {
|
|
297
309
|
const rollbacks = registry.applyUpdate(this.target.name, "replace", {
|
|
298
310
|
data
|
|
299
|
-
});
|
|
311
|
+
}, this.options?.scope);
|
|
300
312
|
return () => rollbacks.forEach((rb) => rb());
|
|
301
313
|
}
|
|
302
314
|
};
|
|
@@ -304,7 +316,7 @@ var channel = ((target, options) => {
|
|
|
304
316
|
if (target._type === "collection") {
|
|
305
317
|
return new CollectionChannel(target, options);
|
|
306
318
|
} else {
|
|
307
|
-
return new EntityChannel(target);
|
|
319
|
+
return new EntityChannel(target, options);
|
|
308
320
|
}
|
|
309
321
|
});
|
|
310
322
|
function useQuery(def, options) {
|