Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 60 additions & 36 deletions packages/query/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -726,9 +726,8 @@ const getQueryFnArguments = ({
};

const generateQueryImplementation = ({
queryOption: { name, queryParam, options, type },
queryOption: { name, queryParam, options, type, queryKeyFnName },
operationName,
queryKeyFnName,
queryProperties,
queryKeyProperties,
queryParams,
Expand Down Expand Up @@ -759,10 +758,10 @@ const generateQueryImplementation = ({
options?: object | boolean;
type: QueryType;
queryParam?: string;
queryKeyFnName: string;
};
isRequestOptions: boolean;
operationName: string;
queryKeyFnName: string;
queryProperties: string;
queryKeyProperties: string;
params: GetterParams;
Expand Down Expand Up @@ -1262,6 +1261,7 @@ const generateQueryHook = async (
options: query?.options,
type: QueryType.INFINITE,
queryParam: query?.useInfiniteQueryParam,
queryKeyFnName: camel(`get-${operationName}-infinite-query-key`),
},
]
: []),
Expand All @@ -1271,6 +1271,7 @@ const generateQueryHook = async (
name: operationName,
options: query?.options,
type: QueryType.QUERY,
queryKeyFnName: camel(`get-${operationName}-query-key`),
},
]
: []),
Expand All @@ -1280,6 +1281,7 @@ const generateQueryHook = async (
name: camel(`${operationName}-suspense`),
options: query?.options,
type: QueryType.SUSPENSE_QUERY,
queryKeyFnName: camel(`get-${operationName}-query-key`),
},
]
: []),
Expand All @@ -1291,12 +1293,12 @@ const generateQueryHook = async (
options: query?.options,
type: QueryType.SUSPENSE_INFINITE,
queryParam: query?.useInfiniteQueryParam,
queryKeyFnName: camel(`get-${operationName}-infinite-query-key`),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now each query type has own queryKeyFnName

},
]
: []),
];

const queryKeyFnName = camel(`get-${operationName}-queryKey`);
// Convert "param: Type" to "param?: Type" for queryKey functions
// to enable cache invalidation without type assertion
const makeParamsOptional = (params: string) => {
Expand All @@ -1316,41 +1318,63 @@ const generateQueryHook = async (
);
};

const queryKeyProps = makeParamsOptional(
toObjectString(
props.filter((prop) => prop.type !== GetterPropType.HEADER),
'implementation',
),
const uniqueQueryOptionsByKeys = queries.filter(
(obj, index, self) =>
index ===
self.findIndex((t) => t.queryKeyFnName === obj.queryKeyFnName),
);

const routeString =
isVue(outputClient) || override.query.shouldSplitQueryKey
? getRouteAsArray(route) // Note: this is required for reactivity to work, we will lose it if route params are converted into string, only as array they will be tracked // TODO: add tests for this
: `\`${route}\``;

// Use operation ID as query key if enabled, otherwise use route string
const queryKeyIdentifier = override.query.useOperationIdAsQueryKey
? operationName
: routeString;

// Note: do not unref() params in Vue - this will make key lose reactivity
const queryKeyFn = `${
override.query.shouldExportQueryKey ? 'export ' : ''
}const ${queryKeyFnName} = (${queryKeyProps}) => {
return [${queryKeyIdentifier}${queryParams ? ', ...(params ? [params]: [])' : ''}${
body.implementation ? `, ${body.implementation}` : ''
}] as const;
}`;

implementation += `${queryKeyMutator ? '' : queryKeyFn}

${queries.reduce(
(acc, queryOption) =>
implementation += `
${
!queryKeyMutator
? uniqueQueryOptionsByKeys.reduce((acc, queryOption) => {
const queryKeyProps = makeParamsOptional(
toObjectString(
props.filter((prop) => prop.type !== GetterPropType.HEADER),
'implementation',
),
);

const routeString =
isVue(outputClient) || override.query.shouldSplitQueryKey
? getRouteAsArray(route) // Note: this is required for reactivity to work, we will lose it if route params are converted into string, only as array they will be tracked // TODO: add tests for this
: `\`${route}\``;

// Use operation ID as query key if enabled, otherwise use route string
const queryKeyIdentifier = override.query.useOperationIdAsQueryKey
? operationName
: routeString;

// Note: do not unref() params in Vue - this will make key lose reactivity
const queryKeyFn = `
${override.query.shouldExportQueryKey ? 'export ' : ''}const ${queryOption.queryKeyFnName} = (${queryKeyProps}) => {
return [
${[
queryOption.type === QueryType.INFINITE ||
queryOption.type === QueryType.SUSPENSE_INFINITE
? `'infinate'`
: '',
queryKeyIdentifier,
queryParams ? '...(params ? [params]: [])' : '',
body.implementation,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, the value was used only if body.implementation existed, as shown below. Is it okay to remove this existence check?

body.implementation ? , ${body.implementation} : ''

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We drop falsy value in next line filter

]
.filter((x) => !!x)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since all values ​​are normalized, this process is unnecessary.

Suggested change
.filter((x) => !!x)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need drop falsy value (like a empty body.implementation, queryParams and etc ) from query key generator . Without this filter we can get query key like a ['', '/api/blabla/', '','']

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, that's because it's now treated as an array instead of a string. And since you need to check for existence anyway, it's no longer necessary to check for the existence of just body.implementation.

.join(', ')}
] as const;
}
`;
return acc + queryKeyFn;
}, '')
: ''
}`;

implementation += `
${queries.reduce((acc, queryOption) => {
return (
acc +
generateQueryImplementation({
queryOption,
operationName,
queryKeyFnName,
queryProperties,
queryKeyProperties,
params,
Expand Down Expand Up @@ -1378,9 +1402,9 @@ const generateQueryHook = async (
usePrefetch: query.usePrefetch,
useQuery: query.useQuery,
useInfinite: query.useInfinite,
}),
'',
)}
})
);
}, '')}
`;

mutators =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ export const listPets = (
});
};

export const getListPetsInfiniteQueryKey = (
params?: ListPetsParams,
version: number = 1,
) => {
return [
'infinate',
`/v${version}/pets`,
...(params ? [params] : []),
] as const;
};

export const getListPetsQueryKey = (
params?: ListPetsParams,
version: number = 1,
Expand Down Expand Up @@ -95,7 +106,7 @@ export const getListPetsInfiniteQueryOptions = <
const { query: queryOptions } = options ?? {};

const queryKey =
queryOptions?.queryKey ?? getListPetsQueryKey(params, version);
queryOptions?.queryKey ?? getListPetsInfiniteQueryKey(params, version);

const queryFn: QueryFunction<
Awaited<ReturnType<typeof listPets>>,
Expand Down Expand Up @@ -556,7 +567,7 @@ export const getListPetsSuspenseInfiniteQueryOptions = <
const { query: queryOptions } = options ?? {};

const queryKey =
queryOptions?.queryKey ?? getListPetsQueryKey(params, version);
queryOptions?.queryKey ?? getListPetsInfiniteQueryKey(params, version);

const queryFn: QueryFunction<
Awaited<ReturnType<typeof listPets>>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ export const listPets = (
});
};

export const getListPetsInfiniteQueryKey = (
params?: MaybeRef<ListPetsParams>,
version: MaybeRef<number | undefined | null> = 1,
) => {
return [
'infinate',
'v',
version,
'pets',
...(params ? [params] : []),
] as const;
};

export const getListPetsQueryKey = (
params?: MaybeRef<ListPetsParams>,
version: MaybeRef<number | undefined | null> = 1,
Expand Down Expand Up @@ -82,7 +95,7 @@ export const getListPetsInfiniteQueryOptions = <
) => {
const { query: queryOptions } = options ?? {};

const queryKey = getListPetsQueryKey(params, version);
const queryKey = getListPetsInfiniteQueryKey(params, version);

const queryFn: QueryFunction<
Awaited<ReturnType<typeof listPets>>,
Expand Down Expand Up @@ -337,6 +350,13 @@ export const showPetById = (
});
};

export const getShowPetByIdInfiniteQueryKey = (
petId?: MaybeRef<string | undefined | null>,
version: MaybeRef<number | undefined | null> = 1,
) => {
return ['infinate', 'v', version, 'pets', petId] as const;
};

export const getShowPetByIdQueryKey = (
petId?: MaybeRef<string | undefined | null>,
version: MaybeRef<number | undefined | null> = 1,
Expand All @@ -362,7 +382,7 @@ export const getShowPetByIdInfiniteQueryOptions = <
) => {
const { query: queryOptions } = options ?? {};

const queryKey = getShowPetByIdQueryKey(petId, version);
const queryKey = getShowPetByIdInfiniteQueryKey(petId, version);

const queryFn: QueryFunction<Awaited<ReturnType<typeof showPetById>>> = ({
signal,
Expand Down
Loading