diff --git a/packages/plugins/tanstack-query/src/generator.ts b/packages/plugins/tanstack-query/src/generator.ts index 1b5e4178e..4c0ddee3c 100644 --- a/packages/plugins/tanstack-query/src/generator.ts +++ b/packages/plugins/tanstack-query/src/generator.ts @@ -62,7 +62,8 @@ function generateQueryHook( optionalInput: boolean, overrideReturnType?: string, overrideInputType?: string, - overrideTypeParameters?: string[] + overrideTypeParameters?: string[], + infinite = false ) { const capOperation = upperCaseFirst(operation); @@ -70,10 +71,10 @@ function generateQueryHook( const inputType = `Prisma.SelectSubset`; const returnType = overrideReturnType ?? (returnArray ? `Array>` : `Prisma.${model}GetPayload`); - const optionsType = makeQueryOptions(target, returnType); + const optionsType = makeQueryOptions(target, returnType, infinite); const func = sf.addFunction({ - name: `use${capOperation}${model}`, + name: `use${infinite ? 'Infinite' : ''}${capOperation}${model}`, typeParameters: overrideTypeParameters ?? [`T extends ${argsType}`], parameters: [ { @@ -90,7 +91,7 @@ function generateQueryHook( func.addStatements([ makeGetContext(target), - `return query<${returnType}>('${model}', \`\${endpoint}/${lowerCaseFirst( + `return ${infinite ? 'infiniteQuery' : 'query'}<${returnType}>('${model}', \`\${endpoint}/${lowerCaseFirst( model )}/${operation}\`, args, options, fetch);`, ]); @@ -248,7 +249,10 @@ function generateModelHooks( // findMany if (mapping.findMany) { + // regular findMany generateQueryHook(target, sf, model.name, 'findMany', true, true); + // infinite findMany + generateQueryHook(target, sf, model.name, 'findMany', true, true, undefined, undefined, undefined, true); } // findUnique @@ -431,14 +435,14 @@ function makeGetContext(target: TargetFramework) { function makeBaseImports(target: TargetFramework) { const shared = [ - `import { query, postMutation, putMutation, deleteMutation } from '@zenstackhq/tanstack-query/runtime/${target}';`, + `import { query, infiniteQuery, postMutation, putMutation, deleteMutation } from '@zenstackhq/tanstack-query/runtime/${target}';`, `import type { PickEnumerable, CheckSelect } from '@zenstackhq/tanstack-query/runtime';`, ]; switch (target) { case 'react': return [ `import { useContext } from 'react';`, - `import type { UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';`, + `import type { UseMutationOptions, UseQueryOptions, UseInfiniteQueryOptions } from '@tanstack/react-query';`, `import { RequestHandlerContext } from '@zenstackhq/tanstack-query/runtime/${target}';`, ...shared, ]; @@ -446,7 +450,7 @@ function makeBaseImports(target: TargetFramework) { return [ `import { getContext } from 'svelte';`, `import { derived } from 'svelte/store';`, - `import type { MutationOptions, QueryOptions } from '@tanstack/svelte-query';`, + `import type { MutationOptions, QueryOptions, CreateInfiniteQueryOptions } from '@tanstack/svelte-query';`, `import { SvelteQueryContextKey, type RequestHandlerContext } from '@zenstackhq/tanstack-query/runtime/${target}';`, ...shared, ]; @@ -455,12 +459,12 @@ function makeBaseImports(target: TargetFramework) { } } -function makeQueryOptions(target: string, returnType: string) { +function makeQueryOptions(target: string, returnType: string, infinite: boolean) { switch (target) { case 'react': - return `UseQueryOptions<${returnType}>`; + return `Use${infinite ? 'Infinite' : ''}QueryOptions<${returnType}>`; case 'svelte': - return `QueryOptions<${returnType}>`; + return `${infinite ? 'CreateInfinite' : ''}QueryOptions<${returnType}>`; default: throw new PluginError(name, `Unsupported target: ${target}`); } diff --git a/packages/plugins/tanstack-query/src/runtime/react.ts b/packages/plugins/tanstack-query/src/runtime/react.ts index cdbbe1b68..1eca9f045 100644 --- a/packages/plugins/tanstack-query/src/runtime/react.ts +++ b/packages/plugins/tanstack-query/src/runtime/react.ts @@ -1,10 +1,12 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { + useInfiniteQuery, useMutation, useQuery, useQueryClient, type MutateFunction, type QueryClient, + type UseInfiniteQueryOptions, type UseMutationOptions, type UseQueryOptions, } from '@tanstack/react-query'; @@ -41,7 +43,6 @@ export const Provider = RequestHandlerContext.Provider; * @param options The react-query options object * @returns useQuery hook */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any export function query(model: string, url: string, args?: unknown, options?: UseQueryOptions, fetch?: FetchFn) { const reqUrl = makeUrl(url, args); return useQuery({ @@ -51,6 +52,31 @@ export function query(model: string, url: string, args?: unknown, options?: U }); } +/** + * Creates a react-query infinite query. + * + * @param model The name of the model under query. + * @param url The request URL. + * @param args The initial request args object, URL-encoded and appended as "?q=" parameter + * @param options The react-query infinite query options object + * @returns useInfiniteQuery hook + */ +export function infiniteQuery( + model: string, + url: string, + args?: unknown, + options?: UseInfiniteQueryOptions, + fetch?: FetchFn +) { + return useInfiniteQuery({ + queryKey: [QUERY_KEY_PREFIX + model, url, args], + queryFn: ({ pageParam }) => { + return fetcher(makeUrl(url, pageParam ?? args), undefined, fetch, false); + }, + ...options, + }); +} + /** * Creates a POST mutation with react-query. * diff --git a/packages/plugins/tanstack-query/src/runtime/svelte.ts b/packages/plugins/tanstack-query/src/runtime/svelte.ts index 7edab8edc..3b888e87e 100644 --- a/packages/plugins/tanstack-query/src/runtime/svelte.ts +++ b/packages/plugins/tanstack-query/src/runtime/svelte.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { + createInfiniteQuery, createMutation, createQuery, useQueryClient, + type CreateInfiniteQueryOptions, type MutateFunction, type MutationOptions, type QueryClient, @@ -26,7 +28,6 @@ export const SvelteQueryContextKey = 'zenstack-svelte-query-context'; * @param options The svelte-query options object * @returns useQuery hook */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any export function query(model: string, url: string, args?: unknown, options?: QueryOptions, fetch?: FetchFn) { const reqUrl = makeUrl(url, args); return createQuery({ @@ -36,6 +37,29 @@ export function query(model: string, url: string, args?: unknown, options?: Q }); } +/** + * Creates a svelte-query infinite query. + * + * @param model The name of the model under query. + * @param url The request URL. + * @param args The initial request args object, URL-encoded and appended as "?q=" parameter + * @param options The svelte-query infinite query options object + * @returns useQuery hook + */ +export function infiniteQuery( + model: string, + url: string, + args?: unknown, + options?: CreateInfiniteQueryOptions, + fetch?: FetchFn +) { + return createInfiniteQuery({ + queryKey: [QUERY_KEY_PREFIX + model, url, args], + queryFn: ({ pageParam }) => fetcher(makeUrl(url, pageParam ?? args), undefined, fetch, false), + ...options, + }); +} + /** * Creates a POST mutation with svelte-query. *