query-optimistic 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,6 +51,7 @@ interface QueryOptions {
51
51
  enabled?: boolean;
52
52
  staleTime?: number;
53
53
  cacheTime?: number;
54
+ placeholderData?: unknown | ((previousData: unknown, previousQuery: unknown) => unknown);
54
55
  refetchOnMount?: boolean;
55
56
  refetchOnWindowFocus?: boolean;
56
57
  refetchInterval?: number | false;
@@ -128,7 +129,8 @@ declare class CollectionChannel<TEntity> {
128
129
  /** Channel for an entity - provides typed optimistic mutation methods */
129
130
  declare class EntityChannel<TEntity> {
130
131
  private readonly target;
131
- constructor(target: EntityDef<TEntity, any>);
132
+ private readonly options?;
133
+ constructor(target: EntityDef<TEntity, any>, options?: ChannelOptions | undefined);
132
134
  /**
133
135
  * Update the entity
134
136
  * @returns Rollback function to undo the change
@@ -165,7 +167,7 @@ declare class EntityChannel<TEntity> {
165
167
  */
166
168
  interface Channel {
167
169
  <TEntity>(target: CollectionDef<TEntity, any>, options?: ChannelOptions): CollectionChannel<TEntity>;
168
- <TEntity>(target: EntityDef<TEntity, any>): EntityChannel<TEntity>;
170
+ <TEntity>(target: EntityDef<TEntity, any>, options?: ChannelOptions): EntityChannel<TEntity>;
169
171
  }
170
172
  /**
171
173
  * Create a channel for optimistic mutations.
@@ -51,6 +51,7 @@ interface QueryOptions {
51
51
  enabled?: boolean;
52
52
  staleTime?: number;
53
53
  cacheTime?: number;
54
+ placeholderData?: unknown | ((previousData: unknown, previousQuery: unknown) => unknown);
54
55
  refetchOnMount?: boolean;
55
56
  refetchOnWindowFocus?: boolean;
56
57
  refetchInterval?: number | false;
@@ -128,7 +129,8 @@ declare class CollectionChannel<TEntity> {
128
129
  /** Channel for an entity - provides typed optimistic mutation methods */
129
130
  declare class EntityChannel<TEntity> {
130
131
  private readonly target;
131
- constructor(target: EntityDef<TEntity, any>);
132
+ private readonly options?;
133
+ constructor(target: EntityDef<TEntity, any>, options?: ChannelOptions | undefined);
132
134
  /**
133
135
  * Update the entity
134
136
  * @returns Rollback function to undo the change
@@ -165,7 +167,7 @@ declare class EntityChannel<TEntity> {
165
167
  */
166
168
  interface Channel {
167
169
  <TEntity>(target: CollectionDef<TEntity, any>, options?: ChannelOptions): CollectionChannel<TEntity>;
168
- <TEntity>(target: EntityDef<TEntity, any>): EntityChannel<TEntity>;
170
+ <TEntity>(target: EntityDef<TEntity, any>, options?: ChannelOptions): EntityChannel<TEntity>;
169
171
  }
170
172
  /**
171
173
  * Create a channel for optimistic mutations.
@@ -1,5 +1,5 @@
1
- import { I as IdGetter, c as CollectionDef, d as EntityDef, M as MutationDef, O as Optimistic } from '../channel-OFFEKFI1.mjs';
2
- export { A as AnyDef, C as Channel, a as ChannelOptions, b as CollectionChannel, E as EntityChannel, e as OptimisticAction, f as OptimisticInstruction, g as OptimisticStatus, h as OptimisticTransaction, P as PaginatedOptions, Q as QueryOptions, i as channel } from '../channel-OFFEKFI1.mjs';
1
+ import { I as IdGetter, c as CollectionDef, d as EntityDef, M as MutationDef, O as Optimistic } from '../channel-DzHL5NZo.mjs';
2
+ export { A as AnyDef, C as Channel, a as ChannelOptions, b as CollectionChannel, E as EntityChannel, e as OptimisticAction, f as OptimisticInstruction, g as OptimisticStatus, h as OptimisticTransaction, P as PaginatedOptions, Q as QueryOptions, i as channel } from '../channel-DzHL5NZo.mjs';
3
3
  import { QueryClient } from '@tanstack/react-query';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { I as IdGetter, c as CollectionDef, d as EntityDef, M as MutationDef, O as Optimistic } from '../channel-OFFEKFI1.js';
2
- export { A as AnyDef, C as Channel, a as ChannelOptions, b as CollectionChannel, E as EntityChannel, e as OptimisticAction, f as OptimisticInstruction, g as OptimisticStatus, h as OptimisticTransaction, P as PaginatedOptions, Q as QueryOptions, i as channel } from '../channel-OFFEKFI1.js';
1
+ import { I as IdGetter, c as CollectionDef, d as EntityDef, M as MutationDef, O as Optimistic } from '../channel-DzHL5NZo.js';
2
+ export { A as AnyDef, C as Channel, a as ChannelOptions, b as CollectionChannel, E as EntityChannel, e as OptimisticAction, f as OptimisticInstruction, g as OptimisticStatus, h as OptimisticTransaction, P as PaginatedOptions, Q as QueryOptions, i as channel } from '../channel-DzHL5NZo.js';
3
3
  import { QueryClient } from '@tanstack/react-query';
4
4
 
5
5
  /**
@@ -127,8 +127,7 @@ var QueryRegistry = class {
127
127
  /** Apply update directly to query cache (used when scope is provided) */
128
128
  applyDirectCacheUpdate(name, action, payload, scope) {
129
129
  if (!this.queryClient) return [];
130
- const def = this.collectionDefs.get(name);
131
- if (!def) return [];
130
+ const collectionDef = this.collectionDefs.get(name);
132
131
  const rollbacks = [];
133
132
  const queries = this.queryClient.getQueriesData({
134
133
  queryKey: [name]
@@ -137,28 +136,40 @@ var QueryRegistry = class {
137
136
  if (!data) continue;
138
137
  const params = queryKey[1];
139
138
  if (!this.matchesScope(params, scope)) continue;
140
- const isPaginated = data && typeof data === "object" && "pages" in data;
141
- if (isPaginated) {
142
- const paginatedData = data;
143
- const previous = paginatedData;
144
- rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
145
- this.queryClient.setQueryData(queryKey, (prev) => {
146
- if (!prev) return prev;
147
- return {
148
- ...prev,
149
- pages: prev.pages.map(
150
- (page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, def.id) : page
151
- )
152
- };
153
- });
139
+ if (collectionDef) {
140
+ const isPaginated = data && typeof data === "object" && "pages" in data;
141
+ if (isPaginated) {
142
+ const paginatedData = data;
143
+ const previous = paginatedData;
144
+ rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
145
+ this.queryClient.setQueryData(queryKey, (prev) => {
146
+ if (!prev) return prev;
147
+ return {
148
+ ...prev,
149
+ pages: prev.pages.map(
150
+ (page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, collectionDef.id) : page
151
+ )
152
+ };
153
+ });
154
+ } else {
155
+ const previous = data;
156
+ rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
157
+ this.queryClient.setQueryData(queryKey, (prev) => {
158
+ if (!prev) return prev;
159
+ return this.applyCollectionUpdate(prev, action, payload, collectionDef.id);
160
+ });
161
+ }
154
162
  } else {
155
- const arrayData = data;
156
- const previous = arrayData;
163
+ const previous = data;
157
164
  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, def.id);
161
- });
165
+ if (action === "update" && payload.update) {
166
+ this.queryClient.setQueryData(
167
+ queryKey,
168
+ (prev) => prev ? payload.update(prev) : prev
169
+ );
170
+ } else if (action === "replace" && payload.data) {
171
+ this.queryClient.setQueryData(queryKey, payload.data);
172
+ }
162
173
  }
163
174
  }
164
175
  return rollbacks;
@@ -275,8 +286,9 @@ var CollectionChannel = class {
275
286
  }
276
287
  };
277
288
  var EntityChannel = class {
278
- constructor(target) {
289
+ constructor(target, options) {
279
290
  this.target = target;
291
+ this.options = options;
280
292
  }
281
293
  /**
282
294
  * Update the entity
@@ -285,7 +297,7 @@ var EntityChannel = class {
285
297
  update(updateFn, options) {
286
298
  const rollbacks = registry.applyUpdate(this.target.name, "update", {
287
299
  update: updateFn
288
- });
300
+ }, this.options?.scope);
289
301
  return () => rollbacks.forEach((rb) => rb());
290
302
  }
291
303
  /**
@@ -295,7 +307,7 @@ var EntityChannel = class {
295
307
  replace(data, options) {
296
308
  const rollbacks = registry.applyUpdate(this.target.name, "replace", {
297
309
  data
298
- });
310
+ }, this.options?.scope);
299
311
  return () => rollbacks.forEach((rb) => rb());
300
312
  }
301
313
  };
@@ -303,7 +315,7 @@ var channel = ((target, options) => {
303
315
  if (target._type === "collection") {
304
316
  return new CollectionChannel(target, options);
305
317
  } else {
306
- return new EntityChannel(target);
318
+ return new EntityChannel(target, options);
307
319
  }
308
320
  });
309
321
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/define.ts","../../src/core/registry.ts","../../src/core/channel.ts"],"names":["nanoid"],"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"]}
1
+ {"version":3,"sources":["../../src/core/define.ts","../../src/core/registry.ts","../../src/core/channel.ts"],"names":["nanoid"],"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"]}
@@ -125,8 +125,7 @@ var QueryRegistry = class {
125
125
  /** Apply update directly to query cache (used when scope is provided) */
126
126
  applyDirectCacheUpdate(name, action, payload, scope) {
127
127
  if (!this.queryClient) return [];
128
- const def = this.collectionDefs.get(name);
129
- if (!def) return [];
128
+ const collectionDef = this.collectionDefs.get(name);
130
129
  const rollbacks = [];
131
130
  const queries = this.queryClient.getQueriesData({
132
131
  queryKey: [name]
@@ -135,28 +134,40 @@ var QueryRegistry = class {
135
134
  if (!data) continue;
136
135
  const params = queryKey[1];
137
136
  if (!this.matchesScope(params, scope)) continue;
138
- const isPaginated = data && typeof data === "object" && "pages" in data;
139
- if (isPaginated) {
140
- const paginatedData = data;
141
- const previous = paginatedData;
142
- rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
143
- this.queryClient.setQueryData(queryKey, (prev) => {
144
- if (!prev) return prev;
145
- return {
146
- ...prev,
147
- pages: prev.pages.map(
148
- (page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, def.id) : page
149
- )
150
- };
151
- });
137
+ if (collectionDef) {
138
+ const isPaginated = data && typeof data === "object" && "pages" in data;
139
+ if (isPaginated) {
140
+ const paginatedData = data;
141
+ const previous = paginatedData;
142
+ rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
143
+ this.queryClient.setQueryData(queryKey, (prev) => {
144
+ if (!prev) return prev;
145
+ return {
146
+ ...prev,
147
+ pages: prev.pages.map(
148
+ (page, i) => i === 0 ? this.applyCollectionUpdate(page, action, payload, collectionDef.id) : page
149
+ )
150
+ };
151
+ });
152
+ } else {
153
+ const previous = data;
154
+ rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
155
+ this.queryClient.setQueryData(queryKey, (prev) => {
156
+ if (!prev) return prev;
157
+ return this.applyCollectionUpdate(prev, action, payload, collectionDef.id);
158
+ });
159
+ }
152
160
  } else {
153
- const arrayData = data;
154
- const previous = arrayData;
161
+ const previous = data;
155
162
  rollbacks.push(() => this.queryClient.setQueryData(queryKey, previous));
156
- this.queryClient.setQueryData(queryKey, (prev) => {
157
- if (!prev) return prev;
158
- return this.applyCollectionUpdate(prev, action, payload, def.id);
159
- });
163
+ if (action === "update" && payload.update) {
164
+ this.queryClient.setQueryData(
165
+ queryKey,
166
+ (prev) => prev ? payload.update(prev) : prev
167
+ );
168
+ } else if (action === "replace" && payload.data) {
169
+ this.queryClient.setQueryData(queryKey, payload.data);
170
+ }
160
171
  }
161
172
  }
162
173
  return rollbacks;
@@ -273,8 +284,9 @@ var CollectionChannel = class {
273
284
  }
274
285
  };
275
286
  var EntityChannel = class {
276
- constructor(target) {
287
+ constructor(target, options) {
277
288
  this.target = target;
289
+ this.options = options;
278
290
  }
279
291
  /**
280
292
  * Update the entity
@@ -283,7 +295,7 @@ var EntityChannel = class {
283
295
  update(updateFn, options) {
284
296
  const rollbacks = registry.applyUpdate(this.target.name, "update", {
285
297
  update: updateFn
286
- });
298
+ }, this.options?.scope);
287
299
  return () => rollbacks.forEach((rb) => rb());
288
300
  }
289
301
  /**
@@ -293,7 +305,7 @@ var EntityChannel = class {
293
305
  replace(data, options) {
294
306
  const rollbacks = registry.applyUpdate(this.target.name, "replace", {
295
307
  data
296
- });
308
+ }, this.options?.scope);
297
309
  return () => rollbacks.forEach((rb) => rb());
298
310
  }
299
311
  };
@@ -301,7 +313,7 @@ var channel = ((target, options) => {
301
313
  if (target._type === "collection") {
302
314
  return new CollectionChannel(target, options);
303
315
  } else {
304
- return new EntityChannel(target);
316
+ return new EntityChannel(target, options);
305
317
  }
306
318
  });
307
319
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/define.ts","../../src/core/registry.ts","../../src/core/channel.ts"],"names":[],"mappings":"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","file":"index.mjs","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"]}
1
+ {"version":3,"sources":["../../src/core/define.ts","../../src/core/registry.ts","../../src/core/channel.ts"],"names":[],"mappings":"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","file":"index.mjs","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"]}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AnyDef, C as Channel, a as ChannelOptions, b as CollectionChannel, c as CollectionDef, E as EntityChannel, d as EntityDef, I as IdGetter, M as MutationDef, O as Optimistic, e as OptimisticAction, f as OptimisticInstruction, g as OptimisticStatus, h as OptimisticTransaction, P as PaginatedOptions, Q as QueryOptions, i as channel } from './channel-OFFEKFI1.mjs';
1
+ export { A as AnyDef, C as Channel, a as ChannelOptions, b as CollectionChannel, c as CollectionDef, E as EntityChannel, d as EntityDef, I as IdGetter, M as MutationDef, O as Optimistic, e as OptimisticAction, f as OptimisticInstruction, g as OptimisticStatus, h as OptimisticTransaction, P as PaginatedOptions, Q as QueryOptions, i as channel } from './channel-DzHL5NZo.mjs';
2
2
  export { RegisteredCollection, RegisteredEntity, RegisteredEntry, RegisteredPaginatedCollection, defineCollection, defineEntity, defineMutation, registry } from './core/index.mjs';
3
3
  export { EntityResult, OptimisticConfig, OptimisticQueryProvider, OptimisticQueryProviderProps, PaginatedQueryResult, QueryResult, UseMutationOptions, UseQueryHookOptions, useMutation, useQueries, useQuery } from './react/index.mjs';
4
4
  import '@tanstack/react-query';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AnyDef, C as Channel, a as ChannelOptions, b as CollectionChannel, c as CollectionDef, E as EntityChannel, d as EntityDef, I as IdGetter, M as MutationDef, O as Optimistic, e as OptimisticAction, f as OptimisticInstruction, g as OptimisticStatus, h as OptimisticTransaction, P as PaginatedOptions, Q as QueryOptions, i as channel } from './channel-OFFEKFI1.js';
1
+ export { A as AnyDef, C as Channel, a as ChannelOptions, b as CollectionChannel, c as CollectionDef, E as EntityChannel, d as EntityDef, I as IdGetter, M as MutationDef, O as Optimistic, e as OptimisticAction, f as OptimisticInstruction, g as OptimisticStatus, h as OptimisticTransaction, P as PaginatedOptions, Q as QueryOptions, i as channel } from './channel-DzHL5NZo.js';
2
2
  export { RegisteredCollection, RegisteredEntity, RegisteredEntry, RegisteredPaginatedCollection, defineCollection, defineEntity, defineMutation, registry } from './core/index.js';
3
3
  export { EntityResult, OptimisticConfig, OptimisticQueryProvider, OptimisticQueryProviderProps, PaginatedQueryResult, QueryResult, UseMutationOptions, UseQueryHookOptions, useMutation, useQueries, useQuery } from './react/index.js';
4
4
  import '@tanstack/react-query';