@zenstackhq/tanstack-query 2.0.0-alpha.7 → 2.0.0-beta.10

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.
Files changed (60) hide show
  1. package/generator.d.ts +1 -2
  2. package/generator.js +55 -55
  3. package/generator.js.map +1 -1
  4. package/package.json +6 -7
  5. package/runtime/common--_wRp2eo.d.mts +121 -0
  6. package/runtime/common--_wRp2eo.d.ts +121 -0
  7. package/runtime/index.d.mts +1 -1
  8. package/runtime/index.d.ts +1 -1
  9. package/runtime/index.js +3 -1
  10. package/runtime/index.js.map +1 -1
  11. package/runtime/index.mjs +3 -1
  12. package/runtime/index.mjs.map +1 -1
  13. package/runtime/react.d.mts +3 -6
  14. package/runtime/react.d.ts +3 -6
  15. package/runtime/react.js +37 -8
  16. package/runtime/react.js.map +1 -1
  17. package/runtime/react.mjs +37 -8
  18. package/runtime/react.mjs.map +1 -1
  19. package/runtime/svelte.d.mts +3 -6
  20. package/runtime/svelte.d.ts +3 -6
  21. package/runtime/svelte.js +37 -8
  22. package/runtime/svelte.js.map +1 -1
  23. package/runtime/svelte.mjs +37 -8
  24. package/runtime/svelte.mjs.map +1 -1
  25. package/runtime/vue.d.mts +5 -7
  26. package/runtime/vue.d.ts +5 -7
  27. package/runtime/vue.js +59 -19
  28. package/runtime/vue.js.map +1 -1
  29. package/runtime/vue.mjs +60 -20
  30. package/runtime/vue.mjs.map +1 -1
  31. package/runtime-v5/common--_wRp2eo.d.mts +121 -0
  32. package/runtime-v5/common--_wRp2eo.d.ts +121 -0
  33. package/runtime-v5/index.d.mts +1 -1
  34. package/runtime-v5/index.d.ts +1 -1
  35. package/runtime-v5/index.js +3 -1
  36. package/runtime-v5/index.js.map +1 -1
  37. package/runtime-v5/index.mjs +3 -1
  38. package/runtime-v5/index.mjs.map +1 -1
  39. package/runtime-v5/react.d.mts +8 -12
  40. package/runtime-v5/react.d.ts +8 -12
  41. package/runtime-v5/react.js +43 -11
  42. package/runtime-v5/react.js.map +1 -1
  43. package/runtime-v5/react.mjs +43 -11
  44. package/runtime-v5/react.mjs.map +1 -1
  45. package/runtime-v5/svelte.d.mts +3 -5
  46. package/runtime-v5/svelte.d.ts +3 -5
  47. package/runtime-v5/svelte.js +37 -8
  48. package/runtime-v5/svelte.js.map +1 -1
  49. package/runtime-v5/svelte.mjs +37 -8
  50. package/runtime-v5/svelte.mjs.map +1 -1
  51. package/runtime-v5/vue.d.mts +5 -7
  52. package/runtime-v5/vue.d.ts +5 -7
  53. package/runtime-v5/vue.js +59 -19
  54. package/runtime-v5/vue.js.map +1 -1
  55. package/runtime-v5/vue.mjs +60 -20
  56. package/runtime-v5/vue.mjs.map +1 -1
  57. package/runtime/common-ZSgIGN1q.d.mts +0 -56
  58. package/runtime/common-ZSgIGN1q.d.ts +0 -56
  59. package/runtime-v5/common-ZSgIGN1q.d.mts +0 -56
  60. package/runtime-v5/common-ZSgIGN1q.d.ts +0 -56
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime-v5/react.ts","../../src/runtime/common.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n UseSuspenseInfiniteQueryOptions,\n UseSuspenseQueryOptions,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n type InfiniteData,\n type UseInfiniteQueryOptions,\n type UseMutationOptions,\n type UseQueryOptions,\n} from '@tanstack/react-query-v5';\nimport type { ModelMeta } from '@zenstackhq/runtime/cross';\nimport { createContext, useContext } from 'react';\nimport {\n DEFAULT_QUERY_ENDPOINT,\n fetcher,\n getQueryKey,\n makeUrl,\n marshal,\n setupInvalidation,\n setupOptimisticUpdate,\n type APIContext,\n type FetchFn,\n} from '../runtime/common';\n\n/**\n * Context for configuring react hooks.\n */\nexport const RequestHandlerContext = createContext<APIContext>({\n endpoint: DEFAULT_QUERY_ENDPOINT,\n fetch: undefined,\n});\n\n/**\n * Hooks context.\n */\nexport function getHooksContext() {\n const { endpoint, ...rest } = useContext(RequestHandlerContext);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Context provider.\n */\nexport const Provider = RequestHandlerContext.Provider;\n\n/**\n * Creates a react-query query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @param optimisticUpdate Whether to enable automatic optimistic update\n * @returns useQuery hook\n */\nexport function useModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args?: unknown,\n options?: Omit<UseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,\n fetch?: FetchFn,\n optimisticUpdate = false\n) {\n const reqUrl = makeUrl(url, args);\n return useQuery({\n queryKey: getQueryKey(model, url, args, false, optimisticUpdate),\n queryFn: () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false),\n ...options,\n });\n}\n\n/**\n * Creates a react-query suspense query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @param optimisticUpdate Whether to enable automatic optimistic update\n * @returns useSuspenseQuery hook\n */\nexport function useSuspenseModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args?: unknown,\n options?: Omit<UseSuspenseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,\n fetch?: FetchFn,\n optimisticUpdate = false\n) {\n const reqUrl = makeUrl(url, args);\n return useSuspenseQuery({\n queryKey: getQueryKey(model, url, args, false, optimisticUpdate),\n queryFn: () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false),\n ...options,\n });\n}\n\n/**\n * Creates a react-query infinite query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The initial request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query infinite query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @returns useInfiniteQuery hook\n */\nexport function useInfiniteModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args: unknown,\n options: Omit<UseInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey'>,\n fetch?: FetchFn\n) {\n return useInfiniteQuery({\n queryKey: getQueryKey(model, url, args, true),\n queryFn: ({ pageParam }) => {\n return fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);\n },\n ...options,\n });\n}\n\n/**\n * Creates a react-query infinite suspense query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The initial request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query infinite query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @returns useSuspenseInfiniteQuery hook\n */\nexport function useSuspenseInfiniteModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args: unknown,\n options: Omit<UseSuspenseInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey'>,\n fetch?: FetchFn\n) {\n return useSuspenseInfiniteQuery({\n queryKey: getQueryKey(model, url, args, true),\n queryFn: ({ pageParam }) => {\n return fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);\n },\n ...options,\n });\n}\n\n/**\n * Creates a react-query mutation\n *\n * @param model The name of the model under mutation.\n * @param method The HTTP method.\n * @param url The request URL.\n * @param modelMeta The model metadata.\n * @param options The react-query options.\n * @param fetch The fetch function to use for sending the HTTP request\n * @param invalidateQueries Whether to invalidate queries after mutation.\n * @param checkReadBack Whether to check for read back errors and return undefined if found.\n * @param optimisticUpdate Whether to enable automatic optimistic update\n */\nexport function useModelMutation<\n TArgs,\n TError,\n R = any,\n C extends boolean = boolean,\n Result = C extends true ? R | undefined : R\n>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n modelMeta: ModelMeta,\n options?: Omit<UseMutationOptions<Result, TError, TArgs>, 'mutationFn'>,\n fetch?: FetchFn,\n invalidateQueries = true,\n checkReadBack?: C,\n optimisticUpdate = false\n) {\n const queryClient = useQueryClient();\n const mutationFn = (data: any) => {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const fetchInit: RequestInit = {\n method,\n ...(method !== 'DELETE' && {\n headers: {\n 'content-type': 'application/json',\n },\n body: marshal(data),\n }),\n };\n return fetcher<R, C>(reqUrl, fetchInit, fetch, checkReadBack) as Promise<Result>;\n };\n\n const finalOptions = { ...options, mutationFn };\n const operation = url.split('/').pop();\n\n if (operation) {\n const { logging } = useContext(RequestHandlerContext);\n if (invalidateQueries) {\n setupInvalidation(\n model,\n operation,\n modelMeta,\n finalOptions,\n (predicate) => queryClient.invalidateQueries({ predicate }),\n logging\n );\n }\n\n if (optimisticUpdate) {\n setupOptimisticUpdate(\n model,\n operation,\n modelMeta,\n finalOptions,\n queryClient.getQueryCache().getAll(),\n (queryKey, data) => {\n // update query cache\n queryClient.setQueryData<unknown>(queryKey, data);\n // cancel on-flight queries to avoid redundant cache updates,\n // the settlement of the current mutation will trigger a new revalidation\n queryClient.cancelQueries({ queryKey }, { revert: false, silent: true });\n },\n invalidateQueries ? (predicate) => queryClient.invalidateQueries({ predicate }) : undefined,\n logging\n );\n }\n }\n\n return useMutation(finalOptions);\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport {\n applyMutation,\n getMutatedModels,\n getReadModels,\n type ModelMeta,\n type PrismaWriteActionType,\n} from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\n\n/**\n * The default query endpoint.\n */\nexport const DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Prefix for react-query keys.\n */\nexport const QUERY_KEY_PREFIX = 'zenstack';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Type for query and mutation errors.\n */\nexport type QueryError = Error & {\n /**\n * Additional error information.\n */\n info?: unknown;\n\n /**\n * HTTP status code.\n */\n status?: number;\n};\n\n/**\n * Context type for configuring the hooks.\n */\nexport type APIContext = {\n /**\n * The endpoint to use for the queries.\n */\n endpoint?: string;\n\n /**\n * A custom fetch function for sending the HTTP requests.\n */\n fetch?: FetchFn;\n\n /**\n * If logging is enabled.\n */\n logging?: boolean;\n};\n\nexport async function fetcher<R, C extends boolean>(\n url: string,\n options?: RequestInit,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? R | undefined : R> {\n const _fetch = fetch ?? crossFetch.fetch;\n const res = await _fetch(url, options);\n if (!res.ok) {\n const errData = unmarshal(await res.text());\n if (\n checkReadBack !== false &&\n errData.error?.prisma &&\n errData.error?.code === 'P2004' &&\n errData.error?.reason === 'RESULT_NOT_READABLE'\n ) {\n // policy doesn't allow mutation result to be read back, just return undefined\n return undefined as any;\n }\n const error: QueryError = new Error('An error occurred while fetching the data.');\n error.info = errData.error;\n error.status = res.status;\n throw error;\n }\n\n const textResult = await res.text();\n try {\n return unmarshal(textResult).data as R;\n } catch (err) {\n console.error(`Unable to deserialize data:`, textResult);\n throw err;\n }\n}\n\ntype QueryKey = [\n string /* prefix */,\n string /* model */,\n string /* operation */,\n unknown /* args */,\n {\n infinite: boolean;\n optimisticUpdate: boolean;\n } /* flags */\n];\n\n/**\n * Computes query key for the given model, operation and query args.\n * @param model Model name.\n * @param urlOrOperation Prisma operation (e.g, `findMany`) or request URL. If it's a URL, the last path segment will be used as the operation name.\n * @param args Prisma query arguments.\n * @param infinite Whether the query is infinite.\n * @param optimisticUpdate Whether the query is optimistically updated.\n * @returns Query key\n */\nexport function getQueryKey(\n model: string,\n urlOrOperation: string,\n args: unknown,\n infinite = false,\n optimisticUpdate = false\n): QueryKey {\n if (!urlOrOperation) {\n throw new Error('Invalid urlOrOperation');\n }\n const operation = urlOrOperation.split('/').pop();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return [QUERY_KEY_PREFIX, model, operation!, args, { infinite, optimisticUpdate }];\n}\n\nexport function marshal(value: unknown) {\n const { data, meta } = serialize(value);\n if (meta) {\n return JSON.stringify({ ...(data as any), meta: { serialization: meta } });\n } else {\n return JSON.stringify(data);\n }\n}\n\nexport function unmarshal(value: string) {\n const parsed = JSON.parse(value);\n if (parsed.data && parsed.meta?.serialization) {\n const deserializedData = deserialize(parsed.data, parsed.meta.serialization);\n return { ...parsed, data: deserializedData };\n } else {\n return parsed;\n }\n}\n\nexport function makeUrl(url: string, args: unknown) {\n if (!args) {\n return url;\n }\n\n const { data, meta } = serialize(args);\n let result = `${url}?q=${encodeURIComponent(JSON.stringify(data))}`;\n if (meta) {\n result += `&meta=${encodeURIComponent(JSON.stringify({ serialization: meta }))}`;\n }\n return result;\n}\n\ntype InvalidationPredicate = ({ queryKey }: { queryKey: readonly unknown[] }) => boolean;\ntype InvalidateFunc = (predicate: InvalidationPredicate) => Promise<void>;\ntype MutationOptions = {\n onMutate?: (...args: any[]) => any;\n onSuccess?: (...args: any[]) => any;\n onSettled?: (...args: any[]) => any;\n};\n\n// sets up invalidation hook for a mutation\nexport function setupInvalidation(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: MutationOptions,\n invalidate: InvalidateFunc,\n logging = false\n) {\n const origOnSuccess = options?.onSuccess;\n options.onSuccess = async (...args: unknown[]) => {\n const [_, variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n return origOnSuccess?.(...args);\n };\n}\n\n// gets a predicate for evaluating whether a query should be invalidated\nasync function getInvalidationPredicate(\n model: string,\n operation: PrismaWriteActionType,\n mutationArgs: any,\n modelMeta: ModelMeta,\n logging = false\n) {\n const mutatedModels = await getMutatedModels(model, operation, mutationArgs, modelMeta);\n\n return ({ queryKey }: { queryKey: readonly unknown[] }) => {\n const [_, queryModel, , args] = queryKey as QueryKey;\n\n if (mutatedModels.includes(queryModel)) {\n // direct match\n if (logging) {\n console.log(`Invalidating query ${JSON.stringify(queryKey)} due to mutation \"${model}.${operation}\"`);\n }\n return true;\n }\n\n if (args) {\n // traverse query args to find nested reads that match the model under mutation\n if (findNestedRead(queryModel, mutatedModels, modelMeta, args)) {\n if (logging) {\n console.log(\n `Invalidating query ${JSON.stringify(queryKey)} due to mutation \"${model}.${operation}\"`\n );\n }\n return true;\n }\n }\n\n return false;\n };\n}\n\n// find nested reads that match the given models\nfunction findNestedRead(visitingModel: string, targetModels: string[], modelMeta: ModelMeta, args: any) {\n const modelsRead = getReadModels(visitingModel, modelMeta, args);\n return targetModels.some((m) => modelsRead.includes(m));\n}\n\ntype QueryCache = {\n queryKey: readonly unknown[];\n state: {\n data: unknown;\n error: unknown;\n };\n}[];\n\ntype SetCacheFunc = (queryKey: readonly unknown[], data: unknown) => void;\n\nexport function setupOptimisticUpdate(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: MutationOptions,\n queryCache: QueryCache,\n setCache: SetCacheFunc,\n invalidate?: InvalidateFunc,\n logging = false\n) {\n const origOnMutate = options?.onMutate;\n const origOnSettled = options?.onSettled;\n\n // optimistic update on mutate\n options.onMutate = async (...args: unknown[]) => {\n const [variables] = args;\n await optimisticUpdate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n queryCache,\n setCache,\n logging\n );\n return origOnMutate?.(...args);\n };\n\n // invalidate on settled\n options.onSettled = async (...args: unknown[]) => {\n if (invalidate) {\n const [, , variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n }\n return origOnSettled?.(...args);\n };\n}\n\n// optimistically updates query cache\nasync function optimisticUpdate(\n mutationModel: string,\n mutationOp: string,\n mutationArgs: any,\n modelMeta: ModelMeta,\n queryCache: QueryCache,\n setCache: SetCacheFunc,\n logging = false\n) {\n for (const cacheItem of queryCache) {\n const {\n queryKey,\n state: { data, error },\n } = cacheItem;\n\n if (error) {\n if (logging) {\n console.warn(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to error:`, error);\n }\n continue;\n }\n\n const [_, queryModel, queryOp, _queryArgs, { optimisticUpdate }] = queryKey as QueryKey;\n if (!optimisticUpdate) {\n if (logging) {\n console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to opt-out`);\n }\n continue;\n }\n\n const mutatedData = await applyMutation(\n queryModel,\n queryOp,\n data,\n mutationModel,\n mutationOp as PrismaWriteActionType,\n mutationArgs,\n modelMeta,\n logging\n );\n\n if (mutatedData !== undefined) {\n // mutation applicable to this query, update cache\n if (logging) {\n console.log(\n `Optimistically updating query ${JSON.stringify(\n queryKey\n )} due to mutation \"${mutationModel}.${mutationOp}\"`\n );\n }\n setCache(queryKey, mutatedData);\n }\n }\n}\n"],"mappings":"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","names":["fetch","optimisticUpdate","fetch","optimisticUpdate"]}
1
+ {"version":3,"sources":["../../src/runtime-v5/react.ts","../../src/runtime/common.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n UseSuspenseInfiniteQueryOptions,\n UseSuspenseQueryOptions,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n type InfiniteData,\n type UseInfiniteQueryOptions,\n type UseMutationOptions,\n type UseQueryOptions,\n} from '@tanstack/react-query-v5';\nimport type { ModelMeta } from '@zenstackhq/runtime/cross';\nimport { createContext, useContext } from 'react';\nimport {\n DEFAULT_QUERY_ENDPOINT,\n fetcher,\n getQueryKey,\n makeUrl,\n marshal,\n setupInvalidation,\n setupOptimisticUpdate,\n type APIContext,\n type ExtraMutationOptions,\n type ExtraQueryOptions,\n type FetchFn,\n} from '../runtime/common';\n\n/**\n * Context for configuring react hooks.\n */\nexport const RequestHandlerContext = createContext<APIContext>({\n endpoint: DEFAULT_QUERY_ENDPOINT,\n fetch: undefined,\n});\n\n/**\n * Hooks context.\n */\nexport function getHooksContext() {\n const { endpoint, ...rest } = useContext(RequestHandlerContext);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Context provider.\n */\nexport const Provider = RequestHandlerContext.Provider;\n\n/**\n * Creates a react-query query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @returns useQuery hook\n */\nexport function useModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args?: unknown,\n options?: Omit<UseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'> & ExtraQueryOptions,\n fetch?: FetchFn\n) {\n const reqUrl = makeUrl(url, args);\n return useQuery({\n queryKey: getQueryKey(model, url, args, {\n infinite: false,\n optimisticUpdate: options?.optimisticUpdate !== false,\n }),\n queryFn: () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false),\n ...options,\n });\n}\n\n/**\n * Creates a react-query suspense query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @returns useSuspenseQuery hook\n */\nexport function useSuspenseModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args?: unknown,\n options?: Omit<UseSuspenseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'> & ExtraQueryOptions,\n fetch?: FetchFn\n) {\n const reqUrl = makeUrl(url, args);\n return useSuspenseQuery({\n queryKey: getQueryKey(model, url, args, {\n infinite: false,\n optimisticUpdate: options?.optimisticUpdate !== false,\n }),\n queryFn: () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false),\n ...options,\n });\n}\n\n/**\n * Creates a react-query infinite query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The initial request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query infinite query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @returns useInfiniteQuery hook\n */\nexport function useInfiniteModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args: unknown,\n options: Omit<UseInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey'>,\n fetch?: FetchFn\n) {\n return useInfiniteQuery({\n queryKey: getQueryKey(model, url, args, { infinite: true, optimisticUpdate: false }),\n queryFn: ({ pageParam }) => {\n return fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);\n },\n ...options,\n });\n}\n\n/**\n * Creates a react-query infinite suspense query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The initial request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query infinite query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @returns useSuspenseInfiniteQuery hook\n */\nexport function useSuspenseInfiniteModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args: unknown,\n options: Omit<UseSuspenseInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey'>,\n fetch?: FetchFn\n) {\n return useSuspenseInfiniteQuery({\n queryKey: getQueryKey(model, url, args, { infinite: true, optimisticUpdate: false }),\n queryFn: ({ pageParam }) => {\n return fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);\n },\n ...options,\n });\n}\n\n/**\n * Creates a react-query mutation\n *\n * @param model The name of the model under mutation.\n * @param method The HTTP method.\n * @param url The request URL.\n * @param modelMeta The model metadata.\n * @param options The react-query options.\n * @param fetch The fetch function to use for sending the HTTP request\n * @param checkReadBack Whether to check for read back errors and return undefined if found.\n */\nexport function useModelMutation<\n TArgs,\n TError,\n R = any,\n C extends boolean = boolean,\n Result = C extends true ? R | undefined : R\n>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n modelMeta: ModelMeta,\n options?: Omit<UseMutationOptions<Result, TError, TArgs>, 'mutationFn'> & ExtraMutationOptions,\n fetch?: FetchFn,\n checkReadBack?: C\n) {\n const queryClient = useQueryClient();\n const mutationFn = (data: any) => {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const fetchInit: RequestInit = {\n method,\n ...(method !== 'DELETE' && {\n headers: {\n 'content-type': 'application/json',\n },\n body: marshal(data),\n }),\n };\n return fetcher<R, C>(reqUrl, fetchInit, fetch, checkReadBack) as Promise<Result>;\n };\n\n const finalOptions = { ...options, mutationFn };\n const operation = url.split('/').pop();\n const invalidateQueries = options?.invalidateQueries !== false;\n const optimisticUpdate = !!options?.optimisticUpdate;\n\n if (operation) {\n const { logging } = useContext(RequestHandlerContext);\n if (invalidateQueries) {\n setupInvalidation(\n model,\n operation,\n modelMeta,\n finalOptions,\n (predicate) => queryClient.invalidateQueries({ predicate }),\n logging\n );\n }\n\n if (optimisticUpdate) {\n setupOptimisticUpdate(\n model,\n operation,\n modelMeta,\n finalOptions,\n queryClient.getQueryCache().getAll(),\n (queryKey, data) => {\n // update query cache\n queryClient.setQueryData<unknown>(queryKey, data);\n // cancel on-flight queries to avoid redundant cache updates,\n // the settlement of the current mutation will trigger a new revalidation\n queryClient.cancelQueries({ queryKey }, { revert: false, silent: true });\n },\n invalidateQueries ? (predicate) => queryClient.invalidateQueries({ predicate }) : undefined,\n logging\n );\n }\n }\n\n return useMutation(finalOptions);\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport {\n applyMutation,\n getMutatedModels,\n getReadModels,\n type ModelMeta,\n type PrismaWriteActionType,\n} from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\n\n/**\n * The default query endpoint.\n */\nexport const DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Prefix for react-query keys.\n */\nexport const QUERY_KEY_PREFIX = 'zenstack';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Type for query and mutation errors.\n */\nexport type QueryError = Error & {\n /**\n * Additional error information.\n */\n info?: unknown;\n\n /**\n * HTTP status code.\n */\n status?: number;\n};\n\n/**\n * Result of optimistic data provider.\n */\nexport type OptimisticDataProviderResult = {\n /**\n * Kind of the result.\n * - Update: use the `data` field to update the query cache.\n * - Skip: skip the optimistic update for this query.\n * - ProceedDefault: proceed with the default optimistic update.\n */\n kind: 'Update' | 'Skip' | 'ProceedDefault';\n\n /**\n * Data to update the query cache. Only applicable if `kind` is 'Update'.\n *\n * If the data is an object with fields updated, it should have a `$optimistic`\n * field set to `true`. If it's an array and an element object is created or updated,\n * the element should have a `$optimistic` field set to `true`.\n */\n data?: any;\n};\n\n/**\n * Optimistic data provider.\n *\n * @param args Arguments.\n * @param args.queryModel The model of the query.\n * @param args.queryOperation The operation of the query, `findMany`, `count`, etc.\n * @param args.queryArgs The arguments of the query.\n * @param args.currentData The current cache data for the query.\n * @param args.mutationArgs The arguments of the mutation.\n */\nexport type OptimisticDataProvider = (args: {\n queryModel: string;\n queryOperation: string;\n queryArgs: any;\n currentData: any;\n mutationArgs: any;\n}) => OptimisticDataProviderResult | Promise<OptimisticDataProviderResult>;\n\n/**\n * Extra mutation options.\n */\nexport type ExtraMutationOptions = {\n /**\n * Whether to automatically invalidate queries potentially affected by the mutation. Defaults to `true`.\n */\n invalidateQueries?: boolean;\n\n /**\n * Whether to optimistically update queries potentially affected by the mutation. Defaults to `false`.\n */\n optimisticUpdate?: boolean;\n\n /**\n * A callback for computing optimistic update data for each query cache entry.\n */\n optimisticDataProvider?: OptimisticDataProvider;\n};\n\n/**\n * Extra query options.\n */\nexport type ExtraQueryOptions = {\n /**\n * Whether to opt-in to optimistic updates for this query. Defaults to `true`.\n */\n optimisticUpdate?: boolean;\n};\n\n/**\n * Context type for configuring the hooks.\n */\nexport type APIContext = {\n /**\n * The endpoint to use for the queries.\n */\n endpoint?: string;\n\n /**\n * A custom fetch function for sending the HTTP requests.\n */\n fetch?: FetchFn;\n\n /**\n * If logging is enabled.\n */\n logging?: boolean;\n};\n\nexport async function fetcher<R, C extends boolean>(\n url: string,\n options?: RequestInit,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? R | undefined : R> {\n const _fetch = fetch ?? crossFetch.fetch;\n const res = await _fetch(url, options);\n if (!res.ok) {\n const errData = unmarshal(await res.text());\n if (\n checkReadBack !== false &&\n errData.error?.prisma &&\n errData.error?.code === 'P2004' &&\n errData.error?.reason === 'RESULT_NOT_READABLE'\n ) {\n // policy doesn't allow mutation result to be read back, just return undefined\n return undefined as any;\n }\n const error: QueryError = new Error('An error occurred while fetching the data.');\n error.info = errData.error;\n error.status = res.status;\n throw error;\n }\n\n const textResult = await res.text();\n try {\n return unmarshal(textResult).data as R;\n } catch (err) {\n console.error(`Unable to deserialize data:`, textResult);\n throw err;\n }\n}\n\ntype QueryKey = [\n string /* prefix */,\n string /* model */,\n string /* operation */,\n unknown /* args */,\n {\n infinite: boolean;\n optimisticUpdate: boolean;\n } /* flags */\n];\n\n/**\n * Computes query key for the given model, operation and query args.\n * @param model Model name.\n * @param urlOrOperation Prisma operation (e.g, `findMany`) or request URL. If it's a URL, the last path segment will be used as the operation name.\n * @param args Prisma query arguments.\n * @param options Query options, including `infinite` indicating if it's an infinite query (defaults to false), and `optimisticUpdate` indicating if optimistic updates are enabled (defaults to true).\n * @returns Query key\n */\nexport function getQueryKey(\n model: string,\n urlOrOperation: string,\n args: unknown,\n options: { infinite: boolean; optimisticUpdate: boolean } = { infinite: false, optimisticUpdate: true }\n): QueryKey {\n if (!urlOrOperation) {\n throw new Error('Invalid urlOrOperation');\n }\n const operation = urlOrOperation.split('/').pop();\n\n const infinite = options.infinite;\n // infinite query doesn't support optimistic updates\n const optimisticUpdate = options.infinite ? false : options.optimisticUpdate;\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return [QUERY_KEY_PREFIX, model, operation!, args, { infinite, optimisticUpdate }];\n}\n\nexport function marshal(value: unknown) {\n const { data, meta } = serialize(value);\n if (meta) {\n return JSON.stringify({ ...(data as any), meta: { serialization: meta } });\n } else {\n return JSON.stringify(data);\n }\n}\n\nexport function unmarshal(value: string) {\n const parsed = JSON.parse(value);\n if (parsed.data && parsed.meta?.serialization) {\n const deserializedData = deserialize(parsed.data, parsed.meta.serialization);\n return { ...parsed, data: deserializedData };\n } else {\n return parsed;\n }\n}\n\nexport function makeUrl(url: string, args: unknown) {\n if (!args) {\n return url;\n }\n\n const { data, meta } = serialize(args);\n let result = `${url}?q=${encodeURIComponent(JSON.stringify(data))}`;\n if (meta) {\n result += `&meta=${encodeURIComponent(JSON.stringify({ serialization: meta }))}`;\n }\n return result;\n}\n\ntype InvalidationPredicate = ({ queryKey }: { queryKey: readonly unknown[] }) => boolean;\ntype InvalidateFunc = (predicate: InvalidationPredicate) => Promise<void>;\ntype MutationOptions = {\n onMutate?: (...args: any[]) => any;\n onSuccess?: (...args: any[]) => any;\n onSettled?: (...args: any[]) => any;\n};\n\n// sets up invalidation hook for a mutation\nexport function setupInvalidation(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: MutationOptions,\n invalidate: InvalidateFunc,\n logging = false\n) {\n const origOnSuccess = options?.onSuccess;\n options.onSuccess = async (...args: unknown[]) => {\n const [_, variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n return origOnSuccess?.(...args);\n };\n}\n\n// gets a predicate for evaluating whether a query should be invalidated\nasync function getInvalidationPredicate(\n model: string,\n operation: PrismaWriteActionType,\n mutationArgs: any,\n modelMeta: ModelMeta,\n logging = false\n) {\n const mutatedModels = await getMutatedModels(model, operation, mutationArgs, modelMeta);\n\n return ({ queryKey }: { queryKey: readonly unknown[] }) => {\n const [_, queryModel, , args] = queryKey as QueryKey;\n\n if (mutatedModels.includes(queryModel)) {\n // direct match\n if (logging) {\n console.log(`Invalidating query ${JSON.stringify(queryKey)} due to mutation \"${model}.${operation}\"`);\n }\n return true;\n }\n\n if (args) {\n // traverse query args to find nested reads that match the model under mutation\n if (findNestedRead(queryModel, mutatedModels, modelMeta, args)) {\n if (logging) {\n console.log(\n `Invalidating query ${JSON.stringify(queryKey)} due to mutation \"${model}.${operation}\"`\n );\n }\n return true;\n }\n }\n\n return false;\n };\n}\n\n// find nested reads that match the given models\nfunction findNestedRead(visitingModel: string, targetModels: string[], modelMeta: ModelMeta, args: any) {\n const modelsRead = getReadModels(visitingModel, modelMeta, args);\n return targetModels.some((m) => modelsRead.includes(m));\n}\n\ntype QueryCache = {\n queryKey: readonly unknown[];\n state: {\n data: unknown;\n error: unknown;\n };\n}[];\n\ntype SetCacheFunc = (queryKey: readonly unknown[], data: unknown) => void;\n\n/**\n * Sets up optimistic update and invalidation (after settled) for a mutation.\n */\nexport function setupOptimisticUpdate(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: MutationOptions & ExtraMutationOptions,\n queryCache: QueryCache,\n setCache: SetCacheFunc,\n invalidate?: InvalidateFunc,\n logging = false\n) {\n const origOnMutate = options?.onMutate;\n const origOnSettled = options?.onSettled;\n\n // optimistic update on mutate\n options.onMutate = async (...args: unknown[]) => {\n const [variables] = args;\n await optimisticUpdate(\n model,\n operation as PrismaWriteActionType,\n variables,\n options,\n modelMeta,\n queryCache,\n setCache,\n logging\n );\n return origOnMutate?.(...args);\n };\n\n // invalidate on settled\n options.onSettled = async (...args: unknown[]) => {\n if (invalidate) {\n const [, , variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n }\n return origOnSettled?.(...args);\n };\n}\n\n// optimistically updates query cache\nasync function optimisticUpdate(\n mutationModel: string,\n mutationOp: string,\n mutationArgs: any,\n options: MutationOptions & ExtraMutationOptions,\n modelMeta: ModelMeta,\n queryCache: QueryCache,\n setCache: SetCacheFunc,\n logging = false\n) {\n for (const cacheItem of queryCache) {\n const {\n queryKey,\n state: { data, error },\n } = cacheItem;\n\n if (error) {\n if (logging) {\n console.warn(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to error:`, error);\n }\n continue;\n }\n\n const [_, queryModel, queryOperation, queryArgs, { optimisticUpdate }] = queryKey as QueryKey;\n if (!optimisticUpdate) {\n if (logging) {\n console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to opt-out`);\n }\n continue;\n }\n\n if (options.optimisticDataProvider) {\n const providerResult = await options.optimisticDataProvider({\n queryModel,\n queryOperation,\n queryArgs,\n currentData: data,\n mutationArgs,\n });\n\n if (providerResult?.kind === 'Skip') {\n // skip\n if (logging) {\n console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to provider`);\n }\n continue;\n } else if (providerResult?.kind === 'Update') {\n // update cache\n if (logging) {\n console.log(`Optimistically updating query ${JSON.stringify(queryKey)} due to provider`);\n }\n setCache(queryKey, providerResult.data);\n continue;\n }\n }\n\n // proceed with default optimistic update\n const mutatedData = await applyMutation(\n queryModel,\n queryOperation,\n data,\n mutationModel,\n mutationOp as PrismaWriteActionType,\n mutationArgs,\n modelMeta,\n logging\n );\n\n if (mutatedData !== undefined) {\n // mutation applicable to this query, update cache\n if (logging) {\n console.log(\n `Optimistically updating query ${JSON.stringify(\n queryKey\n )} due to mutation \"${mutationModel}.${mutationOp}\"`\n );\n }\n setCache(queryKey, mutatedData);\n }\n }\n}\n"],"mappings":"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","names":["fetch","optimisticUpdate","fetch","optimisticUpdate"]}
@@ -1,7 +1,7 @@
1
1
  import * as _tanstack_svelte_query_v5 from '@tanstack/svelte-query';
2
2
  import { StoreOrVal, CreateQueryOptions, CreateInfiniteQueryOptions, InfiniteData, MutationOptions } from '@tanstack/svelte-query';
3
3
  import { ModelMeta } from '@zenstackhq/runtime/cross';
4
- import { A as APIContext, F as FetchFn } from './common-ZSgIGN1q.mjs';
4
+ import { A as APIContext, F as FetchFn, a as ExtraQueryOptions, E as ExtraMutationOptions } from './common--_wRp2eo.mjs';
5
5
 
6
6
  /**
7
7
  * Key for setting and getting the global query context.
@@ -27,10 +27,9 @@ declare function getHooksContext(): {
27
27
  * @param args The request args object, URL-encoded and appended as "?q=" parameter
28
28
  * @param options The svelte-query options object
29
29
  * @param fetch The fetch function to use for sending the HTTP request
30
- * @param optimisticUpdate Whether to enable automatic optimistic update
31
30
  * @returns useQuery hook
32
31
  */
33
- declare function useModelQuery<TQueryFnData, TData, TError>(model: string, url: string, args?: unknown, options?: StoreOrVal<Omit<CreateQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>>, fetch?: FetchFn, optimisticUpdate?: boolean): _tanstack_svelte_query_v5.CreateQueryResult<unknown, Error>;
32
+ declare function useModelQuery<TQueryFnData, TData, TError>(model: string, url: string, args?: unknown, options?: StoreOrVal<Omit<CreateQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>> & ExtraQueryOptions, fetch?: FetchFn): _tanstack_svelte_query_v5.CreateQueryResult<unknown, Error>;
34
33
  /**
35
34
  * Creates a svelte-query infinite query.
36
35
  *
@@ -49,9 +48,8 @@ declare function useInfiniteModelQuery<TQueryFnData, TData, TError>(model: strin
49
48
  * @param modelMeta The model metadata.
50
49
  * @param url The request URL.
51
50
  * @param options The svelte-query options.
52
- * @param invalidateQueries Whether to invalidate queries after mutation.
53
51
  * @returns useMutation hooks
54
52
  */
55
- declare function useModelMutation<TArgs, TError, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(model: string, method: 'POST' | 'PUT' | 'DELETE', url: string, modelMeta: ModelMeta, options?: Omit<MutationOptions<Result, TError, TArgs>, 'mutationFn'>, fetch?: FetchFn, invalidateQueries?: boolean, checkReadBack?: C, optimisticUpdate?: boolean): _tanstack_svelte_query_v5.CreateMutationResult<Result, TError, TArgs, unknown>;
53
+ declare function useModelMutation<TArgs, TError, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(model: string, method: 'POST' | 'PUT' | 'DELETE', url: string, modelMeta: ModelMeta, options?: Omit<MutationOptions<Result, TError, TArgs>, 'mutationFn'> & ExtraMutationOptions, fetch?: FetchFn, checkReadBack?: C): _tanstack_svelte_query_v5.CreateMutationResult<Result, TError, TArgs, unknown>;
56
54
 
57
55
  export { APIContext as RequestHandlerContext, SvelteQueryContextKey, getHooksContext, setHooksContext, useInfiniteModelQuery, useModelMutation, useModelQuery };
@@ -1,7 +1,7 @@
1
1
  import * as _tanstack_svelte_query_v5 from '@tanstack/svelte-query';
2
2
  import { StoreOrVal, CreateQueryOptions, CreateInfiniteQueryOptions, InfiniteData, MutationOptions } from '@tanstack/svelte-query';
3
3
  import { ModelMeta } from '@zenstackhq/runtime/cross';
4
- import { A as APIContext, F as FetchFn } from './common-ZSgIGN1q.js';
4
+ import { A as APIContext, F as FetchFn, a as ExtraQueryOptions, E as ExtraMutationOptions } from './common--_wRp2eo.js';
5
5
 
6
6
  /**
7
7
  * Key for setting and getting the global query context.
@@ -27,10 +27,9 @@ declare function getHooksContext(): {
27
27
  * @param args The request args object, URL-encoded and appended as "?q=" parameter
28
28
  * @param options The svelte-query options object
29
29
  * @param fetch The fetch function to use for sending the HTTP request
30
- * @param optimisticUpdate Whether to enable automatic optimistic update
31
30
  * @returns useQuery hook
32
31
  */
33
- declare function useModelQuery<TQueryFnData, TData, TError>(model: string, url: string, args?: unknown, options?: StoreOrVal<Omit<CreateQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>>, fetch?: FetchFn, optimisticUpdate?: boolean): _tanstack_svelte_query_v5.CreateQueryResult<unknown, Error>;
32
+ declare function useModelQuery<TQueryFnData, TData, TError>(model: string, url: string, args?: unknown, options?: StoreOrVal<Omit<CreateQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>> & ExtraQueryOptions, fetch?: FetchFn): _tanstack_svelte_query_v5.CreateQueryResult<unknown, Error>;
34
33
  /**
35
34
  * Creates a svelte-query infinite query.
36
35
  *
@@ -49,9 +48,8 @@ declare function useInfiniteModelQuery<TQueryFnData, TData, TError>(model: strin
49
48
  * @param modelMeta The model metadata.
50
49
  * @param url The request URL.
51
50
  * @param options The svelte-query options.
52
- * @param invalidateQueries Whether to invalidate queries after mutation.
53
51
  * @returns useMutation hooks
54
52
  */
55
- declare function useModelMutation<TArgs, TError, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(model: string, method: 'POST' | 'PUT' | 'DELETE', url: string, modelMeta: ModelMeta, options?: Omit<MutationOptions<Result, TError, TArgs>, 'mutationFn'>, fetch?: FetchFn, invalidateQueries?: boolean, checkReadBack?: C, optimisticUpdate?: boolean): _tanstack_svelte_query_v5.CreateMutationResult<Result, TError, TArgs, unknown>;
53
+ declare function useModelMutation<TArgs, TError, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(model: string, method: 'POST' | 'PUT' | 'DELETE', url: string, modelMeta: ModelMeta, options?: Omit<MutationOptions<Result, TError, TArgs>, 'mutationFn'> & ExtraMutationOptions, fetch?: FetchFn, checkReadBack?: C): _tanstack_svelte_query_v5.CreateMutationResult<Result, TError, TArgs, unknown>;
56
54
 
57
55
  export { APIContext as RequestHandlerContext, SvelteQueryContextKey, getHooksContext, setHooksContext, useInfiniteModelQuery, useModelMutation, useModelQuery };
@@ -121,11 +121,13 @@ function fetcher(url, options, fetch2, checkReadBack) {
121
121
  }
122
122
  });
123
123
  }
124
- function getQueryKey(model, urlOrOperation, args, infinite = false, optimisticUpdate2 = false) {
124
+ function getQueryKey(model, urlOrOperation, args, options = { infinite: false, optimisticUpdate: true }) {
125
125
  if (!urlOrOperation) {
126
126
  throw new Error("Invalid urlOrOperation");
127
127
  }
128
128
  const operation = urlOrOperation.split("/").pop();
129
+ const infinite = options.infinite;
130
+ const optimisticUpdate2 = options.infinite ? false : options.optimisticUpdate;
129
131
  return [QUERY_KEY_PREFIX, model, operation, args, { infinite, optimisticUpdate: optimisticUpdate2 }];
130
132
  }
131
133
  function marshal(value) {
@@ -210,6 +212,7 @@ function setupOptimisticUpdate(model, operation, modelMeta, options, queryCache,
210
212
  model,
211
213
  operation,
212
214
  variables,
215
+ options,
213
216
  modelMeta,
214
217
  queryCache,
215
218
  setCache,
@@ -232,7 +235,7 @@ function setupOptimisticUpdate(model, operation, modelMeta, options, queryCache,
232
235
  return origOnSettled == null ? void 0 : origOnSettled(...args);
233
236
  });
234
237
  }
235
- function optimisticUpdate(mutationModel, mutationOp, mutationArgs, modelMeta, queryCache, setCache, logging = false) {
238
+ function optimisticUpdate(mutationModel, mutationOp, mutationArgs, options, modelMeta, queryCache, setCache, logging = false) {
236
239
  return __async(this, null, function* () {
237
240
  for (const cacheItem of queryCache) {
238
241
  const {
@@ -245,16 +248,37 @@ function optimisticUpdate(mutationModel, mutationOp, mutationArgs, modelMeta, qu
245
248
  }
246
249
  continue;
247
250
  }
248
- const [_, queryModel, queryOp, _queryArgs, { optimisticUpdate: optimisticUpdate2 }] = queryKey;
251
+ const [_, queryModel, queryOperation, queryArgs, { optimisticUpdate: optimisticUpdate2 }] = queryKey;
249
252
  if (!optimisticUpdate2) {
250
253
  if (logging) {
251
254
  console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to opt-out`);
252
255
  }
253
256
  continue;
254
257
  }
258
+ if (options.optimisticDataProvider) {
259
+ const providerResult = yield options.optimisticDataProvider({
260
+ queryModel,
261
+ queryOperation,
262
+ queryArgs,
263
+ currentData: data,
264
+ mutationArgs
265
+ });
266
+ if ((providerResult == null ? void 0 : providerResult.kind) === "Skip") {
267
+ if (logging) {
268
+ console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to provider`);
269
+ }
270
+ continue;
271
+ } else if ((providerResult == null ? void 0 : providerResult.kind) === "Update") {
272
+ if (logging) {
273
+ console.log(`Optimistically updating query ${JSON.stringify(queryKey)} due to provider`);
274
+ }
275
+ setCache(queryKey, providerResult.data);
276
+ continue;
277
+ }
278
+ }
255
279
  const mutatedData = yield (0, import_cross.applyMutation)(
256
280
  queryModel,
257
- queryOp,
281
+ queryOperation,
258
282
  data,
259
283
  mutationModel,
260
284
  mutationOp,
@@ -285,9 +309,12 @@ function getHooksContext() {
285
309
  const _a = (0, import_svelte.getContext)(SvelteQueryContextKey), { endpoint } = _a, rest = __objRest(_a, ["endpoint"]);
286
310
  return __spreadValues({ endpoint: endpoint != null ? endpoint : DEFAULT_QUERY_ENDPOINT }, rest);
287
311
  }
288
- function useModelQuery(model, url, args, options, fetch2, optimisticUpdate2 = false) {
312
+ function useModelQuery(model, url, args, options, fetch2) {
289
313
  const reqUrl = makeUrl(url, args);
290
- const queryKey = getQueryKey(model, url, args, false, optimisticUpdate2);
314
+ const queryKey = getQueryKey(model, url, args, {
315
+ infinite: false,
316
+ optimisticUpdate: (options == null ? void 0 : options.optimisticUpdate) !== false
317
+ });
291
318
  const queryFn = () => fetcher(reqUrl, void 0, fetch2, false);
292
319
  let mergedOpt;
293
320
  if (isStore(options)) {
@@ -306,7 +333,7 @@ function useModelQuery(model, url, args, options, fetch2, optimisticUpdate2 = fa
306
333
  return (0, import_svelte_query_v5.createQuery)(mergedOpt);
307
334
  }
308
335
  function useInfiniteModelQuery(model, url, args, options, fetch2) {
309
- const queryKey = getQueryKey(model, url, args, true);
336
+ const queryKey = getQueryKey(model, url, args, { infinite: true, optimisticUpdate: false });
310
337
  const queryFn = ({ pageParam }) => fetcher(makeUrl(url, pageParam != null ? pageParam : args), void 0, fetch2, false);
311
338
  let mergedOpt;
312
339
  if (isStore(options)) {
@@ -327,7 +354,7 @@ function useInfiniteModelQuery(model, url, args, options, fetch2) {
327
354
  function isStore(opt) {
328
355
  return typeof (opt == null ? void 0 : opt.subscribe) === "function";
329
356
  }
330
- function useModelMutation(model, method, url, modelMeta, options, fetch2, invalidateQueries = true, checkReadBack, optimisticUpdate2 = false) {
357
+ function useModelMutation(model, method, url, modelMeta, options, fetch2, checkReadBack) {
331
358
  const queryClient = (0, import_svelte_query_v5.useQueryClient)();
332
359
  const mutationFn = (data) => {
333
360
  const reqUrl = method === "DELETE" ? makeUrl(url, data) : url;
@@ -343,6 +370,8 @@ function useModelMutation(model, method, url, modelMeta, options, fetch2, invali
343
370
  };
344
371
  const finalOptions = __spreadProps(__spreadValues({}, options), { mutationFn });
345
372
  const operation = url.split("/").pop();
373
+ const invalidateQueries = (options == null ? void 0 : options.invalidateQueries) !== false;
374
+ const optimisticUpdate2 = !!(options == null ? void 0 : options.optimisticUpdate);
346
375
  if (operation) {
347
376
  const { logging } = (0, import_svelte.getContext)(SvelteQueryContextKey);
348
377
  if (invalidateQueries) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime-v5/svelte.ts","../../src/runtime/common.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n createInfiniteQuery,\n createMutation,\n createQuery,\n useQueryClient,\n type CreateInfiniteQueryOptions,\n type CreateQueryOptions,\n type InfiniteData,\n type MutationOptions,\n type StoreOrVal,\n} from '@tanstack/svelte-query-v5';\nimport { ModelMeta } from '@zenstackhq/runtime/cross';\nimport { getContext, setContext } from 'svelte';\nimport { Readable, derived } from 'svelte/store';\nimport {\n APIContext,\n DEFAULT_QUERY_ENDPOINT,\n fetcher,\n getQueryKey,\n makeUrl,\n marshal,\n setupInvalidation,\n setupOptimisticUpdate,\n type FetchFn,\n} from '../runtime/common';\n\nexport { APIContext as RequestHandlerContext } from '../runtime/common';\n\n/**\n * Key for setting and getting the global query context.\n */\nexport const SvelteQueryContextKey = 'zenstack-svelte-query-context';\n\n/**\n * Set context for the generated TanStack Query hooks.\n */\nexport function setHooksContext(context: APIContext) {\n setContext(SvelteQueryContextKey, context);\n}\n\n/**\n * Hooks context.\n */\nexport function getHooksContext() {\n const { endpoint, ...rest } = getContext<APIContext>(SvelteQueryContextKey);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Creates a svelte-query query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The svelte-query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @param optimisticUpdate Whether to enable automatic optimistic update\n * @returns useQuery hook\n */\nexport function useModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args?: unknown,\n options?: StoreOrVal<Omit<CreateQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>>,\n fetch?: FetchFn,\n optimisticUpdate = false\n) {\n const reqUrl = makeUrl(url, args);\n const queryKey = getQueryKey(model, url, args, false, optimisticUpdate);\n const queryFn = () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false);\n\n let mergedOpt: any;\n if (isStore(options)) {\n // options is store\n mergedOpt = derived([options], ([$opt]) => {\n return {\n queryKey,\n queryFn,\n ...($opt as object),\n };\n });\n } else {\n // options is value\n mergedOpt = {\n queryKey,\n queryFn,\n ...options,\n };\n }\n return createQuery(mergedOpt);\n}\n\n/**\n * Creates a svelte-query infinite query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The initial request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The svelte-query infinite query options object\n * @returns useQuery hook\n */\nexport function useInfiniteModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args: unknown,\n options: StoreOrVal<Omit<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey'>>,\n fetch?: FetchFn\n) {\n const queryKey = getQueryKey(model, url, args, true);\n const queryFn = ({ pageParam }: { pageParam: unknown }) =>\n fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);\n\n let mergedOpt: StoreOrVal<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>>;\n if (isStore<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>>(options)) {\n // options is store\n mergedOpt = derived([options], ([$opt]) => {\n return {\n queryKey,\n queryFn,\n ...$opt,\n };\n });\n } else {\n // options is value\n mergedOpt = {\n queryKey,\n queryFn,\n ...options,\n };\n }\n return createInfiniteQuery<TQueryFnData, TError, InfiniteData<TData>>(mergedOpt);\n}\n\nfunction isStore<T>(opt: unknown): opt is Readable<T> {\n return typeof (opt as any)?.subscribe === 'function';\n}\n\n/**\n * Creates a POST mutation with svelte-query.\n *\n * @param model The name of the model under mutation.\n * @param method The HTTP method.\n * @param modelMeta The model metadata.\n * @param url The request URL.\n * @param options The svelte-query options.\n * @param invalidateQueries Whether to invalidate queries after mutation.\n * @returns useMutation hooks\n */\nexport function useModelMutation<\n TArgs,\n TError,\n R = any,\n C extends boolean = boolean,\n Result = C extends true ? R | undefined : R\n>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n modelMeta: ModelMeta,\n options?: Omit<MutationOptions<Result, TError, TArgs>, 'mutationFn'>,\n fetch?: FetchFn,\n invalidateQueries = true,\n checkReadBack?: C,\n optimisticUpdate = false\n) {\n const queryClient = useQueryClient();\n const mutationFn = (data: any) => {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const fetchInit: RequestInit = {\n method,\n ...(method !== 'DELETE' && {\n headers: {\n 'content-type': 'application/json',\n },\n body: marshal(data),\n }),\n };\n return fetcher<R, C>(reqUrl, fetchInit, fetch, checkReadBack) as Promise<Result>;\n };\n\n const finalOptions = { ...options, mutationFn };\n const operation = url.split('/').pop();\n\n if (operation) {\n const { logging } = getContext<APIContext>(SvelteQueryContextKey);\n if (invalidateQueries) {\n setupInvalidation(\n model,\n operation,\n modelMeta,\n finalOptions,\n (predicate) => queryClient.invalidateQueries({ predicate }),\n logging\n );\n }\n\n if (optimisticUpdate) {\n setupOptimisticUpdate(\n model,\n operation,\n modelMeta,\n finalOptions,\n queryClient.getQueryCache().getAll(),\n (queryKey, data) => queryClient.setQueryData<unknown>(queryKey, data),\n invalidateQueries ? (predicate) => queryClient.invalidateQueries({ predicate }) : undefined,\n logging\n );\n }\n }\n\n return createMutation(finalOptions);\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport {\n applyMutation,\n getMutatedModels,\n getReadModels,\n type ModelMeta,\n type PrismaWriteActionType,\n} from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\n\n/**\n * The default query endpoint.\n */\nexport const DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Prefix for react-query keys.\n */\nexport const QUERY_KEY_PREFIX = 'zenstack';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Type for query and mutation errors.\n */\nexport type QueryError = Error & {\n /**\n * Additional error information.\n */\n info?: unknown;\n\n /**\n * HTTP status code.\n */\n status?: number;\n};\n\n/**\n * Context type for configuring the hooks.\n */\nexport type APIContext = {\n /**\n * The endpoint to use for the queries.\n */\n endpoint?: string;\n\n /**\n * A custom fetch function for sending the HTTP requests.\n */\n fetch?: FetchFn;\n\n /**\n * If logging is enabled.\n */\n logging?: boolean;\n};\n\nexport async function fetcher<R, C extends boolean>(\n url: string,\n options?: RequestInit,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? R | undefined : R> {\n const _fetch = fetch ?? crossFetch.fetch;\n const res = await _fetch(url, options);\n if (!res.ok) {\n const errData = unmarshal(await res.text());\n if (\n checkReadBack !== false &&\n errData.error?.prisma &&\n errData.error?.code === 'P2004' &&\n errData.error?.reason === 'RESULT_NOT_READABLE'\n ) {\n // policy doesn't allow mutation result to be read back, just return undefined\n return undefined as any;\n }\n const error: QueryError = new Error('An error occurred while fetching the data.');\n error.info = errData.error;\n error.status = res.status;\n throw error;\n }\n\n const textResult = await res.text();\n try {\n return unmarshal(textResult).data as R;\n } catch (err) {\n console.error(`Unable to deserialize data:`, textResult);\n throw err;\n }\n}\n\ntype QueryKey = [\n string /* prefix */,\n string /* model */,\n string /* operation */,\n unknown /* args */,\n {\n infinite: boolean;\n optimisticUpdate: boolean;\n } /* flags */\n];\n\n/**\n * Computes query key for the given model, operation and query args.\n * @param model Model name.\n * @param urlOrOperation Prisma operation (e.g, `findMany`) or request URL. If it's a URL, the last path segment will be used as the operation name.\n * @param args Prisma query arguments.\n * @param infinite Whether the query is infinite.\n * @param optimisticUpdate Whether the query is optimistically updated.\n * @returns Query key\n */\nexport function getQueryKey(\n model: string,\n urlOrOperation: string,\n args: unknown,\n infinite = false,\n optimisticUpdate = false\n): QueryKey {\n if (!urlOrOperation) {\n throw new Error('Invalid urlOrOperation');\n }\n const operation = urlOrOperation.split('/').pop();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return [QUERY_KEY_PREFIX, model, operation!, args, { infinite, optimisticUpdate }];\n}\n\nexport function marshal(value: unknown) {\n const { data, meta } = serialize(value);\n if (meta) {\n return JSON.stringify({ ...(data as any), meta: { serialization: meta } });\n } else {\n return JSON.stringify(data);\n }\n}\n\nexport function unmarshal(value: string) {\n const parsed = JSON.parse(value);\n if (parsed.data && parsed.meta?.serialization) {\n const deserializedData = deserialize(parsed.data, parsed.meta.serialization);\n return { ...parsed, data: deserializedData };\n } else {\n return parsed;\n }\n}\n\nexport function makeUrl(url: string, args: unknown) {\n if (!args) {\n return url;\n }\n\n const { data, meta } = serialize(args);\n let result = `${url}?q=${encodeURIComponent(JSON.stringify(data))}`;\n if (meta) {\n result += `&meta=${encodeURIComponent(JSON.stringify({ serialization: meta }))}`;\n }\n return result;\n}\n\ntype InvalidationPredicate = ({ queryKey }: { queryKey: readonly unknown[] }) => boolean;\ntype InvalidateFunc = (predicate: InvalidationPredicate) => Promise<void>;\ntype MutationOptions = {\n onMutate?: (...args: any[]) => any;\n onSuccess?: (...args: any[]) => any;\n onSettled?: (...args: any[]) => any;\n};\n\n// sets up invalidation hook for a mutation\nexport function setupInvalidation(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: MutationOptions,\n invalidate: InvalidateFunc,\n logging = false\n) {\n const origOnSuccess = options?.onSuccess;\n options.onSuccess = async (...args: unknown[]) => {\n const [_, variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n return origOnSuccess?.(...args);\n };\n}\n\n// gets a predicate for evaluating whether a query should be invalidated\nasync function getInvalidationPredicate(\n model: string,\n operation: PrismaWriteActionType,\n mutationArgs: any,\n modelMeta: ModelMeta,\n logging = false\n) {\n const mutatedModels = await getMutatedModels(model, operation, mutationArgs, modelMeta);\n\n return ({ queryKey }: { queryKey: readonly unknown[] }) => {\n const [_, queryModel, , args] = queryKey as QueryKey;\n\n if (mutatedModels.includes(queryModel)) {\n // direct match\n if (logging) {\n console.log(`Invalidating query ${JSON.stringify(queryKey)} due to mutation \"${model}.${operation}\"`);\n }\n return true;\n }\n\n if (args) {\n // traverse query args to find nested reads that match the model under mutation\n if (findNestedRead(queryModel, mutatedModels, modelMeta, args)) {\n if (logging) {\n console.log(\n `Invalidating query ${JSON.stringify(queryKey)} due to mutation \"${model}.${operation}\"`\n );\n }\n return true;\n }\n }\n\n return false;\n };\n}\n\n// find nested reads that match the given models\nfunction findNestedRead(visitingModel: string, targetModels: string[], modelMeta: ModelMeta, args: any) {\n const modelsRead = getReadModels(visitingModel, modelMeta, args);\n return targetModels.some((m) => modelsRead.includes(m));\n}\n\ntype QueryCache = {\n queryKey: readonly unknown[];\n state: {\n data: unknown;\n error: unknown;\n };\n}[];\n\ntype SetCacheFunc = (queryKey: readonly unknown[], data: unknown) => void;\n\nexport function setupOptimisticUpdate(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: MutationOptions,\n queryCache: QueryCache,\n setCache: SetCacheFunc,\n invalidate?: InvalidateFunc,\n logging = false\n) {\n const origOnMutate = options?.onMutate;\n const origOnSettled = options?.onSettled;\n\n // optimistic update on mutate\n options.onMutate = async (...args: unknown[]) => {\n const [variables] = args;\n await optimisticUpdate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n queryCache,\n setCache,\n logging\n );\n return origOnMutate?.(...args);\n };\n\n // invalidate on settled\n options.onSettled = async (...args: unknown[]) => {\n if (invalidate) {\n const [, , variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n }\n return origOnSettled?.(...args);\n };\n}\n\n// optimistically updates query cache\nasync function optimisticUpdate(\n mutationModel: string,\n mutationOp: string,\n mutationArgs: any,\n modelMeta: ModelMeta,\n queryCache: QueryCache,\n setCache: SetCacheFunc,\n logging = false\n) {\n for (const cacheItem of queryCache) {\n const {\n queryKey,\n state: { data, error },\n } = cacheItem;\n\n if (error) {\n if (logging) {\n console.warn(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to error:`, error);\n }\n continue;\n }\n\n const [_, queryModel, queryOp, _queryArgs, { optimisticUpdate }] = queryKey as QueryKey;\n if (!optimisticUpdate) {\n if (logging) {\n console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to opt-out`);\n }\n continue;\n }\n\n const mutatedData = await applyMutation(\n queryModel,\n queryOp,\n data,\n mutationModel,\n mutationOp as PrismaWriteActionType,\n mutationArgs,\n modelMeta,\n logging\n );\n\n if (mutatedData !== undefined) {\n // mutation applicable to this query, update cache\n if (logging) {\n console.log(\n `Optimistically updating query ${JSON.stringify(\n queryKey\n )} due to mutation \"${mutationModel}.${mutationOp}\"`\n );\n }\n setCache(queryKey, mutatedData);\n }\n }\n}\n"],"mappings":"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","names":["fetch","optimisticUpdate","fetch","optimisticUpdate"]}
1
+ {"version":3,"sources":["../../src/runtime-v5/svelte.ts","../../src/runtime/common.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n createInfiniteQuery,\n createMutation,\n createQuery,\n useQueryClient,\n type CreateInfiniteQueryOptions,\n type CreateQueryOptions,\n type InfiniteData,\n type MutationOptions,\n type StoreOrVal,\n} from '@tanstack/svelte-query-v5';\nimport { ModelMeta } from '@zenstackhq/runtime/cross';\nimport { getContext, setContext } from 'svelte';\nimport { Readable, derived } from 'svelte/store';\nimport {\n APIContext,\n DEFAULT_QUERY_ENDPOINT,\n fetcher,\n getQueryKey,\n makeUrl,\n marshal,\n setupInvalidation,\n setupOptimisticUpdate,\n type ExtraMutationOptions,\n type ExtraQueryOptions,\n type FetchFn,\n} from '../runtime/common';\n\nexport { APIContext as RequestHandlerContext } from '../runtime/common';\n\n/**\n * Key for setting and getting the global query context.\n */\nexport const SvelteQueryContextKey = 'zenstack-svelte-query-context';\n\n/**\n * Set context for the generated TanStack Query hooks.\n */\nexport function setHooksContext(context: APIContext) {\n setContext(SvelteQueryContextKey, context);\n}\n\n/**\n * Hooks context.\n */\nexport function getHooksContext() {\n const { endpoint, ...rest } = getContext<APIContext>(SvelteQueryContextKey);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Creates a svelte-query query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The svelte-query options object\n * @param fetch The fetch function to use for sending the HTTP request\n * @returns useQuery hook\n */\nexport function useModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args?: unknown,\n options?: StoreOrVal<Omit<CreateQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>> & ExtraQueryOptions,\n fetch?: FetchFn\n) {\n const reqUrl = makeUrl(url, args);\n const queryKey = getQueryKey(model, url, args, {\n infinite: false,\n optimisticUpdate: options?.optimisticUpdate !== false,\n });\n const queryFn = () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false);\n\n let mergedOpt: any;\n if (isStore(options)) {\n // options is store\n mergedOpt = derived([options], ([$opt]) => {\n return {\n queryKey,\n queryFn,\n ...($opt as object),\n };\n });\n } else {\n // options is value\n mergedOpt = {\n queryKey,\n queryFn,\n ...options,\n };\n }\n return createQuery(mergedOpt);\n}\n\n/**\n * Creates a svelte-query infinite query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The initial request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The svelte-query infinite query options object\n * @returns useQuery hook\n */\nexport function useInfiniteModelQuery<TQueryFnData, TData, TError>(\n model: string,\n url: string,\n args: unknown,\n options: StoreOrVal<Omit<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey'>>,\n fetch?: FetchFn\n) {\n const queryKey = getQueryKey(model, url, args, { infinite: true, optimisticUpdate: false });\n const queryFn = ({ pageParam }: { pageParam: unknown }) =>\n fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);\n\n let mergedOpt: StoreOrVal<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>>;\n if (isStore<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>>(options)) {\n // options is store\n mergedOpt = derived([options], ([$opt]) => {\n return {\n queryKey,\n queryFn,\n ...$opt,\n };\n });\n } else {\n // options is value\n mergedOpt = {\n queryKey,\n queryFn,\n ...options,\n };\n }\n return createInfiniteQuery<TQueryFnData, TError, InfiniteData<TData>>(mergedOpt);\n}\n\nfunction isStore<T>(opt: unknown): opt is Readable<T> {\n return typeof (opt as any)?.subscribe === 'function';\n}\n\n/**\n * Creates a POST mutation with svelte-query.\n *\n * @param model The name of the model under mutation.\n * @param method The HTTP method.\n * @param modelMeta The model metadata.\n * @param url The request URL.\n * @param options The svelte-query options.\n * @returns useMutation hooks\n */\nexport function useModelMutation<\n TArgs,\n TError,\n R = any,\n C extends boolean = boolean,\n Result = C extends true ? R | undefined : R\n>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n modelMeta: ModelMeta,\n options?: Omit<MutationOptions<Result, TError, TArgs>, 'mutationFn'> & ExtraMutationOptions,\n fetch?: FetchFn,\n checkReadBack?: C\n) {\n const queryClient = useQueryClient();\n const mutationFn = (data: any) => {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const fetchInit: RequestInit = {\n method,\n ...(method !== 'DELETE' && {\n headers: {\n 'content-type': 'application/json',\n },\n body: marshal(data),\n }),\n };\n return fetcher<R, C>(reqUrl, fetchInit, fetch, checkReadBack) as Promise<Result>;\n };\n\n const finalOptions = { ...options, mutationFn };\n const operation = url.split('/').pop();\n const invalidateQueries = options?.invalidateQueries !== false;\n const optimisticUpdate = !!options?.optimisticUpdate;\n\n if (operation) {\n const { logging } = getContext<APIContext>(SvelteQueryContextKey);\n if (invalidateQueries) {\n setupInvalidation(\n model,\n operation,\n modelMeta,\n finalOptions,\n (predicate) => queryClient.invalidateQueries({ predicate }),\n logging\n );\n }\n\n if (optimisticUpdate) {\n setupOptimisticUpdate(\n model,\n operation,\n modelMeta,\n finalOptions,\n queryClient.getQueryCache().getAll(),\n (queryKey, data) => queryClient.setQueryData<unknown>(queryKey, data),\n invalidateQueries ? (predicate) => queryClient.invalidateQueries({ predicate }) : undefined,\n logging\n );\n }\n }\n\n return createMutation(finalOptions);\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport {\n applyMutation,\n getMutatedModels,\n getReadModels,\n type ModelMeta,\n type PrismaWriteActionType,\n} from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\n\n/**\n * The default query endpoint.\n */\nexport const DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Prefix for react-query keys.\n */\nexport const QUERY_KEY_PREFIX = 'zenstack';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Type for query and mutation errors.\n */\nexport type QueryError = Error & {\n /**\n * Additional error information.\n */\n info?: unknown;\n\n /**\n * HTTP status code.\n */\n status?: number;\n};\n\n/**\n * Result of optimistic data provider.\n */\nexport type OptimisticDataProviderResult = {\n /**\n * Kind of the result.\n * - Update: use the `data` field to update the query cache.\n * - Skip: skip the optimistic update for this query.\n * - ProceedDefault: proceed with the default optimistic update.\n */\n kind: 'Update' | 'Skip' | 'ProceedDefault';\n\n /**\n * Data to update the query cache. Only applicable if `kind` is 'Update'.\n *\n * If the data is an object with fields updated, it should have a `$optimistic`\n * field set to `true`. If it's an array and an element object is created or updated,\n * the element should have a `$optimistic` field set to `true`.\n */\n data?: any;\n};\n\n/**\n * Optimistic data provider.\n *\n * @param args Arguments.\n * @param args.queryModel The model of the query.\n * @param args.queryOperation The operation of the query, `findMany`, `count`, etc.\n * @param args.queryArgs The arguments of the query.\n * @param args.currentData The current cache data for the query.\n * @param args.mutationArgs The arguments of the mutation.\n */\nexport type OptimisticDataProvider = (args: {\n queryModel: string;\n queryOperation: string;\n queryArgs: any;\n currentData: any;\n mutationArgs: any;\n}) => OptimisticDataProviderResult | Promise<OptimisticDataProviderResult>;\n\n/**\n * Extra mutation options.\n */\nexport type ExtraMutationOptions = {\n /**\n * Whether to automatically invalidate queries potentially affected by the mutation. Defaults to `true`.\n */\n invalidateQueries?: boolean;\n\n /**\n * Whether to optimistically update queries potentially affected by the mutation. Defaults to `false`.\n */\n optimisticUpdate?: boolean;\n\n /**\n * A callback for computing optimistic update data for each query cache entry.\n */\n optimisticDataProvider?: OptimisticDataProvider;\n};\n\n/**\n * Extra query options.\n */\nexport type ExtraQueryOptions = {\n /**\n * Whether to opt-in to optimistic updates for this query. Defaults to `true`.\n */\n optimisticUpdate?: boolean;\n};\n\n/**\n * Context type for configuring the hooks.\n */\nexport type APIContext = {\n /**\n * The endpoint to use for the queries.\n */\n endpoint?: string;\n\n /**\n * A custom fetch function for sending the HTTP requests.\n */\n fetch?: FetchFn;\n\n /**\n * If logging is enabled.\n */\n logging?: boolean;\n};\n\nexport async function fetcher<R, C extends boolean>(\n url: string,\n options?: RequestInit,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? R | undefined : R> {\n const _fetch = fetch ?? crossFetch.fetch;\n const res = await _fetch(url, options);\n if (!res.ok) {\n const errData = unmarshal(await res.text());\n if (\n checkReadBack !== false &&\n errData.error?.prisma &&\n errData.error?.code === 'P2004' &&\n errData.error?.reason === 'RESULT_NOT_READABLE'\n ) {\n // policy doesn't allow mutation result to be read back, just return undefined\n return undefined as any;\n }\n const error: QueryError = new Error('An error occurred while fetching the data.');\n error.info = errData.error;\n error.status = res.status;\n throw error;\n }\n\n const textResult = await res.text();\n try {\n return unmarshal(textResult).data as R;\n } catch (err) {\n console.error(`Unable to deserialize data:`, textResult);\n throw err;\n }\n}\n\ntype QueryKey = [\n string /* prefix */,\n string /* model */,\n string /* operation */,\n unknown /* args */,\n {\n infinite: boolean;\n optimisticUpdate: boolean;\n } /* flags */\n];\n\n/**\n * Computes query key for the given model, operation and query args.\n * @param model Model name.\n * @param urlOrOperation Prisma operation (e.g, `findMany`) or request URL. If it's a URL, the last path segment will be used as the operation name.\n * @param args Prisma query arguments.\n * @param options Query options, including `infinite` indicating if it's an infinite query (defaults to false), and `optimisticUpdate` indicating if optimistic updates are enabled (defaults to true).\n * @returns Query key\n */\nexport function getQueryKey(\n model: string,\n urlOrOperation: string,\n args: unknown,\n options: { infinite: boolean; optimisticUpdate: boolean } = { infinite: false, optimisticUpdate: true }\n): QueryKey {\n if (!urlOrOperation) {\n throw new Error('Invalid urlOrOperation');\n }\n const operation = urlOrOperation.split('/').pop();\n\n const infinite = options.infinite;\n // infinite query doesn't support optimistic updates\n const optimisticUpdate = options.infinite ? false : options.optimisticUpdate;\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return [QUERY_KEY_PREFIX, model, operation!, args, { infinite, optimisticUpdate }];\n}\n\nexport function marshal(value: unknown) {\n const { data, meta } = serialize(value);\n if (meta) {\n return JSON.stringify({ ...(data as any), meta: { serialization: meta } });\n } else {\n return JSON.stringify(data);\n }\n}\n\nexport function unmarshal(value: string) {\n const parsed = JSON.parse(value);\n if (parsed.data && parsed.meta?.serialization) {\n const deserializedData = deserialize(parsed.data, parsed.meta.serialization);\n return { ...parsed, data: deserializedData };\n } else {\n return parsed;\n }\n}\n\nexport function makeUrl(url: string, args: unknown) {\n if (!args) {\n return url;\n }\n\n const { data, meta } = serialize(args);\n let result = `${url}?q=${encodeURIComponent(JSON.stringify(data))}`;\n if (meta) {\n result += `&meta=${encodeURIComponent(JSON.stringify({ serialization: meta }))}`;\n }\n return result;\n}\n\ntype InvalidationPredicate = ({ queryKey }: { queryKey: readonly unknown[] }) => boolean;\ntype InvalidateFunc = (predicate: InvalidationPredicate) => Promise<void>;\ntype MutationOptions = {\n onMutate?: (...args: any[]) => any;\n onSuccess?: (...args: any[]) => any;\n onSettled?: (...args: any[]) => any;\n};\n\n// sets up invalidation hook for a mutation\nexport function setupInvalidation(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: MutationOptions,\n invalidate: InvalidateFunc,\n logging = false\n) {\n const origOnSuccess = options?.onSuccess;\n options.onSuccess = async (...args: unknown[]) => {\n const [_, variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n return origOnSuccess?.(...args);\n };\n}\n\n// gets a predicate for evaluating whether a query should be invalidated\nasync function getInvalidationPredicate(\n model: string,\n operation: PrismaWriteActionType,\n mutationArgs: any,\n modelMeta: ModelMeta,\n logging = false\n) {\n const mutatedModels = await getMutatedModels(model, operation, mutationArgs, modelMeta);\n\n return ({ queryKey }: { queryKey: readonly unknown[] }) => {\n const [_, queryModel, , args] = queryKey as QueryKey;\n\n if (mutatedModels.includes(queryModel)) {\n // direct match\n if (logging) {\n console.log(`Invalidating query ${JSON.stringify(queryKey)} due to mutation \"${model}.${operation}\"`);\n }\n return true;\n }\n\n if (args) {\n // traverse query args to find nested reads that match the model under mutation\n if (findNestedRead(queryModel, mutatedModels, modelMeta, args)) {\n if (logging) {\n console.log(\n `Invalidating query ${JSON.stringify(queryKey)} due to mutation \"${model}.${operation}\"`\n );\n }\n return true;\n }\n }\n\n return false;\n };\n}\n\n// find nested reads that match the given models\nfunction findNestedRead(visitingModel: string, targetModels: string[], modelMeta: ModelMeta, args: any) {\n const modelsRead = getReadModels(visitingModel, modelMeta, args);\n return targetModels.some((m) => modelsRead.includes(m));\n}\n\ntype QueryCache = {\n queryKey: readonly unknown[];\n state: {\n data: unknown;\n error: unknown;\n };\n}[];\n\ntype SetCacheFunc = (queryKey: readonly unknown[], data: unknown) => void;\n\n/**\n * Sets up optimistic update and invalidation (after settled) for a mutation.\n */\nexport function setupOptimisticUpdate(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: MutationOptions & ExtraMutationOptions,\n queryCache: QueryCache,\n setCache: SetCacheFunc,\n invalidate?: InvalidateFunc,\n logging = false\n) {\n const origOnMutate = options?.onMutate;\n const origOnSettled = options?.onSettled;\n\n // optimistic update on mutate\n options.onMutate = async (...args: unknown[]) => {\n const [variables] = args;\n await optimisticUpdate(\n model,\n operation as PrismaWriteActionType,\n variables,\n options,\n modelMeta,\n queryCache,\n setCache,\n logging\n );\n return origOnMutate?.(...args);\n };\n\n // invalidate on settled\n options.onSettled = async (...args: unknown[]) => {\n if (invalidate) {\n const [, , variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n }\n return origOnSettled?.(...args);\n };\n}\n\n// optimistically updates query cache\nasync function optimisticUpdate(\n mutationModel: string,\n mutationOp: string,\n mutationArgs: any,\n options: MutationOptions & ExtraMutationOptions,\n modelMeta: ModelMeta,\n queryCache: QueryCache,\n setCache: SetCacheFunc,\n logging = false\n) {\n for (const cacheItem of queryCache) {\n const {\n queryKey,\n state: { data, error },\n } = cacheItem;\n\n if (error) {\n if (logging) {\n console.warn(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to error:`, error);\n }\n continue;\n }\n\n const [_, queryModel, queryOperation, queryArgs, { optimisticUpdate }] = queryKey as QueryKey;\n if (!optimisticUpdate) {\n if (logging) {\n console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to opt-out`);\n }\n continue;\n }\n\n if (options.optimisticDataProvider) {\n const providerResult = await options.optimisticDataProvider({\n queryModel,\n queryOperation,\n queryArgs,\n currentData: data,\n mutationArgs,\n });\n\n if (providerResult?.kind === 'Skip') {\n // skip\n if (logging) {\n console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to provider`);\n }\n continue;\n } else if (providerResult?.kind === 'Update') {\n // update cache\n if (logging) {\n console.log(`Optimistically updating query ${JSON.stringify(queryKey)} due to provider`);\n }\n setCache(queryKey, providerResult.data);\n continue;\n }\n }\n\n // proceed with default optimistic update\n const mutatedData = await applyMutation(\n queryModel,\n queryOperation,\n data,\n mutationModel,\n mutationOp as PrismaWriteActionType,\n mutationArgs,\n modelMeta,\n logging\n );\n\n if (mutatedData !== undefined) {\n // mutation applicable to this query, update cache\n if (logging) {\n console.log(\n `Optimistically updating query ${JSON.stringify(\n queryKey\n )} due to mutation \"${mutationModel}.${mutationOp}\"`\n );\n }\n setCache(queryKey, mutatedData);\n }\n }\n}\n"],"mappings":"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","names":["fetch","optimisticUpdate","fetch","optimisticUpdate"]}
@@ -94,11 +94,13 @@ function fetcher(url, options, fetch2, checkReadBack) {
94
94
  }
95
95
  });
96
96
  }
97
- function getQueryKey(model, urlOrOperation, args, infinite = false, optimisticUpdate2 = false) {
97
+ function getQueryKey(model, urlOrOperation, args, options = { infinite: false, optimisticUpdate: true }) {
98
98
  if (!urlOrOperation) {
99
99
  throw new Error("Invalid urlOrOperation");
100
100
  }
101
101
  const operation = urlOrOperation.split("/").pop();
102
+ const infinite = options.infinite;
103
+ const optimisticUpdate2 = options.infinite ? false : options.optimisticUpdate;
102
104
  return [QUERY_KEY_PREFIX, model, operation, args, { infinite, optimisticUpdate: optimisticUpdate2 }];
103
105
  }
104
106
  function marshal(value) {
@@ -183,6 +185,7 @@ function setupOptimisticUpdate(model, operation, modelMeta, options, queryCache,
183
185
  model,
184
186
  operation,
185
187
  variables,
188
+ options,
186
189
  modelMeta,
187
190
  queryCache,
188
191
  setCache,
@@ -205,7 +208,7 @@ function setupOptimisticUpdate(model, operation, modelMeta, options, queryCache,
205
208
  return origOnSettled == null ? void 0 : origOnSettled(...args);
206
209
  });
207
210
  }
208
- function optimisticUpdate(mutationModel, mutationOp, mutationArgs, modelMeta, queryCache, setCache, logging = false) {
211
+ function optimisticUpdate(mutationModel, mutationOp, mutationArgs, options, modelMeta, queryCache, setCache, logging = false) {
209
212
  return __async(this, null, function* () {
210
213
  for (const cacheItem of queryCache) {
211
214
  const {
@@ -218,16 +221,37 @@ function optimisticUpdate(mutationModel, mutationOp, mutationArgs, modelMeta, qu
218
221
  }
219
222
  continue;
220
223
  }
221
- const [_, queryModel, queryOp, _queryArgs, { optimisticUpdate: optimisticUpdate2 }] = queryKey;
224
+ const [_, queryModel, queryOperation, queryArgs, { optimisticUpdate: optimisticUpdate2 }] = queryKey;
222
225
  if (!optimisticUpdate2) {
223
226
  if (logging) {
224
227
  console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to opt-out`);
225
228
  }
226
229
  continue;
227
230
  }
231
+ if (options.optimisticDataProvider) {
232
+ const providerResult = yield options.optimisticDataProvider({
233
+ queryModel,
234
+ queryOperation,
235
+ queryArgs,
236
+ currentData: data,
237
+ mutationArgs
238
+ });
239
+ if ((providerResult == null ? void 0 : providerResult.kind) === "Skip") {
240
+ if (logging) {
241
+ console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to provider`);
242
+ }
243
+ continue;
244
+ } else if ((providerResult == null ? void 0 : providerResult.kind) === "Update") {
245
+ if (logging) {
246
+ console.log(`Optimistically updating query ${JSON.stringify(queryKey)} due to provider`);
247
+ }
248
+ setCache(queryKey, providerResult.data);
249
+ continue;
250
+ }
251
+ }
228
252
  const mutatedData = yield applyMutation(
229
253
  queryModel,
230
- queryOp,
254
+ queryOperation,
231
255
  data,
232
256
  mutationModel,
233
257
  mutationOp,
@@ -258,9 +282,12 @@ function getHooksContext() {
258
282
  const _a = getContext(SvelteQueryContextKey), { endpoint } = _a, rest = __objRest(_a, ["endpoint"]);
259
283
  return __spreadValues({ endpoint: endpoint != null ? endpoint : DEFAULT_QUERY_ENDPOINT }, rest);
260
284
  }
261
- function useModelQuery(model, url, args, options, fetch2, optimisticUpdate2 = false) {
285
+ function useModelQuery(model, url, args, options, fetch2) {
262
286
  const reqUrl = makeUrl(url, args);
263
- const queryKey = getQueryKey(model, url, args, false, optimisticUpdate2);
287
+ const queryKey = getQueryKey(model, url, args, {
288
+ infinite: false,
289
+ optimisticUpdate: (options == null ? void 0 : options.optimisticUpdate) !== false
290
+ });
264
291
  const queryFn = () => fetcher(reqUrl, void 0, fetch2, false);
265
292
  let mergedOpt;
266
293
  if (isStore(options)) {
@@ -279,7 +306,7 @@ function useModelQuery(model, url, args, options, fetch2, optimisticUpdate2 = fa
279
306
  return createQuery(mergedOpt);
280
307
  }
281
308
  function useInfiniteModelQuery(model, url, args, options, fetch2) {
282
- const queryKey = getQueryKey(model, url, args, true);
309
+ const queryKey = getQueryKey(model, url, args, { infinite: true, optimisticUpdate: false });
283
310
  const queryFn = ({ pageParam }) => fetcher(makeUrl(url, pageParam != null ? pageParam : args), void 0, fetch2, false);
284
311
  let mergedOpt;
285
312
  if (isStore(options)) {
@@ -300,7 +327,7 @@ function useInfiniteModelQuery(model, url, args, options, fetch2) {
300
327
  function isStore(opt) {
301
328
  return typeof (opt == null ? void 0 : opt.subscribe) === "function";
302
329
  }
303
- function useModelMutation(model, method, url, modelMeta, options, fetch2, invalidateQueries = true, checkReadBack, optimisticUpdate2 = false) {
330
+ function useModelMutation(model, method, url, modelMeta, options, fetch2, checkReadBack) {
304
331
  const queryClient = useQueryClient();
305
332
  const mutationFn = (data) => {
306
333
  const reqUrl = method === "DELETE" ? makeUrl(url, data) : url;
@@ -316,6 +343,8 @@ function useModelMutation(model, method, url, modelMeta, options, fetch2, invali
316
343
  };
317
344
  const finalOptions = __spreadProps(__spreadValues({}, options), { mutationFn });
318
345
  const operation = url.split("/").pop();
346
+ const invalidateQueries = (options == null ? void 0 : options.invalidateQueries) !== false;
347
+ const optimisticUpdate2 = !!(options == null ? void 0 : options.optimisticUpdate);
319
348
  if (operation) {
320
349
  const { logging } = getContext(SvelteQueryContextKey);
321
350
  if (invalidateQueries) {