From abcbe83f9afba1fe8d69c851305fc17a9f0256de Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 28 Sep 2023 12:31:28 +0800 Subject: [PATCH 01/43] refactor: formatQueryParameters --- .vscode/settings.json | 5 ++++- .../react-query/src/fetcher-custom-mapper.ts | 9 ++++++--- .../src/fetcher-fetch-hardcoded.ts | 9 ++++++--- .../react-query/src/fetcher-fetch.ts | 9 ++++++--- .../src/fetcher-graphql-request.ts | 17 ++++++++++------ .../react-query/src/variables-generator.ts | 20 +++++++++++++++++++ 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9c22884fe..2148080f8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -19,5 +19,8 @@ }, "typescript.tsdk": "node_modules/typescript/lib", "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } } diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 20767012a..a0a16aaaa 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -7,6 +7,7 @@ import { import { CustomFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + formatQueryParameters, generateInfiniteQueryKey, generateMutationKey, generateQueryKey, @@ -114,9 +115,11 @@ export class CustomMapperFetcher implements FetcherRenderer { ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryKey(node, hasRequiredVariables)}, - ${impl}, - options + ${formatQueryParameters({ + reactQueryVersion: 4, + queryKey: generateQueryKey(node, hasRequiredVariables), + queryFn: impl, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index af9948f00..4f6a27bed 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -2,6 +2,7 @@ import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + formatQueryParameters, generateInfiniteQueryKey, generateMutationKey, generateQueryKey, @@ -117,9 +118,11 @@ ${this.getFetchParams()} ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryKey(node, hasRequiredVariables)}, - fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables), - options + ${formatQueryParameters({ + reactQueryVersion: 4, + queryKey: generateQueryKey(node, hasRequiredVariables), + queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)`, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index ca1d49afc..731cff722 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,6 +1,7 @@ import { OperationDefinitionNode } from 'graphql'; import { FetcherRenderer } from './fetcher.js'; import { + formatQueryParameters, generateInfiniteQueryKey, generateMutationKey, generateQueryKey, @@ -94,9 +95,11 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryKey(node, hasRequiredVariables)}, - fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables), - options + ${formatQueryParameters({ + reactQueryVersion: 4, + queryKey: generateQueryKey(node, hasRequiredVariables), + queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 0e4c8e1db..c8d09e86b 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -2,6 +2,7 @@ import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + formatQueryParameters, generateInfiniteQueryKey, generateMutationKey, generateQueryKey, @@ -126,9 +127,11 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryKey(node, hasRequiredVariables)}, - fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers), - options + ${formatQueryParameters({ + reactQueryVersion: 4, + queryKey: generateQueryKey(node, hasRequiredVariables), + queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, + })} );` : `export const use${operationName} = < TData = ${operationResultType}, @@ -140,9 +143,11 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryKey(node, hasRequiredVariables)}, - fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers), - options + ${formatQueryParameters({ + reactQueryVersion: 4, + queryKey: generateQueryKey(node, hasRequiredVariables), + queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/variables-generator.ts b/packages/plugins/typescript/react-query/src/variables-generator.ts index bb4b0f6f4..cf4b09fc2 100644 --- a/packages/plugins/typescript/react-query/src/variables-generator.ts +++ b/packages/plugins/typescript/react-query/src/variables-generator.ts @@ -6,6 +6,26 @@ export function generateQueryVariablesSignature( ): string { return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; } + +interface FormatQueryParametersPayload { + reactQueryVersion: number; + queryKey: string; + queryFn: string; +} +export function formatQueryParameters(payload: FormatQueryParametersPayload): string { + const { reactQueryVersion, queryKey, queryFn } = payload; + if (reactQueryVersion <= 4) { + return `${queryKey}, + ${queryFn}, + options`; + } + return `{ + queryKey:${queryKey}, + queryFn:${queryFn}, + ...options + }`; +} + export function generateInfiniteQueryKey( node: OperationDefinitionNode, hasRequiredVariables: boolean, From 983183bb729bd545835f11d3ec9b1fea60a1d571 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 28 Sep 2023 12:34:27 +0800 Subject: [PATCH 02/43] refactor: rename --- .../typescript/react-query/src/fetcher-custom-mapper.ts | 4 ++-- .../typescript/react-query/src/fetcher-fetch-hardcoded.ts | 4 ++-- .../plugins/typescript/react-query/src/fetcher-fetch.ts | 4 ++-- .../typescript/react-query/src/fetcher-graphql-request.ts | 6 +++--- .../typescript/react-query/src/variables-generator.ts | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index a0a16aaaa..d804b07db 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -7,7 +7,7 @@ import { import { CustomFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { - formatQueryParameters, + generateFormattedQueryParameters, generateInfiniteQueryKey, generateMutationKey, generateQueryKey, @@ -115,7 +115,7 @@ export class CustomMapperFetcher implements FetcherRenderer { ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${formatQueryParameters({ + ${generateFormattedQueryParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: impl, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 4f6a27bed..95119bdcd 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -2,7 +2,7 @@ import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { - formatQueryParameters, + generateFormattedQueryParameters, generateInfiniteQueryKey, generateMutationKey, generateQueryKey, @@ -118,7 +118,7 @@ ${this.getFetchParams()} ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${formatQueryParameters({ + ${generateFormattedQueryParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)`, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 731cff722..eafd3bf0e 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,7 +1,7 @@ import { OperationDefinitionNode } from 'graphql'; import { FetcherRenderer } from './fetcher.js'; import { - formatQueryParameters, + generateFormattedQueryParameters, generateInfiniteQueryKey, generateMutationKey, generateQueryKey, @@ -95,7 +95,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${formatQueryParameters({ + ${generateFormattedQueryParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index c8d09e86b..d9e505794 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -2,7 +2,7 @@ import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { - formatQueryParameters, + generateFormattedQueryParameters, generateInfiniteQueryKey, generateMutationKey, generateQueryKey, @@ -127,7 +127,7 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${formatQueryParameters({ + ${generateFormattedQueryParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, @@ -143,7 +143,7 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${formatQueryParameters({ + ${generateFormattedQueryParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, diff --git a/packages/plugins/typescript/react-query/src/variables-generator.ts b/packages/plugins/typescript/react-query/src/variables-generator.ts index cf4b09fc2..b837c0f56 100644 --- a/packages/plugins/typescript/react-query/src/variables-generator.ts +++ b/packages/plugins/typescript/react-query/src/variables-generator.ts @@ -12,7 +12,7 @@ interface FormatQueryParametersPayload { queryKey: string; queryFn: string; } -export function formatQueryParameters(payload: FormatQueryParametersPayload): string { +export function generateFormattedQueryParameters(payload: FormatQueryParametersPayload): string { const { reactQueryVersion, queryKey, queryFn } = payload; if (reactQueryVersion <= 4) { return `${queryKey}, From 63946dc5daeb1f529fa604a61960d46307bab0e2 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 28 Sep 2023 12:53:53 +0800 Subject: [PATCH 03/43] refactor: generateFormattedMutationParameters --- .../react-query/src/fetcher-custom-mapper.ts | 9 ++- .../src/fetcher-fetch-hardcoded.ts | 9 ++- .../react-query/src/fetcher-fetch.ts | 9 ++- .../src/fetcher-graphql-request.ts | 17 ++++-- .../react-query/src/variables-generator.ts | 61 +++++++++++++------ 5 files changed, 71 insertions(+), 34 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index d804b07db..c9ea15f1b 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -7,6 +7,7 @@ import { import { CustomFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + generateFormattedMutationParameters, generateFormattedQueryParameters, generateInfiniteQueryKey, generateMutationKey, @@ -149,9 +150,11 @@ export class CustomMapperFetcher implements FetcherRenderer { ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationKey(node)}, - ${impl}, - options + ${generateFormattedMutationParameters({ + reactQueryVersion: 4, + mutationKey: generateMutationKey(node), + mutationFn: impl, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 95119bdcd..955c3418b 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -2,6 +2,7 @@ import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + generateFormattedMutationParameters, generateFormattedQueryParameters, generateInfiniteQueryKey, generateMutationKey, @@ -148,9 +149,11 @@ ${this.getFetchParams()} ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationKey(node)}, - (${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)(), - options + ${generateFormattedMutationParameters({ + reactQueryVersion: 4, + mutationKey: generateMutationKey(node), + mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)()`, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index eafd3bf0e..85570039d 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,6 +1,7 @@ import { OperationDefinitionNode } from 'graphql'; import { FetcherRenderer } from './fetcher.js'; import { + generateFormattedMutationParameters, generateFormattedQueryParameters, generateInfiniteQueryKey, generateMutationKey, @@ -128,9 +129,11 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationKey(node)}, - (${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)(), - options + ${generateFormattedMutationParameters({ + reactQueryVersion: 4, + mutationKey: generateMutationKey(node), + mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)()`, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index d9e505794..469feb5fb 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -2,6 +2,7 @@ import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + generateFormattedMutationParameters, generateFormattedQueryParameters, generateInfiniteQueryKey, generateMutationKey, @@ -181,9 +182,11 @@ function fetcher(client: Graph ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationKey(node)}, - (${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)(), - options + ${generateFormattedMutationParameters({ + reactQueryVersion: 4, + mutationKey: generateMutationKey(node), + mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)()`, + })} );` : `export const use${operationName} = < TError = ${this.visitor.config.errorType}, @@ -196,9 +199,11 @@ function fetcher(client: Graph ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationKey(node)}, - (${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)(), - options + ${generateFormattedMutationParameters({ + reactQueryVersion: 4, + mutationKey: generateMutationKey(node), + mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)()`, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/variables-generator.ts b/packages/plugins/typescript/react-query/src/variables-generator.ts index b837c0f56..53457d757 100644 --- a/packages/plugins/typescript/react-query/src/variables-generator.ts +++ b/packages/plugins/typescript/react-query/src/variables-generator.ts @@ -7,25 +7,6 @@ export function generateQueryVariablesSignature( return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; } -interface FormatQueryParametersPayload { - reactQueryVersion: number; - queryKey: string; - queryFn: string; -} -export function generateFormattedQueryParameters(payload: FormatQueryParametersPayload): string { - const { reactQueryVersion, queryKey, queryFn } = payload; - if (reactQueryVersion <= 4) { - return `${queryKey}, - ${queryFn}, - options`; - } - return `{ - queryKey:${queryKey}, - queryFn:${queryFn}, - ...options - }`; -} - export function generateInfiniteQueryKey( node: OperationDefinitionNode, hasRequiredVariables: boolean, @@ -86,3 +67,45 @@ export function generateMutationKey(node: OperationDefinitionNode): string { export function generateMutationKeyMaker(node: OperationDefinitionNode, operationName: string) { return `\nuse${operationName}.getKey = () => ${generateMutationKey(node)};\n`; } + +interface GenerateFormattedQueryParametersPayload { + reactQueryVersion: number; + queryKey: string; + queryFn: string; +} +export function generateFormattedQueryParameters( + payload: GenerateFormattedQueryParametersPayload, +): string { + const { reactQueryVersion, queryKey, queryFn } = payload; + if (reactQueryVersion <= 4) { + return `${queryKey}, + ${queryFn}, + options`; + } + return `{ + queryKey:${queryKey}, + queryFn:${queryFn}, + ...options + }`; +} + +interface GenerateFormattedMutationParametersPayload { + reactQueryVersion: number; + mutationKey: string; + mutationFn: string; +} +export function generateFormattedMutationParameters( + payload: GenerateFormattedMutationParametersPayload, +): string { + const { reactQueryVersion, mutationKey, mutationFn } = payload; + if (reactQueryVersion <= 4) { + return `${mutationKey}, + ${mutationFn}, + options`; + } + return `{ + mutationKey:${mutationKey}, + mutationFn:${mutationFn}, + ...options + }`; +} From 33b5fe0027df897ff4149725866a852595a78148 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 28 Sep 2023 13:07:23 +0800 Subject: [PATCH 04/43] refactor: rename --- .../react-query/src/fetcher-custom-mapper.ts | 8 ++--- .../src/fetcher-fetch-hardcoded.ts | 8 ++--- .../react-query/src/fetcher-fetch.ts | 8 ++--- .../src/fetcher-graphql-request.ts | 12 +++---- .../react-query/src/variables-generator.ts | 33 +++++++++++++++---- 5 files changed, 45 insertions(+), 24 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index c9ea15f1b..f9e05b494 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -7,10 +7,10 @@ import { import { CustomFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { - generateFormattedMutationParameters, - generateFormattedQueryParameters, generateInfiniteQueryKey, + generateMutationFormattedParameters, generateMutationKey, + generateQueryFormattedParameters, generateQueryKey, } from './variables-generator.js'; import { ReactQueryVisitor } from './visitor.js'; @@ -116,7 +116,7 @@ export class CustomMapperFetcher implements FetcherRenderer { ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateFormattedQueryParameters({ + ${generateQueryFormattedParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: impl, @@ -150,7 +150,7 @@ export class CustomMapperFetcher implements FetcherRenderer { ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateFormattedMutationParameters({ + ${generateMutationFormattedParameters({ reactQueryVersion: 4, mutationKey: generateMutationKey(node), mutationFn: impl, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 955c3418b..7217a6802 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -2,10 +2,10 @@ import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { - generateFormattedMutationParameters, - generateFormattedQueryParameters, generateInfiniteQueryKey, + generateMutationFormattedParameters, generateMutationKey, + generateQueryFormattedParameters, generateQueryKey, generateQueryVariablesSignature, } from './variables-generator.js'; @@ -119,7 +119,7 @@ ${this.getFetchParams()} ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateFormattedQueryParameters({ + ${generateQueryFormattedParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)`, @@ -149,7 +149,7 @@ ${this.getFetchParams()} ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateFormattedMutationParameters({ + ${generateMutationFormattedParameters({ reactQueryVersion: 4, mutationKey: generateMutationKey(node), mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)()`, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 85570039d..ce443c498 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,10 +1,10 @@ import { OperationDefinitionNode } from 'graphql'; import { FetcherRenderer } from './fetcher.js'; import { - generateFormattedMutationParameters, - generateFormattedQueryParameters, generateInfiniteQueryKey, + generateMutationFormattedParameters, generateMutationKey, + generateQueryFormattedParameters, generateQueryKey, generateQueryVariablesSignature, } from './variables-generator.js'; @@ -96,7 +96,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateFormattedQueryParameters({ + ${generateQueryFormattedParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, @@ -129,7 +129,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateFormattedMutationParameters({ + ${generateMutationFormattedParameters({ reactQueryVersion: 4, mutationKey: generateMutationKey(node), mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)()`, diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 469feb5fb..f1b5b1398 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -2,10 +2,10 @@ import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { - generateFormattedMutationParameters, - generateFormattedQueryParameters, generateInfiniteQueryKey, + generateMutationFormattedParameters, generateMutationKey, + generateQueryFormattedParameters, generateQueryKey, generateQueryVariablesSignature, } from './variables-generator.js'; @@ -128,7 +128,7 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateFormattedQueryParameters({ + ${generateQueryFormattedParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, @@ -144,7 +144,7 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateFormattedQueryParameters({ + ${generateQueryFormattedParameters({ reactQueryVersion: 4, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, @@ -182,7 +182,7 @@ function fetcher(client: Graph ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateFormattedMutationParameters({ + ${generateMutationFormattedParameters({ reactQueryVersion: 4, mutationKey: generateMutationKey(node), mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)()`, @@ -199,7 +199,7 @@ function fetcher(client: Graph ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateFormattedMutationParameters({ + ${generateMutationFormattedParameters({ reactQueryVersion: 4, mutationKey: generateMutationKey(node), mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)()`, diff --git a/packages/plugins/typescript/react-query/src/variables-generator.ts b/packages/plugins/typescript/react-query/src/variables-generator.ts index 53457d757..1bda6810e 100644 --- a/packages/plugins/typescript/react-query/src/variables-generator.ts +++ b/packages/plugins/typescript/react-query/src/variables-generator.ts @@ -68,13 +68,34 @@ export function generateMutationKeyMaker(node: OperationDefinitionNode, operatio return `\nuse${operationName}.getKey = () => ${generateMutationKey(node)};\n`; } -interface GenerateFormattedQueryParametersPayload { +interface GenerateInfiniteQueryFormattedParametersPayload { reactQueryVersion: number; queryKey: string; queryFn: string; } -export function generateFormattedQueryParameters( - payload: GenerateFormattedQueryParametersPayload, +export function generateInfiniteQueryFormattedParameters( + payload: GenerateInfiniteQueryFormattedParametersPayload, +) { + const { reactQueryVersion, queryKey, queryFn } = payload; + if (reactQueryVersion <= 4) { + return `${queryKey}, + ${queryFn}, + options`; + } + return `{ + queryKey:${queryKey}, + queryFn:${queryFn}, + ...options + }`; +} + +interface GenerateQueryParametersFormattedPayload { + reactQueryVersion: number; + queryKey: string; + queryFn: string; +} +export function generateQueryFormattedParameters( + payload: GenerateQueryParametersFormattedPayload, ): string { const { reactQueryVersion, queryKey, queryFn } = payload; if (reactQueryVersion <= 4) { @@ -89,13 +110,13 @@ export function generateFormattedQueryParameters( }`; } -interface GenerateFormattedMutationParametersPayload { +interface GenerateMutationFormattedParametersPayload { reactQueryVersion: number; mutationKey: string; mutationFn: string; } -export function generateFormattedMutationParameters( - payload: GenerateFormattedMutationParametersPayload, +export function generateMutationFormattedParameters( + payload: GenerateMutationFormattedParametersPayload, ): string { const { reactQueryVersion, mutationKey, mutationFn } = payload; if (reactQueryVersion <= 4) { From a44e46bb5720f148dfbadc33ff96cbb191427486 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 28 Sep 2023 13:19:46 +0800 Subject: [PATCH 05/43] refactor: generateInfiniteQueryFormattedParameters --- .../react-query/src/fetcher-custom-mapper.ts | 9 ++++++--- .../react-query/src/fetcher-fetch-hardcoded.ts | 9 ++++++--- .../typescript/react-query/src/fetcher-fetch.ts | 9 ++++++--- .../react-query/src/fetcher-graphql-request.ts | 17 +++++++++++------ 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index f9e05b494..1c58bd78d 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -7,6 +7,7 @@ import { import { CustomFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + generateInfiniteQueryFormattedParameters, generateInfiniteQueryKey, generateMutationFormattedParameters, generateMutationKey, @@ -81,9 +82,11 @@ export class CustomMapperFetcher implements FetcherRenderer { ) =>{ ${implHookOuter} return ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryKey(node, hasRequiredVariables)}, - ${impl}, - options + ${generateInfiniteQueryFormattedParameters({ + reactQueryVersion: 4, + queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), + queryFn: impl, + })} )};`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 7217a6802..a6b847d06 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -2,6 +2,7 @@ import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + generateInfiniteQueryFormattedParameters, generateInfiniteQueryKey, generateMutationFormattedParameters, generateMutationKey, @@ -87,9 +88,11 @@ ${this.getFetchParams()} ${options} ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryKey(node, hasRequiredVariables)}, - (metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})(), - options + ${generateInfiniteQueryFormattedParameters({ + reactQueryVersion: 4, + queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), + queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index ce443c498..9e40b5c1f 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,6 +1,7 @@ import { OperationDefinitionNode } from 'graphql'; import { FetcherRenderer } from './fetcher.js'; import { + generateInfiniteQueryFormattedParameters, generateInfiniteQueryKey, generateMutationFormattedParameters, generateMutationKey, @@ -63,9 +64,11 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${options} ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryKey(node, hasRequiredVariables)}, - (metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})(), - options + ${generateInfiniteQueryFormattedParameters({ + reactQueryVersion: 4, + queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), + queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, + })} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index f1b5b1398..2249f9c1b 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -2,6 +2,7 @@ import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; import { FetcherRenderer } from './fetcher.js'; import { + generateInfiniteQueryFormattedParameters, generateInfiniteQueryKey, generateMutationFormattedParameters, generateMutationKey, @@ -72,9 +73,11 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryKey(node, hasRequiredVariables)}, - (metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})}, headers)(), - options + ${generateInfiniteQueryFormattedParameters({ + reactQueryVersion: 4, + queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), + queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, [pageParamKey]: metaData.pageParam}, headers)()`, + })} );` : `export const useInfinite${operationName} = < TData = ${operationResultType}, @@ -86,9 +89,11 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryKey(node, hasRequiredVariables)}, - (metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})}, headers)(), - options + ${generateInfiniteQueryFormattedParameters({ + reactQueryVersion: 4, + queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), + queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})}, headers)()`, + })} );`; } From 6e2c03c6a7b79f5c5d7f09f72aa913795b3f838c Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 28 Sep 2023 13:50:36 +0800 Subject: [PATCH 06/43] feat: plugin config for support v5 --- .../typescript/react-query/src/config.ts | 6 ++ .../react-query/src/fetcher-custom-mapper.ts | 6 +- .../src/fetcher-fetch-hardcoded.ts | 6 +- .../react-query/src/fetcher-fetch.ts | 6 +- .../src/fetcher-graphql-request.ts | 12 ++-- .../typescript/react-query/src/visitor.ts | 7 ++ .../react-query/tests/react-query.spec.ts | 71 +++++++++++++++++++ 7 files changed, 99 insertions(+), 15 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/config.ts b/packages/plugins/typescript/react-query/src/config.ts index 63fe5f768..3f86be4cf 100644 --- a/packages/plugins/typescript/react-query/src/config.ts +++ b/packages/plugins/typescript/react-query/src/config.ts @@ -115,6 +115,12 @@ export interface ReactQueryRawPluginConfig */ legacyMode?: boolean; + /** + * @default 4 + * @description The version of react-query to use. Default is 4. legacyMode must be false to active this flag. + */ + reactQueryVersion?: 4 | 5; + /** * @default empty * @description Add custom import for react-query. diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 1c58bd78d..65f8c7156 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -83,7 +83,7 @@ export class CustomMapperFetcher implements FetcherRenderer { ${implHookOuter} return ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), queryFn: impl, })} @@ -120,7 +120,7 @@ export class CustomMapperFetcher implements FetcherRenderer { ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( ${generateQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: impl, })} @@ -154,7 +154,7 @@ export class CustomMapperFetcher implements FetcherRenderer { hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( ${generateMutationFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, mutationKey: generateMutationKey(node), mutationFn: impl, })} diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index a6b847d06..8f508d785 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -89,7 +89,7 @@ ${this.getFetchParams()} ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, })} @@ -123,7 +123,7 @@ ${this.getFetchParams()} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( ${generateQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)`, })} @@ -153,7 +153,7 @@ ${this.getFetchParams()} hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( ${generateMutationFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, mutationKey: generateMutationKey(node), mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)()`, })} diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 9e40b5c1f..3a6b4e3e7 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -65,7 +65,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, })} @@ -100,7 +100,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( ${generateQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, })} @@ -133,7 +133,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( ${generateMutationFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, mutationKey: generateMutationKey(node), mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)()`, })} diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 2249f9c1b..0f0623139 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -74,7 +74,7 @@ function fetcher(client: Graph ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, [pageParamKey]: metaData.pageParam}, headers)()`, })} @@ -90,7 +90,7 @@ function fetcher(client: Graph ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})}, headers)()`, })} @@ -134,7 +134,7 @@ function fetcher(client: Graph ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( ${generateQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, })} @@ -150,7 +150,7 @@ function fetcher(client: Graph ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( ${generateQueryFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, queryKey: generateQueryKey(node, hasRequiredVariables), queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, })} @@ -188,7 +188,7 @@ function fetcher(client: Graph hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( ${generateMutationFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, mutationKey: generateMutationKey(node), mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)()`, })} @@ -205,7 +205,7 @@ function fetcher(client: Graph hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( ${generateMutationFormattedParameters({ - reactQueryVersion: 4, + reactQueryVersion: this.visitor.config.reactQueryVersion, mutationKey: generateMutationKey(node), mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)()`, })} diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index 544aa5872..6966a229e 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -32,6 +32,7 @@ export interface ReactQueryPluginConfig extends ClientSideBasePluginConfig { exposeFetcher: boolean; addInfiniteQuery: boolean; legacyMode: boolean; + reactQueryVersion: 4 | 5; reactQueryImportFrom?: string; } @@ -90,8 +91,14 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< exposeFetcher: getConfigValue(rawConfig.exposeFetcher, false), addInfiniteQuery: getConfigValue(rawConfig.addInfiniteQuery, false), legacyMode: getConfigValue(rawConfig.legacyMode, false), + reactQueryVersion: getConfigValue(rawConfig.reactQueryVersion, 4), reactQueryImportFrom: getConfigValue(rawConfig.reactQueryImportFrom, ''), }); + + if (super.config.legacyMode && super.config.reactQueryVersion > 4) { + throw new Error('reactQueryVersion cannot more than 4 when legacyMode is true'); + } + this._externalImportPrefix = this.config.importOperationTypesFrom ? `${this.config.importOperationTypesFrom}.` : ''; diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index 6f8eeebb1..aa321107c 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -3,6 +3,7 @@ import { mergeOutputs, Types } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; import { plugin as tsPlugin } from '@graphql-codegen/typescript'; import { plugin as tsDocumentsPlugin } from '@graphql-codegen/typescript-operations'; +import type { ReactQueryRawPluginConfig } from '../src/config'; import { plugin } from '../src/index.js'; const validateTypeScript = async ( @@ -117,6 +118,76 @@ export const useTestMutation = < options );`); }); + + it('should throw when using v5 config with legacyMode', async () => { + const config: ReactQueryRawPluginConfig = { + legacyMode: true, + reactQueryVersion: 5, + addInfiniteQuery: true, + }; + try { + plugin(schema, docs, config); + } catch (e) { + expect(e.message).toBe('reactQueryVersion cannot more than 4 when legacyMode is true'); + } + }); + + it('support v5 syntax', async () => { + const config: ReactQueryRawPluginConfig = { + addInfiniteQuery: true, + reactQueryVersion: 5, + }; + + const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; + + expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < + TData = TestQuery, + TError = unknown +>( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables?: TestQueryVariables, + options?: UseQueryOptions +) => +useQuery( + { + queryKey:variables === undefined ? ['test'] : ['test', variables], + queryFn:fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), + ...options + } +);`); + + expect(out.content).toBeSimilarStringTo(`export const useInfiniteTestQuery = < + TData = TestQuery, + TError = unknown +>( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables?: TestQueryVariables, + options?: UseInfiniteQueryOptions +) => +useInfiniteQuery( + { + queryKey:variables === undefined ? ['test.infinite'] : ['test.infinite', variables], + queryFn:(metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), + ...options + } +);`); + + expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < + TError = unknown, + TContext = unknown +>( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + options?: UseMutationOptions +) => +useMutation( + { + mutationKey:['test'], + mutationFn:(variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), + ...options + } +);`); + }); + it('Duplicated nested fragments are removed', async () => { const schema = buildSchema(/* GraphQL */ ` schema { From c1901359822bc8abaff521bcd83c066f8fa591c1 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Mon, 2 Oct 2023 12:00:55 +0800 Subject: [PATCH 07/43] fix: infiniteQuery option to required --- .../plugins/typescript/react-query/src/fetcher-custom-mapper.ts | 2 +- .../typescript/react-query/src/fetcher-fetch-hardcoded.ts | 2 +- packages/plugins/typescript/react-query/src/fetcher-fetch.ts | 2 +- .../typescript/react-query/src/fetcher-graphql-request.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 65f8c7156..1807edc20 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -63,7 +63,7 @@ export class CustomMapperFetcher implements FetcherRenderer { this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = `options: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); const implHookOuter = this._isReactHook diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 8f508d785..33bae369b 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -78,7 +78,7 @@ ${this.getFetchParams()} this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = `options: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; return `export const useInfinite${operationName} = < TData = ${operationResultType}, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 3a6b4e3e7..d1f07a191 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -53,7 +53,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = `options: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; return `export const useInfinite${operationName} = < TData = ${operationResultType}, diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 0f0623139..0f49ac51c 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -60,7 +60,7 @@ function fetcher(client: Graph this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = `options: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; return this.clientPath ? `export const useInfinite${operationName} = < From b1d99e09d0d2dc681895b99950a9590c68aa8d3f Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Mon, 2 Oct 2023 12:16:07 +0800 Subject: [PATCH 08/43] fix: infinite query type --- .../react-query/src/variables-generator.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/variables-generator.ts b/packages/plugins/typescript/react-query/src/variables-generator.ts index 1bda6810e..7a52b8dac 100644 --- a/packages/plugins/typescript/react-query/src/variables-generator.ts +++ b/packages/plugins/typescript/react-query/src/variables-generator.ts @@ -82,11 +82,14 @@ export function generateInfiniteQueryFormattedParameters( ${queryFn}, options`; } - return `{ - queryKey:${queryKey}, - queryFn:${queryFn}, - ...options - }`; + return `(() => { + const { queryKey: optionsQueryKey, ...restOptions } = options; + return { + queryKey: optionsQueryKey ?? ${queryKey}, + queryFn: ${queryFn}, + ...restOptions + } + })()`; } interface GenerateQueryParametersFormattedPayload { @@ -104,8 +107,8 @@ export function generateQueryFormattedParameters( options`; } return `{ - queryKey:${queryKey}, - queryFn:${queryFn}, + queryKey: ${queryKey}, + queryFn: ${queryFn}, ...options }`; } @@ -125,8 +128,8 @@ export function generateMutationFormattedParameters( options`; } return `{ - mutationKey:${mutationKey}, - mutationFn:${mutationFn}, + mutationKey: ${mutationKey}, + mutationFn: ${mutationFn}, ...options }`; } From 1d2687086a26e7faa1bfa1c2bfded63b2da1d430 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Mon, 2 Oct 2023 12:19:30 +0800 Subject: [PATCH 09/43] fix: Unnecessary semicolon --- packages/plugins/typescript/react-query/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugins/typescript/react-query/package.json b/packages/plugins/typescript/react-query/package.json index 389cd86cb..14b8fbcd3 100644 --- a/packages/plugins/typescript/react-query/package.json +++ b/packages/plugins/typescript/react-query/package.json @@ -1,6 +1,6 @@ { - "name": "@graphql-codegen/typescript-react-query", - "version": "5.0.0", + "name": "@neil585456525/typescript-react-query", + "version": "5.0.1", "type": "module", "description": "GraphQL Code Generator plugin for generating a ready-to-use React-Query Hooks based on GraphQL operations", "repository": { From d5fe04644fe7f283137ac501de716277b62154a2 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Mon, 2 Oct 2023 14:03:21 +0800 Subject: [PATCH 10/43] fix: test --- .../typescript/react-query/src/visitor.ts | 4 +- .../__snapshots__/react-query.spec.ts.snap | 6 +- .../react-query/tests/react-query.spec.ts | 83 ++++++++++--------- 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index 6966a229e..bcc101dff 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -207,7 +207,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< operationName, operationVariablesTypes, hasRequiredVariables, - )};\n`; + )}\n`; } if (this.config.exposeQueryRootKeys) { query += `\n${generateQueryRootKeyMaker(node, operationName)}`; @@ -227,7 +227,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< operationName, operationVariablesTypes, hasRequiredVariables, - )};\n`; + )}\n`; } if (this.config.exposeQueryRootKeys) { query += `\n${generateInfiniteQueryRootKeyMaker(node, operationName)}`; diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 88e2aed62..e0f3591d0 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -32,7 +32,7 @@ export const useTestQuery = < ); useTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test'] : ['test', variables]; -; + export const TestDocument = \` mutation test($name: String) { @@ -87,7 +87,7 @@ export const useTestQuery = < ); useTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test'] : ['test', variables]; -; + export const useInfiniteTestQuery = < TData = TestQuery, @@ -105,7 +105,7 @@ export const useInfiniteTestQuery = < useInfiniteTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test.infinite'] : ['test.infinite', variables]; -; + export const TestDocument = \` mutation test($name: String) { diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index aa321107c..9793d0315 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -141,51 +141,54 @@ export const useTestMutation = < const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TestQuery, - TError = unknown ->( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables?: TestQueryVariables, - options?: UseQueryOptions -) => -useQuery( - { - queryKey:variables === undefined ? ['test'] : ['test', variables], - queryFn:fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), - ...options - } -);`); + TData = TestQuery, + TError = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables?: TestQueryVariables, + options?: UseQueryOptions + ) => + useQuery( + { + queryKey: variables === undefined ? ['test'] : ['test', variables], + queryFn: fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), + ...options +} + );`); expect(out.content).toBeSimilarStringTo(`export const useInfiniteTestQuery = < - TData = TestQuery, - TError = unknown ->( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables?: TestQueryVariables, - options?: UseInfiniteQueryOptions -) => -useInfiniteQuery( - { - queryKey:variables === undefined ? ['test.infinite'] : ['test.infinite', variables], - queryFn:(metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), - ...options + TData = TestQuery, + TError = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables?: TestQueryVariables, + options?: UseInfiniteQueryOptions + ) => + useInfiniteQuery( + (() => { + const { queryKey: optionsQueryKey, ...restOptions } = options; + return { + queryKey: optionsQueryKey ?? variables === undefined ? ['test.infinite'] : ['test.infinite', variables], + queryFn: (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), + ...restOptions } -);`); +})() + );`); expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown ->( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - options?: UseMutationOptions -) => -useMutation( - { - mutationKey:['test'], - mutationFn:(variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), - ...options - } -);`); + TError = unknown, + TContext = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + options?: UseMutationOptions + ) => + useMutation( + { + mutationKey: ['test'], + mutationFn: (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), + ...options +} + );`); }); it('Duplicated nested fragments are removed', async () => { From ca36a52ca2f7c21eebf33b0bd8db0b85620f8e45 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Mon, 2 Oct 2023 14:34:27 +0800 Subject: [PATCH 11/43] refactor: use class inherent --- .../react-query/src/fetcher-custom-mapper.ts | 41 ++--- .../src/fetcher-fetch-hardcoded.ts | 52 +++---- .../react-query/src/fetcher-fetch.ts | 52 +++---- .../src/fetcher-graphql-request.ts | 78 ++++------ .../typescript/react-query/src/fetcher.ts | 141 ++++++++++++++++-- .../react-query/src/variables-generator.ts | 135 ----------------- .../typescript/react-query/src/visitor.ts | 17 +-- 7 files changed, 228 insertions(+), 288 deletions(-) delete mode 100644 packages/plugins/typescript/react-query/src/variables-generator.ts diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 1807edc20..910eac0e2 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -1,3 +1,4 @@ +import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { buildMapperImport, @@ -6,26 +7,20 @@ import { } from '@graphql-codegen/visitor-plugin-common'; import { CustomFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; -import { - generateInfiniteQueryFormattedParameters, - generateInfiniteQueryKey, - generateMutationFormattedParameters, - generateMutationKey, - generateQueryFormattedParameters, - generateQueryKey, -} from './variables-generator.js'; import { ReactQueryVisitor } from './visitor.js'; -export class CustomMapperFetcher implements FetcherRenderer { +export class CustomMapperFetcher extends FetcherRenderer { private _mapper: ParsedMapper; private _isReactHook: boolean; - constructor(private visitor: ReactQueryVisitor, customFetcher: CustomFetch) { + constructor(protected visitor: ReactQueryVisitor, customFetcher: CustomFetch) { + super(visitor); if (typeof customFetcher === 'string') { customFetcher = { func: customFetcher }; } this._mapper = parseMapper(customFetcher.func); this._isReactHook = customFetcher.isReactHook; + autoBind(this); } private getFetcherFnName(operationResultType: string, operationVariablesTypes: string): string { @@ -63,7 +58,7 @@ export class CustomMapperFetcher implements FetcherRenderer { this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); const implHookOuter = this._isReactHook @@ -82,11 +77,10 @@ export class CustomMapperFetcher implements FetcherRenderer { ) =>{ ${implHookOuter} return ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), - queryFn: impl, - })} + ${this.generateInfiniteQueryFormattedParameters( + this.generateInfiniteQueryKey(node, hasRequiredVariables), + impl, + )} )};`; } @@ -119,11 +113,10 @@ export class CustomMapperFetcher implements FetcherRenderer { ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateQueryKey(node, hasRequiredVariables), - queryFn: impl, - })} + ${this.generateQueryFormattedParameters( + this.generateQueryKey(node, hasRequiredVariables), + impl, + )} );`; } @@ -153,11 +146,7 @@ export class CustomMapperFetcher implements FetcherRenderer { ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - mutationKey: generateMutationKey(node), - mutationFn: impl, - })} + ${this.generateMutationFormattedParameters(this.generateMutationKey(node), impl)} );`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 33bae369b..17c0d8f9a 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -1,19 +1,14 @@ +import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; import { FetcherRenderer } from './fetcher.js'; -import { - generateInfiniteQueryFormattedParameters, - generateInfiniteQueryKey, - generateMutationFormattedParameters, - generateMutationKey, - generateQueryFormattedParameters, - generateQueryKey, - generateQueryVariablesSignature, -} from './variables-generator.js'; import { ReactQueryVisitor } from './visitor.js'; -export class HardcodedFetchFetcher implements FetcherRenderer { - constructor(private visitor: ReactQueryVisitor, private config: HardcodedFetch) {} +export class HardcodedFetchFetcher extends FetcherRenderer { + constructor(protected visitor: ReactQueryVisitor, private config: HardcodedFetch) { + super(visitor); + autoBind(this); + } private getEndpoint(): string { try { @@ -70,7 +65,7 @@ ${this.getFetchParams()} operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -78,7 +73,7 @@ ${this.getFetchParams()} this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; return `export const useInfinite${operationName} = < TData = ${operationResultType}, @@ -88,11 +83,10 @@ ${this.getFetchParams()} ${options} ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), - queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, - })} + ${this.generateInfiniteQueryFormattedParameters( + this.generateInfiniteQueryKey(node, hasRequiredVariables), + `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, + )} );`; } @@ -104,7 +98,7 @@ ${this.getFetchParams()} operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -122,11 +116,10 @@ ${this.getFetchParams()} ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateQueryKey(node, hasRequiredVariables), - queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)`, - })} + ${this.generateQueryFormattedParameters( + this.generateQueryKey(node, hasRequiredVariables), + `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)`, + )} );`; } @@ -152,11 +145,10 @@ ${this.getFetchParams()} ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - mutationKey: generateMutationKey(node), - mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)()`, - })} + ${this.generateMutationFormattedParameters( + this.generateMutationKey(node), + `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)()`, + )} );`; } @@ -168,7 +160,7 @@ ${this.getFetchParams()} operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index d1f07a191..4e82b3fe7 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,18 +1,13 @@ +import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { FetcherRenderer } from './fetcher.js'; -import { - generateInfiniteQueryFormattedParameters, - generateInfiniteQueryKey, - generateMutationFormattedParameters, - generateMutationKey, - generateQueryFormattedParameters, - generateQueryKey, - generateQueryVariablesSignature, -} from './variables-generator.js'; import { ReactQueryVisitor } from './visitor.js'; -export class FetchFetcher implements FetcherRenderer { - constructor(private visitor: ReactQueryVisitor) {} +export class FetchFetcher extends FetcherRenderer { + constructor(protected visitor: ReactQueryVisitor) { + super(visitor); + autoBind(this); + } generateFetcherImplementaion(): string { return ` @@ -45,7 +40,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -53,7 +48,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; return `export const useInfinite${operationName} = < TData = ${operationResultType}, @@ -64,11 +59,10 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${options} ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), - queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, - })} + ${this.generateInfiniteQueryFormattedParameters( + this.generateInfiniteQueryKey(node, hasRequiredVariables), + `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, + )} );`; } @@ -80,7 +74,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -99,11 +93,10 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${options} ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateQueryKey(node, hasRequiredVariables), - queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, - })} + ${this.generateQueryFormattedParameters( + this.generateQueryKey(node, hasRequiredVariables), + `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, + )} );`; } @@ -132,11 +125,10 @@ function fetcher(endpoint: string, requestInit: RequestInit, ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - mutationKey: generateMutationKey(node), - mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)()`, - })} + ${this.generateMutationFormattedParameters( + this.generateMutationKey(node), + `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)()`, + )} );`; } @@ -148,7 +140,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 0f49ac51c..944a0f7d7 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -1,22 +1,16 @@ +import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; import { FetcherRenderer } from './fetcher.js'; -import { - generateInfiniteQueryFormattedParameters, - generateInfiniteQueryKey, - generateMutationFormattedParameters, - generateMutationKey, - generateQueryFormattedParameters, - generateQueryKey, - generateQueryVariablesSignature, -} from './variables-generator.js'; import { ReactQueryVisitor } from './visitor.js'; -export class GraphQLRequestClientFetcher implements FetcherRenderer { +export class GraphQLRequestClientFetcher extends FetcherRenderer { private clientPath: string | null; - constructor(private visitor: ReactQueryVisitor, config: GraphQlRequest) { + constructor(protected visitor: ReactQueryVisitor, config: GraphQlRequest) { + super(visitor); this.clientPath = typeof config === 'object' ? config.clientImportPath : null; + autoBind(this); } generateFetcherImplementaion(): string { @@ -47,7 +41,7 @@ function fetcher(client: Graph operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -60,7 +54,7 @@ function fetcher(client: Graph this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; return this.clientPath ? `export const useInfinite${operationName} = < @@ -73,11 +67,10 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), - queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, [pageParamKey]: metaData.pageParam}, headers)()`, - })} + ${this.generateInfiniteQueryFormattedParameters( + this.generateInfiniteQueryKey(node, hasRequiredVariables), + `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, [pageParamKey]: metaData.pageParam}, headers)()`, + )} );` : `export const useInfinite${operationName} = < TData = ${operationResultType}, @@ -89,11 +82,10 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${generateInfiniteQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateInfiniteQueryKey(node, hasRequiredVariables), - queryFn: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})}, headers)()`, - })} + ${this.generateInfiniteQueryFormattedParameters( + this.generateInfiniteQueryKey(node, hasRequiredVariables), + `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})}, headers)()`, + )} );`; } @@ -105,7 +97,7 @@ function fetcher(client: Graph operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -133,11 +125,10 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateQueryKey(node, hasRequiredVariables), - queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, - })} + ${this.generateQueryFormattedParameters( + this.generateQueryKey(node, hasRequiredVariables), + `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, + )} );` : `export const use${operationName} = < TData = ${operationResultType}, @@ -149,11 +140,10 @@ function fetcher(client: Graph headers?: RequestInit['headers'] ) => ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${generateQueryFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - queryKey: generateQueryKey(node, hasRequiredVariables), - queryFn: `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, - })} + ${this.generateQueryFormattedParameters( + this.generateQueryKey(node, hasRequiredVariables), + `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, + )} );`; } @@ -187,11 +177,10 @@ function fetcher(client: Graph ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - mutationKey: generateMutationKey(node), - mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)()`, - })} + ${this.generateMutationFormattedParameters( + this.generateMutationKey(node), + `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)()`, + )} );` : `export const use${operationName} = < TError = ${this.visitor.config.errorType}, @@ -204,11 +193,10 @@ function fetcher(client: Graph ${ hookConfig.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${generateMutationFormattedParameters({ - reactQueryVersion: this.visitor.config.reactQueryVersion, - mutationKey: generateMutationKey(node), - mutationFn: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)()`, - })} + ${this.generateMutationFormattedParameters( + this.generateMutationKey(node), + `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)()`, + )} );`; } @@ -220,7 +208,7 @@ function fetcher(client: Graph operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = generateQueryVariablesSignature( + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index e49eff7fc..ba989c9e6 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -1,37 +1,158 @@ +import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; +import { ReactQueryVisitor } from './visitor.js'; -export interface FetcherRenderer { - generateFetcherImplementaion: () => string; - generateQueryHook: ( +export class BaseFetcherRenderer { + constructor(protected visitor: ReactQueryVisitor) { + autoBind(this); + } + + generateQueryVariablesSignature( + hasRequiredVariables: boolean, + operationVariablesTypes: string, + ): string { + return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; + } + + generateInfiniteQueryKey(node: OperationDefinitionNode, hasRequiredVariables: boolean): string { + if (hasRequiredVariables) return `['${node.name.value}.infinite', variables]`; + return `variables === undefined ? ['${node.name.value}.infinite'] : ['${node.name.value}.infinite', variables]`; + } + + generateInfiniteQueryKeyMaker( + node: OperationDefinitionNode, + operationName: string, + operationVariablesTypes: string, + hasRequiredVariables: boolean, + ) { + const signature = this.generateQueryVariablesSignature( + hasRequiredVariables, + operationVariablesTypes, + ); + return `\nuseInfinite${operationName}.getKey = (${signature}) => ${this.generateInfiniteQueryKey( + node, + hasRequiredVariables, + )};\n`; + } + + generateInfiniteQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { + return `\nuseInfinite${operationName}.rootKey = '${node.name.value}.infinite';\n`; + } + + generateQueryKey(node: OperationDefinitionNode, hasRequiredVariables: boolean): string { + if (hasRequiredVariables) return `['${node.name.value}', variables]`; + return `variables === undefined ? ['${node.name.value}'] : ['${node.name.value}', variables]`; + } + + generateQueryKeyMaker( + node: OperationDefinitionNode, + operationName: string, + operationVariablesTypes: string, + hasRequiredVariables: boolean, + ) { + const signature = this.generateQueryVariablesSignature( + hasRequiredVariables, + operationVariablesTypes, + ); + return `\nuse${operationName}.getKey = (${signature}) => ${this.generateQueryKey( + node, + hasRequiredVariables, + )};\n`; + } + + generateQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { + return `\nuse${operationName}.rootKey = '${node.name.value}';\n`; + } + + generateMutationKey(node: OperationDefinitionNode): string { + return `['${node.name.value}']`; + } + + generateMutationKeyMaker(node: OperationDefinitionNode, operationName: string) { + return `\nuse${operationName}.getKey = () => ${this.generateMutationKey(node)};\n`; + } + + generateInfiniteQueryRequired() { + if (this.visitor.config.reactQueryVersion <= 4) { + return '?'; + } + return ''; + } + + generateInfiniteQueryFormattedParameters(queryKey: string, queryFn: string) { + if (this.visitor.config.reactQueryVersion <= 4) { + return `${queryKey}, + ${queryFn}, + options`; + } + return `(() => { + const { queryKey: optionsQueryKey, ...restOptions } = options; + return { + queryKey: optionsQueryKey ?? ${queryKey}, + queryFn: ${queryFn}, + ...restOptions + } + })()`; + } + + generateQueryFormattedParameters(queryKey: string, queryFn: string): string { + if (this.visitor.config.reactQueryVersion <= 4) { + return `${queryKey}, + ${queryFn}, + options`; + } + return `{ + queryKey: ${queryKey}, + queryFn: ${queryFn}, + ...options + }`; + } + + generateMutationFormattedParameters(mutationKey: string, mutationFn: string): string { + if (this.visitor.config.reactQueryVersion <= 4) { + return `${mutationKey}, + ${mutationFn}, + options`; + } + return `{ + mutationKey: ${mutationKey}, + mutationFn: ${mutationFn}, + ...options + }`; + } +} +export abstract class FetcherRenderer extends BaseFetcherRenderer { + abstract generateFetcherImplementaion(): string; + abstract generateQueryHook( node: OperationDefinitionNode, documentVariableName: string, operationName: string, operationResultType: string, operationVariablesTypes: string, hasRequiredVariables: boolean, - ) => string; - generateInfiniteQueryHook: ( + ): string; + abstract generateInfiniteQueryHook( node: OperationDefinitionNode, documentVariableName: string, operationName: string, operationResultType: string, operationVariablesTypes: string, hasRequiredVariables: boolean, - ) => string; - generateMutationHook: ( + ): string; + abstract generateMutationHook( node: OperationDefinitionNode, documentVariableName: string, operationName: string, operationResultType: string, operationVariablesTypes: string, hasRequiredVariables: boolean, - ) => string; - generateFetcherFetch: ( + ): string; + abstract generateFetcherFetch( node: OperationDefinitionNode, documentVariableName: string, operationName: string, operationResultType: string, operationVariablesTypes: string, hasRequiredVariables: boolean, - ) => string; + ): string; } diff --git a/packages/plugins/typescript/react-query/src/variables-generator.ts b/packages/plugins/typescript/react-query/src/variables-generator.ts deleted file mode 100644 index 7a52b8dac..000000000 --- a/packages/plugins/typescript/react-query/src/variables-generator.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { OperationDefinitionNode } from 'graphql'; - -export function generateQueryVariablesSignature( - hasRequiredVariables: boolean, - operationVariablesTypes: string, -): string { - return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; -} - -export function generateInfiniteQueryKey( - node: OperationDefinitionNode, - hasRequiredVariables: boolean, -): string { - if (hasRequiredVariables) return `['${node.name.value}.infinite', variables]`; - return `variables === undefined ? ['${node.name.value}.infinite'] : ['${node.name.value}.infinite', variables]`; -} - -export function generateInfiniteQueryKeyMaker( - node: OperationDefinitionNode, - operationName: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, -) { - const signature = generateQueryVariablesSignature(hasRequiredVariables, operationVariablesTypes); - return `\nuseInfinite${operationName}.getKey = (${signature}) => ${generateInfiniteQueryKey( - node, - hasRequiredVariables, - )};\n`; -} - -export function generateInfiniteQueryRootKeyMaker( - node: OperationDefinitionNode, - operationName: string, -) { - return `\nuseInfinite${operationName}.rootKey = '${node.name.value}.infinite';\n`; -} - -export function generateQueryKey( - node: OperationDefinitionNode, - hasRequiredVariables: boolean, -): string { - if (hasRequiredVariables) return `['${node.name.value}', variables]`; - return `variables === undefined ? ['${node.name.value}'] : ['${node.name.value}', variables]`; -} - -export function generateQueryKeyMaker( - node: OperationDefinitionNode, - operationName: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, -) { - const signature = generateQueryVariablesSignature(hasRequiredVariables, operationVariablesTypes); - return `\nuse${operationName}.getKey = (${signature}) => ${generateQueryKey( - node, - hasRequiredVariables, - )};\n`; -} - -export function generateQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { - return `\nuse${operationName}.rootKey = '${node.name.value}';\n`; -} - -export function generateMutationKey(node: OperationDefinitionNode): string { - return `['${node.name.value}']`; -} - -export function generateMutationKeyMaker(node: OperationDefinitionNode, operationName: string) { - return `\nuse${operationName}.getKey = () => ${generateMutationKey(node)};\n`; -} - -interface GenerateInfiniteQueryFormattedParametersPayload { - reactQueryVersion: number; - queryKey: string; - queryFn: string; -} -export function generateInfiniteQueryFormattedParameters( - payload: GenerateInfiniteQueryFormattedParametersPayload, -) { - const { reactQueryVersion, queryKey, queryFn } = payload; - if (reactQueryVersion <= 4) { - return `${queryKey}, - ${queryFn}, - options`; - } - return `(() => { - const { queryKey: optionsQueryKey, ...restOptions } = options; - return { - queryKey: optionsQueryKey ?? ${queryKey}, - queryFn: ${queryFn}, - ...restOptions - } - })()`; -} - -interface GenerateQueryParametersFormattedPayload { - reactQueryVersion: number; - queryKey: string; - queryFn: string; -} -export function generateQueryFormattedParameters( - payload: GenerateQueryParametersFormattedPayload, -): string { - const { reactQueryVersion, queryKey, queryFn } = payload; - if (reactQueryVersion <= 4) { - return `${queryKey}, - ${queryFn}, - options`; - } - return `{ - queryKey: ${queryKey}, - queryFn: ${queryFn}, - ...options - }`; -} - -interface GenerateMutationFormattedParametersPayload { - reactQueryVersion: number; - mutationKey: string; - mutationFn: string; -} -export function generateMutationFormattedParameters( - payload: GenerateMutationFormattedParametersPayload, -): string { - const { reactQueryVersion, mutationKey, mutationFn } = payload; - if (reactQueryVersion <= 4) { - return `${mutationKey}, - ${mutationFn}, - options`; - } - return `{ - mutationKey: ${mutationKey}, - mutationFn: ${mutationFn}, - ...options - }`; -} diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index bcc101dff..5ee4f799b 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -15,13 +15,6 @@ import { HardcodedFetchFetcher } from './fetcher-fetch-hardcoded.js'; import { FetchFetcher } from './fetcher-fetch.js'; import { GraphQLRequestClientFetcher } from './fetcher-graphql-request.js'; import { FetcherRenderer } from './fetcher.js'; -import { - generateInfiniteQueryKeyMaker, - generateInfiniteQueryRootKeyMaker, - generateMutationKeyMaker, - generateQueryKeyMaker, - generateQueryRootKeyMaker, -} from './variables-generator.js'; export interface ReactQueryPluginConfig extends ClientSideBasePluginConfig { errorType: string; @@ -202,7 +195,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< query += `\nuse${operationName}.document = ${documentVariableName};\n`; } if (this.config.exposeQueryKeys) { - query += `\n${generateQueryKeyMaker( + query += `\n${this.fetcher.generateQueryKeyMaker( node, operationName, operationVariablesTypes, @@ -210,7 +203,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< )}\n`; } if (this.config.exposeQueryRootKeys) { - query += `\n${generateQueryRootKeyMaker(node, operationName)}`; + query += `\n${this.fetcher.generateQueryRootKeyMaker(node, operationName)}`; } if (this.config.addInfiniteQuery) { query += `\n${this.fetcher.generateInfiniteQueryHook( @@ -222,7 +215,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< hasRequiredVariables, )}\n`; if (this.config.exposeQueryKeys) { - query += `\n${generateInfiniteQueryKeyMaker( + query += `\n${this.fetcher.generateInfiniteQueryKeyMaker( node, operationName, operationVariablesTypes, @@ -230,7 +223,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< )}\n`; } if (this.config.exposeQueryRootKeys) { - query += `\n${generateInfiniteQueryRootKeyMaker(node, operationName)}`; + query += `\n${this.fetcher.generateInfiniteQueryRootKeyMaker(node, operationName)}`; } } @@ -259,7 +252,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< hasRequiredVariables, ); if (this.config.exposeMutationKeys) { - query += generateMutationKeyMaker(node, operationName); + query += this.fetcher.generateMutationKeyMaker(node, operationName); } if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { query += this.fetcher.generateFetcherFetch( From 5102f38a5a68c646f2d16226dcde898e6495dc4c Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Mon, 2 Oct 2023 15:30:35 +0800 Subject: [PATCH 12/43] fix: v5 parameters type --- .../typescript/react-query/package.json | 2 +- .../react-query/src/fetcher-custom-mapper.ts | 10 ++++++++-- .../src/fetcher-fetch-hardcoded.ts | 7 +++++-- .../react-query/src/fetcher-fetch.ts | 7 +++++-- .../src/fetcher-graphql-request.ts | 7 +++++-- .../typescript/react-query/src/fetcher.ts | 20 +++++++++++++++++++ .../react-query/tests/react-query.spec.ts | 4 ++-- 7 files changed, 46 insertions(+), 11 deletions(-) diff --git a/packages/plugins/typescript/react-query/package.json b/packages/plugins/typescript/react-query/package.json index 14b8fbcd3..73f4035a3 100644 --- a/packages/plugins/typescript/react-query/package.json +++ b/packages/plugins/typescript/react-query/package.json @@ -1,5 +1,5 @@ { - "name": "@neil585456525/typescript-react-query", + "name": "@graphql-codegen/typescript-react-query", "version": "5.0.1", "type": "module", "description": "GraphQL Code Generator plugin for generating a ready-to-use React-Query Hooks based on GraphQL operations", diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 910eac0e2..e90866750 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -52,13 +52,19 @@ export class CustomMapperFetcher extends FetcherRenderer { operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; + const variables = this.generateInfiniteQueryVariablesSignature( + hasRequiredVariables, + operationVariablesTypes, + ); const hookConfig = this.visitor.queryMethodMap; this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = this.generateInfiniteQueryOptionsSignature( + hookConfig.infiniteQuery.options, + operationResultType, + ); const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); const implHookOuter = this._isReactHook diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 17c0d8f9a..20fa7037f 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -65,7 +65,7 @@ ${this.getFetchParams()} operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = this.generateQueryVariablesSignature( + const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -73,7 +73,10 @@ ${this.getFetchParams()} this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = this.generateInfiniteQueryOptionsSignature( + hookConfig.infiniteQuery.options, + operationResultType, + ); return `export const useInfinite${operationName} = < TData = ${operationResultType}, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 4e82b3fe7..3aef8bea4 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -40,7 +40,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = this.generateQueryVariablesSignature( + const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -48,7 +48,10 @@ function fetcher(endpoint: string, requestInit: RequestInit, this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = this.generateInfiniteQueryOptionsSignature( + hookConfig.infiniteQuery.options, + operationResultType, + ); return `export const useInfinite${operationName} = < TData = ${operationResultType}, diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 944a0f7d7..092cbfde2 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -41,7 +41,7 @@ function fetcher(client: Graph operationVariablesTypes: string, hasRequiredVariables: boolean, ): string { - const variables = this.generateQueryVariablesSignature( + const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); @@ -54,7 +54,10 @@ function fetcher(client: Graph this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - const options = `options?: ${hookConfig.infiniteQuery.options}<${operationResultType}, TError, TData>`; + const options = this.generateInfiniteQueryOptionsSignature( + hookConfig.infiniteQuery.options, + operationResultType, + ); return this.clientPath ? `export const useInfinite${operationName} = < diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index ba989c9e6..a03e0dd33 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -14,6 +14,26 @@ export class BaseFetcherRenderer { return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; } + generateInfiniteQueryVariablesSignature( + hasRequiredVariables: boolean, + operationVariablesTypes: string, + ): string { + if (this.visitor.config.reactQueryVersion <= 4) { + return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; + } + return `variables: ${operationVariablesTypes}`; + } + + generateInfiniteQueryOptionsSignature( + infiniteQueryOptions: string, + operationResultType: string, + ): string { + if (this.visitor.config.reactQueryVersion <= 4) { + return `options?: ${infiniteQueryOptions}<${operationResultType}, TError, TData>`; + } + return `options: Omit<${infiniteQueryOptions}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${infiniteQueryOptions}<${operationResultType}, TError, TData>['queryKey'] }`; + } + generateInfiniteQueryKey(node: OperationDefinitionNode, hasRequiredVariables: boolean): string { if (hasRequiredVariables) return `['${node.name.value}.infinite', variables]`; return `variables === undefined ? ['${node.name.value}.infinite'] : ['${node.name.value}.infinite', variables]`; diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index 9793d0315..45d7c17f4 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -161,8 +161,8 @@ export const useTestMutation = < TError = unknown >( dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables?: TestQueryVariables, - options?: UseInfiniteQueryOptions + variables: TestQueryVariables, + options: Omit, 'queryKey'> & { queryKey?: UseInfiniteQueryOptions['queryKey'] } ) => useInfiniteQuery( (() => { From 52ce6ead145a2aa117f169d12baf607d4592d588 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Mon, 2 Oct 2023 15:34:32 +0800 Subject: [PATCH 13/43] add: changeset --- .changeset/twelve-mugs-reflect.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/twelve-mugs-reflect.md diff --git a/.changeset/twelve-mugs-reflect.md b/.changeset/twelve-mugs-reflect.md new file mode 100644 index 000000000..13d39a15d --- /dev/null +++ b/.changeset/twelve-mugs-reflect.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-react-query': major +--- + +Support react-query v5 From 18f5d32bf9511ca858960f9291f737bfe5175ffe Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 12 Oct 2023 16:47:13 +0800 Subject: [PATCH 14/43] refactor: interface --- .../typescript/react-query/src/config.ts | 84 +++++++++++-------- .../typescript/react-query/src/visitor.ts | 31 ++++--- 2 files changed, 65 insertions(+), 50 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/config.ts b/packages/plugins/typescript/react-query/src/config.ts index 3f86be4cf..90e059c1d 100644 --- a/packages/plugins/typescript/react-query/src/config.ts +++ b/packages/plugins/typescript/react-query/src/config.ts @@ -4,38 +4,12 @@ export type HardcodedFetch = { endpoint: string; fetchParams?: string | Record **If you are using the `react-query` package instead of the `@tanstack/react-query` package in your project, please set the `legacyMode` option to `true`.** - * - */ -export interface ReactQueryRawPluginConfig - extends Omit< - RawClientSideBasePluginConfig, - | 'documentMode' - | 'noGraphQLTag' - | 'gqlImport' - | 'documentNodeImport' - | 'noExport' - | 'importOperationTypesFrom' - | 'importDocumentNodeExternallyFrom' - | 'useTypeImports' - | 'legacyMode' - > { +export interface BaseReactQueryPluginConfig { /** - * @description Customize the fetcher you wish to use in the generated file. React-Query is agnostic to the data-fetching layer, so you should provide it, or use a custom one. - * - * The following options are available to use: - * - * - 'fetch' - requires you to specify endpoint and headers on each call, and uses `fetch` to do the actual http call. - * - `{ endpoint: string, fetchParams: RequestInit }`: hardcode your endpoint and fetch options into the generated output, using the environment `fetch` method. You can also use `process.env.MY_VAR` as endpoint or header value. - * - `file#identifier` - You can use custom fetcher method that should implement the exported `ReactQueryFetcher` interface. Example: `./my-fetcher#myCustomFetcher`. - * - `graphql-request`: Will generate each hook with `client` argument, where you should pass your own `GraphQLClient` (created from `graphql-request`). + * @default unknown + * @description Changes the default "TError" generic type. */ - fetcher?: 'fetch' | HardcodedFetch | GraphQlRequest | CustomFetch; + errorType?: string; /** * @default false @@ -98,28 +72,29 @@ export interface ReactQueryRawPluginConfig exposeFetcher?: boolean; /** - * @default unknown - * @description Changes the default "TError" generic type. + * @default false + * @description Adds an Infinite Query along side the standard one */ - errorType?: string; + addInfiniteQuery?: boolean; /** * @default false - * @description Adds an Infinite Query along side the standard one + * @description Adds a Suspense Query along side the standard one */ - addInfiniteQuery?: boolean; + addSuspenseQuery?: boolean; /** * @default false * @description If true, it imports `react-query` not `@tanstack/react-query`, default is false. + * @deprecated Please use `reactQueryVersion` instead. */ legacyMode?: boolean; /** * @default 4 - * @description The version of react-query to use. Default is 4. legacyMode must be false to active this flag. + * @description The version of react-query to use. Will override the legacyMode option. */ - reactQueryVersion?: 4 | 5; + reactQueryVersion?: 3 | 4 | 5; /** * @default empty @@ -132,3 +107,38 @@ export interface ReactQueryRawPluginConfig */ reactQueryImportFrom?: string; } + +/** + * @description This plugin generates `React-Query` Hooks with TypeScript typings. + * + * It extends the basic TypeScript plugins: `@graphql-codegen/typescript`, `@graphql-codegen/typescript-operations` - and thus shares a similar configuration. + * + * > **If you are using the `react-query` package instead of the `@tanstack/react-query` package in your project, please set the `legacyMode` option to `true`.** + * + */ +export interface ReactQueryRawPluginConfig + extends Omit< + RawClientSideBasePluginConfig, + | 'documentMode' + | 'noGraphQLTag' + | 'gqlImport' + | 'documentNodeImport' + | 'noExport' + | 'importOperationTypesFrom' + | 'importDocumentNodeExternallyFrom' + | 'useTypeImports' + | 'legacyMode' + >, + BaseReactQueryPluginConfig { + /** + * @description Customize the fetcher you wish to use in the generated file. React-Query is agnostic to the data-fetching layer, so you should provide it, or use a custom one. + * + * The following options are available to use: + * + * - 'fetch' - requires you to specify endpoint and headers on each call, and uses `fetch` to do the actual http call. + * - `{ endpoint: string, fetchParams: RequestInit }`: hardcode your endpoint and fetch options into the generated output, using the environment `fetch` method. You can also use `process.env.MY_VAR` as endpoint or header value. + * - `file#identifier` - You can use custom fetcher method that should implement the exported `ReactQueryFetcher` interface. Example: `./my-fetcher#myCustomFetcher`. + * - `graphql-request`: Will generate each hook with `client` argument, where you should pass your own `GraphQLClient` (created from `graphql-request`). + */ + fetcher?: 'fetch' | HardcodedFetch | GraphQlRequest | CustomFetch; +} diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index 5ee4f799b..93fb7e7b8 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -9,31 +9,28 @@ import { getConfigValue, LoadedFragment, } from '@graphql-codegen/visitor-plugin-common'; -import { ReactQueryRawPluginConfig } from './config.js'; +import { BaseReactQueryPluginConfig, ReactQueryRawPluginConfig } from './config.js'; import { CustomMapperFetcher } from './fetcher-custom-mapper.js'; import { HardcodedFetchFetcher } from './fetcher-fetch-hardcoded.js'; import { FetchFetcher } from './fetcher-fetch.js'; import { GraphQLRequestClientFetcher } from './fetcher-graphql-request.js'; import { FetcherRenderer } from './fetcher.js'; -export interface ReactQueryPluginConfig extends ClientSideBasePluginConfig { - errorType: string; - exposeDocument: boolean; - exposeQueryKeys: boolean; - exposeQueryRootKeys: boolean; - exposeMutationKeys: boolean; - exposeFetcher: boolean; - addInfiniteQuery: boolean; - legacyMode: boolean; - reactQueryVersion: 4 | 5; - reactQueryImportFrom?: string; -} +export type ReactQueryPluginConfig = BaseReactQueryPluginConfig & ClientSideBasePluginConfig; export interface ReactQueryMethodMap { infiniteQuery: { hook: string; options: string; }; + suspenseInfiniteQuery: { + hook: string; + options: string; + }; + suspenseQuery: { + hook: string; + options: string; + }; query: { hook: string; options: string; @@ -58,6 +55,14 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< hook: 'useInfiniteQuery', options: 'UseInfiniteQueryOptions', }, + suspenseInfiniteQuery: { + hook: 'useSuspenseInfiniteQuery', + options: 'UseSuspenseInfiniteQueryOptions', + }, + suspenseQuery: { + hook: 'useSuspenseQuery', + options: 'UseSuspenseQueryOptions', + }, query: { hook: 'useQuery', options: 'UseQueryOptions', From 39530e5e7d9573cad5a3074e7661dcea99128c41 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 12 Oct 2023 16:57:13 +0800 Subject: [PATCH 15/43] fix: typo --- .../typescript/react-query/src/fetcher-custom-mapper.ts | 2 +- .../typescript/react-query/src/fetcher-fetch-hardcoded.ts | 2 +- packages/plugins/typescript/react-query/src/fetcher-fetch.ts | 2 +- .../typescript/react-query/src/fetcher-graphql-request.ts | 2 +- packages/plugins/typescript/react-query/src/fetcher.ts | 4 +++- packages/plugins/typescript/react-query/src/visitor.ts | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index e90866750..c8447e024 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -27,7 +27,7 @@ export class CustomMapperFetcher extends FetcherRenderer { return `${this._mapper.type}<${operationResultType}, ${operationVariablesTypes}>`; } - generateFetcherImplementaion(): string { + generateFetcherImplementation(): string { if (this._mapper.isExternal) { return buildMapperImport( this._mapper.source, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 20fa7037f..21772ff2c 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -35,7 +35,7 @@ export class HardcodedFetchFetcher extends FetcherRenderer { return ` method: "POST",${fetchParamsPartial}`; } - generateFetcherImplementaion(): string { + generateFetcherImplementation(): string { return ` function fetcher(query: string, variables?: TVariables) { return async (): Promise => { diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 3aef8bea4..84a05c678 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -9,7 +9,7 @@ export class FetchFetcher extends FetcherRenderer { autoBind(this); } - generateFetcherImplementaion(): string { + generateFetcherImplementation(): string { return ` function fetcher(endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables) { return async (): Promise => { diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 092cbfde2..ebfe56494 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -13,7 +13,7 @@ export class GraphQLRequestClientFetcher extends FetcherRenderer { autoBind(this); } - generateFetcherImplementaion(): string { + generateFetcherImplementation(): string { return this.clientPath ? ` function fetcher(query: string, variables?: TVariables, requestHeaders?: RequestInit['headers']) { diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index a03e0dd33..6c25b76d6 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -7,6 +7,8 @@ export class BaseFetcherRenderer { autoBind(this); } + generateQueryHelper() {} + generateQueryVariablesSignature( hasRequiredVariables: boolean, operationVariablesTypes: string, @@ -142,7 +144,7 @@ export class BaseFetcherRenderer { } } export abstract class FetcherRenderer extends BaseFetcherRenderer { - abstract generateFetcherImplementaion(): string; + abstract generateFetcherImplementation(): string; abstract generateQueryHook( node: OperationDefinitionNode, documentVariableName: string, diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index 93fb7e7b8..e38d190ac 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -152,7 +152,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< } public getFetcherImplementation(): string { - return this.fetcher.generateFetcherImplementaion(); + return this.fetcher.generateFetcherImplementation(); } private _getHookSuffix(name: string, operationType: string) { From 8789c7a12f76457638a01e883e50c987b79d602e Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 12 Oct 2023 17:50:59 +0800 Subject: [PATCH 16/43] refactor: queryHook --- .../react-query/src/fetcher-custom-mapper.ts | 20 +- .../src/fetcher-fetch-hardcoded.ts | 20 +- .../react-query/src/fetcher-fetch.ts | 39 +-- .../src/fetcher-graphql-request.ts | 20 +- .../typescript/react-query/src/fetcher.ts | 72 +++++- .../typescript/react-query/src/visitor.ts | 4 +- .../__snapshots__/react-query.spec.ts.snap | 232 ++++++++++++++++-- .../react-query/tests/react-query.spec.ts | 173 +------------ 8 files changed, 329 insertions(+), 251 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index c8447e024..11cd6eb5d 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -6,7 +6,7 @@ import { parseMapper, } from '@graphql-codegen/visitor-plugin-common'; import { CustomFetch } from './config.js'; -import { FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateQueryHookConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class CustomMapperFetcher extends FetcherRenderer { @@ -90,14 +90,16 @@ export class CustomMapperFetcher extends FetcherRenderer { )};`; } - generateQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateQueryHook(config: GenerateQueryHookConfig): string { + const { + node, + documentVariableName, + operationName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + } = config; + const variables = `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; const hookConfig = this.visitor.queryMethodMap; diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 21772ff2c..c0c15c356 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -1,7 +1,7 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; -import { FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateQueryHookConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class HardcodedFetchFetcher extends FetcherRenderer { @@ -93,14 +93,16 @@ ${this.getFetchParams()} );`; } - generateQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateQueryHook(config: GenerateQueryHookConfig): string { + const { + node, + documentVariableName, + operationName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + } = config; + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 84a05c678..530beb4ab 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,6 +1,6 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; -import { FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateQueryHookConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class FetchFetcher extends FetcherRenderer { @@ -69,38 +69,17 @@ function fetcher(endpoint: string, requestInit: RequestInit, );`; } - generateQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { - const variables = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.query.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.query.options); + generateQueryHook(config: GenerateQueryHookConfig): string { + const { generateBaseQueryHook, variables, options } = this.generateQueryHelper(config); - const options = `options?: ${hookConfig.query.options}<${operationResultType}, TError, TData>`; + const { documentVariableName, operationResultType, operationVariablesTypes } = config; - return `export const use${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, + return generateBaseQueryHook({ + implArguments: `dataSource: { endpoint: string, fetchParams?: RequestInit }, ${variables}, - ${options} - ) => - ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${this.generateQueryFormattedParameters( - this.generateQueryKey(node, hasRequiredVariables), - `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, - )} - );`; + ${options}`, + implFetcher: `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, + }); } generateMutationHook( diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index ebfe56494..69cebcff3 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -1,7 +1,7 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; -import { FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateQueryHookConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class GraphQLRequestClientFetcher extends FetcherRenderer { @@ -92,14 +92,16 @@ function fetcher(client: Graph );`; } - generateQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateQueryHook(config: GenerateQueryHookConfig): string { + const { + node, + documentVariableName, + operationName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + } = config; + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 6c25b76d6..467c030a9 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -2,12 +2,72 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { ReactQueryVisitor } from './visitor.js'; +export interface GenerateQueryHookConfig { + node: OperationDefinitionNode; + documentVariableName: string; + operationName: string; + operationResultType: string; + operationVariablesTypes: string; + hasRequiredVariables: boolean; +} + export class BaseFetcherRenderer { constructor(protected visitor: ReactQueryVisitor) { autoBind(this); } - generateQueryHelper() {} + generateQueryHelper(config: GenerateQueryHookConfig) { + const { + node, + operationName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + } = config; + + const variables = this.generateQueryVariablesSignature( + hasRequiredVariables, + operationVariablesTypes, + ); + const hookConfig = this.visitor.queryMethodMap; + this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.query.hook); + this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.query.options); + + const options = `options?: ${hookConfig.query.options}<${operationResultType}, TError, TData>`; + + const generateBaseQueryHook = (config: { + implArguments?: string; + implHookOuter?: string; + implFetcher: string; + }) => { + const { implArguments = '', implHookOuter = '', implFetcher = '' } = config; + + const argumentsResult = + implArguments ?? + `${variables}, + ${options}`; + + return `export const use${operationName} = < + TData = ${operationResultType}, + TError = ${this.visitor.config.errorType} + >( + ${argumentsResult} + ) => { + ${implHookOuter} + return ${hookConfig.query.hook}<${operationResultType}, TError, TData>( + ${this.generateQueryFormattedParameters( + this.generateQueryKey(node, hasRequiredVariables), + implFetcher, + )} + )};`; + }; + + return { + generateBaseQueryHook, + variables, + options, + }; + } generateQueryVariablesSignature( hasRequiredVariables: boolean, @@ -143,16 +203,10 @@ export class BaseFetcherRenderer { }`; } } + export abstract class FetcherRenderer extends BaseFetcherRenderer { abstract generateFetcherImplementation(): string; - abstract generateQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string; + abstract generateQueryHook(config: GenerateQueryHookConfig): string; abstract generateInfiniteQueryHook( node: OperationDefinitionNode, documentVariableName: string, diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index e38d190ac..65a7ed745 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -188,14 +188,14 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< operationVariablesTypes = this._externalImportPrefix + operationVariablesTypes; if (operationType === 'Query') { - let query = this.fetcher.generateQueryHook( + let query = this.fetcher.generateQueryHook({ node, documentVariableName, operationName, operationResultType, operationVariablesTypes, hasRequiredVariables, - ); + }); if (this.config.exposeDocument) { query += `\nuse${operationName}.document = ${documentVariableName};\n`; } diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index e0f3591d0..bf8a778b8 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -24,12 +24,13 @@ export const useTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), options - ); + )}; useTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test'] : ['test', variables]; @@ -79,12 +80,13 @@ export const useTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), options - ); + )}; useTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test'] : ['test', variables]; @@ -152,12 +154,13 @@ export const useTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), options - ); + )}; useTestQuery.rootKey = 'test'; @@ -206,12 +209,13 @@ export const useTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), options - ); + )}; useTestQuery.rootKey = 'test'; @@ -350,7 +354,7 @@ export const useInfiniteTestQuery = < variables?: TTestQueryVariables, options?: UseInfiniteQueryOptions ) =>{ - + return useInfiniteQuery( variables === undefined ? ['test.infinite'] : ['test.infinite', variables], (metaData) => myCustomFetcher(TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), @@ -422,7 +426,7 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: fetch Should generate query and mutation correctly 1`] = ` +exports[`React-Query fetcher: fetch Should generate query and mutation correctly: content 1`] = ` " export const TestDocument = \` query test { @@ -446,12 +450,13 @@ export const useTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -473,6 +478,32 @@ export const useTestMutation = < );" `; +exports[`React-Query fetcher: fetch Should generate query and mutation correctly: prepend 1`] = ` +[ + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';", + " +function fetcher(endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch(endpoint, { + method: 'POST', + ...requestInit, + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; + exports[`React-Query fetcher: graphql-request Should generate query correctly with client 1`] = ` " export const TestDocument = \` @@ -811,3 +842,170 @@ export const useTestMutation = < options );" `; + +exports[`React-Query support v4 syntax: content 1`] = ` +" +export const TestDocument = \` + query test { + feed { + id + commentCount + repository { + full_name + html_url + owner { + avatar_url + } + } + } +} + \`; +export const useTestQuery = < + TData = TestQuery, + TError = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables?: TestQueryVariables, + options?: UseQueryOptions + ) => { + + return useQuery( + variables === undefined ? ['test'] : ['test', variables], + fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), + options + )}; +export const useInfiniteTestQuery = < + TData = TestQuery, + TError = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables?: TestQueryVariables, + options?: UseInfiniteQueryOptions + ) => + useInfiniteQuery( + variables === undefined ? ['test.infinite'] : ['test.infinite', variables], + (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), + options + ); + +export const TestDocument = \` + mutation test($name: String) { + submitRepository(repoFullName: $name) { + id + } +} + \`; +export const useTestMutation = < + TError = unknown, + TContext = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + options?: UseMutationOptions + ) => + useMutation( + ['test'], + (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), + options + );" +`; + +exports[`React-Query support v4 syntax: prepend 1`] = ` +[ + "import { useQuery, useInfiniteQuery, useMutation, type UseQueryOptions, type UseInfiniteQueryOptions, type UseMutationOptions } from '@tanstack/react-query';", + " +function fetcher(endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch(endpoint, { + method: 'POST', + ...requestInit, + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; + +exports[`React-Query support v5 syntax 1`] = ` +" +export const TestDocument = \` + query test { + feed { + id + commentCount + repository { + full_name + html_url + owner { + avatar_url + } + } + } +} + \`; +export const useTestQuery = < + TData = TestQuery, + TError = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables?: TestQueryVariables, + options?: UseQueryOptions + ) => { + + return useQuery( + { + queryKey: variables === undefined ? ['test'] : ['test', variables], + queryFn: fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), + ...options + } + )}; +export const useInfiniteTestQuery = < + TData = TestQuery, + TError = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables: TestQueryVariables, + options: Omit, 'queryKey'> & { queryKey?: UseInfiniteQueryOptions['queryKey'] } + ) => + useInfiniteQuery( + (() => { + const { queryKey: optionsQueryKey, ...restOptions } = options; + return { + queryKey: optionsQueryKey ?? variables === undefined ? ['test.infinite'] : ['test.infinite', variables], + queryFn: (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), + ...restOptions + } + })() + ); + +export const TestDocument = \` + mutation test($name: String) { + submitRepository(repoFullName: $name) { + id + } +} + \`; +export const useTestMutation = < + TError = unknown, + TContext = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + options?: UseMutationOptions + ) => + useMutation( + { + mutationKey: ['test'], + mutationFn: (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), + ...options + } + );" +`; diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index 45d7c17f4..184a74442 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -32,91 +32,9 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toEqual([ - `import { useQuery, useInfiniteQuery, useMutation, type UseQueryOptions, type UseInfiniteQueryOptions, type UseMutationOptions } from '@tanstack/react-query';`, - ` -function fetcher(endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables) { - return async (): Promise => { - const res = await fetch(endpoint, { - method: 'POST', - ...requestInit, - body: JSON.stringify({ query, variables }), - }); - - const json = await res.json(); - - if (json.errors) { - const { message } = json.errors[0]; - - throw new Error(message); - } - - return json.data; - } -}`, - ]); - expect(out.content).toEqual(` -export const TestDocument = \` - query test { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } -} - \`; -export const useTestQuery = < - TData = TestQuery, - TError = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables?: TestQueryVariables, - options?: UseQueryOptions - ) => - useQuery( - variables === undefined ? ['test'] : ['test', variables], - fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), - options - ); -export const useInfiniteTestQuery = < - TData = TestQuery, - TError = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables?: TestQueryVariables, - options?: UseInfiniteQueryOptions - ) => - useInfiniteQuery( - variables === undefined ? ['test.infinite'] : ['test.infinite', variables], - (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), - options - ); - -export const TestDocument = \` - mutation test($name: String) { - submitRepository(repoFullName: $name) { - id - } -} - \`; -export const useTestMutation = < - TError = unknown, - TContext = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - options?: UseMutationOptions - ) => - useMutation( - ['test'], - (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), - options - );`); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); + await validateTypeScript(mergeOutputs(out), schema, docs, config); }); it('should throw when using v5 config with legacyMode', async () => { @@ -140,55 +58,8 @@ export const useTestMutation = < const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TestQuery, - TError = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables?: TestQueryVariables, - options?: UseQueryOptions - ) => - useQuery( - { - queryKey: variables === undefined ? ['test'] : ['test', variables], - queryFn: fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), - ...options -} - );`); - - expect(out.content).toBeSimilarStringTo(`export const useInfiniteTestQuery = < - TData = TestQuery, - TError = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables: TestQueryVariables, - options: Omit, 'queryKey'> & { queryKey?: UseInfiniteQueryOptions['queryKey'] } - ) => - useInfiniteQuery( - (() => { - const { queryKey: optionsQueryKey, ...restOptions } = options; - return { - queryKey: optionsQueryKey ?? variables === undefined ? ['test.infinite'] : ['test.infinite', variables], - queryFn: (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), - ...restOptions - } -})() - );`); - - expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - options?: UseMutationOptions - ) => - useMutation( - { - mutationKey: ['test'], - mutationFn: (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), - ...options -} - );`); + expect(out.content).toMatchSnapshot(); + await validateTypeScript(mergeOutputs(out), schema, docs, config); }); it('Duplicated nested fragments are removed', async () => { @@ -1247,38 +1118,8 @@ export const useTestMutation = < const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toContain( - `import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';`, - ); - - expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TTestQuery, - TError = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables?: TTestQueryVariables, - options?: UseQueryOptions - ) => - useQuery( - variables === undefined ? ['test'] : ['test', variables], - fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), - options - );`); - - expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - options?: UseMutationOptions - ) => - useMutation( - ['test'], - (variables?: TTestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), - options - );`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); From 0c6f67c8ecb638369aeba25c9459e9e3e351878c Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 12 Oct 2023 18:15:33 +0800 Subject: [PATCH 17/43] refactor: test & custom-mapper query --- .../react-query/src/fetcher-custom-mapper.ts | 33 +- .../typescript/react-query/src/fetcher.ts | 4 +- .../__snapshots__/react-query.spec.ts.snap | 264 +++++++++++-- .../react-query/tests/react-query.spec.ts | 358 ++---------------- 4 files changed, 266 insertions(+), 393 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 11cd6eb5d..42a67778b 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -91,41 +91,18 @@ export class CustomMapperFetcher extends FetcherRenderer { } generateQueryHook(config: GenerateQueryHookConfig): string { - const { - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - } = config; - - const variables = `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; - - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.query.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.query.options); + const { generateBaseQueryHook } = this.generateQueryHelper(config); - const options = `options?: ${hookConfig.query.options}<${operationResultType}, TError, TData>`; + const { documentVariableName, operationResultType, operationVariablesTypes } = config; const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); const impl = this._isReactHook ? `${typedFetcher}(${documentVariableName}).bind(null, variables)` : `${typedFetcher}(${documentVariableName}, variables)`; - return `export const use${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( - ${variables}, - ${options} - ) => - ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${this.generateQueryFormattedParameters( - this.generateQueryKey(node, hasRequiredVariables), - impl, - )} - );`; + return generateBaseQueryHook({ + implFetcher: impl, + }); } generateMutationHook( diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 467c030a9..df0c0e744 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -40,12 +40,12 @@ export class BaseFetcherRenderer { implHookOuter?: string; implFetcher: string; }) => { - const { implArguments = '', implHookOuter = '', implFetcher = '' } = config; + const { implArguments, implHookOuter = '', implFetcher } = config; const argumentsResult = implArguments ?? `${variables}, - ${options}`; + ${options}`; return `export const use${operationName} = < TData = ${operationResultType}, diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index bf8a778b8..d4d4692f7 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -25,7 +25,7 @@ export const useTestQuery = < variables?: TestQueryVariables, options?: UseQueryOptions ) => { - + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), @@ -81,7 +81,7 @@ export const useTestQuery = < variables?: TestQueryVariables, options?: UseQueryOptions ) => { - + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), @@ -155,7 +155,7 @@ export const useTestQuery = < variables?: TestQueryVariables, options?: UseQueryOptions ) => { - + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), @@ -210,7 +210,7 @@ export const useTestQuery = < variables?: TestQueryVariables, options?: UseQueryOptions ) => { - + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), @@ -257,7 +257,7 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: custom-mapper Should generate mutation correctly with lazy variables 1`] = ` +exports[`React-Query fetcher: custom-mapper Should generate mutation correctly with lazy variables: content 1`] = ` " export const TestDocument = \` query test { @@ -280,12 +280,13 @@ export const useTestQuery = < >( variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], useCustomFetcher(TestDocument).bind(null, variables), options - ); + )}; export const useInfiniteTestQuery = < TData = TTestQuery, TError = unknown @@ -318,7 +319,14 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: custom-mapper Should generate query correctly with external mapper 1`] = ` +exports[`React-Query fetcher: custom-mapper Should generate mutation correctly with lazy variables: prepend 1`] = ` +[ + "import { useQuery, useInfiniteQuery, useMutation, UseQueryOptions, UseInfiniteQueryOptions, UseMutationOptions } from 'react-query';", + "import { useCustomFetcher } from './my-file';", +] +`; + +exports[`React-Query fetcher: custom-mapper Should generate query correctly with external mapper: content 1`] = ` " export const TestDocument = \` query test { @@ -341,12 +349,13 @@ export const useTestQuery = < >( variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], myCustomFetcher(TestDocument, variables), options - ); + )}; export const useInfiniteTestQuery = < TData = TTestQuery, TError = unknown @@ -354,7 +363,7 @@ export const useInfiniteTestQuery = < variables?: TTestQueryVariables, options?: UseInfiniteQueryOptions ) =>{ - + return useInfiniteQuery( variables === undefined ? ['test.infinite'] : ['test.infinite', variables], (metaData) => myCustomFetcher(TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), @@ -379,7 +388,14 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: custom-mapper Should generate query correctly with internal mapper 1`] = ` +exports[`React-Query fetcher: custom-mapper Should generate query correctly with external mapper: prepend 1`] = ` +[ + "import { useQuery, useInfiniteQuery, useMutation, UseQueryOptions, UseInfiniteQueryOptions, UseMutationOptions } from 'react-query';", + "import { myCustomFetcher } from './my-file';", +] +`; + +exports[`React-Query fetcher: custom-mapper Should generate query correctly with internal mapper: content 1`] = ` " export const TestDocument = \` query test { @@ -402,12 +418,13 @@ export const useTestQuery = < >( variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], myCustomFetcher(TestDocument, variables), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -426,6 +443,13 @@ export const useTestMutation = < );" `; +exports[`React-Query fetcher: custom-mapper Should generate query correctly with internal mapper: prepend 1`] = ` +[ + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';", + null, +] +`; + exports[`React-Query fetcher: fetch Should generate query and mutation correctly: content 1`] = ` " export const TestDocument = \` @@ -451,7 +475,7 @@ export const useTestQuery = < variables?: TTestQueryVariables, options?: UseQueryOptions ) => { - + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), @@ -504,7 +528,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, ] `; -exports[`React-Query fetcher: graphql-request Should generate query correctly with client 1`] = ` +exports[`React-Query fetcher: graphql-request Should generate query correctly with client: content 1`] = ` " export const TestDocument = \` query test { @@ -557,7 +581,23 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: graphql-request with clientImportPath Should generate query correctly with client 1`] = ` +exports[`React-Query fetcher: graphql-request Should generate query correctly with client: prepend 1`] = ` +[ + "import { GraphQLClient } from 'graphql-request';", + "import { RequestInit } from 'graphql-request/dist/types.dom';", + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';", + " +function fetcher(client: GraphQLClient, query: string, variables?: TVariables, requestHeaders?: RequestInit['headers']) { + return async (): Promise => client.request({ + document: query, + variables, + requestHeaders + }); +}", +] +`; + +exports[`React-Query fetcher: graphql-request with clientImportPath Should generate query correctly with client: content 1`] = ` " export const TestDocument = \` query test { @@ -608,7 +648,24 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config 2`] = ` +exports[`React-Query fetcher: graphql-request with clientImportPath Should generate query correctly with client: prepend 1`] = ` +[ + "import { client as graphqlClient } from 'client.ts';", + "import { GraphQLClient } from 'graphql-request';", + "import { RequestInit } from 'graphql-request/dist/types.dom';", + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';", + " +function fetcher(query: string, variables?: TVariables, requestHeaders?: RequestInit['headers']) { + return async (): Promise => graphqlClient.request({ + document: query, + variables, + requestHeaders + }); +}", +] +`; + +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config and fetchParams object: content 1`] = ` " export const TestDocument = \` query test { @@ -655,7 +712,33 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config and fetchParams object 2`] = ` +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config and fetchParams object: prepend 1`] = ` +[ + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';", + " +function fetcher(query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch("http://localhost:3000/graphql", { + method: "POST", + ...({"headers":{"Authorization":"Bearer XYZ"}}), + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; + +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config: content 1`] = ` " export const TestDocument = \` query test { @@ -702,7 +785,33 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint 1`] = ` +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config: prepend 1`] = ` +[ + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';", + " +function fetcher(query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch("http://localhost:3000/graphql", { + method: "POST", + ...({"headers":{"Authorization":"Bearer XYZ"}}), + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; + +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from env var: content 1`] = ` " export const TestDocument = \` query test { @@ -749,7 +858,32 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from env var 1`] = ` +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from env var: prepend 1`] = ` +[ + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';", + " +function fetcher(query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch(process.env.ENDPOINT_URL as string, { + method: "POST", + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; + +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from just identifier: content 1`] = ` " export const TestDocument = \` query test { @@ -796,7 +930,32 @@ export const useTestMutation = < );" `; -exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from just identifier 1`] = ` +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from just identifier: prepend 1`] = ` +[ + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';", + " +function fetcher(query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch(myEndpoint as string, { + method: "POST", + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; + +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint: content 1`] = ` " export const TestDocument = \` query test { @@ -843,6 +1002,57 @@ export const useTestMutation = < );" `; +exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint: prepend 1`] = ` +[ + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';", + " +function fetcher(query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch("http://localhost:3000/graphql", { + method: "POST", + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; + +exports[`React-Query reactQueryImportFrom: custom-path Should import react-query from custom path: prepend 1`] = ` +[ + "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'custom-react-query';", + " +function fetcher(endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch(endpoint, { + method: 'POST', + ...requestInit, + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; + exports[`React-Query support v4 syntax: content 1`] = ` " export const TestDocument = \` @@ -868,7 +1078,7 @@ export const useTestQuery = < variables?: TestQueryVariables, options?: UseQueryOptions ) => { - + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), @@ -960,7 +1170,7 @@ export const useTestQuery = < variables?: TestQueryVariables, options?: UseQueryOptions ) => { - + return useQuery( { queryKey: variables === undefined ? ['test'] : ['test', variables], diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index 184a74442..a5b7ad620 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -186,47 +186,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toContain( - `import { useQuery, useInfiniteQuery, useMutation, UseQueryOptions, UseInfiniteQueryOptions, UseMutationOptions } from 'react-query';`, - ); - - expect(out.prepend).toContain(`import { myCustomFetcher } from './my-file';`); - expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TTestQuery, - TError = unknown - >( - variables?: TTestQueryVariables, - options?: UseQueryOptions - ) => - useQuery( - variables === undefined ? ['test'] : ['test', variables], - myCustomFetcher(TestDocument, variables), - options - );`); - - expect(out.content).toBeSimilarStringTo(`export const useInfiniteTestQuery = < - TData = TTestQuery, - TError = unknown - >( - variables?: TTestQueryVariables, - options?: UseInfiniteQueryOptions - ) =>{ - return useInfiniteQuery( - variables === undefined ? ['test.infinite'] : ['test.infinite', variables], - (metaData) => myCustomFetcher(TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), - options - )};`); - expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown - >(options?: UseMutationOptions) => - useMutation( - ['test'], - (variables?: TTestMutationVariables) => myCustomFetcher(TestDocument, variables)(), - options - );`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); @@ -239,33 +200,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toContain( - `import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';`, - ); - expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TTestQuery, - TError = unknown - >( - variables?: TTestQueryVariables, - options?: UseQueryOptions - ) => - useQuery( - variables === undefined ? ['test'] : ['test', variables], - myCustomFetcher(TestDocument, variables), - options - );`); - - expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown - >(options?: UseMutationOptions) => - useMutation( - ['test'], - (variables?: TTestMutationVariables) => myCustomFetcher(TestDocument, variables)(), - options - );`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); @@ -282,47 +218,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toContain( - `import { useQuery, useInfiniteQuery, useMutation, UseQueryOptions, UseInfiniteQueryOptions, UseMutationOptions } from 'react-query';`, - ); - expect(out.prepend).toContain(`import { useCustomFetcher } from './my-file';`); - expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TTestQuery, - TError = unknown - >( - variables?: TTestQueryVariables, - options?: UseQueryOptions - ) => - useQuery( - variables === undefined ? ['test'] : ['test', variables], - useCustomFetcher(TestDocument).bind(null, variables), - options - );`); - - expect(out.content).toBeSimilarStringTo(`export const useInfiniteTestQuery = < - TData = TTestQuery, - TError = unknown - >( - variables?: TTestQueryVariables, - options?: UseInfiniteQueryOptions - ) =>{ - const query = useCustomFetcher(TestDocument) - return useInfiniteQuery( - variables === undefined ? ['test.infinite'] : ['test.infinite', variables], - (metaData) => query({...variables, ...(metaData.pageParam ?? {})}), - options - )};`); - expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown - >(options?: UseMutationOptions) => - useMutation( - ['test'], - useCustomFetcher(TestDocument), - options - );`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); @@ -522,49 +419,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toContain( - `import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';`, - ); - expect(out.prepend).toContain(`import { GraphQLClient } from 'graphql-request';`); - expect(out.prepend).toContain( - `import { RequestInit } from 'graphql-request/dist/types.dom';`, - ); - expect(out.prepend[3]) - .toBeSimilarStringTo(` function fetcher(client: GraphQLClient, query: string, variables?: TVariables, requestHeaders?: RequestInit['headers']) { - return async (): Promise => client.request({ - document: query, - variables, - requestHeaders - `); - expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TTestQuery, - TError = unknown - >( - client: GraphQLClient, - variables?: TTestQueryVariables, - options?: UseQueryOptions, - headers?: RequestInit['headers'] - ) => - useQuery( - variables === undefined ? ['test'] : ['test', variables], - fetcher(client, TestDocument, variables, headers), - options - );`); - expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown - >( - client: GraphQLClient, - options?: UseMutationOptions, - headers?: RequestInit['headers'] - ) => - useMutation( - ['test'], - (variables?: TTestMutationVariables) => fetcher(client, TestDocument, variables, headers)(), - options - );`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); it('Should support useTypeImports', async () => { @@ -713,48 +569,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toContain( - `import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';`, - ); - expect(out.prepend).toContain(clientImportPath); - expect(out.prepend).toContain(`import { GraphQLClient } from 'graphql-request';`); - expect(out.prepend).toContain( - `import { RequestInit } from 'graphql-request/dist/types.dom';`, - ); - expect(out.prepend[4]) - .toBeSimilarStringTo(` function fetcher(query: string, variables?: TVariables, requestHeaders?: RequestInit['headers']) { - return async (): Promise => graphqlClient.request({ - document: query, - variables, - requestHeaders - `); - expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TTestQuery, - TError = unknown - >( - variables?: TTestQueryVariables, - options?: UseQueryOptions, - headers?: RequestInit['headers'] - ) => - useQuery( - variables === undefined ? ['test'] : ['test', variables], - fetcher(TestDocument, variables, headers), - options - );`); - expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown - >( - options?: UseMutationOptions, - headers?: RequestInit['headers'] - ) => - useMutation( - ['test'], - (variables?: TTestMutationVariables) => fetcher(TestDocument, variables, headers)(), - options - );`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); it('Should generate fetcher field when exposeFetcher is true', async () => { @@ -784,52 +600,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toContain( - `import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';`, - ); - expect(out.prepend[1]) - .toBeSimilarStringTo(` function fetcher(query: string, variables?: TVariables) { - return async (): Promise => { - const res = await fetch("http://localhost:3000/graphql", { - method: "POST", - body: JSON.stringify({ query, variables }), - }); - - const json = await res.json(); - - if (json.errors) { - const { message } = json.errors[0]; - - throw new Error(message); - } - - return json.data; - } - }`); - expect(out.content).toBeSimilarStringTo(`export const useTestQuery = < - TData = TTestQuery, - TError = unknown - >( - variables?: TTestQueryVariables, - options?: UseQueryOptions - ) => - useQuery( - variables === undefined ? ['test'] : ['test', variables], - fetcher(TestDocument, variables), - options - );`); - - expect(out.content).toBeSimilarStringTo(`export const useTestMutation = < - TError = unknown, - TContext = unknown - >(options?: UseMutationOptions) => - useMutation( - ['test'], - (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), - options - );`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); @@ -848,30 +620,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend[1]).toMatchInlineSnapshot(` - " - function fetcher(query: string, variables?: TVariables) { - return async (): Promise => { - const res = await fetch("http://localhost:3000/graphql", { - method: "POST", - ...({"headers":{"Authorization":"Bearer XYZ"}}), - body: JSON.stringify({ query, variables }), - }); - - const json = await res.json(); - - if (json.errors) { - const { message } = json.errors[0]; - - throw new Error(message); - } - - return json.data; - } - }" - `); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); @@ -890,30 +640,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend[1]).toMatchInlineSnapshot(` - " - function fetcher(query: string, variables?: TVariables) { - return async (): Promise => { - const res = await fetch("http://localhost:3000/graphql", { - method: "POST", - ...({"headers":{"Authorization":"Bearer XYZ"}}), - body: JSON.stringify({ query, variables }), - }); - - const json = await res.json(); - - if (json.errors) { - const { message } = json.errors[0]; - - throw new Error(message); - } - - return json.data; - } - }" - `); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); @@ -927,27 +655,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend[1]) - .toBeSimilarStringTo(`function fetcher(query: string, variables?: TVariables) { - return async (): Promise => { - const res = await fetch(process.env.ENDPOINT_URL as string, { - method: "POST", - body: JSON.stringify({ query, variables }), - }); - - const json = await res.json(); - - if (json.errors) { - const { message } = json.errors[0]; - - throw new Error(message); - } - - return json.data; - } - }`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); @@ -961,27 +670,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend[1]) - .toBeSimilarStringTo(` function fetcher(query: string, variables?: TVariables) { - return async (): Promise => { - const res = await fetch(myEndpoint as string, { - method: "POST", - body: JSON.stringify({ query, variables }), - }); - - const json = await res.json(); - - if (json.errors) { - const { message } = json.errors[0]; - - throw new Error(message); - } - - return json.data; - } - }`); - - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); @@ -1363,12 +1053,8 @@ describe('React-Query', () => { reactQueryImportFrom: 'custom-react-query', }; const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.prepend).toContain( - "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'custom-react-query';", - ); - expect(out.prepend).not.toContain( - `"import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';"`, - ); + expect(out.prepend).toMatchSnapshot('prepend'); + await validateTypeScript(mergeOutputs(out), schema, docs, config); }); }); }); From 166c2f19aa2cbf9bd0438d3d7b7f3f25aa9a38e3 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 12 Oct 2023 18:22:10 +0800 Subject: [PATCH 18/43] refactor: generateQuery --- .../src/fetcher-fetch-hardcoded.ts | 35 ++---------- .../src/fetcher-graphql-request.ts | 56 ++++--------------- .../__snapshots__/react-query.spec.ts.snap | 49 +++++++++------- 3 files changed, 45 insertions(+), 95 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index c0c15c356..79c0c02c2 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -94,38 +94,13 @@ ${this.getFetchParams()} } generateQueryHook(config: GenerateQueryHookConfig): string { - const { - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - } = config; - - const variables = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.query.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.query.options); + const { generateBaseQueryHook } = this.generateQueryHelper(config); - const options = `options?: ${hookConfig.query.options}<${operationResultType}, TError, TData>`; + const { documentVariableName, operationResultType, operationVariablesTypes } = config; - return `export const use${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( - ${variables}, - ${options} - ) => - ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${this.generateQueryFormattedParameters( - this.generateQueryKey(node, hasRequiredVariables), - `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)`, - )} - );`; + return generateBaseQueryHook({ + implFetcher: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)`, + }); } generateMutationHook( diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 69cebcff3..4bee22ec7 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -93,20 +93,6 @@ function fetcher(client: Graph } generateQueryHook(config: GenerateQueryHookConfig): string { - const { - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - } = config; - - const variables = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); - const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); @@ -114,42 +100,24 @@ function fetcher(client: Graph `${typeImport} { RequestInit } from 'graphql-request/dist/types.dom';`, ); - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.query.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.query.options); + const { generateBaseQueryHook, variables, options } = this.generateQueryHelper(config); - const options = `options?: ${hookConfig.query.options}<${operationResultType}, TError, TData>`; + const { documentVariableName, operationResultType, operationVariablesTypes } = config; return this.clientPath - ? `export const use${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( - ${variables}, + ? generateBaseQueryHook({ + implArguments: `${variables}, ${options}, - headers?: RequestInit['headers'] - ) => - ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${this.generateQueryFormattedParameters( - this.generateQueryKey(node, hasRequiredVariables), - `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, - )} - );` - : `export const use${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( - client: GraphQLClient, + headers?: RequestInit['headers']`, + implFetcher: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, + }) + : generateBaseQueryHook({ + implArguments: `client: GraphQLClient, ${variables}, ${options}, - headers?: RequestInit['headers'] - ) => - ${hookConfig.query.hook}<${operationResultType}, TError, TData>( - ${this.generateQueryFormattedParameters( - this.generateQueryKey(node, hasRequiredVariables), - `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, - )} - );`; + headers?: RequestInit['headers']`, + implFetcher: `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, + }); } generateMutationHook( diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index d4d4692f7..6438e6b41 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -553,12 +553,13 @@ export const useTestQuery = < variables?: TTestQueryVariables, options?: UseQueryOptions, headers?: RequestInit['headers'] - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(client, TestDocument, variables, headers), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -621,12 +622,13 @@ export const useTestQuery = < variables?: TTestQueryVariables, options?: UseQueryOptions, headers?: RequestInit['headers'] - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(TestDocument, variables, headers), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -688,12 +690,13 @@ export const useTestQuery = < >( variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(TestDocument, variables), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -761,12 +764,13 @@ export const useTestQuery = < >( variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(TestDocument, variables), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -834,12 +838,13 @@ export const useTestQuery = < >( variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(TestDocument, variables), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -906,12 +911,13 @@ export const useTestQuery = < >( variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(TestDocument, variables), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -978,12 +984,13 @@ export const useTestQuery = < >( variables?: TTestQueryVariables, options?: UseQueryOptions - ) => - useQuery( + ) => { + + return useQuery( variables === undefined ? ['test'] : ['test', variables], fetcher(TestDocument, variables), options - ); + )}; export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { From afd2cc2c0279529a31aa554745acadcfdf7f9f42 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Thu, 12 Oct 2023 18:39:02 +0800 Subject: [PATCH 19/43] refactor: interface --- .../react-query/src/fetcher-custom-mapper.ts | 38 +++++++++--------- .../src/fetcher-fetch-hardcoded.ts | 39 ++++++++++--------- .../react-query/src/fetcher-fetch.ts | 39 ++++++++++--------- .../src/fetcher-graphql-request.ts | 39 ++++++++++--------- .../typescript/react-query/src/fetcher.ts | 24 +++--------- .../typescript/react-query/src/visitor.ts | 8 ++-- 6 files changed, 92 insertions(+), 95 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 42a67778b..512122df9 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -6,7 +6,7 @@ import { parseMapper, } from '@graphql-codegen/visitor-plugin-common'; import { CustomFetch } from './config.js'; -import { FetcherRenderer, type GenerateQueryHookConfig } from './fetcher.js'; +import { FetcherRenderer, type GenerateHookConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class CustomMapperFetcher extends FetcherRenderer { @@ -44,14 +44,16 @@ export class CustomMapperFetcher extends FetcherRenderer { return null; } - generateInfiniteQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateInfiniteQueryHook(config: GenerateHookConfig): string { + const { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + operationName, + hasRequiredVariables, + } = config; + const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, @@ -90,7 +92,7 @@ export class CustomMapperFetcher extends FetcherRenderer { )};`; } - generateQueryHook(config: GenerateQueryHookConfig): string { + generateQueryHook(config: GenerateHookConfig): string { const { generateBaseQueryHook } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -105,14 +107,14 @@ export class CustomMapperFetcher extends FetcherRenderer { }); } - generateMutationHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateMutationHook(config: GenerateHookConfig): string { + const { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + operationName, + } = config; const variables = `variables?: ${operationVariablesTypes}`; const hookConfig = this.visitor.queryMethodMap; this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 79c0c02c2..0b7f7b67d 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -1,7 +1,7 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; -import { FetcherRenderer, type GenerateQueryHookConfig } from './fetcher.js'; +import { FetcherRenderer, type GenerateHookConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class HardcodedFetchFetcher extends FetcherRenderer { @@ -57,14 +57,16 @@ ${this.getFetchParams()} }`; } - generateInfiniteQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateInfiniteQueryHook(config: GenerateHookConfig): string { + const { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + operationName, + hasRequiredVariables, + } = config; + const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, @@ -93,7 +95,7 @@ ${this.getFetchParams()} );`; } - generateQueryHook(config: GenerateQueryHookConfig): string { + generateQueryHook(config: GenerateHookConfig): string { const { generateBaseQueryHook } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -103,14 +105,15 @@ ${this.getFetchParams()} }); } - generateMutationHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateMutationHook(config: GenerateHookConfig): string { + const { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + operationName, + } = config; + const variables = `variables?: ${operationVariablesTypes}`; const hookConfig = this.visitor.queryMethodMap; this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 530beb4ab..2d61f570e 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,6 +1,6 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; -import { FetcherRenderer, type GenerateQueryHookConfig } from './fetcher.js'; +import { FetcherRenderer, type GenerateHookConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class FetchFetcher extends FetcherRenderer { @@ -32,14 +32,16 @@ function fetcher(endpoint: string, requestInit: RequestInit, }`; } - generateInfiniteQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateInfiniteQueryHook(config: GenerateHookConfig): string { + const { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + operationName, + hasRequiredVariables, + } = config; + const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, @@ -69,7 +71,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, );`; } - generateQueryHook(config: GenerateQueryHookConfig): string { + generateQueryHook(config: GenerateHookConfig): string { const { generateBaseQueryHook, variables, options } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -82,14 +84,15 @@ function fetcher(endpoint: string, requestInit: RequestInit, }); } - generateMutationHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateMutationHook(config: GenerateHookConfig): string { + const { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + operationName, + } = config; + const variables = `variables?: ${operationVariablesTypes}`; const hookConfig = this.visitor.queryMethodMap; this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 4bee22ec7..fffe9cd1a 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -1,7 +1,7 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; -import { FetcherRenderer, type GenerateQueryHookConfig } from './fetcher.js'; +import { FetcherRenderer, type GenerateHookConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class GraphQLRequestClientFetcher extends FetcherRenderer { @@ -33,14 +33,16 @@ function fetcher(client: Graph }`; } - generateInfiniteQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateInfiniteQueryHook(config: GenerateHookConfig): string { + const { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + operationName, + hasRequiredVariables, + } = config; + const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, @@ -92,7 +94,7 @@ function fetcher(client: Graph );`; } - generateQueryHook(config: GenerateQueryHookConfig): string { + generateQueryHook(config: GenerateHookConfig): string { const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); @@ -120,14 +122,15 @@ function fetcher(client: Graph }); } - generateMutationHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateMutationHook(config: GenerateHookConfig): string { + const { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + operationName, + } = config; + const variables = `variables?: ${operationVariablesTypes}`; const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index df0c0e744..3662818f1 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -2,7 +2,7 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { ReactQueryVisitor } from './visitor.js'; -export interface GenerateQueryHookConfig { +export interface GenerateHookConfig { node: OperationDefinitionNode; documentVariableName: string; operationName: string; @@ -16,7 +16,7 @@ export class BaseFetcherRenderer { autoBind(this); } - generateQueryHelper(config: GenerateQueryHookConfig) { + generateQueryHelper(config: GenerateHookConfig) { const { node, operationName, @@ -206,23 +206,9 @@ export class BaseFetcherRenderer { export abstract class FetcherRenderer extends BaseFetcherRenderer { abstract generateFetcherImplementation(): string; - abstract generateQueryHook(config: GenerateQueryHookConfig): string; - abstract generateInfiniteQueryHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string; - abstract generateMutationHook( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string; + abstract generateQueryHook(config: GenerateHookConfig): string; + abstract generateInfiniteQueryHook(config: GenerateHookConfig): string; + abstract generateMutationHook(config: GenerateHookConfig): string; abstract generateFetcherFetch( node: OperationDefinitionNode, documentVariableName: string, diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index 65a7ed745..acbefd0fa 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -211,14 +211,14 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< query += `\n${this.fetcher.generateQueryRootKeyMaker(node, operationName)}`; } if (this.config.addInfiniteQuery) { - query += `\n${this.fetcher.generateInfiniteQueryHook( + query += `\n${this.fetcher.generateInfiniteQueryHook({ node, documentVariableName, operationName, operationResultType, operationVariablesTypes, hasRequiredVariables, - )}\n`; + })}\n`; if (this.config.exposeQueryKeys) { query += `\n${this.fetcher.generateInfiniteQueryKeyMaker( node, @@ -248,14 +248,14 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< return query; } if (operationType === 'Mutation') { - let query = this.fetcher.generateMutationHook( + let query = this.fetcher.generateMutationHook({ node, documentVariableName, operationName, operationResultType, operationVariablesTypes, hasRequiredVariables, - ); + }); if (this.config.exposeMutationKeys) { query += this.fetcher.generateMutationKeyMaker(node, operationName); } From 040249d549d95c0cabca57879eb75ccbb1f9e0bd Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 10:19:53 +0800 Subject: [PATCH 20/43] refactor: type --- .../typescript/react-query/src/visitor.ts | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index acbefd0fa..0da364169 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -18,28 +18,7 @@ import { FetcherRenderer } from './fetcher.js'; export type ReactQueryPluginConfig = BaseReactQueryPluginConfig & ClientSideBasePluginConfig; -export interface ReactQueryMethodMap { - infiniteQuery: { - hook: string; - options: string; - }; - suspenseInfiniteQuery: { - hook: string; - options: string; - }; - suspenseQuery: { - hook: string; - options: string; - }; - query: { - hook: string; - options: string; - }; - mutation: { - hook: string; - options: string; - }; -} +export type ReactQueryMethodMap = { [key: string]: { hook: string; options: string } }; export class ReactQueryVisitor extends ClientSideBaseVisitor< ReactQueryRawPluginConfig, From 45c0e1759d0b45c9ffa493801667f604689c5d07 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 10:35:40 +0800 Subject: [PATCH 21/43] refactor: type --- .../typescript/react-query/src/fetcher-custom-mapper.ts | 8 ++++---- .../typescript/react-query/src/fetcher-fetch-hardcoded.ts | 8 ++++---- .../plugins/typescript/react-query/src/fetcher-fetch.ts | 8 ++++---- .../typescript/react-query/src/fetcher-graphql-request.ts | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 512122df9..aed443f6d 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -6,7 +6,7 @@ import { parseMapper, } from '@graphql-codegen/visitor-plugin-common'; import { CustomFetch } from './config.js'; -import { FetcherRenderer, type GenerateHookConfig } from './fetcher.js'; +import { type BuildOperationConfig, FetcherRenderer } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class CustomMapperFetcher extends FetcherRenderer { @@ -44,7 +44,7 @@ export class CustomMapperFetcher extends FetcherRenderer { return null; } - generateInfiniteQueryHook(config: GenerateHookConfig): string { + generateInfiniteQueryHook(config: BuildOperationConfig): string { const { node, documentVariableName, @@ -92,7 +92,7 @@ export class CustomMapperFetcher extends FetcherRenderer { )};`; } - generateQueryHook(config: GenerateHookConfig): string { + generateQueryHook(config: BuildOperationConfig): string { const { generateBaseQueryHook } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -107,7 +107,7 @@ export class CustomMapperFetcher extends FetcherRenderer { }); } - generateMutationHook(config: GenerateHookConfig): string { + generateMutationHook(config: BuildOperationConfig): string { const { node, documentVariableName, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 0b7f7b67d..5f7e7d45e 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -1,7 +1,7 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; -import { FetcherRenderer, type GenerateHookConfig } from './fetcher.js'; +import { type BuildOperationConfig, FetcherRenderer } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class HardcodedFetchFetcher extends FetcherRenderer { @@ -57,7 +57,7 @@ ${this.getFetchParams()} }`; } - generateInfiniteQueryHook(config: GenerateHookConfig): string { + generateInfiniteQueryHook(config: BuildOperationConfig): string { const { node, documentVariableName, @@ -95,7 +95,7 @@ ${this.getFetchParams()} );`; } - generateQueryHook(config: GenerateHookConfig): string { + generateQueryHook(config: BuildOperationConfig): string { const { generateBaseQueryHook } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -105,7 +105,7 @@ ${this.getFetchParams()} }); } - generateMutationHook(config: GenerateHookConfig): string { + generateMutationHook(config: BuildOperationConfig): string { const { node, documentVariableName, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 2d61f570e..da800d940 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,6 +1,6 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; -import { FetcherRenderer, type GenerateHookConfig } from './fetcher.js'; +import { type BuildOperationConfig, FetcherRenderer } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class FetchFetcher extends FetcherRenderer { @@ -32,7 +32,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, }`; } - generateInfiniteQueryHook(config: GenerateHookConfig): string { + generateInfiniteQueryHook(config: BuildOperationConfig): string { const { node, documentVariableName, @@ -71,7 +71,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, );`; } - generateQueryHook(config: GenerateHookConfig): string { + generateQueryHook(config: BuildOperationConfig): string { const { generateBaseQueryHook, variables, options } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -84,7 +84,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, }); } - generateMutationHook(config: GenerateHookConfig): string { + generateMutationHook(config: BuildOperationConfig): string { const { node, documentVariableName, diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index fffe9cd1a..36ba99d1d 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -1,7 +1,7 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; -import { FetcherRenderer, type GenerateHookConfig } from './fetcher.js'; +import { type BuildOperationConfig, FetcherRenderer } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class GraphQLRequestClientFetcher extends FetcherRenderer { @@ -33,7 +33,7 @@ function fetcher(client: Graph }`; } - generateInfiniteQueryHook(config: GenerateHookConfig): string { + generateInfiniteQueryHook(config: BuildOperationConfig): string { const { node, documentVariableName, @@ -94,7 +94,7 @@ function fetcher(client: Graph );`; } - generateQueryHook(config: GenerateHookConfig): string { + generateQueryHook(config: BuildOperationConfig): string { const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); @@ -122,7 +122,7 @@ function fetcher(client: Graph }); } - generateMutationHook(config: GenerateHookConfig): string { + generateMutationHook(config: BuildOperationConfig): string { const { node, documentVariableName, From 67799eadbf0e86a4ee2971f166169b29f3172be9 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 10:45:21 +0800 Subject: [PATCH 22/43] refactor: fetcher-fetch mutation --- .../react-query/src/fetcher-fetch.ts | 35 +++-------- .../typescript/react-query/src/fetcher.ts | 58 +++++++++++++++---- .../__snapshots__/react-query.spec.ts.snap | 49 +++++++++------- 3 files changed, 83 insertions(+), 59 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index da800d940..f11f073b4 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -85,36 +85,15 @@ function fetcher(endpoint: string, requestInit: RequestInit, } generateMutationHook(config: BuildOperationConfig): string { - const { - node, - documentVariableName, - operationResultType, - operationVariablesTypes, - operationName, - } = config; + const { generateBaseMutationHook, variables, options } = this.generateMutationHelper(config); - const variables = `variables?: ${operationVariablesTypes}`; - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.mutation.options); - - const options = `options?: ${hookConfig.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; + const { documentVariableName, operationResultType, operationVariablesTypes } = config; - return `export const use${operationName} = < - TError = ${this.visitor.config.errorType}, - TContext = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - ${options} - ) => - ${ - hookConfig.mutation.hook - }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${this.generateMutationFormattedParameters( - this.generateMutationKey(node), - `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)()`, - )} - );`; + return generateBaseMutationHook({ + implArguments: `dataSource: { endpoint: string, fetchParams?: RequestInit }, + ${options}`, + implFetcher: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)()`, + }); } generateFetcherFetch( diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 3662818f1..19d15a851 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -2,7 +2,7 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { ReactQueryVisitor } from './visitor.js'; -export interface GenerateHookConfig { +export interface BuildOperationConfig { node: OperationDefinitionNode; documentVariableName: string; operationName: string; @@ -11,12 +11,18 @@ export interface GenerateHookConfig { hasRequiredVariables: boolean; } +interface GenerateBaseHookConfig { + implArguments?: string; + implHookOuter?: string; + implFetcher: string; +} + export class BaseFetcherRenderer { constructor(protected visitor: ReactQueryVisitor) { autoBind(this); } - generateQueryHelper(config: GenerateHookConfig) { + generateQueryHelper(config: BuildOperationConfig) { const { node, operationName, @@ -35,11 +41,7 @@ export class BaseFetcherRenderer { const options = `options?: ${hookConfig.query.options}<${operationResultType}, TError, TData>`; - const generateBaseQueryHook = (config: { - implArguments?: string; - implHookOuter?: string; - implFetcher: string; - }) => { + const generateBaseQueryHook = (config: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = config; const argumentsResult = @@ -69,6 +71,42 @@ export class BaseFetcherRenderer { }; } + generateMutationHelper(config: BuildOperationConfig) { + const { node, operationResultType, operationVariablesTypes, operationName } = config; + + const variables = `variables?: ${operationVariablesTypes}`; + const hookConfig = this.visitor.queryMethodMap; + this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); + this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.mutation.options); + + const options = `options?: ${hookConfig.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; + + const generateBaseMutationHook = (config: GenerateBaseHookConfig) => { + const { implArguments, implHookOuter = '', implFetcher } = config; + + const argumentsResult = implArguments ?? `${options}`; + + return `export const use${operationName} = < + TError = ${this.visitor.config.errorType}, + TContext = unknown + >( + ${argumentsResult} + ) => { + ${implHookOuter} + return ${ + hookConfig.mutation.hook + }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( + ${this.generateMutationFormattedParameters(this.generateMutationKey(node), implFetcher)} + )};`; + }; + + return { + generateBaseMutationHook, + variables, + options, + }; + } + generateQueryVariablesSignature( hasRequiredVariables: boolean, operationVariablesTypes: string, @@ -206,9 +244,9 @@ export class BaseFetcherRenderer { export abstract class FetcherRenderer extends BaseFetcherRenderer { abstract generateFetcherImplementation(): string; - abstract generateQueryHook(config: GenerateHookConfig): string; - abstract generateInfiniteQueryHook(config: GenerateHookConfig): string; - abstract generateMutationHook(config: GenerateHookConfig): string; + abstract generateQueryHook(config: BuildOperationConfig): string; + abstract generateInfiniteQueryHook(config: BuildOperationConfig): string; + abstract generateMutationHook(config: BuildOperationConfig): string; abstract generateFetcherFetch( node: OperationDefinitionNode, documentVariableName: string, diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 6438e6b41..3f4ddc9e1 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -48,12 +48,13 @@ export const useTestMutation = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, options?: UseMutationOptions - ) => - useMutation( + ) => { + + return useMutation( ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - );" + )};" `; exports[`React-Query exposeQueryKeys: true, addInfiniteQuery: true Should generate getKey for each query - also infinite queries 1`] = ` @@ -122,12 +123,13 @@ export const useTestMutation = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, options?: UseMutationOptions - ) => - useMutation( + ) => { + + return useMutation( ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - );" + )};" `; exports[`React-Query exposeQueryRootKeys: true Should generate rootKey for each query 1`] = ` @@ -177,12 +179,13 @@ export const useTestMutation = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, options?: UseMutationOptions - ) => - useMutation( + ) => { + + return useMutation( ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - );" + )};" `; exports[`React-Query exposeQueryRootKeys: true, addInfiniteQuery: true Should generate rootKey for each query - also infinite queries 1`] = ` @@ -249,12 +252,13 @@ export const useTestMutation = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, options?: UseMutationOptions - ) => - useMutation( + ) => { + + return useMutation( ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: custom-mapper Should generate mutation correctly with lazy variables: content 1`] = ` @@ -494,12 +498,13 @@ export const useTestMutation = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, options?: UseMutationOptions - ) => - useMutation( + ) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: fetch Should generate query and mutation correctly: prepend 1`] = ` @@ -1118,12 +1123,13 @@ export const useTestMutation = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, options?: UseMutationOptions - ) => - useMutation( + ) => { + + return useMutation( ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - );" + )};" `; exports[`React-Query support v4 syntax: prepend 1`] = ` @@ -1217,12 +1223,13 @@ export const useTestMutation = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, options?: UseMutationOptions - ) => - useMutation( + ) => { + + return useMutation( { mutationKey: ['test'], mutationFn: (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), ...options } - );" + )};" `; From b47f600c1e097b4590fc859dc0d1c258ae39495e Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 11:00:18 +0800 Subject: [PATCH 23/43] refactor: fetch-hardcode mutation --- .../src/fetcher-fetch-hardcoded.ts | 32 ++++------------- .../react-query/src/fetcher-fetch.ts | 12 ++++--- .../src/fetcher-graphql-request.ts | 12 ++++--- .../typescript/react-query/src/fetcher.ts | 14 ++++---- .../__snapshots__/react-query.spec.ts.snap | 35 +++++++++++-------- 5 files changed, 48 insertions(+), 57 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index 5f7e7d45e..a2031def5 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -106,33 +106,13 @@ ${this.getFetchParams()} } generateMutationHook(config: BuildOperationConfig): string { - const { - node, - documentVariableName, - operationResultType, - operationVariablesTypes, - operationName, - } = config; + const { generateBaseMutationHook, variables } = this.generateMutationHelper(config); - const variables = `variables?: ${operationVariablesTypes}`; - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.mutation.options); - - const options = `options?: ${hookConfig.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; - - return `export const use${operationName} = < - TError = ${this.visitor.config.errorType}, - TContext = unknown - >(${options}) => - ${ - hookConfig.mutation.hook - }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${this.generateMutationFormattedParameters( - this.generateMutationKey(node), - `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)()`, - )} - );`; + const { documentVariableName, operationResultType, operationVariablesTypes } = config; + + return generateBaseMutationHook({ + implFetcher: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables)()`, + }); } generateFetcherFetch( diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index f11f073b4..e1288c0de 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -77,9 +77,11 @@ function fetcher(endpoint: string, requestInit: RequestInit, const { documentVariableName, operationResultType, operationVariablesTypes } = config; return generateBaseQueryHook({ - implArguments: `dataSource: { endpoint: string, fetchParams?: RequestInit }, + implArguments: ` + dataSource: { endpoint: string, fetchParams?: RequestInit }, ${variables}, - ${options}`, + ${options} + `, implFetcher: `fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)`, }); } @@ -90,8 +92,10 @@ function fetcher(endpoint: string, requestInit: RequestInit, const { documentVariableName, operationResultType, operationVariablesTypes } = config; return generateBaseMutationHook({ - implArguments: `dataSource: { endpoint: string, fetchParams?: RequestInit }, - ${options}`, + implArguments: ` + dataSource: { endpoint: string, fetchParams?: RequestInit }, + ${options} + `, implFetcher: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables)()`, }); } diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 36ba99d1d..d0f6b96aa 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -108,16 +108,20 @@ function fetcher(client: Graph return this.clientPath ? generateBaseQueryHook({ - implArguments: `${variables}, + implArguments: ` + ${variables}, ${options}, - headers?: RequestInit['headers']`, + headers?: RequestInit['headers'] + `, implFetcher: `fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)`, }) : generateBaseQueryHook({ - implArguments: `client: GraphQLClient, + implArguments: ` + client: GraphQLClient, ${variables}, ${options}, - headers?: RequestInit['headers']`, + headers?: RequestInit['headers'] + `, implFetcher: `fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)`, }); } diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 19d15a851..53461224e 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -46,15 +46,15 @@ export class BaseFetcherRenderer { const argumentsResult = implArguments ?? - `${variables}, - ${options}`; + ` + ${variables}, + ${options} + `; return `export const use${operationName} = < TData = ${operationResultType}, TError = ${this.visitor.config.errorType} - >( - ${argumentsResult} - ) => { + >(${argumentsResult}) => { ${implHookOuter} return ${hookConfig.query.hook}<${operationResultType}, TError, TData>( ${this.generateQueryFormattedParameters( @@ -89,9 +89,7 @@ export class BaseFetcherRenderer { return `export const use${operationName} = < TError = ${this.visitor.config.errorType}, TContext = unknown - >( - ${argumentsResult} - ) => { + >(${argumentsResult}) => { ${implHookOuter} return ${ hookConfig.mutation.hook diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 3f4ddc9e1..d9cba70a2 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -712,12 +712,13 @@ export const TestDocument = \` export const useTestMutation = < TError = unknown, TContext = unknown - >(options?: UseMutationOptions) => - useMutation( + >(options?: UseMutationOptions) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config and fetchParams object: prepend 1`] = ` @@ -786,12 +787,13 @@ export const TestDocument = \` export const useTestMutation = < TError = unknown, TContext = unknown - >(options?: UseMutationOptions) => - useMutation( + >(options?: UseMutationOptions) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config: prepend 1`] = ` @@ -860,12 +862,13 @@ export const TestDocument = \` export const useTestMutation = < TError = unknown, TContext = unknown - >(options?: UseMutationOptions) => - useMutation( + >(options?: UseMutationOptions) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from env var: prepend 1`] = ` @@ -933,12 +936,13 @@ export const TestDocument = \` export const useTestMutation = < TError = unknown, TContext = unknown - >(options?: UseMutationOptions) => - useMutation( + >(options?: UseMutationOptions) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from just identifier: prepend 1`] = ` @@ -1006,12 +1010,13 @@ export const TestDocument = \` export const useTestMutation = < TError = unknown, TContext = unknown - >(options?: UseMutationOptions) => - useMutation( + >(options?: UseMutationOptions) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint: prepend 1`] = ` From 40f8787f407c508de535f430f2a6c3e484577388 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 11:04:15 +0800 Subject: [PATCH 24/43] refactor: fetch-graphql-request mutation --- .../src/fetcher-graphql-request.ts | 51 +++++-------------- .../__snapshots__/react-query.spec.ts.snap | 14 ++--- 2 files changed, 20 insertions(+), 45 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index d0f6b96aa..dbbec058c 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -127,57 +127,30 @@ function fetcher(client: Graph } generateMutationHook(config: BuildOperationConfig): string { - const { - node, - documentVariableName, - operationResultType, - operationVariablesTypes, - operationName, - } = config; - - const variables = `variables?: ${operationVariablesTypes}`; const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.mutation.options); + const { generateBaseMutationHook, variables, options } = this.generateMutationHelper(config); - const options = `options?: ${hookConfig.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; + const { documentVariableName, operationResultType, operationVariablesTypes } = config; return this.clientPath - ? `export const use${operationName} = < - TError = ${this.visitor.config.errorType}, - TContext = unknown - >( + ? generateBaseMutationHook({ + implArguments: ` ${options}, headers?: RequestInit['headers'] - ) => - ${ - hookConfig.mutation.hook - }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${this.generateMutationFormattedParameters( - this.generateMutationKey(node), - `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)()`, - )} - );` - : `export const use${operationName} = < - TError = ${this.visitor.config.errorType}, - TContext = unknown - >( + `, + implFetcher: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables, headers)()`, + }) + : generateBaseMutationHook({ + implArguments: ` client: GraphQLClient, ${options}, headers?: RequestInit['headers'] - ) => - ${ - hookConfig.mutation.hook - }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${this.generateMutationFormattedParameters( - this.generateMutationKey(node), - `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)()`, - )} - );`; + `, + implFetcher: `(${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, variables, headers)()`, + }); } generateFetcherFetch( diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index d9cba70a2..18395beb7 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -579,12 +579,13 @@ export const useTestMutation = < client: GraphQLClient, options?: UseMutationOptions, headers?: RequestInit['headers'] - ) => - useMutation( + ) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => fetcher(client, TestDocument, variables, headers)(), options - );" + )};" `; exports[`React-Query fetcher: graphql-request Should generate query correctly with client: prepend 1`] = ` @@ -647,12 +648,13 @@ export const useTestMutation = < >( options?: UseMutationOptions, headers?: RequestInit['headers'] - ) => - useMutation( + ) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables, headers)(), options - );" + )};" `; exports[`React-Query fetcher: graphql-request with clientImportPath Should generate query correctly with client: prepend 1`] = ` From 985b834d5947279256b30c2186da44185fde593f Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 11:09:01 +0800 Subject: [PATCH 25/43] refactor: fetch-custom-mapper mutation --- .../react-query/src/fetcher-custom-mapper.ts | 33 +++++-------------- .../__snapshots__/react-query.spec.ts.snap | 21 +++++++----- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index aed443f6d..e1d0a7339 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -98,43 +98,28 @@ export class CustomMapperFetcher extends FetcherRenderer { const { documentVariableName, operationResultType, operationVariablesTypes } = config; const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); - const impl = this._isReactHook + const implFetcher = this._isReactHook ? `${typedFetcher}(${documentVariableName}).bind(null, variables)` : `${typedFetcher}(${documentVariableName}, variables)`; return generateBaseQueryHook({ - implFetcher: impl, + implFetcher, }); } generateMutationHook(config: BuildOperationConfig): string { - const { - node, - documentVariableName, - operationResultType, - operationVariablesTypes, - operationName, - } = config; - const variables = `variables?: ${operationVariablesTypes}`; - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.mutation.options); + const { documentVariableName, operationResultType, operationVariablesTypes } = config; + + const { generateBaseMutationHook, variables } = this.generateMutationHelper(config); - const options = `options?: ${hookConfig.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); - const impl = this._isReactHook + const implFetcher = this._isReactHook ? `${typedFetcher}(${documentVariableName})` : `(${variables}) => ${typedFetcher}(${documentVariableName}, variables)()`; - return `export const use${operationName} = < - TError = ${this.visitor.config.errorType}, - TContext = unknown - >(${options}) => - ${ - hookConfig.mutation.hook - }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${this.generateMutationFormattedParameters(this.generateMutationKey(node), impl)} - );`; + return generateBaseMutationHook({ + implFetcher, + }); } generateFetcherFetch( diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 18395beb7..531dad03c 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -315,12 +315,13 @@ export const TestDocument = \` export const useTestMutation = < TError = unknown, TContext = unknown - >(options?: UseMutationOptions) => - useMutation( + >(options?: UseMutationOptions) => { + + return useMutation( ['test'], useCustomFetcher(TestDocument), options - );" + )};" `; exports[`React-Query fetcher: custom-mapper Should generate mutation correctly with lazy variables: prepend 1`] = ` @@ -384,12 +385,13 @@ export const TestDocument = \` export const useTestMutation = < TError = unknown, TContext = unknown - >(options?: UseMutationOptions) => - useMutation( + >(options?: UseMutationOptions) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => myCustomFetcher(TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: custom-mapper Should generate query correctly with external mapper: prepend 1`] = ` @@ -439,12 +441,13 @@ export const TestDocument = \` export const useTestMutation = < TError = unknown, TContext = unknown - >(options?: UseMutationOptions) => - useMutation( + >(options?: UseMutationOptions) => { + + return useMutation( ['test'], (variables?: TTestMutationVariables) => myCustomFetcher(TestDocument, variables)(), options - );" + )};" `; exports[`React-Query fetcher: custom-mapper Should generate query correctly with internal mapper: prepend 1`] = ` From db04e44b5adc313fd7969df0d1487a6b0cf1a195 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 11:43:56 +0800 Subject: [PATCH 26/43] refactor: fetch-hardcode infiniteQuery --- .../src/fetcher-fetch-hardcoded.ts | 38 ++---------- .../typescript/react-query/src/fetcher.ts | 59 +++++++++++++++++-- .../__snapshots__/react-query.spec.ts.snap | 16 ++++- .../react-query/tests/react-query.spec.ts | 1 + 4 files changed, 76 insertions(+), 38 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index a2031def5..fcd2b2a24 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -58,41 +58,13 @@ ${this.getFetchParams()} } generateInfiniteQueryHook(config: BuildOperationConfig): string { - const { - node, - documentVariableName, - operationResultType, - operationVariablesTypes, - operationName, - hasRequiredVariables, - } = config; + const { generateBaseInfiniteQueryHook } = this.generateInfiniteQueryHelper(config); - const variables = this.generateInfiniteQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - - const options = this.generateInfiniteQueryOptionsSignature( - hookConfig.infiniteQuery.options, - operationResultType, - ); + const { documentVariableName, operationResultType, operationVariablesTypes } = config; - return `export const useInfinite${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( - ${variables}, - ${options} - ) => - ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${this.generateInfiniteQueryFormattedParameters( - this.generateInfiniteQueryKey(node, hasRequiredVariables), - `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, - )} - );`; + return generateBaseInfiniteQueryHook({ + implFetcher: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, + }); } generateQueryHook(config: BuildOperationConfig): string { diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 53461224e..e83de4244 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -22,23 +22,73 @@ export class BaseFetcherRenderer { autoBind(this); } - generateQueryHelper(config: BuildOperationConfig) { + generateInfiniteQueryHelper(config: BuildOperationConfig) { const { node, - operationName, operationResultType, operationVariablesTypes, + operationName, hasRequiredVariables, } = config; - const variables = this.generateQueryVariablesSignature( + const hookConfig = this.visitor.queryMethodMap; + this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); + this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); + + const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); + + const options = this.generateInfiniteQueryOptionsSignature( + hookConfig.infiniteQuery.options, + operationResultType, + ); + + const generateBaseInfiniteQueryHook = (config: GenerateBaseHookConfig) => { + const { implArguments, implHookOuter = '', implFetcher } = config; + + const argumentsResult = + implArguments ?? + ` + ${variables}, + ${options} + `; + + return `export const useInfinite${operationName} = < + TData = ${operationResultType}, + TError = ${this.visitor.config.errorType} + >(${argumentsResult}) => { + ${implHookOuter} + return ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( + ${this.generateInfiniteQueryFormattedParameters( + this.generateInfiniteQueryKey(node, hasRequiredVariables), + implFetcher, + )} + )};`; + }; + + return { generateBaseInfiniteQueryHook, variables, options }; + } + + generateQueryHelper(config: BuildOperationConfig) { + const { + node, + operationName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + } = config; + const hookConfig = this.visitor.queryMethodMap; this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.query.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.query.options); + const variables = this.generateQueryVariablesSignature( + hasRequiredVariables, + operationVariablesTypes, + ); + const options = `options?: ${hookConfig.query.options}<${operationResultType}, TError, TData>`; const generateBaseQueryHook = (config: GenerateBaseHookConfig) => { @@ -74,11 +124,12 @@ export class BaseFetcherRenderer { generateMutationHelper(config: BuildOperationConfig) { const { node, operationResultType, operationVariablesTypes, operationName } = config; - const variables = `variables?: ${operationVariablesTypes}`; const hookConfig = this.visitor.queryMethodMap; this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.mutation.options); + const variables = `variables?: ${operationVariablesTypes}`; + const options = `options?: ${hookConfig.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; const generateBaseMutationHook = (config: GenerateBaseHookConfig) => { diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 531dad03c..fccb20fdb 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -1005,6 +1005,20 @@ export const useTestQuery = < fetcher(TestDocument, variables), options )}; +export const useInfiniteTestQuery = < + TData = TTestQuery, + TError = unknown + >( + variables?: TTestQueryVariables, + options?: UseInfiniteQueryOptions + ) => { + + return useInfiniteQuery( + variables === undefined ? ['test.infinite'] : ['test.infinite', variables], + (metaData) => fetcher(TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), + options + )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -1026,7 +1040,7 @@ export const useTestMutation = < exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint: prepend 1`] = ` [ - "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';", + "import { useQuery, useInfiniteQuery, useMutation, UseQueryOptions, UseInfiniteQueryOptions, UseMutationOptions } from 'react-query';", " function fetcher(query: string, variables?: TVariables) { return async (): Promise => { diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index a5b7ad620..5592bca79 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -596,6 +596,7 @@ describe('React-Query', () => { }, typesPrefix: 'T', legacyMode: true, + addInfiniteQuery: true, }; const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; From 206dea6239969423d1eb0a060a282640efc4f2c7 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 11:46:55 +0800 Subject: [PATCH 27/43] refactor: custom-mapper infiniteQuery --- .../react-query/src/fetcher-custom-mapper.ts | 45 ++++--------------- .../__snapshots__/react-query.spec.ts.snap | 4 +- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index e1d0a7339..afc8fa624 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -45,51 +45,22 @@ export class CustomMapperFetcher extends FetcherRenderer { } generateInfiniteQueryHook(config: BuildOperationConfig): string { - const { - node, - documentVariableName, - operationResultType, - operationVariablesTypes, - operationName, - hasRequiredVariables, - } = config; - - const variables = this.generateInfiniteQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); - - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); - - const options = this.generateInfiniteQueryOptionsSignature( - hookConfig.infiniteQuery.options, - operationResultType, - ); + const { documentVariableName, operationResultType, operationVariablesTypes } = config; const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); const implHookOuter = this._isReactHook ? `const query = ${typedFetcher}(${documentVariableName})` : ''; - const impl = this._isReactHook + const implFetcher = this._isReactHook ? `(metaData) => query({...variables, ...(metaData.pageParam ?? {})})` : `(metaData) => ${typedFetcher}(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`; - return `export const useInfinite${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( - ${variables}, - ${options} - ) =>{ - ${implHookOuter} - return ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${this.generateInfiniteQueryFormattedParameters( - this.generateInfiniteQueryKey(node, hasRequiredVariables), - impl, - )} - )};`; + const { generateBaseInfiniteQueryHook } = this.generateInfiniteQueryHelper(config); + + return generateBaseInfiniteQueryHook({ + implHookOuter, + implFetcher, + }); } generateQueryHook(config: BuildOperationConfig): string { diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index fccb20fdb..0ddef3cf7 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -297,7 +297,7 @@ export const useInfiniteTestQuery = < >( variables?: TTestQueryVariables, options?: UseInfiniteQueryOptions - ) =>{ + ) => { const query = useCustomFetcher(TestDocument) return useInfiniteQuery( variables === undefined ? ['test.infinite'] : ['test.infinite', variables], @@ -367,7 +367,7 @@ export const useInfiniteTestQuery = < >( variables?: TTestQueryVariables, options?: UseInfiniteQueryOptions - ) =>{ + ) => { return useInfiniteQuery( variables === undefined ? ['test.infinite'] : ['test.infinite', variables], From fc3ffaef9d5ad9868914f161a68d21931df7db35 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 11:50:14 +0800 Subject: [PATCH 28/43] refactor: fetch infiniteQuery --- .../react-query/src/fetcher-fetch.ts | 39 ++++--------------- .../__snapshots__/react-query.spec.ts.snap | 28 +++++++------ 2 files changed, 24 insertions(+), 43 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index e1288c0de..a4f329fe6 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -33,42 +33,19 @@ function fetcher(endpoint: string, requestInit: RequestInit, } generateInfiniteQueryHook(config: BuildOperationConfig): string { - const { - node, - documentVariableName, - operationResultType, - operationVariablesTypes, - operationName, - hasRequiredVariables, - } = config; - - const variables = this.generateInfiniteQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); + const { generateBaseInfiniteQueryHook, variables, options } = + this.generateInfiniteQueryHelper(config); - const options = this.generateInfiniteQueryOptionsSignature( - hookConfig.infiniteQuery.options, - operationResultType, - ); + const { documentVariableName, operationResultType, operationVariablesTypes } = config; - return `export const useInfinite${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( + return generateBaseInfiniteQueryHook({ + implArguments: ` dataSource: { endpoint: string, fetchParams?: RequestInit }, ${variables}, ${options} - ) => - ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${this.generateInfiniteQueryFormattedParameters( - this.generateInfiniteQueryKey(node, hasRequiredVariables), - `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, - )} - );`; + `, + implFetcher: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`, + }); } generateQueryHook(config: BuildOperationConfig): string { diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 0ddef3cf7..b01e090d1 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -99,12 +99,13 @@ export const useInfiniteTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, options?: UseInfiniteQueryOptions - ) => - useInfiniteQuery( + ) => { + + return useInfiniteQuery( variables === undefined ? ['test.infinite'] : ['test.infinite', variables], (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), options - ); + )}; useInfiniteTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test.infinite'] : ['test.infinite', variables]; @@ -229,12 +230,13 @@ export const useInfiniteTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, options?: UseInfiniteQueryOptions - ) => - useInfiniteQuery( + ) => { + + return useInfiniteQuery( variables === undefined ? ['test.infinite'] : ['test.infinite', variables], (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), options - ); + )}; useInfiniteTestQuery.rootKey = 'test.infinite'; @@ -1127,12 +1129,13 @@ export const useInfiniteTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, options?: UseInfiniteQueryOptions - ) => - useInfiniteQuery( + ) => { + + return useInfiniteQuery( variables === undefined ? ['test.infinite'] : ['test.infinite', variables], (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), options - ); + )}; export const TestDocument = \` mutation test($name: String) { @@ -1222,8 +1225,9 @@ export const useInfiniteTestQuery = < dataSource: { endpoint: string, fetchParams?: RequestInit }, variables: TestQueryVariables, options: Omit, 'queryKey'> & { queryKey?: UseInfiniteQueryOptions['queryKey'] } - ) => - useInfiniteQuery( + ) => { + + return useInfiniteQuery( (() => { const { queryKey: optionsQueryKey, ...restOptions } = options; return { @@ -1232,7 +1236,7 @@ export const useInfiniteTestQuery = < ...restOptions } })() - ); + )}; export const TestDocument = \` mutation test($name: String) { From 3f1a0621a74a0192bc2404a300d368f9c23a85f3 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 11:57:50 +0800 Subject: [PATCH 29/43] refactor: graphql-request infiniteQuery --- .../src/fetcher-graphql-request.ts | 56 +++++-------------- .../__snapshots__/react-query.spec.ts.snap | 18 +++++- .../react-query/tests/react-query.spec.ts | 1 + 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index dbbec058c..781b38e70 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -34,64 +34,34 @@ function fetcher(client: Graph } generateInfiniteQueryHook(config: BuildOperationConfig): string { - const { - node, - documentVariableName, - operationResultType, - operationVariablesTypes, - operationName, - hasRequiredVariables, - } = config; - - const variables = this.generateInfiniteQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); - const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); + const { generateBaseInfiniteQueryHook, variables, options } = + this.generateInfiniteQueryHelper(config); - const options = this.generateInfiniteQueryOptionsSignature( - hookConfig.infiniteQuery.options, - operationResultType, - ); + const { documentVariableName, operationResultType, operationVariablesTypes } = config; return this.clientPath - ? `export const useInfinite${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( + ? generateBaseInfiniteQueryHook({ + implArguments: ` pageParamKey: keyof ${operationVariablesTypes}, ${variables}, ${options}, headers?: RequestInit['headers'] - ) => - ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${this.generateInfiniteQueryFormattedParameters( - this.generateInfiniteQueryKey(node, hasRequiredVariables), - `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, [pageParamKey]: metaData.pageParam}, headers)()`, - )} - );` - : `export const useInfinite${operationName} = < - TData = ${operationResultType}, - TError = ${this.visitor.config.errorType} - >( + `, + implFetcher: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, {...variables, [pageParamKey]: metaData.pageParam}, headers)()`, + }) + : generateBaseInfiniteQueryHook({ + implArguments: ` client: GraphQLClient, ${variables}, ${options}, headers?: RequestInit['headers'] - ) => - ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( - ${this.generateInfiniteQueryFormattedParameters( - this.generateInfiniteQueryKey(node, hasRequiredVariables), - `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})}, headers)()`, - )} - );`; + `, + implFetcher: `(metaData) => fetcher<${operationResultType}, ${operationVariablesTypes}>(client, ${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})}, headers)()`, + }); } generateQueryHook(config: BuildOperationConfig): string { diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index b01e090d1..4dbb773dd 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -570,6 +570,22 @@ export const useTestQuery = < fetcher(client, TestDocument, variables, headers), options )}; +export const useInfiniteTestQuery = < + TData = TTestQuery, + TError = unknown + >( + client: GraphQLClient, + variables?: TTestQueryVariables, + options?: UseInfiniteQueryOptions, + headers?: RequestInit['headers'] + ) => { + + return useInfiniteQuery( + variables === undefined ? ['test.infinite'] : ['test.infinite', variables], + (metaData) => fetcher(client, TestDocument, {...variables, ...(metaData.pageParam ?? {})}, headers)(), + options + )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -597,7 +613,7 @@ exports[`React-Query fetcher: graphql-request Should generate query correctly wi [ "import { GraphQLClient } from 'graphql-request';", "import { RequestInit } from 'graphql-request/dist/types.dom';", - "import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from 'react-query';", + "import { useQuery, useInfiniteQuery, useMutation, UseQueryOptions, UseInfiniteQueryOptions, UseMutationOptions } from 'react-query';", " function fetcher(client: GraphQLClient, query: string, variables?: TVariables, requestHeaders?: RequestInit['headers']) { return async (): Promise => client.request({ diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index 5592bca79..c8f970780 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -414,6 +414,7 @@ describe('React-Query', () => { const config = { fetcher: 'graphql-request', typesPrefix: 'T', + addInfiniteQuery: true, legacyMode: true, }; From 5dbbcfbfe2092743e1de14bc014c761b3fcb598a Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 12:24:34 +0800 Subject: [PATCH 30/43] fix: v5 queryOptions queryKey type issue --- .../typescript/react-query/src/fetcher.ts | 66 ++++++++++--------- .../__snapshots__/react-query.spec.ts.snap | 2 +- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index e83de4244..7ff8b5eb6 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -22,7 +22,7 @@ export class BaseFetcherRenderer { autoBind(this); } - generateInfiniteQueryHelper(config: BuildOperationConfig) { + protected generateInfiniteQueryHelper(config: BuildOperationConfig) { const { node, operationResultType, @@ -71,7 +71,7 @@ export class BaseFetcherRenderer { return { generateBaseInfiniteQueryHook, variables, options }; } - generateQueryHelper(config: BuildOperationConfig) { + protected generateQueryHelper(config: BuildOperationConfig) { const { node, operationName, @@ -89,7 +89,10 @@ export class BaseFetcherRenderer { operationVariablesTypes, ); - const options = `options?: ${hookConfig.query.options}<${operationResultType}, TError, TData>`; + const options = this.generateQueryOptionsSignature( + hookConfig.query.options, + operationResultType, + ); const generateBaseQueryHook = (config: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = config; @@ -121,7 +124,7 @@ export class BaseFetcherRenderer { }; } - generateMutationHelper(config: BuildOperationConfig) { + protected generateMutationHelper(config: BuildOperationConfig) { const { node, operationResultType, operationVariablesTypes, operationName } = config; const hookConfig = this.visitor.queryMethodMap; @@ -156,14 +159,21 @@ export class BaseFetcherRenderer { }; } - generateQueryVariablesSignature( + protected generateQueryVariablesSignature( hasRequiredVariables: boolean, operationVariablesTypes: string, ): string { return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; } - generateInfiniteQueryVariablesSignature( + private generateQueryOptionsSignature(queryOptions: string, operationResultType: string): string { + if (this.visitor.config.reactQueryVersion <= 4) { + return `options?: ${queryOptions}<${operationResultType}, TError, TData>`; + } + return `options?: Omit<${queryOptions}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${queryOptions}<${operationResultType}, TError, TData>['queryKey'] }`; + } + + private generateInfiniteQueryVariablesSignature( hasRequiredVariables: boolean, operationVariablesTypes: string, ): string { @@ -173,7 +183,7 @@ export class BaseFetcherRenderer { return `variables: ${operationVariablesTypes}`; } - generateInfiniteQueryOptionsSignature( + private generateInfiniteQueryOptionsSignature( infiniteQueryOptions: string, operationResultType: string, ): string { @@ -183,12 +193,15 @@ export class BaseFetcherRenderer { return `options: Omit<${infiniteQueryOptions}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${infiniteQueryOptions}<${operationResultType}, TError, TData>['queryKey'] }`; } - generateInfiniteQueryKey(node: OperationDefinitionNode, hasRequiredVariables: boolean): string { + public generateInfiniteQueryKey( + node: OperationDefinitionNode, + hasRequiredVariables: boolean, + ): string { if (hasRequiredVariables) return `['${node.name.value}.infinite', variables]`; return `variables === undefined ? ['${node.name.value}.infinite'] : ['${node.name.value}.infinite', variables]`; } - generateInfiniteQueryKeyMaker( + public generateInfiniteQueryKeyMaker( node: OperationDefinitionNode, operationName: string, operationVariablesTypes: string, @@ -204,16 +217,16 @@ export class BaseFetcherRenderer { )};\n`; } - generateInfiniteQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { + public generateInfiniteQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { return `\nuseInfinite${operationName}.rootKey = '${node.name.value}.infinite';\n`; } - generateQueryKey(node: OperationDefinitionNode, hasRequiredVariables: boolean): string { + public generateQueryKey(node: OperationDefinitionNode, hasRequiredVariables: boolean): string { if (hasRequiredVariables) return `['${node.name.value}', variables]`; return `variables === undefined ? ['${node.name.value}'] : ['${node.name.value}', variables]`; } - generateQueryKeyMaker( + public generateQueryKeyMaker( node: OperationDefinitionNode, operationName: string, operationVariablesTypes: string, @@ -229,26 +242,19 @@ export class BaseFetcherRenderer { )};\n`; } - generateQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { + public generateQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { return `\nuse${operationName}.rootKey = '${node.name.value}';\n`; } - generateMutationKey(node: OperationDefinitionNode): string { + public generateMutationKey(node: OperationDefinitionNode): string { return `['${node.name.value}']`; } - generateMutationKeyMaker(node: OperationDefinitionNode, operationName: string) { + public generateMutationKeyMaker(node: OperationDefinitionNode, operationName: string) { return `\nuse${operationName}.getKey = () => ${this.generateMutationKey(node)};\n`; } - generateInfiniteQueryRequired() { - if (this.visitor.config.reactQueryVersion <= 4) { - return '?'; - } - return ''; - } - - generateInfiniteQueryFormattedParameters(queryKey: string, queryFn: string) { + private generateInfiniteQueryFormattedParameters(queryKey: string, queryFn: string) { if (this.visitor.config.reactQueryVersion <= 4) { return `${queryKey}, ${queryFn}, @@ -264,7 +270,7 @@ export class BaseFetcherRenderer { })()`; } - generateQueryFormattedParameters(queryKey: string, queryFn: string): string { + private generateQueryFormattedParameters(queryKey: string, queryFn: string): string { if (this.visitor.config.reactQueryVersion <= 4) { return `${queryKey}, ${queryFn}, @@ -277,7 +283,7 @@ export class BaseFetcherRenderer { }`; } - generateMutationFormattedParameters(mutationKey: string, mutationFn: string): string { + private generateMutationFormattedParameters(mutationKey: string, mutationFn: string): string { if (this.visitor.config.reactQueryVersion <= 4) { return `${mutationKey}, ${mutationFn}, @@ -292,11 +298,11 @@ export class BaseFetcherRenderer { } export abstract class FetcherRenderer extends BaseFetcherRenderer { - abstract generateFetcherImplementation(): string; - abstract generateQueryHook(config: BuildOperationConfig): string; - abstract generateInfiniteQueryHook(config: BuildOperationConfig): string; - abstract generateMutationHook(config: BuildOperationConfig): string; - abstract generateFetcherFetch( + public abstract generateFetcherImplementation(): string; + public abstract generateQueryHook(config: BuildOperationConfig): string; + public abstract generateInfiniteQueryHook(config: BuildOperationConfig): string; + public abstract generateMutationHook(config: BuildOperationConfig): string; + public abstract generateFetcherFetch( node: OperationDefinitionNode, documentVariableName: string, operationName: string, diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 4dbb773dd..91b7e71db 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -1224,7 +1224,7 @@ export const useTestQuery = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, - options?: UseQueryOptions + options?: Omit, 'queryKey'> & { queryKey?: UseQueryOptions['queryKey'] } ) => { return useQuery( From ddace77fb0c471c88979118861e7a90acde62fb7 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 12:32:48 +0800 Subject: [PATCH 31/43] refactor: move queryMethodMap to private --- .../typescript/react-query/src/fetcher.ts | 73 +++++++++++-------- .../typescript/react-query/src/visitor.ts | 25 ------- 2 files changed, 43 insertions(+), 55 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 7ff8b5eb6..cbd46e7a0 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -17,11 +17,36 @@ interface GenerateBaseHookConfig { implFetcher: string; } +type ReactQueryMethodMap = { [key: string]: { hook: string; options: string } }; + export class BaseFetcherRenderer { constructor(protected visitor: ReactQueryVisitor) { autoBind(this); } + private queryMethodMap: ReactQueryMethodMap = { + infiniteQuery: { + hook: 'useInfiniteQuery', + options: 'UseInfiniteQueryOptions', + }, + suspenseInfiniteQuery: { + hook: 'useSuspenseInfiniteQuery', + options: 'UseSuspenseInfiniteQueryOptions', + }, + suspenseQuery: { + hook: 'useSuspenseQuery', + options: 'UseSuspenseQueryOptions', + }, + query: { + hook: 'useQuery', + options: 'UseQueryOptions', + }, + mutation: { + hook: 'useMutation', + options: 'UseMutationOptions', + }, + }; + protected generateInfiniteQueryHelper(config: BuildOperationConfig) { const { node, @@ -31,19 +56,15 @@ export class BaseFetcherRenderer { hasRequiredVariables, } = config; - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.infiniteQuery.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.infiniteQuery.options); + this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.infiniteQuery.hook); + this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.infiniteQuery.options); const variables = this.generateInfiniteQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); - const options = this.generateInfiniteQueryOptionsSignature( - hookConfig.infiniteQuery.options, - operationResultType, - ); + const options = this.generateInfiniteQueryOptionsSignature(operationResultType); const generateBaseInfiniteQueryHook = (config: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = config; @@ -60,7 +81,7 @@ export class BaseFetcherRenderer { TError = ${this.visitor.config.errorType} >(${argumentsResult}) => { ${implHookOuter} - return ${hookConfig.infiniteQuery.hook}<${operationResultType}, TError, TData>( + return ${this.queryMethodMap.infiniteQuery.hook}<${operationResultType}, TError, TData>( ${this.generateInfiniteQueryFormattedParameters( this.generateInfiniteQueryKey(node, hasRequiredVariables), implFetcher, @@ -80,19 +101,15 @@ export class BaseFetcherRenderer { hasRequiredVariables, } = config; - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.query.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.query.options); + this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.query.hook); + this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.query.options); const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, ); - const options = this.generateQueryOptionsSignature( - hookConfig.query.options, - operationResultType, - ); + const options = this.generateQueryOptionsSignature(operationResultType); const generateBaseQueryHook = (config: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = config; @@ -109,7 +126,7 @@ export class BaseFetcherRenderer { TError = ${this.visitor.config.errorType} >(${argumentsResult}) => { ${implHookOuter} - return ${hookConfig.query.hook}<${operationResultType}, TError, TData>( + return ${this.queryMethodMap.query.hook}<${operationResultType}, TError, TData>( ${this.generateQueryFormattedParameters( this.generateQueryKey(node, hasRequiredVariables), implFetcher, @@ -127,13 +144,12 @@ export class BaseFetcherRenderer { protected generateMutationHelper(config: BuildOperationConfig) { const { node, operationResultType, operationVariablesTypes, operationName } = config; - const hookConfig = this.visitor.queryMethodMap; - this.visitor.reactQueryHookIdentifiersInUse.add(hookConfig.mutation.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(hookConfig.mutation.options); + this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.mutation.hook); + this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.mutation.options); const variables = `variables?: ${operationVariablesTypes}`; - const options = `options?: ${hookConfig.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; + const options = `options?: ${this.queryMethodMap.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; const generateBaseMutationHook = (config: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = config; @@ -146,7 +162,7 @@ export class BaseFetcherRenderer { >(${argumentsResult}) => { ${implHookOuter} return ${ - hookConfig.mutation.hook + this.queryMethodMap.mutation.hook }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( ${this.generateMutationFormattedParameters(this.generateMutationKey(node), implFetcher)} )};`; @@ -166,11 +182,11 @@ export class BaseFetcherRenderer { return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; } - private generateQueryOptionsSignature(queryOptions: string, operationResultType: string): string { + private generateQueryOptionsSignature(operationResultType: string): string { if (this.visitor.config.reactQueryVersion <= 4) { - return `options?: ${queryOptions}<${operationResultType}, TError, TData>`; + return `options?: ${this.queryMethodMap.query.options}<${operationResultType}, TError, TData>`; } - return `options?: Omit<${queryOptions}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${queryOptions}<${operationResultType}, TError, TData>['queryKey'] }`; + return `options?: Omit<${this.queryMethodMap.query.options}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${this.queryMethodMap.query.options}<${operationResultType}, TError, TData>['queryKey'] }`; } private generateInfiniteQueryVariablesSignature( @@ -183,14 +199,11 @@ export class BaseFetcherRenderer { return `variables: ${operationVariablesTypes}`; } - private generateInfiniteQueryOptionsSignature( - infiniteQueryOptions: string, - operationResultType: string, - ): string { + private generateInfiniteQueryOptionsSignature(operationResultType: string): string { if (this.visitor.config.reactQueryVersion <= 4) { - return `options?: ${infiniteQueryOptions}<${operationResultType}, TError, TData>`; + return `options?: ${this.queryMethodMap.infiniteQuery.options}<${operationResultType}, TError, TData>`; } - return `options: Omit<${infiniteQueryOptions}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${infiniteQueryOptions}<${operationResultType}, TError, TData>['queryKey'] }`; + return `options: Omit<${this.queryMethodMap.infiniteQuery.options}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${this.queryMethodMap.infiniteQuery.options}<${operationResultType}, TError, TData>['queryKey'] }`; } public generateInfiniteQueryKey( diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index 0da364169..fc6d40813 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -18,8 +18,6 @@ import { FetcherRenderer } from './fetcher.js'; export type ReactQueryPluginConfig = BaseReactQueryPluginConfig & ClientSideBasePluginConfig; -export type ReactQueryMethodMap = { [key: string]: { hook: string; options: string } }; - export class ReactQueryVisitor extends ClientSideBaseVisitor< ReactQueryRawPluginConfig, ReactQueryPluginConfig @@ -29,29 +27,6 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< public reactQueryHookIdentifiersInUse = new Set(); public reactQueryOptionsIdentifiersInUse = new Set(); - public queryMethodMap: ReactQueryMethodMap = { - infiniteQuery: { - hook: 'useInfiniteQuery', - options: 'UseInfiniteQueryOptions', - }, - suspenseInfiniteQuery: { - hook: 'useSuspenseInfiniteQuery', - options: 'UseSuspenseInfiniteQueryOptions', - }, - suspenseQuery: { - hook: 'useSuspenseQuery', - options: 'UseSuspenseQueryOptions', - }, - query: { - hook: 'useQuery', - options: 'UseQueryOptions', - }, - mutation: { - hook: 'useMutation', - options: 'UseMutationOptions', - }, - }; - constructor( schema: GraphQLSchema, fragments: LoadedFragment[], From b226b46563cc224b4ad56c6c6e83d77ab0e6c930 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 12:39:52 +0800 Subject: [PATCH 32/43] fix: dev-test --- dev-test/githunt/types.react-query.ts | 39 +++++++++++++++++---------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/dev-test/githunt/types.react-query.ts b/dev-test/githunt/types.react-query.ts index 38315319a..a56a34556 100644 --- a/dev-test/githunt/types.react-query.ts +++ b/dev-test/githunt/types.react-query.ts @@ -504,8 +504,8 @@ export const useCurrentUserForProfileQuery = , -) => - useQuery( +) => { + return useQuery( variables === undefined ? ['CurrentUserForProfile'] : ['CurrentUserForProfile', variables], fetcher( dataSource.endpoint, @@ -515,6 +515,8 @@ export const useCurrentUserForProfileQuery = , -) => - useInfiniteQuery( +) => { + return useInfiniteQuery( variables === undefined ? ['CurrentUserForProfile.infinite'] : ['CurrentUserForProfile.infinite', variables], @@ -536,6 +538,7 @@ export const useInfiniteCurrentUserForProfileQuery = < )(), options, ); +}; export const FeedDocument = ` query Feed($type: FeedType!, $offset: Int, $limit: Int) { @@ -551,8 +554,8 @@ export const useFeedQuery = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, variables: FeedQueryVariables, options?: UseQueryOptions, -) => - useQuery( +) => { + return useQuery( ['Feed', variables], fetcher( dataSource.endpoint, @@ -562,12 +565,14 @@ export const useFeedQuery = ( ), options, ); +}; + export const useInfiniteFeedQuery = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, variables: FeedQueryVariables, options?: UseInfiniteQueryOptions, -) => - useInfiniteQuery( +) => { + return useInfiniteQuery( ['Feed.infinite', variables], metaData => fetcher( @@ -578,6 +583,7 @@ export const useInfiniteFeedQuery = ( )(), options, ); +}; export const SubmitRepositoryDocument = ` mutation submitRepository($repoFullName: String!) { @@ -594,8 +600,8 @@ export const useSubmitRepositoryMutation = , -) => - useMutation( +) => { + return useMutation( ['submitRepository'], (variables?: SubmitRepositoryMutationVariables) => fetcher( @@ -606,6 +612,8 @@ export const useSubmitRepositoryMutation = ( SubmitCommentMutationVariables, TContext >, -) => - useMutation( +) => { + return useMutation( ['submitComment'], (variables?: SubmitCommentMutationVariables) => fetcher( @@ -633,6 +641,8 @@ export const useSubmitCommentMutation = ( )(), options, ); +}; + export const VoteDocument = ` mutation vote($repoFullName: String!, $type: VoteType!) { vote(repoFullName: $repoFullName, type: $type) { @@ -647,8 +657,8 @@ export const VoteDocument = ` export const useVoteMutation = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, options?: UseMutationOptions, -) => - useMutation( +) => { + return useMutation( ['vote'], (variables?: VoteMutationVariables) => fetcher( @@ -659,3 +669,4 @@ export const useVoteMutation = ( )(), options, ); +}; From 2f1c7f123319185d3548551c47585cd9461dee7d Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 14:11:35 +0800 Subject: [PATCH 33/43] fix: text break --- dev-test/githunt/types.react-query.ts | 17 ++- .../typescript/react-query/src/fetcher.ts | 14 +- .../typescript/react-query/src/index.ts | 2 + .../typescript/react-query/src/visitor.ts | 114 ++++++++++------- .../__snapshots__/react-query.spec.ts.snap | 120 ++++++++++++++---- 5 files changed, 185 insertions(+), 82 deletions(-) diff --git a/dev-test/githunt/types.react-query.ts b/dev-test/githunt/types.react-query.ts index a56a34556..f5368df76 100644 --- a/dev-test/githunt/types.react-query.ts +++ b/dev-test/githunt/types.react-query.ts @@ -460,12 +460,13 @@ export const CommentDocument = ` } } ${CommentsPageCommentFragmentDoc}`; + export const useCommentQuery = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, variables: CommentQueryVariables, options?: UseQueryOptions, -) => - useQuery( +) => { + return useQuery( ['Comment', variables], fetcher( dataSource.endpoint, @@ -475,12 +476,14 @@ export const useCommentQuery = ( ), options, ); +}; + export const useInfiniteCommentQuery = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, variables: CommentQueryVariables, options?: UseInfiniteQueryOptions, -) => - useInfiniteQuery( +) => { + return useInfiniteQuery( ['Comment.infinite', variables], metaData => fetcher( @@ -491,6 +494,7 @@ export const useInfiniteCommentQuery = ( )(), options, ); +}; export const CurrentUserForProfileDocument = ` query CurrentUserForProfile { @@ -500,6 +504,7 @@ export const CurrentUserForProfileDocument = ` } } `; + export const useCurrentUserForProfileQuery = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, variables?: CurrentUserForProfileQueryVariables, @@ -550,6 +555,7 @@ export const FeedDocument = ` } } ${FeedEntryFragmentDoc}`; + export const useFeedQuery = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, variables: FeedQueryVariables, @@ -592,6 +598,7 @@ export const SubmitRepositoryDocument = ` } } `; + export const useSubmitRepositoryMutation = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, options?: UseMutationOptions< @@ -621,6 +628,7 @@ export const SubmitCommentDocument = ` } } ${CommentsPageCommentFragmentDoc}`; + export const useSubmitCommentMutation = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, options?: UseMutationOptions< @@ -654,6 +662,7 @@ export const VoteDocument = ` } } `; + export const useVoteMutation = ( dataSource: { endpoint: string; fetchParams?: RequestInit }, options?: UseMutationOptions, diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index cbd46e7a0..d758652dc 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -224,14 +224,14 @@ export class BaseFetcherRenderer { hasRequiredVariables, operationVariablesTypes, ); - return `\nuseInfinite${operationName}.getKey = (${signature}) => ${this.generateInfiniteQueryKey( + return `useInfinite${operationName}.getKey = (${signature}) => ${this.generateInfiniteQueryKey( node, hasRequiredVariables, - )};\n`; + )};`; } public generateInfiniteQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { - return `\nuseInfinite${operationName}.rootKey = '${node.name.value}.infinite';\n`; + return `useInfinite${operationName}.rootKey = '${node.name.value}.infinite';`; } public generateQueryKey(node: OperationDefinitionNode, hasRequiredVariables: boolean): string { @@ -249,14 +249,14 @@ export class BaseFetcherRenderer { hasRequiredVariables, operationVariablesTypes, ); - return `\nuse${operationName}.getKey = (${signature}) => ${this.generateQueryKey( + return `use${operationName}.getKey = (${signature}) => ${this.generateQueryKey( node, hasRequiredVariables, - )};\n`; + )};`; } public generateQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { - return `\nuse${operationName}.rootKey = '${node.name.value}';\n`; + return `use${operationName}.rootKey = '${node.name.value}';`; } public generateMutationKey(node: OperationDefinitionNode): string { @@ -264,7 +264,7 @@ export class BaseFetcherRenderer { } public generateMutationKeyMaker(node: OperationDefinitionNode, operationName: string) { - return `\nuse${operationName}.getKey = () => ${this.generateMutationKey(node)};\n`; + return `use${operationName}.getKey = () => ${this.generateMutationKey(node)};`; } private generateInfiniteQueryFormattedParameters(queryKey: string, queryFn: string) { diff --git a/packages/plugins/typescript/react-query/src/index.ts b/packages/plugins/typescript/react-query/src/index.ts index c24805baa..60cea0b44 100644 --- a/packages/plugins/typescript/react-query/src/index.ts +++ b/packages/plugins/typescript/react-query/src/index.ts @@ -33,6 +33,7 @@ export const plugin: PluginFunction typeof t === 'string'), ].join('\n'), @@ -42,6 +43,7 @@ export const plugin: PluginFunction typeof t === 'string'), ].join('\n'), diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index fc6d40813..b3ab228bd 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -141,48 +141,58 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< operationResultType = this._externalImportPrefix + operationResultType; operationVariablesTypes = this._externalImportPrefix + operationVariablesTypes; + const queries: string[] = []; + if (operationType === 'Query') { - let query = this.fetcher.generateQueryHook({ - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - }); - if (this.config.exposeDocument) { - query += `\nuse${operationName}.document = ${documentVariableName};\n`; - } - if (this.config.exposeQueryKeys) { - query += `\n${this.fetcher.generateQueryKeyMaker( + queries.push( + this.fetcher.generateQueryHook({ node, + documentVariableName, operationName, + operationResultType, operationVariablesTypes, hasRequiredVariables, - )}\n`; + }), + ); + if (this.config.exposeDocument) { + queries.push(`use${operationName}.document = ${documentVariableName};`); + } + if (this.config.exposeQueryKeys) { + queries.push( + this.fetcher.generateQueryKeyMaker( + node, + operationName, + operationVariablesTypes, + hasRequiredVariables, + ), + ); } if (this.config.exposeQueryRootKeys) { - query += `\n${this.fetcher.generateQueryRootKeyMaker(node, operationName)}`; + queries.push(this.fetcher.generateQueryRootKeyMaker(node, operationName)); } if (this.config.addInfiniteQuery) { - query += `\n${this.fetcher.generateInfiniteQueryHook({ - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - })}\n`; - if (this.config.exposeQueryKeys) { - query += `\n${this.fetcher.generateInfiniteQueryKeyMaker( + queries.push( + this.fetcher.generateInfiniteQueryHook({ node, + documentVariableName, operationName, + operationResultType, operationVariablesTypes, hasRequiredVariables, - )}\n`; + }), + ); + if (this.config.exposeQueryKeys) { + queries.push( + this.fetcher.generateInfiniteQueryKeyMaker( + node, + operationName, + operationVariablesTypes, + hasRequiredVariables, + ), + ); } if (this.config.exposeQueryRootKeys) { - query += `\n${this.fetcher.generateInfiniteQueryRootKeyMaker(node, operationName)}`; + queries.push(this.fetcher.generateInfiniteQueryRootKeyMaker(node, operationName)); } } @@ -190,40 +200,46 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< // is to prevent calling generateFetcherFetch for each query since all the queries won't be able to generate // a fetcher field anyways. if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { - query += this.fetcher.generateFetcherFetch( - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, + queries.push( + this.fetcher.generateFetcherFetch( + node, + documentVariableName, + operationName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + ), ); } - return query; + return `\n${queries.join('\n\n')}\n`; } if (operationType === 'Mutation') { - let query = this.fetcher.generateMutationHook({ - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - }); - if (this.config.exposeMutationKeys) { - query += this.fetcher.generateMutationKeyMaker(node, operationName); - } - if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { - query += this.fetcher.generateFetcherFetch( + queries.push( + this.fetcher.generateMutationHook({ node, documentVariableName, operationName, operationResultType, operationVariablesTypes, hasRequiredVariables, + }), + ); + if (this.config.exposeMutationKeys) { + queries.push(this.fetcher.generateMutationKeyMaker(node, operationName)); + } + if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { + queries.push( + this.fetcher.generateFetcherFetch( + node, + documentVariableName, + operationName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + ), ); } - return query; + return `\n${queries.join('\n\n')}\n`; } if (operationType === 'Subscription') { // eslint-disable-next-line no-console diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 91b7e71db..3a0c24645 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -2,6 +2,7 @@ exports[`React-Query exposeQueryKeys: true Should generate getKey for each query 1`] = ` " + export const TestDocument = \` query test { feed { @@ -17,6 +18,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TestQuery, TError = unknown @@ -34,7 +36,6 @@ export const useTestQuery = < useTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test'] : ['test', variables]; - export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -42,6 +43,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -54,11 +56,13 @@ export const useTestMutation = < ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query exposeQueryKeys: true, addInfiniteQuery: true Should generate getKey for each query - also infinite queries 1`] = ` " + export const TestDocument = \` query test { feed { @@ -74,6 +78,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TestQuery, TError = unknown @@ -91,7 +96,6 @@ export const useTestQuery = < useTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test'] : ['test', variables]; - export const useInfiniteTestQuery = < TData = TestQuery, TError = unknown @@ -107,10 +111,8 @@ export const useInfiniteTestQuery = < options )}; - useInfiniteTestQuery.getKey = (variables?: TestQueryVariables) => variables === undefined ? ['test.infinite'] : ['test.infinite', variables]; - export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -118,6 +120,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -130,11 +133,13 @@ export const useTestMutation = < ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query exposeQueryRootKeys: true Should generate rootKey for each query 1`] = ` " + export const TestDocument = \` query test { feed { @@ -150,6 +155,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TestQuery, TError = unknown @@ -174,6 +180,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -186,11 +193,13 @@ export const useTestMutation = < ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query exposeQueryRootKeys: true, addInfiniteQuery: true Should generate rootKey for each query - also infinite queries 1`] = ` " + export const TestDocument = \` query test { feed { @@ -206,6 +215,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TestQuery, TError = unknown @@ -238,7 +248,6 @@ export const useInfiniteTestQuery = < options )}; - useInfiniteTestQuery.rootKey = 'test.infinite'; export const TestDocument = \` @@ -248,6 +257,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -260,11 +270,13 @@ export const useTestMutation = < ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: custom-mapper Should generate mutation correctly with lazy variables: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -280,6 +292,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -293,6 +306,7 @@ export const useTestQuery = < useCustomFetcher(TestDocument).bind(null, variables), options )}; + export const useInfiniteTestQuery = < TData = TTestQuery, TError = unknown @@ -314,6 +328,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -323,7 +338,8 @@ export const useTestMutation = < ['test'], useCustomFetcher(TestDocument), options - )};" + )}; +" `; exports[`React-Query fetcher: custom-mapper Should generate mutation correctly with lazy variables: prepend 1`] = ` @@ -335,6 +351,7 @@ exports[`React-Query fetcher: custom-mapper Should generate mutation correctly w exports[`React-Query fetcher: custom-mapper Should generate query correctly with external mapper: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -350,6 +367,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -363,6 +381,7 @@ export const useTestQuery = < myCustomFetcher(TestDocument, variables), options )}; + export const useInfiniteTestQuery = < TData = TTestQuery, TError = unknown @@ -384,6 +403,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -393,7 +413,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => myCustomFetcher(TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: custom-mapper Should generate query correctly with external mapper: prepend 1`] = ` @@ -405,6 +426,7 @@ exports[`React-Query fetcher: custom-mapper Should generate query correctly with exports[`React-Query fetcher: custom-mapper Should generate query correctly with internal mapper: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -420,6 +442,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -433,6 +456,7 @@ export const useTestQuery = < myCustomFetcher(TestDocument, variables), options )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -440,6 +464,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -449,7 +474,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => myCustomFetcher(TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: custom-mapper Should generate query correctly with internal mapper: prepend 1`] = ` @@ -461,6 +487,7 @@ exports[`React-Query fetcher: custom-mapper Should generate query correctly with exports[`React-Query fetcher: fetch Should generate query and mutation correctly: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -476,6 +503,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -490,6 +518,7 @@ export const useTestQuery = < fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), options )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -497,6 +526,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -509,7 +539,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: fetch Should generate query and mutation correctly: prepend 1`] = ` @@ -540,6 +571,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, exports[`React-Query fetcher: graphql-request Should generate query correctly with client: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -555,6 +587,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -570,6 +603,7 @@ export const useTestQuery = < fetcher(client, TestDocument, variables, headers), options )}; + export const useInfiniteTestQuery = < TData = TTestQuery, TError = unknown @@ -593,6 +627,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -606,7 +641,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => fetcher(client, TestDocument, variables, headers)(), options - )};" + )}; +" `; exports[`React-Query fetcher: graphql-request Should generate query correctly with client: prepend 1`] = ` @@ -627,6 +663,7 @@ function fetcher(client: Graph exports[`React-Query fetcher: graphql-request with clientImportPath Should generate query correctly with client: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -642,6 +679,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -656,6 +694,7 @@ export const useTestQuery = < fetcher(TestDocument, variables, headers), options )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -663,6 +702,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -675,7 +715,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables, headers)(), options - )};" + )}; +" `; exports[`React-Query fetcher: graphql-request with clientImportPath Should generate query correctly with client: prepend 1`] = ` @@ -697,6 +738,7 @@ function fetcher(query: string exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config and fetchParams object: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -712,6 +754,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -725,6 +768,7 @@ export const useTestQuery = < fetcher(TestDocument, variables), options )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -732,6 +776,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -741,7 +786,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config and fetchParams object: prepend 1`] = ` @@ -772,6 +818,7 @@ function fetcher(query: string, variables?: TVariables) { exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -787,6 +834,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -800,6 +848,7 @@ export const useTestQuery = < fetcher(TestDocument, variables), options )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -807,6 +856,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -816,7 +866,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with fetch config: prepend 1`] = ` @@ -847,6 +898,7 @@ function fetcher(query: string, variables?: TVariables) { exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from env var: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -862,6 +914,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -875,6 +928,7 @@ export const useTestQuery = < fetcher(TestDocument, variables), options )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -882,6 +936,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -891,7 +946,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from env var: prepend 1`] = ` @@ -921,6 +977,7 @@ function fetcher(query: string, variables?: TVariables) { exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from just identifier: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -936,6 +993,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -949,6 +1007,7 @@ export const useTestQuery = < fetcher(TestDocument, variables), options )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { @@ -956,6 +1015,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -965,7 +1025,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint from just identifier: prepend 1`] = ` @@ -995,6 +1056,7 @@ function fetcher(query: string, variables?: TVariables) { exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -1010,6 +1072,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TTestQuery, TError = unknown @@ -1023,6 +1086,7 @@ export const useTestQuery = < fetcher(TestDocument, variables), options )}; + export const useInfiniteTestQuery = < TData = TTestQuery, TError = unknown @@ -1044,6 +1108,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -1053,7 +1118,8 @@ export const useTestMutation = < ['test'], (variables?: TTestMutationVariables) => fetcher(TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query fetcher: hardcoded-fetch Should generate query correctly with hardcoded endpoint: prepend 1`] = ` @@ -1109,6 +1175,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, exports[`React-Query support v4 syntax: content 1`] = ` " + export const TestDocument = \` query test { feed { @@ -1124,6 +1191,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TestQuery, TError = unknown @@ -1138,6 +1206,7 @@ export const useTestQuery = < fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), options )}; + export const useInfiniteTestQuery = < TData = TestQuery, TError = unknown @@ -1160,6 +1229,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -1172,7 +1242,8 @@ export const useTestMutation = < ['test'], (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), options - )};" + )}; +" `; exports[`React-Query support v4 syntax: prepend 1`] = ` @@ -1203,6 +1274,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, exports[`React-Query support v5 syntax 1`] = ` " + export const TestDocument = \` query test { feed { @@ -1218,6 +1290,7 @@ export const TestDocument = \` } } \`; + export const useTestQuery = < TData = TestQuery, TError = unknown @@ -1234,6 +1307,7 @@ export const useTestQuery = < ...options } )}; + export const useInfiniteTestQuery = < TData = TestQuery, TError = unknown @@ -1261,6 +1335,7 @@ export const TestDocument = \` } } \`; + export const useTestMutation = < TError = unknown, TContext = unknown @@ -1275,5 +1350,6 @@ export const useTestMutation = < mutationFn: (variables?: TestMutationVariables) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables)(), ...options } - )};" + )}; +" `; From c3d87854625848264fddb032acdcb6f2069c5ae5 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 14:22:13 +0800 Subject: [PATCH 34/43] edit: deprecated legacy mode flag --- .../plugins/typescript/react-query/src/visitor.ts | 11 ++++------- .../react-query/tests/react-query.spec.ts | 13 ------------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index b3ab228bd..7ab796cb5 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -33,6 +33,8 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< protected rawConfig: ReactQueryRawPluginConfig, documents: Types.DocumentFile[], ) { + const defaultReactQueryVersion = !rawConfig.reactQueryVersion && rawConfig.legacyMode ? 3 : 4; + super(schema, fragments, rawConfig, { documentMode: DocumentMode.string, errorType: getConfigValue(rawConfig.errorType, 'unknown'), @@ -42,15 +44,10 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< exposeMutationKeys: getConfigValue(rawConfig.exposeMutationKeys, false), exposeFetcher: getConfigValue(rawConfig.exposeFetcher, false), addInfiniteQuery: getConfigValue(rawConfig.addInfiniteQuery, false), - legacyMode: getConfigValue(rawConfig.legacyMode, false), - reactQueryVersion: getConfigValue(rawConfig.reactQueryVersion, 4), + reactQueryVersion: getConfigValue(rawConfig.reactQueryVersion, defaultReactQueryVersion), reactQueryImportFrom: getConfigValue(rawConfig.reactQueryImportFrom, ''), }); - if (super.config.legacyMode && super.config.reactQueryVersion > 4) { - throw new Error('reactQueryVersion cannot more than 4 when legacyMode is true'); - } - this._externalImportPrefix = this.config.importOperationTypesFrom ? `${this.config.importOperationTypesFrom}.` : ''; @@ -98,7 +95,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< const moduleName = this.config.reactQueryImportFrom ? this.config.reactQueryImportFrom - : this.config.legacyMode + : this.config.reactQueryVersion <= 3 ? 'react-query' : '@tanstack/react-query'; diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index c8f970780..c354b85fe 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -37,19 +37,6 @@ describe('React-Query', () => { await validateTypeScript(mergeOutputs(out), schema, docs, config); }); - it('should throw when using v5 config with legacyMode', async () => { - const config: ReactQueryRawPluginConfig = { - legacyMode: true, - reactQueryVersion: 5, - addInfiniteQuery: true, - }; - try { - plugin(schema, docs, config); - } catch (e) { - expect(e.message).toBe('reactQueryVersion cannot more than 4 when legacyMode is true'); - } - }); - it('support v5 syntax', async () => { const config: ReactQueryRawPluginConfig = { addInfiniteQuery: true, From c81ea601ade6b6cc0291f819d180824a91844553 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 15:21:17 +0800 Subject: [PATCH 35/43] refactor: generate fn args format --- .../react-query/src/fetcher-custom-mapper.ts | 26 +-- .../src/fetcher-fetch-hardcoded.ts | 26 +-- .../react-query/src/fetcher-fetch.ts | 26 +-- .../src/fetcher-graphql-request.ts | 26 +-- .../typescript/react-query/src/fetcher.ts | 213 ++++++++---------- .../typescript/react-query/src/visitor.ts | 97 +++----- 6 files changed, 178 insertions(+), 236 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index afc8fa624..293029ece 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -1,12 +1,11 @@ import autoBind from 'auto-bind'; -import { OperationDefinitionNode } from 'graphql'; import { buildMapperImport, ParsedMapper, parseMapper, } from '@graphql-codegen/visitor-plugin-common'; import { CustomFetch } from './config.js'; -import { type BuildOperationConfig, FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class CustomMapperFetcher extends FetcherRenderer { @@ -44,7 +43,7 @@ export class CustomMapperFetcher extends FetcherRenderer { return null; } - generateInfiniteQueryHook(config: BuildOperationConfig): string { + generateInfiniteQueryHook(config: GenerateConfig): string { const { documentVariableName, operationResultType, operationVariablesTypes } = config; const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); @@ -63,7 +62,7 @@ export class CustomMapperFetcher extends FetcherRenderer { }); } - generateQueryHook(config: BuildOperationConfig): string { + generateQueryHook(config: GenerateConfig): string { const { generateBaseQueryHook } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -78,7 +77,7 @@ export class CustomMapperFetcher extends FetcherRenderer { }); } - generateMutationHook(config: BuildOperationConfig): string { + generateMutationHook(config: GenerateConfig): string { const { documentVariableName, operationResultType, operationVariablesTypes } = config; const { generateBaseMutationHook, variables } = this.generateMutationHelper(config); @@ -93,14 +92,15 @@ export class CustomMapperFetcher extends FetcherRenderer { }); } - generateFetcherFetch( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateFetcherFetch(config: GenerateConfig): string { + const { + documentVariableName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + operationName, + } = config; + // We can't generate a fetcher field since we can't call react hooks outside of a React Fucntion Component // Related: https://reactjs.org/docs/hooks-rules.html if (this._isReactHook) return ''; diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index fcd2b2a24..a3f3571d2 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -1,7 +1,6 @@ import autoBind from 'auto-bind'; -import { OperationDefinitionNode } from 'graphql'; import { HardcodedFetch } from './config.js'; -import { type BuildOperationConfig, FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class HardcodedFetchFetcher extends FetcherRenderer { @@ -57,7 +56,7 @@ ${this.getFetchParams()} }`; } - generateInfiniteQueryHook(config: BuildOperationConfig): string { + generateInfiniteQueryHook(config: GenerateConfig): string { const { generateBaseInfiniteQueryHook } = this.generateInfiniteQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -67,7 +66,7 @@ ${this.getFetchParams()} }); } - generateQueryHook(config: BuildOperationConfig): string { + generateQueryHook(config: GenerateConfig): string { const { generateBaseQueryHook } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -77,7 +76,7 @@ ${this.getFetchParams()} }); } - generateMutationHook(config: BuildOperationConfig): string { + generateMutationHook(config: GenerateConfig): string { const { generateBaseMutationHook, variables } = this.generateMutationHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -87,14 +86,15 @@ ${this.getFetchParams()} }); } - generateFetcherFetch( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateFetcherFetch(config: GenerateConfig): string { + const { + documentVariableName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + operationName, + } = config; + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index a4f329fe6..5462738dd 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -1,6 +1,5 @@ import autoBind from 'auto-bind'; -import { OperationDefinitionNode } from 'graphql'; -import { type BuildOperationConfig, FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class FetchFetcher extends FetcherRenderer { @@ -32,7 +31,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, }`; } - generateInfiniteQueryHook(config: BuildOperationConfig): string { + generateInfiniteQueryHook(config: GenerateConfig): string { const { generateBaseInfiniteQueryHook, variables, options } = this.generateInfiniteQueryHelper(config); @@ -48,7 +47,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, }); } - generateQueryHook(config: BuildOperationConfig): string { + generateQueryHook(config: GenerateConfig): string { const { generateBaseQueryHook, variables, options } = this.generateQueryHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -63,7 +62,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, }); } - generateMutationHook(config: BuildOperationConfig): string { + generateMutationHook(config: GenerateConfig): string { const { generateBaseMutationHook, variables, options } = this.generateMutationHelper(config); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -77,14 +76,15 @@ function fetcher(endpoint: string, requestInit: RequestInit, }); } - generateFetcherFetch( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateFetcherFetch(config: GenerateConfig): string { + const { + documentVariableName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + operationName, + } = config; + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 781b38e70..88ace9866 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -1,7 +1,6 @@ import autoBind from 'auto-bind'; -import { OperationDefinitionNode } from 'graphql'; import { GraphQlRequest } from './config.js'; -import { type BuildOperationConfig, FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateConfig } from './fetcher.js'; import { ReactQueryVisitor } from './visitor.js'; export class GraphQLRequestClientFetcher extends FetcherRenderer { @@ -33,7 +32,7 @@ function fetcher(client: Graph }`; } - generateInfiniteQueryHook(config: BuildOperationConfig): string { + generateInfiniteQueryHook(config: GenerateConfig): string { const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); @@ -64,7 +63,7 @@ function fetcher(client: Graph }); } - generateQueryHook(config: BuildOperationConfig): string { + generateQueryHook(config: GenerateConfig): string { const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); @@ -96,7 +95,7 @@ function fetcher(client: Graph }); } - generateMutationHook(config: BuildOperationConfig): string { + generateMutationHook(config: GenerateConfig): string { const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); @@ -123,14 +122,15 @@ function fetcher(client: Graph }); } - generateFetcherFetch( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string { + generateFetcherFetch(config: GenerateConfig): string { + const { + documentVariableName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + operationName, + } = config; + const variables = this.generateQueryVariablesSignature( hasRequiredVariables, operationVariablesTypes, diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index d758652dc..a29fb05f9 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -2,13 +2,14 @@ import autoBind from 'auto-bind'; import { OperationDefinitionNode } from 'graphql'; import { ReactQueryVisitor } from './visitor.js'; -export interface BuildOperationConfig { +export interface GenerateConfig { node: OperationDefinitionNode; documentVariableName: string; operationName: string; operationResultType: string; operationVariablesTypes: string; hasRequiredVariables: boolean; + isSuspense?: boolean; } interface GenerateBaseHookConfig { @@ -17,7 +18,12 @@ interface GenerateBaseHookConfig { implFetcher: string; } -type ReactQueryMethodMap = { [key: string]: { hook: string; options: string } }; +type ReactQueryMethodMap = { + [key: string]: { + getHook: (config?: { isSuspense?: boolean; operationName?: string }) => string; + getOptions: (config?: { isSuspense?: boolean }) => string; + }; +}; export class BaseFetcherRenderer { constructor(protected visitor: ReactQueryVisitor) { @@ -26,48 +32,36 @@ export class BaseFetcherRenderer { private queryMethodMap: ReactQueryMethodMap = { infiniteQuery: { - hook: 'useInfiniteQuery', - options: 'UseInfiniteQueryOptions', - }, - suspenseInfiniteQuery: { - hook: 'useSuspenseInfiniteQuery', - options: 'UseSuspenseInfiniteQueryOptions', - }, - suspenseQuery: { - hook: 'useSuspenseQuery', - options: 'UseSuspenseQueryOptions', + getHook: ({ isSuspense = false, operationName = 'Query' } = {}) => + `use${isSuspense ? 'Suspense' : ''}Infinite${operationName}`, + getOptions: ({ isSuspense = false } = {}) => + `Use${isSuspense ? 'Suspense' : ''}InfiniteQueryOptions`, }, query: { - hook: 'useQuery', - options: 'UseQueryOptions', + getHook: ({ isSuspense = false, operationName = 'Query' } = {}) => + `use${isSuspense ? 'Suspense' : ''}${operationName}`, + getOptions: ({ isSuspense = false } = {}) => `Use${isSuspense ? 'Suspense' : ''}QueryOptions`, }, mutation: { - hook: 'useMutation', - options: 'UseMutationOptions', + getHook: ({ operationName = 'Mutation' } = {}) => `use${operationName}`, + getOptions: () => `UseMutationOptions`, }, }; - protected generateInfiniteQueryHelper(config: BuildOperationConfig) { - const { - node, - operationResultType, - operationVariablesTypes, - operationName, - hasRequiredVariables, - } = config; - - this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.infiniteQuery.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.infiniteQuery.options); + protected generateInfiniteQueryHelper(config: GenerateConfig) { + const { operationResultType, operationName } = config; - const variables = this.generateInfiniteQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, + this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.infiniteQuery.getHook()); + this.visitor.reactQueryOptionsIdentifiersInUse.add( + this.queryMethodMap.infiniteQuery.getOptions(), ); - const options = this.generateInfiniteQueryOptionsSignature(operationResultType); + const variables = this.generateInfiniteQueryVariablesSignature(config); - const generateBaseInfiniteQueryHook = (config: GenerateBaseHookConfig) => { - const { implArguments, implHookOuter = '', implFetcher } = config; + const options = this.generateInfiniteQueryOptionsSignature(config); + + const generateBaseInfiniteQueryHook = (hookConfig: GenerateBaseHookConfig) => { + const { implArguments, implHookOuter = '', implFetcher } = hookConfig; const argumentsResult = implArguments ?? @@ -81,9 +75,9 @@ export class BaseFetcherRenderer { TError = ${this.visitor.config.errorType} >(${argumentsResult}) => { ${implHookOuter} - return ${this.queryMethodMap.infiniteQuery.hook}<${operationResultType}, TError, TData>( + return ${this.queryMethodMap.infiniteQuery.getHook()}<${operationResultType}, TError, TData>( ${this.generateInfiniteQueryFormattedParameters( - this.generateInfiniteQueryKey(node, hasRequiredVariables), + this.generateInfiniteQueryKey(config), implFetcher, )} )};`; @@ -92,17 +86,12 @@ export class BaseFetcherRenderer { return { generateBaseInfiniteQueryHook, variables, options }; } - protected generateQueryHelper(config: BuildOperationConfig) { - const { - node, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - } = config; + protected generateQueryHelper(config: GenerateConfig) { + const { operationName, operationResultType, operationVariablesTypes, hasRequiredVariables } = + config; - this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.query.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.query.options); + this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.query.getHook()); + this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.query.getOptions()); const variables = this.generateQueryVariablesSignature( hasRequiredVariables, @@ -111,8 +100,8 @@ export class BaseFetcherRenderer { const options = this.generateQueryOptionsSignature(operationResultType); - const generateBaseQueryHook = (config: GenerateBaseHookConfig) => { - const { implArguments, implHookOuter = '', implFetcher } = config; + const generateBaseQueryHook = (hookConfig: GenerateBaseHookConfig) => { + const { implArguments, implHookOuter = '', implFetcher } = hookConfig; const argumentsResult = implArguments ?? @@ -126,11 +115,8 @@ export class BaseFetcherRenderer { TError = ${this.visitor.config.errorType} >(${argumentsResult}) => { ${implHookOuter} - return ${this.queryMethodMap.query.hook}<${operationResultType}, TError, TData>( - ${this.generateQueryFormattedParameters( - this.generateQueryKey(node, hasRequiredVariables), - implFetcher, - )} + return ${this.queryMethodMap.query.getHook()}<${operationResultType}, TError, TData>( + ${this.generateQueryFormattedParameters(this.generateQueryKey(config), implFetcher)} )};`; }; @@ -141,18 +127,18 @@ export class BaseFetcherRenderer { }; } - protected generateMutationHelper(config: BuildOperationConfig) { - const { node, operationResultType, operationVariablesTypes, operationName } = config; + protected generateMutationHelper(config: GenerateConfig) { + const { operationResultType, operationVariablesTypes, operationName } = config; - this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.mutation.hook); - this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.mutation.options); + this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.mutation.getHook()); + this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.mutation.getOptions()); const variables = `variables?: ${operationVariablesTypes}`; - const options = `options?: ${this.queryMethodMap.mutation.options}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; + const options = `options?: ${this.queryMethodMap.mutation.getOptions()}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; - const generateBaseMutationHook = (config: GenerateBaseHookConfig) => { - const { implArguments, implHookOuter = '', implFetcher } = config; + const generateBaseMutationHook = (hookConfig: GenerateBaseHookConfig) => { + const { implArguments, implHookOuter = '', implFetcher } = hookConfig; const argumentsResult = implArguments ?? `${options}`; @@ -161,10 +147,8 @@ export class BaseFetcherRenderer { TContext = unknown >(${argumentsResult}) => { ${implHookOuter} - return ${ - this.queryMethodMap.mutation.hook - }<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( - ${this.generateMutationFormattedParameters(this.generateMutationKey(node), implFetcher)} + return ${this.queryMethodMap.mutation.getHook()}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( + ${this.generateMutationFormattedParameters(this.generateMutationKey(config), implFetcher)} )};`; }; @@ -184,87 +168,77 @@ export class BaseFetcherRenderer { private generateQueryOptionsSignature(operationResultType: string): string { if (this.visitor.config.reactQueryVersion <= 4) { - return `options?: ${this.queryMethodMap.query.options}<${operationResultType}, TError, TData>`; + return `options?: ${this.queryMethodMap.query.getOptions()}<${operationResultType}, TError, TData>`; } - return `options?: Omit<${this.queryMethodMap.query.options}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${this.queryMethodMap.query.options}<${operationResultType}, TError, TData>['queryKey'] }`; + return `options?: Omit<${this.queryMethodMap.query.getOptions()}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${this.queryMethodMap.query.getOptions()}<${operationResultType}, TError, TData>['queryKey'] }`; } - private generateInfiniteQueryVariablesSignature( - hasRequiredVariables: boolean, - operationVariablesTypes: string, - ): string { + private generateInfiniteQueryVariablesSignature(config: GenerateConfig): string { if (this.visitor.config.reactQueryVersion <= 4) { - return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; + return `variables${config.hasRequiredVariables ? '' : '?'}: ${ + config.operationVariablesTypes + }`; } - return `variables: ${operationVariablesTypes}`; + return `variables: ${config.operationVariablesTypes}`; } - private generateInfiniteQueryOptionsSignature(operationResultType: string): string { + private generateInfiniteQueryOptionsSignature(config: GenerateConfig): string { if (this.visitor.config.reactQueryVersion <= 4) { - return `options?: ${this.queryMethodMap.infiniteQuery.options}<${operationResultType}, TError, TData>`; + return `options?: ${this.queryMethodMap.infiniteQuery.getOptions()}<${ + config.operationResultType + }, TError, TData>`; } - return `options: Omit<${this.queryMethodMap.infiniteQuery.options}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${this.queryMethodMap.infiniteQuery.options}<${operationResultType}, TError, TData>['queryKey'] }`; + return `options: Omit<${this.queryMethodMap.infiniteQuery.getOptions()}<${ + config.operationResultType + }, TError, TData>, 'queryKey'> & { queryKey?: ${this.queryMethodMap.infiniteQuery.getOptions()}<${ + config.operationResultType + }, TError, TData>['queryKey'] }`; } - public generateInfiniteQueryKey( - node: OperationDefinitionNode, - hasRequiredVariables: boolean, - ): string { - if (hasRequiredVariables) return `['${node.name.value}.infinite', variables]`; - return `variables === undefined ? ['${node.name.value}.infinite'] : ['${node.name.value}.infinite', variables]`; + public generateInfiniteQueryKey(config: GenerateConfig): string { + if (config.hasRequiredVariables) return `['${config.node.name.value}.infinite', variables]`; + return `variables === undefined ? ['${config.node.name.value}.infinite'] : ['${config.node.name.value}.infinite', variables]`; } - public generateInfiniteQueryKeyMaker( - node: OperationDefinitionNode, - operationName: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ) { + public generateInfiniteQueryKeyMaker(config: GenerateConfig) { const signature = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, + config.hasRequiredVariables, + config.operationVariablesTypes, ); - return `useInfinite${operationName}.getKey = (${signature}) => ${this.generateInfiniteQueryKey( - node, - hasRequiredVariables, - )};`; + return `useInfinite${ + config.operationName + }.getKey = (${signature}) => ${this.generateInfiniteQueryKey(config)};`; } - public generateInfiniteQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { - return `useInfinite${operationName}.rootKey = '${node.name.value}.infinite';`; + public generateInfiniteQueryRootKeyMaker(config: GenerateConfig) { + return `useInfinite${config.operationName}.rootKey = '${config.node.name.value}.infinite';`; } - public generateQueryKey(node: OperationDefinitionNode, hasRequiredVariables: boolean): string { - if (hasRequiredVariables) return `['${node.name.value}', variables]`; - return `variables === undefined ? ['${node.name.value}'] : ['${node.name.value}', variables]`; + public generateQueryKey(config: GenerateConfig): string { + if (config.hasRequiredVariables) return `['${config.node.name.value}', variables]`; + return `variables === undefined ? ['${config.node.name.value}'] : ['${config.node.name.value}', variables]`; } - public generateQueryKeyMaker( - node: OperationDefinitionNode, - operationName: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ) { + public generateQueryKeyMaker(config: GenerateConfig) { const signature = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, + config.hasRequiredVariables, + config.operationVariablesTypes, ); - return `use${operationName}.getKey = (${signature}) => ${this.generateQueryKey( - node, - hasRequiredVariables, + return `use${config.operationName}.getKey = (${signature}) => ${this.generateQueryKey( + config, )};`; } - public generateQueryRootKeyMaker(node: OperationDefinitionNode, operationName: string) { + public generateQueryRootKeyMaker({ operationName, node }: GenerateConfig) { return `use${operationName}.rootKey = '${node.name.value}';`; } - public generateMutationKey(node: OperationDefinitionNode): string { + public generateMutationKey({ node }: GenerateConfig): string { return `['${node.name.value}']`; } - public generateMutationKeyMaker(node: OperationDefinitionNode, operationName: string) { - return `use${operationName}.getKey = () => ${this.generateMutationKey(node)};`; + public generateMutationKeyMaker(config: GenerateConfig) { + return `use${config.operationName}.getKey = () => ${this.generateMutationKey(config)};`; } private generateInfiniteQueryFormattedParameters(queryKey: string, queryFn: string) { @@ -312,15 +286,8 @@ export class BaseFetcherRenderer { export abstract class FetcherRenderer extends BaseFetcherRenderer { public abstract generateFetcherImplementation(): string; - public abstract generateQueryHook(config: BuildOperationConfig): string; - public abstract generateInfiniteQueryHook(config: BuildOperationConfig): string; - public abstract generateMutationHook(config: BuildOperationConfig): string; - public abstract generateFetcherFetch( - node: OperationDefinitionNode, - documentVariableName: string, - operationName: string, - operationResultType: string, - operationVariablesTypes: string, - hasRequiredVariables: boolean, - ): string; + public abstract generateQueryHook(config: GenerateConfig): string; + public abstract generateInfiniteQueryHook(config: GenerateConfig): string; + public abstract generateMutationHook(config: GenerateConfig): string; + public abstract generateFetcherFetch(config: GenerateConfig): string; } diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index 7ab796cb5..c5bfefdb7 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -14,7 +14,7 @@ import { CustomMapperFetcher } from './fetcher-custom-mapper.js'; import { HardcodedFetchFetcher } from './fetcher-fetch-hardcoded.js'; import { FetchFetcher } from './fetcher-fetch.js'; import { GraphQLRequestClientFetcher } from './fetcher-graphql-request.js'; -import { FetcherRenderer } from './fetcher.js'; +import { FetcherRenderer, type GenerateConfig } from './fetcher.js'; export type ReactQueryPluginConfig = BaseReactQueryPluginConfig & ClientSideBasePluginConfig; @@ -35,6 +35,12 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< ) { const defaultReactQueryVersion = !rawConfig.reactQueryVersion && rawConfig.legacyMode ? 3 : 4; + if (rawConfig.reactQueryVersion !== 5 && rawConfig.addSuspenseQuery) { + throw new Error( + `Suspense queries are only supported in react-query@5. Please upgrade your react-query version.`, + ); + } + super(schema, fragments, rawConfig, { documentMode: DocumentMode.string, errorType: getConfigValue(rawConfig.errorType, 'unknown'), @@ -44,6 +50,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< exposeMutationKeys: getConfigValue(rawConfig.exposeMutationKeys, false), exposeFetcher: getConfigValue(rawConfig.exposeFetcher, false), addInfiniteQuery: getConfigValue(rawConfig.addInfiniteQuery, false), + addSuspenseQuery: getConfigValue(rawConfig.addSuspenseQuery, false), reactQueryVersion: getConfigValue(rawConfig.reactQueryVersion, defaultReactQueryVersion), reactQueryImportFrom: getConfigValue(rawConfig.reactQueryImportFrom, ''), }); @@ -135,37 +142,30 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< useTypesSuffix: false, }); + const generateConfig: GenerateConfig = { + node, + documentVariableName, + operationResultType, + operationVariablesTypes, + hasRequiredVariables, + operationName, + }; + operationResultType = this._externalImportPrefix + operationResultType; operationVariablesTypes = this._externalImportPrefix + operationVariablesTypes; const queries: string[] = []; if (operationType === 'Query') { - queries.push( - this.fetcher.generateQueryHook({ - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - }), - ); + queries.push(this.fetcher.generateQueryHook(generateConfig)); if (this.config.exposeDocument) { queries.push(`use${operationName}.document = ${documentVariableName};`); } if (this.config.exposeQueryKeys) { - queries.push( - this.fetcher.generateQueryKeyMaker( - node, - operationName, - operationVariablesTypes, - hasRequiredVariables, - ), - ); + queries.push(this.fetcher.generateQueryKeyMaker(generateConfig)); } if (this.config.exposeQueryRootKeys) { - queries.push(this.fetcher.generateQueryRootKeyMaker(node, operationName)); + queries.push(this.fetcher.generateQueryRootKeyMaker(generateConfig)); } if (this.config.addInfiniteQuery) { queries.push( @@ -179,62 +179,37 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< }), ); if (this.config.exposeQueryKeys) { - queries.push( - this.fetcher.generateInfiniteQueryKeyMaker( - node, - operationName, - operationVariablesTypes, - hasRequiredVariables, - ), - ); + queries.push(this.fetcher.generateInfiniteQueryKeyMaker(generateConfig)); } if (this.config.exposeQueryRootKeys) { - queries.push(this.fetcher.generateInfiniteQueryRootKeyMaker(node, operationName)); + queries.push(this.fetcher.generateInfiniteQueryRootKeyMaker(generateConfig)); + } + } + if (this.config.addSuspenseQuery) { + const generateSuspenseConfig: GenerateConfig = { ...generateConfig, isSuspense: true }; + queries.push(this.fetcher.generateInfiniteQueryHook(generateSuspenseConfig)); + if (this.config.exposeQueryKeys) { + queries.push(this.fetcher.generateInfiniteQueryKeyMaker(generateSuspenseConfig)); + } + if (this.config.exposeQueryRootKeys) { + queries.push(this.fetcher.generateInfiniteQueryRootKeyMaker(generateSuspenseConfig)); } } - // The reason we're looking at the private field of the CustomMapperFetcher to see if it's a react hook // is to prevent calling generateFetcherFetch for each query since all the queries won't be able to generate // a fetcher field anyways. if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { - queries.push( - this.fetcher.generateFetcherFetch( - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - ), - ); + queries.push(this.fetcher.generateFetcherFetch(generateConfig)); } return `\n${queries.join('\n\n')}\n`; } if (operationType === 'Mutation') { - queries.push( - this.fetcher.generateMutationHook({ - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - }), - ); + queries.push(this.fetcher.generateMutationHook(generateConfig)); if (this.config.exposeMutationKeys) { - queries.push(this.fetcher.generateMutationKeyMaker(node, operationName)); + queries.push(this.fetcher.generateMutationKeyMaker(generateConfig)); } if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { - queries.push( - this.fetcher.generateFetcherFetch( - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - ), - ); + queries.push(this.fetcher.generateFetcherFetch(generateConfig)); } return `\n${queries.join('\n\n')}\n`; } From f1ea720a4a55bedff033ad88cdda8d51daf4ffca Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 17:08:43 +0800 Subject: [PATCH 36/43] add: v5 suspense support --- .../react-query/src/fetcher-custom-mapper.ts | 8 +- .../src/fetcher-fetch-hardcoded.ts | 24 +-- .../react-query/src/fetcher-fetch.ts | 31 ++- .../src/fetcher-graphql-request.ts | 31 ++- .../typescript/react-query/src/fetcher.ts | 202 ++++++++++-------- .../typescript/react-query/src/index.ts | 8 +- .../typescript/react-query/src/visitor.ts | 77 +++---- .../__snapshots__/react-query.spec.ts.snap | 37 ++++ .../react-query/tests/react-query.spec.ts | 3 +- 9 files changed, 225 insertions(+), 196 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts index 293029ece..65b3c918d 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-custom-mapper.ts @@ -43,7 +43,7 @@ export class CustomMapperFetcher extends FetcherRenderer { return null; } - generateInfiniteQueryHook(config: GenerateConfig): string { + generateInfiniteQueryHook(config: GenerateConfig, isSuspense = false): string { const { documentVariableName, operationResultType, operationVariablesTypes } = config; const typedFetcher = this.getFetcherFnName(operationResultType, operationVariablesTypes); @@ -54,7 +54,7 @@ export class CustomMapperFetcher extends FetcherRenderer { ? `(metaData) => query({...variables, ...(metaData.pageParam ?? {})})` : `(metaData) => ${typedFetcher}(${documentVariableName}, {...variables, ...(metaData.pageParam ?? {})})()`; - const { generateBaseInfiniteQueryHook } = this.generateInfiniteQueryHelper(config); + const { generateBaseInfiniteQueryHook } = this.generateInfiniteQueryHelper(config, isSuspense); return generateBaseInfiniteQueryHook({ implHookOuter, @@ -62,8 +62,8 @@ export class CustomMapperFetcher extends FetcherRenderer { }); } - generateQueryHook(config: GenerateConfig): string { - const { generateBaseQueryHook } = this.generateQueryHelper(config); + generateQueryHook(config: GenerateConfig, isSuspense = false): string { + const { generateBaseQueryHook } = this.generateQueryHelper(config, isSuspense); const { documentVariableName, operationResultType, operationVariablesTypes } = config; diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts index a3f3571d2..cf1b25f49 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch-hardcoded.ts @@ -56,8 +56,8 @@ ${this.getFetchParams()} }`; } - generateInfiniteQueryHook(config: GenerateConfig): string { - const { generateBaseInfiniteQueryHook } = this.generateInfiniteQueryHelper(config); + generateInfiniteQueryHook(config: GenerateConfig, isSuspense = false): string { + const { generateBaseInfiniteQueryHook } = this.generateInfiniteQueryHelper(config, isSuspense); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -66,8 +66,8 @@ ${this.getFetchParams()} }); } - generateQueryHook(config: GenerateConfig): string { - const { generateBaseQueryHook } = this.generateQueryHelper(config); + generateQueryHook(config: GenerateConfig, isSuspense = false): string { + const { generateBaseQueryHook } = this.generateQueryHelper(config, isSuspense); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -87,18 +87,10 @@ ${this.getFetchParams()} } generateFetcherFetch(config: GenerateConfig): string { - const { - documentVariableName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - operationName, - } = config; - - const variables = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); + const { documentVariableName, operationResultType, operationVariablesTypes, operationName } = + config; + + const variables = this.generateQueryVariablesSignature(config); return `\nuse${operationName}.fetcher = (${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, variables);`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts index 5462738dd..ee9363913 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-fetch.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-fetch.ts @@ -31,9 +31,11 @@ function fetcher(endpoint: string, requestInit: RequestInit, }`; } - generateInfiniteQueryHook(config: GenerateConfig): string { - const { generateBaseInfiniteQueryHook, variables, options } = - this.generateInfiniteQueryHelper(config); + generateInfiniteQueryHook(config: GenerateConfig, isSuspense = false): string { + const { generateBaseInfiniteQueryHook, variables, options } = this.generateInfiniteQueryHelper( + config, + isSuspense, + ); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -47,8 +49,11 @@ function fetcher(endpoint: string, requestInit: RequestInit, }); } - generateQueryHook(config: GenerateConfig): string { - const { generateBaseQueryHook, variables, options } = this.generateQueryHelper(config); + generateQueryHook(config: GenerateConfig, isSuspense = false): string { + const { generateBaseQueryHook, variables, options } = this.generateQueryHelper( + config, + isSuspense, + ); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -77,18 +82,10 @@ function fetcher(endpoint: string, requestInit: RequestInit, } generateFetcherFetch(config: GenerateConfig): string { - const { - documentVariableName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - operationName, - } = config; - - const variables = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); + const { documentVariableName, operationResultType, operationVariablesTypes, operationName } = + config; + + const variables = this.generateQueryVariablesSignature(config); return `\nuse${operationName}.fetcher = (dataSource: { endpoint: string, fetchParams?: RequestInit }, ${variables}) => fetcher<${operationResultType}, ${operationVariablesTypes}>(dataSource.endpoint, dataSource.fetchParams || {}, ${documentVariableName}, variables);`; } diff --git a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts index 88ace9866..9a61e8fb0 100644 --- a/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts +++ b/packages/plugins/typescript/react-query/src/fetcher-graphql-request.ts @@ -32,13 +32,15 @@ function fetcher(client: Graph }`; } - generateInfiniteQueryHook(config: GenerateConfig): string { + generateInfiniteQueryHook(config: GenerateConfig, isSuspense = false): string { const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); - const { generateBaseInfiniteQueryHook, variables, options } = - this.generateInfiniteQueryHelper(config); + const { generateBaseInfiniteQueryHook, variables, options } = this.generateInfiniteQueryHelper( + config, + isSuspense, + ); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -63,7 +65,7 @@ function fetcher(client: Graph }); } - generateQueryHook(config: GenerateConfig): string { + generateQueryHook(config: GenerateConfig, isSuspense = false): string { const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add(`${typeImport} { GraphQLClient } from 'graphql-request';`); @@ -71,7 +73,10 @@ function fetcher(client: Graph `${typeImport} { RequestInit } from 'graphql-request/dist/types.dom';`, ); - const { generateBaseQueryHook, variables, options } = this.generateQueryHelper(config); + const { generateBaseQueryHook, variables, options } = this.generateQueryHelper( + config, + isSuspense, + ); const { documentVariableName, operationResultType, operationVariablesTypes } = config; @@ -123,18 +128,10 @@ function fetcher(client: Graph } generateFetcherFetch(config: GenerateConfig): string { - const { - documentVariableName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - operationName, - } = config; - - const variables = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); + const { documentVariableName, operationResultType, operationVariablesTypes, operationName } = + config; + + const variables = this.generateQueryVariablesSignature(config); const typeImport = this.visitor.config.useTypeImports ? 'import type' : 'import'; if (this.clientPath) this.visitor.imports.add(this.clientPath); this.visitor.imports.add( diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index a29fb05f9..c36d107a4 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -9,7 +9,6 @@ export interface GenerateConfig { operationResultType: string; operationVariablesTypes: string; hasRequiredVariables: boolean; - isSuspense?: boolean; } interface GenerateBaseHookConfig { @@ -20,41 +19,52 @@ interface GenerateBaseHookConfig { type ReactQueryMethodMap = { [key: string]: { - getHook: (config?: { isSuspense?: boolean; operationName?: string }) => string; - getOptions: (config?: { isSuspense?: boolean }) => string; + getHook: (operationName?: string) => string; + getOptions: () => string; }; }; -export class BaseFetcherRenderer { +export abstract class FetcherRenderer { constructor(protected visitor: ReactQueryVisitor) { autoBind(this); } - private queryMethodMap: ReactQueryMethodMap = { - infiniteQuery: { - getHook: ({ isSuspense = false, operationName = 'Query' } = {}) => - `use${isSuspense ? 'Suspense' : ''}Infinite${operationName}`, - getOptions: ({ isSuspense = false } = {}) => - `Use${isSuspense ? 'Suspense' : ''}InfiniteQueryOptions`, - }, - query: { - getHook: ({ isSuspense = false, operationName = 'Query' } = {}) => - `use${isSuspense ? 'Suspense' : ''}${operationName}`, - getOptions: ({ isSuspense = false } = {}) => `Use${isSuspense ? 'Suspense' : ''}QueryOptions`, - }, - mutation: { - getHook: ({ operationName = 'Mutation' } = {}) => `use${operationName}`, - getOptions: () => `UseMutationOptions`, - }, - }; + public abstract generateFetcherImplementation(): string; + public abstract generateFetcherFetch(config: GenerateConfig): string; + protected abstract generateQueryHook(config: GenerateConfig, isSuspense?: boolean): string; + protected abstract generateInfiniteQueryHook( + config: GenerateConfig, + isSuspense?: boolean, + ): string; + protected abstract generateMutationHook(config: GenerateConfig): string; + + public createQueryMethodMap(isSuspense = false) { + const queryMethodMap: ReactQueryMethodMap = { + infiniteQuery: { + getHook: (operationName = 'Query') => + `use${isSuspense ? 'Suspense' : ''}Infinite${operationName}`, + getOptions: () => `Use${isSuspense ? 'Suspense' : ''}InfiniteQueryOptions`, + }, + query: { + getHook: (operationName = 'Query') => `use${isSuspense ? 'Suspense' : ''}${operationName}`, + getOptions: () => `Use${isSuspense ? 'Suspense' : ''}QueryOptions`, + }, + mutation: { + getHook: (operationName = 'Mutation') => `use${operationName}`, + getOptions: () => `UseMutationOptions`, + }, + }; - protected generateInfiniteQueryHelper(config: GenerateConfig) { + return queryMethodMap; + } + + protected generateInfiniteQueryHelper(config: GenerateConfig, isSuspense: boolean) { const { operationResultType, operationName } = config; - this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.infiniteQuery.getHook()); - this.visitor.reactQueryOptionsIdentifiersInUse.add( - this.queryMethodMap.infiniteQuery.getOptions(), - ); + const { infiniteQuery } = this.createQueryMethodMap(isSuspense); + + this.visitor.reactQueryHookIdentifiersInUse.add(infiniteQuery.getHook()); + this.visitor.reactQueryOptionsIdentifiersInUse.add(infiniteQuery.getOptions()); const variables = this.generateInfiniteQueryVariablesSignature(config); @@ -70,12 +80,12 @@ export class BaseFetcherRenderer { ${options} `; - return `export const useInfinite${operationName} = < + return `export const ${infiniteQuery.getHook(operationName)} = < TData = ${operationResultType}, TError = ${this.visitor.config.errorType} >(${argumentsResult}) => { ${implHookOuter} - return ${this.queryMethodMap.infiniteQuery.getHook()}<${operationResultType}, TError, TData>( + return ${infiniteQuery.getHook()}<${operationResultType}, TError, TData>( ${this.generateInfiniteQueryFormattedParameters( this.generateInfiniteQueryKey(config), implFetcher, @@ -86,19 +96,17 @@ export class BaseFetcherRenderer { return { generateBaseInfiniteQueryHook, variables, options }; } - protected generateQueryHelper(config: GenerateConfig) { - const { operationName, operationResultType, operationVariablesTypes, hasRequiredVariables } = - config; + protected generateQueryHelper(config: GenerateConfig, isSuspense: boolean) { + const { operationName, operationResultType } = config; + + const { query } = this.createQueryMethodMap(isSuspense); - this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.query.getHook()); - this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.query.getOptions()); + this.visitor.reactQueryHookIdentifiersInUse.add(query.getHook()); + this.visitor.reactQueryOptionsIdentifiersInUse.add(query.getOptions()); - const variables = this.generateQueryVariablesSignature( - hasRequiredVariables, - operationVariablesTypes, - ); + const variables = this.generateQueryVariablesSignature(config); - const options = this.generateQueryOptionsSignature(operationResultType); + const options = this.generateQueryOptionsSignature(config); const generateBaseQueryHook = (hookConfig: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = hookConfig; @@ -110,12 +118,12 @@ export class BaseFetcherRenderer { ${options} `; - return `export const use${operationName} = < + return `export const ${query.getHook(operationName)} = < TData = ${operationResultType}, TError = ${this.visitor.config.errorType} >(${argumentsResult}) => { ${implHookOuter} - return ${this.queryMethodMap.query.getHook()}<${operationResultType}, TError, TData>( + return ${query.getHook()}<${operationResultType}, TError, TData>( ${this.generateQueryFormattedParameters(this.generateQueryKey(config), implFetcher)} )};`; }; @@ -130,24 +138,26 @@ export class BaseFetcherRenderer { protected generateMutationHelper(config: GenerateConfig) { const { operationResultType, operationVariablesTypes, operationName } = config; - this.visitor.reactQueryHookIdentifiersInUse.add(this.queryMethodMap.mutation.getHook()); - this.visitor.reactQueryOptionsIdentifiersInUse.add(this.queryMethodMap.mutation.getOptions()); + const { mutation } = this.createQueryMethodMap(); + + this.visitor.reactQueryHookIdentifiersInUse.add(mutation.getHook()); + this.visitor.reactQueryOptionsIdentifiersInUse.add(mutation.getOptions()); const variables = `variables?: ${operationVariablesTypes}`; - const options = `options?: ${this.queryMethodMap.mutation.getOptions()}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; + const options = `options?: ${mutation.getOptions()}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; const generateBaseMutationHook = (hookConfig: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = hookConfig; const argumentsResult = implArguments ?? `${options}`; - return `export const use${operationName} = < + return `export const ${mutation.getHook(operationName)} = < TError = ${this.visitor.config.errorType}, TContext = unknown >(${argumentsResult}) => { ${implHookOuter} - return ${this.queryMethodMap.mutation.getHook()}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( + return ${mutation.getHook()}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>( ${this.generateMutationFormattedParameters(this.generateMutationKey(config), implFetcher)} )};`; }; @@ -159,18 +169,23 @@ export class BaseFetcherRenderer { }; } - protected generateQueryVariablesSignature( - hasRequiredVariables: boolean, - operationVariablesTypes: string, - ): string { + protected generateQueryVariablesSignature({ + hasRequiredVariables, + operationVariablesTypes, + }: GenerateConfig): string { return `variables${hasRequiredVariables ? '' : '?'}: ${operationVariablesTypes}`; } - private generateQueryOptionsSignature(operationResultType: string): string { + private generateQueryOptionsSignature( + { operationResultType }: GenerateConfig, + isSuspense = false, + ): string { + const { query } = this.createQueryMethodMap(isSuspense); + if (this.visitor.config.reactQueryVersion <= 4) { - return `options?: ${this.queryMethodMap.query.getOptions()}<${operationResultType}, TError, TData>`; + return `options?: ${query.getOptions()}<${operationResultType}, TError, TData>`; } - return `options?: Omit<${this.queryMethodMap.query.getOptions()}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${this.queryMethodMap.query.getOptions()}<${operationResultType}, TError, TData>['queryKey'] }`; + return `options?: Omit<${query.getOptions()}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${query.getOptions()}<${operationResultType}, TError, TData>['queryKey'] }`; } private generateInfiniteQueryVariablesSignature(config: GenerateConfig): string { @@ -182,17 +197,16 @@ export class BaseFetcherRenderer { return `variables: ${config.operationVariablesTypes}`; } - private generateInfiniteQueryOptionsSignature(config: GenerateConfig): string { + private generateInfiniteQueryOptionsSignature( + { operationResultType }: GenerateConfig, + isSuspense = false, + ): string { + const { infiniteQuery } = this.createQueryMethodMap(isSuspense); + if (this.visitor.config.reactQueryVersion <= 4) { - return `options?: ${this.queryMethodMap.infiniteQuery.getOptions()}<${ - config.operationResultType - }, TError, TData>`; + return `options?: ${infiniteQuery.getOptions()}<${operationResultType}, TError, TData>`; } - return `options: Omit<${this.queryMethodMap.infiniteQuery.getOptions()}<${ - config.operationResultType - }, TError, TData>, 'queryKey'> & { queryKey?: ${this.queryMethodMap.infiniteQuery.getOptions()}<${ - config.operationResultType - }, TError, TData>['queryKey'] }`; + return `options: Omit<${infiniteQuery.getOptions()}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${infiniteQuery.getOptions()}<${operationResultType}, TError, TData>['queryKey'] }`; } public generateInfiniteQueryKey(config: GenerateConfig): string { @@ -200,18 +214,17 @@ export class BaseFetcherRenderer { return `variables === undefined ? ['${config.node.name.value}.infinite'] : ['${config.node.name.value}.infinite', variables]`; } - public generateInfiniteQueryKeyMaker(config: GenerateConfig) { - const signature = this.generateQueryVariablesSignature( - config.hasRequiredVariables, - config.operationVariablesTypes, - ); - return `useInfinite${ - config.operationName - }.getKey = (${signature}) => ${this.generateInfiniteQueryKey(config)};`; - } - - public generateInfiniteQueryRootKeyMaker(config: GenerateConfig) { - return `useInfinite${config.operationName}.rootKey = '${config.node.name.value}.infinite';`; + public generateInfiniteQueryOutput(config: GenerateConfig, isSuspense = false) { + const { infiniteQuery } = this.createQueryMethodMap(isSuspense); + const signature = this.generateQueryVariablesSignature(config); + const { operationName, node } = config; + return { + hook: this.generateInfiniteQueryHook(config, isSuspense), + getKey: `${infiniteQuery.getHook( + operationName, + )}.getKey = (${signature}) => ${this.generateInfiniteQueryKey(config)};`, + rootKey: `${infiniteQuery.getHook(operationName)}.rootKey = '${node.name.value}.infinite';`, + }; } public generateQueryKey(config: GenerateConfig): string { @@ -219,26 +232,33 @@ export class BaseFetcherRenderer { return `variables === undefined ? ['${config.node.name.value}'] : ['${config.node.name.value}', variables]`; } - public generateQueryKeyMaker(config: GenerateConfig) { - const signature = this.generateQueryVariablesSignature( - config.hasRequiredVariables, - config.operationVariablesTypes, - ); - return `use${config.operationName}.getKey = (${signature}) => ${this.generateQueryKey( - config, - )};`; - } - - public generateQueryRootKeyMaker({ operationName, node }: GenerateConfig) { - return `use${operationName}.rootKey = '${node.name.value}';`; + public generateQueryOutput(config: GenerateConfig, isSuspense = false) { + const { query } = this.createQueryMethodMap(isSuspense); + const signature = this.generateQueryVariablesSignature(config); + const { operationName, node, documentVariableName } = config; + return { + hook: this.generateQueryHook(config, isSuspense), + document: `${query.getHook(operationName)}.document = ${documentVariableName};`, + getKey: `${query.getHook(operationName)}.getKey = (${signature}) => ${this.generateQueryKey( + config, + )};`, + rootKey: `${query.getHook(operationName)}.rootKey = '${node.name.value}';`, + }; } public generateMutationKey({ node }: GenerateConfig): string { return `['${node.name.value}']`; } - public generateMutationKeyMaker(config: GenerateConfig) { - return `use${config.operationName}.getKey = () => ${this.generateMutationKey(config)};`; + public generateMutationOutput(config: GenerateConfig) { + const { mutation } = this.createQueryMethodMap(); + const { operationName } = config; + return { + hook: this.generateMutationHook(config), + getKey: `${mutation.getHook(operationName)}.getKey = () => ${this.generateMutationKey( + config, + )};`, + }; } private generateInfiniteQueryFormattedParameters(queryKey: string, queryFn: string) { @@ -283,11 +303,3 @@ export class BaseFetcherRenderer { }`; } } - -export abstract class FetcherRenderer extends BaseFetcherRenderer { - public abstract generateFetcherImplementation(): string; - public abstract generateQueryHook(config: GenerateConfig): string; - public abstract generateInfiniteQueryHook(config: GenerateConfig): string; - public abstract generateMutationHook(config: GenerateConfig): string; - public abstract generateFetcherFetch(config: GenerateConfig): string; -} diff --git a/packages/plugins/typescript/react-query/src/index.ts b/packages/plugins/typescript/react-query/src/index.ts index 60cea0b44..b9e62dc2a 100644 --- a/packages/plugins/typescript/react-query/src/index.ts +++ b/packages/plugins/typescript/react-query/src/index.ts @@ -53,12 +53,18 @@ export const plugin: PluginFunction = async ( schema: GraphQLSchema, documents: Types.DocumentFile[], - config: ReactQueryVisitor, + config: ReactQueryRawPluginConfig, outputFile: string, ) => { if (extname(outputFile) !== '.ts' && extname(outputFile) !== '.tsx') { throw new Error(`Plugin "typescript-react-query" requires extension to be ".ts" or ".tsx"!`); } + + if (config.reactQueryVersion !== 5 && config.addSuspenseQuery) { + throw new Error( + `Suspense queries are only supported in react-query@5. Please upgrade your react-query version.`, + ); + } }; export { ReactQueryVisitor }; diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index c5bfefdb7..50011a86f 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -35,12 +35,6 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< ) { const defaultReactQueryVersion = !rawConfig.reactQueryVersion && rawConfig.legacyMode ? 3 : 4; - if (rawConfig.reactQueryVersion !== 5 && rawConfig.addSuspenseQuery) { - throw new Error( - `Suspense queries are only supported in react-query@5. Please upgrade your react-query version.`, - ); - } - super(schema, fragments, rawConfig, { documentMode: DocumentMode.string, errorType: getConfigValue(rawConfig.errorType, 'unknown'), @@ -157,42 +151,36 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< const queries: string[] = []; if (operationType === 'Query') { - queries.push(this.fetcher.generateQueryHook(generateConfig)); - if (this.config.exposeDocument) { - queries.push(`use${operationName}.document = ${documentVariableName};`); - } - if (this.config.exposeQueryKeys) { - queries.push(this.fetcher.generateQueryKeyMaker(generateConfig)); - } - if (this.config.exposeQueryRootKeys) { - queries.push(this.fetcher.generateQueryRootKeyMaker(generateConfig)); - } - if (this.config.addInfiniteQuery) { - queries.push( - this.fetcher.generateInfiniteQueryHook({ - node, - documentVariableName, - operationName, - operationResultType, - operationVariablesTypes, - hasRequiredVariables, - }), + const addQuery = (generateConfig: GenerateConfig, isSuspense = false) => { + const { hook, getKey, rootKey, document } = this.fetcher.generateQueryOutput( + generateConfig, + isSuspense, ); - if (this.config.exposeQueryKeys) { - queries.push(this.fetcher.generateInfiniteQueryKeyMaker(generateConfig)); - } - if (this.config.exposeQueryRootKeys) { - queries.push(this.fetcher.generateInfiniteQueryRootKeyMaker(generateConfig)); - } - } - if (this.config.addSuspenseQuery) { - const generateSuspenseConfig: GenerateConfig = { ...generateConfig, isSuspense: true }; - queries.push(this.fetcher.generateInfiniteQueryHook(generateSuspenseConfig)); - if (this.config.exposeQueryKeys) { - queries.push(this.fetcher.generateInfiniteQueryKeyMaker(generateSuspenseConfig)); - } - if (this.config.exposeQueryRootKeys) { - queries.push(this.fetcher.generateInfiniteQueryRootKeyMaker(generateSuspenseConfig)); + queries.push(hook); + if (this.config.exposeDocument) queries.push(document); + if (this.config.exposeQueryKeys) queries.push(getKey); + if (this.config.exposeQueryRootKeys) queries.push(rootKey); + }; + + addQuery(generateConfig); + + if (this.config.addSuspenseQuery) addQuery(generateConfig, true); + + if (this.config.addInfiniteQuery) { + const addInfiniteQuery = (generateConfig: GenerateConfig, isSuspense = false) => { + const { hook, getKey, rootKey } = this.fetcher.generateInfiniteQueryOutput( + generateConfig, + isSuspense, + ); + queries.push(hook); + if (this.config.exposeQueryKeys) queries.push(getKey); + if (this.config.exposeQueryRootKeys) queries.push(rootKey); + }; + + addInfiniteQuery(generateConfig); + + if (this.config.addSuspenseQuery) { + addInfiniteQuery(generateConfig, true); } } // The reason we're looking at the private field of the CustomMapperFetcher to see if it's a react hook @@ -204,10 +192,9 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< return `\n${queries.join('\n\n')}\n`; } if (operationType === 'Mutation') { - queries.push(this.fetcher.generateMutationHook(generateConfig)); - if (this.config.exposeMutationKeys) { - queries.push(this.fetcher.generateMutationKeyMaker(generateConfig)); - } + const { hook, getKey } = this.fetcher.generateMutationOutput(generateConfig); + queries.push(hook); + if (this.config.exposeMutationKeys) queries.push(getKey); if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { queries.push(this.fetcher.generateFetcherFetch(generateConfig)); } diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 3a0c24645..181caa46e 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -1308,6 +1308,23 @@ export const useTestQuery = < } )}; +export const useSuspenseTestQuery = < + TData = TestQuery, + TError = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables?: TestQueryVariables, + options?: Omit, 'queryKey'> & { queryKey?: UseQueryOptions['queryKey'] } + ) => { + + return useSuspenseQuery( + { + queryKey: variables === undefined ? ['test'] : ['test', variables], + queryFn: fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), + ...options + } + )}; + export const useInfiniteTestQuery = < TData = TestQuery, TError = unknown @@ -1328,6 +1345,26 @@ export const useInfiniteTestQuery = < })() )}; +export const useSuspenseInfiniteTestQuery = < + TData = TestQuery, + TError = unknown + >( + dataSource: { endpoint: string, fetchParams?: RequestInit }, + variables: TestQueryVariables, + options: Omit, 'queryKey'> & { queryKey?: UseInfiniteQueryOptions['queryKey'] } + ) => { + + return useSuspenseInfiniteQuery( + (() => { + const { queryKey: optionsQueryKey, ...restOptions } = options; + return { + queryKey: optionsQueryKey ?? variables === undefined ? ['test.infinite'] : ['test.infinite', variables], + queryFn: (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), + ...restOptions + } + })() + )}; + export const TestDocument = \` mutation test($name: String) { submitRepository(repoFullName: $name) { diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index c354b85fe..83d123f4b 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -39,8 +39,9 @@ describe('React-Query', () => { it('support v5 syntax', async () => { const config: ReactQueryRawPluginConfig = { - addInfiniteQuery: true, reactQueryVersion: 5, + addInfiniteQuery: true, + addSuspenseQuery: true, }; const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; From adece6bc6c4cf64be6a69cf54c5462a69a07be66 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 17:12:06 +0800 Subject: [PATCH 37/43] refactor: dry --- packages/plugins/typescript/react-query/src/visitor.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/visitor.ts b/packages/plugins/typescript/react-query/src/visitor.ts index 50011a86f..89c5f75d4 100644 --- a/packages/plugins/typescript/react-query/src/visitor.ts +++ b/packages/plugins/typescript/react-query/src/visitor.ts @@ -149,6 +149,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< operationVariablesTypes = this._externalImportPrefix + operationVariablesTypes; const queries: string[] = []; + const getOutputFromQueries = () => `\n${queries.join('\n\n')}\n`; if (operationType === 'Query') { const addQuery = (generateConfig: GenerateConfig, isSuspense = false) => { @@ -189,7 +190,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { queries.push(this.fetcher.generateFetcherFetch(generateConfig)); } - return `\n${queries.join('\n\n')}\n`; + return getOutputFromQueries(); } if (operationType === 'Mutation') { const { hook, getKey } = this.fetcher.generateMutationOutput(generateConfig); @@ -198,7 +199,7 @@ export class ReactQueryVisitor extends ClientSideBaseVisitor< if (this.config.exposeFetcher && !(this.fetcher as any)._isReactHook) { queries.push(this.fetcher.generateFetcherFetch(generateConfig)); } - return `\n${queries.join('\n\n')}\n`; + return getOutputFromQueries(); } if (operationType === 'Subscription') { // eslint-disable-next-line no-console From d1735f738192facb9146fc6e28f0400a1cda5168 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 17:21:42 +0800 Subject: [PATCH 38/43] fix: suspense queryKey --- .../typescript/react-query/src/fetcher.ts | 25 ++++++++++++------- .../__snapshots__/react-query.spec.ts.snap | 4 +-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index c36d107a4..0a0ecd8c1 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -87,7 +87,7 @@ export abstract class FetcherRenderer { ${implHookOuter} return ${infiniteQuery.getHook()}<${operationResultType}, TError, TData>( ${this.generateInfiniteQueryFormattedParameters( - this.generateInfiniteQueryKey(config), + this.generateInfiniteQueryKey(config, isSuspense), implFetcher, )} )};`; @@ -124,7 +124,10 @@ export abstract class FetcherRenderer { >(${argumentsResult}) => { ${implHookOuter} return ${query.getHook()}<${operationResultType}, TError, TData>( - ${this.generateQueryFormattedParameters(this.generateQueryKey(config), implFetcher)} + ${this.generateQueryFormattedParameters( + this.generateQueryKey(config, isSuspense), + implFetcher, + )} )};`; }; @@ -209,9 +212,11 @@ export abstract class FetcherRenderer { return `options: Omit<${infiniteQuery.getOptions()}<${operationResultType}, TError, TData>, 'queryKey'> & { queryKey?: ${infiniteQuery.getOptions()}<${operationResultType}, TError, TData>['queryKey'] }`; } - public generateInfiniteQueryKey(config: GenerateConfig): string { - if (config.hasRequiredVariables) return `['${config.node.name.value}.infinite', variables]`; - return `variables === undefined ? ['${config.node.name.value}.infinite'] : ['${config.node.name.value}.infinite', variables]`; + public generateInfiniteQueryKey(config: GenerateConfig, isSuspense: boolean): string { + const identifier = isSuspense ? 'infiniteSuspense' : 'infinite'; + if (config.hasRequiredVariables) + return `['${config.node.name.value}.${identifier}', variables]`; + return `variables === undefined ? ['${config.node.name.value}.${identifier}'] : ['${config.node.name.value}.${identifier}', variables]`; } public generateInfiniteQueryOutput(config: GenerateConfig, isSuspense = false) { @@ -222,14 +227,15 @@ export abstract class FetcherRenderer { hook: this.generateInfiniteQueryHook(config, isSuspense), getKey: `${infiniteQuery.getHook( operationName, - )}.getKey = (${signature}) => ${this.generateInfiniteQueryKey(config)};`, + )}.getKey = (${signature}) => ${this.generateInfiniteQueryKey(config, isSuspense)};`, rootKey: `${infiniteQuery.getHook(operationName)}.rootKey = '${node.name.value}.infinite';`, }; } - public generateQueryKey(config: GenerateConfig): string { - if (config.hasRequiredVariables) return `['${config.node.name.value}', variables]`; - return `variables === undefined ? ['${config.node.name.value}'] : ['${config.node.name.value}', variables]`; + public generateQueryKey(config: GenerateConfig, isSuspense: boolean): string { + const identifier = isSuspense ? `${config.node.name.value}Suspense` : config.node.name.value; + if (config.hasRequiredVariables) return `['${identifier}', variables]`; + return `variables === undefined ? ['${identifier}'] : ['${identifier}', variables]`; } public generateQueryOutput(config: GenerateConfig, isSuspense = false) { @@ -241,6 +247,7 @@ export abstract class FetcherRenderer { document: `${query.getHook(operationName)}.document = ${documentVariableName};`, getKey: `${query.getHook(operationName)}.getKey = (${signature}) => ${this.generateQueryKey( config, + isSuspense, )};`, rootKey: `${query.getHook(operationName)}.rootKey = '${node.name.value}';`, }; diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 181caa46e..afa4bcf55 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -1319,7 +1319,7 @@ export const useSuspenseTestQuery = < return useSuspenseQuery( { - queryKey: variables === undefined ? ['test'] : ['test', variables], + queryKey: variables === undefined ? ['testSuspense'] : ['testSuspense', variables], queryFn: fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, variables), ...options } @@ -1358,7 +1358,7 @@ export const useSuspenseInfiniteTestQuery = < (() => { const { queryKey: optionsQueryKey, ...restOptions } = options; return { - queryKey: optionsQueryKey ?? variables === undefined ? ['test.infinite'] : ['test.infinite', variables], + queryKey: optionsQueryKey ?? variables === undefined ? ['test.infiniteSuspense'] : ['test.infiniteSuspense', variables], queryFn: (metaData) => fetcher(dataSource.endpoint, dataSource.fetchParams || {}, TestDocument, {...variables, ...(metaData.pageParam ?? {})})(), ...restOptions } From cbb32c35e832687d78b6133c8e6edf08798a4fdc Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Fri, 13 Oct 2023 17:25:11 +0800 Subject: [PATCH 39/43] fix: suspense optionsType --- packages/plugins/typescript/react-query/src/fetcher.ts | 8 ++++---- .../tests/__snapshots__/react-query.spec.ts.snap | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 0a0ecd8c1..7a69ebba7 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -68,7 +68,7 @@ export abstract class FetcherRenderer { const variables = this.generateInfiniteQueryVariablesSignature(config); - const options = this.generateInfiniteQueryOptionsSignature(config); + const options = this.generateInfiniteQueryOptionsSignature(config, isSuspense); const generateBaseInfiniteQueryHook = (hookConfig: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = hookConfig; @@ -106,7 +106,7 @@ export abstract class FetcherRenderer { const variables = this.generateQueryVariablesSignature(config); - const options = this.generateQueryOptionsSignature(config); + const options = this.generateQueryOptionsSignature(config, isSuspense); const generateBaseQueryHook = (hookConfig: GenerateBaseHookConfig) => { const { implArguments, implHookOuter = '', implFetcher } = hookConfig; @@ -181,7 +181,7 @@ export abstract class FetcherRenderer { private generateQueryOptionsSignature( { operationResultType }: GenerateConfig, - isSuspense = false, + isSuspense: boolean, ): string { const { query } = this.createQueryMethodMap(isSuspense); @@ -202,7 +202,7 @@ export abstract class FetcherRenderer { private generateInfiniteQueryOptionsSignature( { operationResultType }: GenerateConfig, - isSuspense = false, + isSuspense: boolean, ): string { const { infiniteQuery } = this.createQueryMethodMap(isSuspense); diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index afa4bcf55..0eb94f400 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -1314,7 +1314,7 @@ export const useSuspenseTestQuery = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, variables?: TestQueryVariables, - options?: Omit, 'queryKey'> & { queryKey?: UseQueryOptions['queryKey'] } + options?: Omit, 'queryKey'> & { queryKey?: UseSuspenseQueryOptions['queryKey'] } ) => { return useSuspenseQuery( @@ -1351,7 +1351,7 @@ export const useSuspenseInfiniteTestQuery = < >( dataSource: { endpoint: string, fetchParams?: RequestInit }, variables: TestQueryVariables, - options: Omit, 'queryKey'> & { queryKey?: UseInfiniteQueryOptions['queryKey'] } + options: Omit, 'queryKey'> & { queryKey?: UseSuspenseInfiniteQueryOptions['queryKey'] } ) => { return useSuspenseInfiniteQuery( From a2ac5550ab68aaf85f64ea51fafeb5504f373193 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Sat, 14 Oct 2023 14:15:46 +0800 Subject: [PATCH 40/43] refactor: dry --- packages/plugins/typescript/react-query/src/fetcher.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 7a69ebba7..c44728852 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -39,15 +39,15 @@ export abstract class FetcherRenderer { protected abstract generateMutationHook(config: GenerateConfig): string; public createQueryMethodMap(isSuspense = false) { + const suspenseText = isSuspense ? 'Suspense' : ''; const queryMethodMap: ReactQueryMethodMap = { infiniteQuery: { - getHook: (operationName = 'Query') => - `use${isSuspense ? 'Suspense' : ''}Infinite${operationName}`, - getOptions: () => `Use${isSuspense ? 'Suspense' : ''}InfiniteQueryOptions`, + getHook: (operationName = 'Query') => `use${suspenseText}Infinite${operationName}`, + getOptions: () => `Use${suspenseText}InfiniteQueryOptions`, }, query: { - getHook: (operationName = 'Query') => `use${isSuspense ? 'Suspense' : ''}${operationName}`, - getOptions: () => `Use${isSuspense ? 'Suspense' : ''}QueryOptions`, + getHook: (operationName = 'Query') => `use${suspenseText}${operationName}`, + getOptions: () => `Use${suspenseText}QueryOptions`, }, mutation: { getHook: (operationName = 'Mutation') => `use${operationName}`, From b22c111ab6e9e5bd8fda58934013b711b4db059b Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Sun, 15 Oct 2023 15:51:33 +0800 Subject: [PATCH 41/43] refactor: format --- packages/plugins/typescript/react-query/src/fetcher.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index c44728852..451043871 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -67,7 +67,6 @@ export abstract class FetcherRenderer { this.visitor.reactQueryOptionsIdentifiersInUse.add(infiniteQuery.getOptions()); const variables = this.generateInfiniteQueryVariablesSignature(config); - const options = this.generateInfiniteQueryOptionsSignature(config, isSuspense); const generateBaseInfiniteQueryHook = (hookConfig: GenerateBaseHookConfig) => { @@ -105,7 +104,6 @@ export abstract class FetcherRenderer { this.visitor.reactQueryOptionsIdentifiersInUse.add(query.getOptions()); const variables = this.generateQueryVariablesSignature(config); - const options = this.generateQueryOptionsSignature(config, isSuspense); const generateBaseQueryHook = (hookConfig: GenerateBaseHookConfig) => { @@ -147,7 +145,6 @@ export abstract class FetcherRenderer { this.visitor.reactQueryOptionsIdentifiersInUse.add(mutation.getOptions()); const variables = `variables?: ${operationVariablesTypes}`; - const options = `options?: ${mutation.getOptions()}<${operationResultType}, TError, ${operationVariablesTypes}, TContext>`; const generateBaseMutationHook = (hookConfig: GenerateBaseHookConfig) => { From a36fe2a320b2a710173399e855789910cc8d5cc0 Mon Sep 17 00:00:00 2001 From: sam585456525 Date: Sun, 15 Oct 2023 16:08:06 +0800 Subject: [PATCH 42/43] fix: infiniteData type --- .../typescript/react-query/src/fetcher.ts | 15 ++++++++- .../__snapshots__/react-query.spec.ts.snap | 32 +++++++++++++++++-- .../react-query/tests/react-query.spec.ts | 3 +- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/packages/plugins/typescript/react-query/src/fetcher.ts b/packages/plugins/typescript/react-query/src/fetcher.ts index 451043871..9d7991ad7 100644 --- a/packages/plugins/typescript/react-query/src/fetcher.ts +++ b/packages/plugins/typescript/react-query/src/fetcher.ts @@ -21,6 +21,7 @@ type ReactQueryMethodMap = { [key: string]: { getHook: (operationName?: string) => string; getOptions: () => string; + getOtherTypes?: () => { [key: string]: string }; }; }; @@ -44,6 +45,7 @@ export abstract class FetcherRenderer { infiniteQuery: { getHook: (operationName = 'Query') => `use${suspenseText}Infinite${operationName}`, getOptions: () => `Use${suspenseText}InfiniteQueryOptions`, + getOtherTypes: () => ({ infiniteData: 'InfiniteData' }), }, query: { getHook: (operationName = 'Query') => `use${suspenseText}${operationName}`, @@ -63,8 +65,15 @@ export abstract class FetcherRenderer { const { infiniteQuery } = this.createQueryMethodMap(isSuspense); + const isNextVersion = this.visitor.config.reactQueryVersion >= 5; + this.visitor.reactQueryHookIdentifiersInUse.add(infiniteQuery.getHook()); this.visitor.reactQueryOptionsIdentifiersInUse.add(infiniteQuery.getOptions()); + if (isNextVersion) { + this.visitor.reactQueryOptionsIdentifiersInUse.add( + infiniteQuery.getOtherTypes().infiniteData, + ); + } const variables = this.generateInfiniteQueryVariablesSignature(config); const options = this.generateInfiniteQueryOptionsSignature(config, isSuspense); @@ -80,7 +89,11 @@ export abstract class FetcherRenderer { `; return `export const ${infiniteQuery.getHook(operationName)} = < - TData = ${operationResultType}, + TData = ${ + isNextVersion + ? `${infiniteQuery.getOtherTypes().infiniteData}<${operationResultType}>` + : operationResultType + }, TError = ${this.visitor.config.errorType} >(${argumentsResult}) => { ${implHookOuter} diff --git a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap index 0eb94f400..ccfed1a09 100644 --- a/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap +++ b/packages/plugins/typescript/react-query/tests/__snapshots__/react-query.spec.ts.snap @@ -1272,7 +1272,7 @@ function fetcher(endpoint: string, requestInit: RequestInit, ] `; -exports[`React-Query support v5 syntax 1`] = ` +exports[`React-Query support v5 syntax: content 1`] = ` " export const TestDocument = \` @@ -1326,7 +1326,7 @@ export const useSuspenseTestQuery = < )}; export const useInfiniteTestQuery = < - TData = TestQuery, + TData = InfiniteData, TError = unknown >( dataSource: { endpoint: string, fetchParams?: RequestInit }, @@ -1346,7 +1346,7 @@ export const useInfiniteTestQuery = < )}; export const useSuspenseInfiniteTestQuery = < - TData = TestQuery, + TData = InfiniteData, TError = unknown >( dataSource: { endpoint: string, fetchParams?: RequestInit }, @@ -1390,3 +1390,29 @@ export const useTestMutation = < )}; " `; + +exports[`React-Query support v5 syntax: prepend 1`] = ` +[ + "import { useQuery, useSuspenseQuery, useInfiniteQuery, useSuspenseInfiniteQuery, useMutation, UseQueryOptions, UseSuspenseQueryOptions, UseInfiniteQueryOptions, InfiniteData, UseSuspenseInfiniteQueryOptions, UseMutationOptions } from '@tanstack/react-query';", + " +function fetcher(endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables) { + return async (): Promise => { + const res = await fetch(endpoint, { + method: 'POST', + ...requestInit, + body: JSON.stringify({ query, variables }), + }); + + const json = await res.json(); + + if (json.errors) { + const { message } = json.errors[0]; + + throw new Error(message); + } + + return json.data; + } +}", +] +`; diff --git a/packages/plugins/typescript/react-query/tests/react-query.spec.ts b/packages/plugins/typescript/react-query/tests/react-query.spec.ts index 83d123f4b..815432f1d 100644 --- a/packages/plugins/typescript/react-query/tests/react-query.spec.ts +++ b/packages/plugins/typescript/react-query/tests/react-query.spec.ts @@ -46,7 +46,8 @@ describe('React-Query', () => { const out = (await plugin(schema, docs, config)) as Types.ComplexPluginOutput; - expect(out.content).toMatchSnapshot(); + expect(out.prepend).toMatchSnapshot('prepend'); + expect(out.content).toMatchSnapshot('content'); await validateTypeScript(mergeOutputs(out), schema, docs, config); }); From 753e9290bbb05ab4adcff0e24cdac8606471a85c Mon Sep 17 00:00:00 2001 From: Saihajpreet Singh Date: Tue, 24 Oct 2023 19:35:21 -0500 Subject: [PATCH 43/43] Update packages/plugins/typescript/react-query/package.json --- packages/plugins/typescript/react-query/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/typescript/react-query/package.json b/packages/plugins/typescript/react-query/package.json index 73f4035a3..389cd86cb 100644 --- a/packages/plugins/typescript/react-query/package.json +++ b/packages/plugins/typescript/react-query/package.json @@ -1,6 +1,6 @@ { "name": "@graphql-codegen/typescript-react-query", - "version": "5.0.1", + "version": "5.0.0", "type": "module", "description": "GraphQL Code Generator plugin for generating a ready-to-use React-Query Hooks based on GraphQL operations", "repository": {