Skip to content

Commit 98acb82

Browse files
committed
Type fixes and include prefix in query key by default
1 parent f731256 commit 98acb82

File tree

8 files changed

+148
-48
lines changed

8 files changed

+148
-48
lines changed

packages/tanstack-react-query/src/internals/createOptionsProxy.ts

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,15 @@ type UtilsMethods =
323323
export function createTRPCOptionsProxy<TRouter extends AnyTRPCRouter>(
324324
opts: TRPCOptionsProxyOptions<TRouter>,
325325
): TRPCOptionsProxy<TRouter> {
326+
const queryKeyPrefix: string[] = [];
327+
if (opts.queryKeyPrefix) {
328+
if (Array.isArray(opts.queryKeyPrefix)) {
329+
queryKeyPrefix.push(...opts.queryKeyPrefix);
330+
} else {
331+
queryKeyPrefix.push(opts.queryKeyPrefix);
332+
}
333+
}
334+
326335
const callIt = (type: TRPCProcedureType): any => {
327336
return (path: string, input: unknown, trpcOpts: TRPCRequestOptions) => {
328337
if ('router' in opts) {
@@ -349,28 +358,19 @@ export function createTRPCOptionsProxy<TRouter extends AnyTRPCRouter>(
349358

350359
return createTRPCRecursiveProxy(({ args, path: _path }) => {
351360
const path = [..._path];
352-
353-
const queryKeyPath = [...path];
354-
if (opts.queryKeyPrefix) {
355-
const prefix = Array.isArray(opts.queryKeyPrefix)
356-
? opts.queryKeyPrefix
357-
: [opts.queryKeyPrefix];
358-
queryKeyPath.unshift(...prefix);
359-
}
360-
361361
const utilName = path.pop() as UtilsMethods;
362362
const [arg1, arg2] = args as any[];
363363

364364
const contextMap: Record<UtilsMethods, () => unknown> = {
365365
'~types': undefined as any,
366366

367367
pathKey: () => {
368-
return getQueryKeyInternal(path);
368+
return getQueryKeyInternal(path, { prefix: queryKeyPrefix });
369369
},
370370
pathFilter: (): QueryFilters => {
371371
return {
372372
...arg1,
373-
queryKey: getQueryKeyInternal(path),
373+
queryKey: getQueryKeyInternal(path, { prefix: queryKeyPrefix }),
374374
};
375375
},
376376

@@ -380,17 +380,29 @@ export function createTRPCOptionsProxy<TRouter extends AnyTRPCRouter>(
380380
opts: arg2,
381381
path,
382382
queryClient: opts.queryClient,
383-
queryKey: getQueryKeyInternal(queryKeyPath, arg1, 'query'),
383+
queryKey: getQueryKeyInternal(path, {
384+
input: arg1,
385+
type: 'query',
386+
prefix: queryKeyPrefix,
387+
}),
384388
query: callIt('query'),
385389
});
386390
},
387391
queryKey: () => {
388-
return getQueryKeyInternal(queryKeyPath, arg1, 'query');
392+
return getQueryKeyInternal(path, {
393+
input: arg1,
394+
type: 'query',
395+
prefix: queryKeyPrefix,
396+
});
389397
},
390398
queryFilter: (): QueryFilters => {
391399
return {
392400
...arg2,
393-
queryKey: getQueryKeyInternal(queryKeyPath, arg1, 'query'),
401+
queryKey: getQueryKeyInternal(path, {
402+
input: arg1,
403+
type: 'query',
404+
prefix: queryKeyPrefix,
405+
}),
394406
};
395407
},
396408

@@ -400,17 +412,29 @@ export function createTRPCOptionsProxy<TRouter extends AnyTRPCRouter>(
400412
opts: arg2,
401413
path,
402414
queryClient: opts.queryClient,
403-
queryKey: getQueryKeyInternal(queryKeyPath, arg1, 'infinite'),
415+
queryKey: getQueryKeyInternal(path, {
416+
input: arg1,
417+
type: 'infinite',
418+
prefix: queryKeyPrefix,
419+
}),
404420
query: callIt('query'),
405421
});
406422
},
407423
infiniteQueryKey: () => {
408-
return getQueryKeyInternal(queryKeyPath, arg1, 'infinite');
424+
return getQueryKeyInternal(path, {
425+
input: arg1,
426+
type: 'infinite',
427+
prefix: queryKeyPrefix,
428+
});
409429
},
410430
infiniteQueryFilter: (): QueryFilters => {
411431
return {
412432
...arg2,
413-
queryKey: getQueryKeyInternal(queryKeyPath, arg1, 'infinite'),
433+
queryKey: getQueryKeyInternal(path, {
434+
input: arg1,
435+
type: 'infinite',
436+
prefix: queryKeyPrefix,
437+
}),
414438
};
415439
},
416440

@@ -424,14 +448,18 @@ export function createTRPCOptionsProxy<TRouter extends AnyTRPCRouter>(
424448
});
425449
},
426450
mutationKey: () => {
427-
return getMutationKeyInternal(queryKeyPath);
451+
return getMutationKeyInternal(path);
428452
},
429453

430454
subscriptionOptions: () => {
431455
return trpcSubscriptionOptions({
432456
opts: arg2,
433457
path,
434-
queryKey: getQueryKeyInternal(queryKeyPath, arg1, 'any'),
458+
queryKey: getQueryKeyInternal(path, {
459+
input: arg1,
460+
type: 'any',
461+
prefix: queryKeyPrefix,
462+
}),
435463
subscribe: callIt('subscription'),
436464
});
437465
},

packages/tanstack-react-query/src/internals/mutationOptions.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ export function trpcMutationOptions(args: {
106106
overrides?.onSuccess ?? ((options) => options.originalFn());
107107

108108
const mutationFn: MutationFunction = async (input) => {
109-
const result = await mutate(...getClientArgs([path, { input }], opts));
109+
const result = await mutate(
110+
...getClientArgs([mutationKey[0], path, { input }], opts),
111+
);
110112

111113
return result;
112114
};

packages/tanstack-react-query/src/internals/subscriptionOptions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export const trpcSubscriptionOptions = (args: {
128128
opts?: AnyTRPCSubscriptionOptionsIn;
129129
}): AnyTRPCSubscriptionOptionsOut => {
130130
const { subscribe, path, queryKey, opts = {} } = args;
131-
const input = queryKey[1]?.input;
131+
const input = queryKey[2]?.input;
132132
const enabled = 'enabled' in opts ? !!opts.enabled : input !== skipToken;
133133

134134
const _subscribe: ReturnType<TRPCSubscriptionOptions<any>>['subscribe'] = (

packages/tanstack-react-query/src/internals/types.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,15 @@ export type QueryType = 'any' | 'infinite' | 'query';
8484
* @public
8585
*/
8686
export type TRPCQueryKey = [
87-
readonly string[],
88-
{ input?: unknown; type?: Exclude<QueryType, 'any'> }?,
87+
prefix: readonly string[],
88+
path: readonly string[],
89+
opts?: { input?: unknown; type?: Exclude<QueryType, 'any'> },
8990
];
9091

9192
/**
9293
* @public
9394
*/
94-
export type TRPCMutationKey = [readonly string[]]; // = [TRPCQueryKey[0]]
95+
export type TRPCMutationKey = [
96+
prefix: readonly string[],
97+
path: readonly string[],
98+
];

packages/tanstack-react-query/src/internals/utils.ts

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ export function getClientArgs<TOptions>(
3131
direction: 'forward' | 'backward';
3232
},
3333
) {
34-
const path = queryKey[0];
35-
let input = queryKey[1]?.input;
34+
const path = queryKey[1];
35+
let input = queryKey[2]?.input;
3636
if (infiniteParams) {
3737
input = {
3838
...(input ?? {}),
@@ -84,35 +84,42 @@ export async function buildQueryFromAsyncIterable(
8484
*/
8585
export function getQueryKeyInternal(
8686
path: readonly string[],
87-
input?: unknown,
88-
type?: QueryType,
87+
opts: {
88+
input?: unknown;
89+
type?: QueryType;
90+
prefix?: readonly string[];
91+
} = {},
8992
): TRPCQueryKey {
9093
// Construct a query key that is easy to destructure and flexible for
9194
// partial selecting etc.
9295
// https://github.com/trpc/trpc/issues/3128
9396

9497
// some parts of the path may be dot-separated, split them up
98+
const prefix = opts.prefix ?? [];
9599
const splitPath = path.flatMap((part) => part.split('.'));
96100

97-
if (!input && (!type || type === 'any')) {
101+
if (!opts.input && (!opts.type || opts.type === 'any')) {
98102
// this matches also all mutations (see `getMutationKeyInternal`)
99103

100104
// for `utils.invalidate()` to match all queries (including vanilla react-query)
101105
// we don't want nested array if path is empty, i.e. `[]` instead of `[[]]`
102-
return splitPath.length ? [splitPath] : ([] as unknown as TRPCQueryKey);
106+
return splitPath.length
107+
? [prefix, splitPath]
108+
: ([prefix] as unknown as TRPCQueryKey);
103109
}
104110

105111
if (
106-
type === 'infinite' &&
107-
isObject(input) &&
108-
('direction' in input || 'cursor' in input)
112+
opts.type === 'infinite' &&
113+
isObject(opts.input) &&
114+
('direction' in opts.input || 'cursor' in opts.input)
109115
) {
110116
const {
111117
cursor: _,
112118
direction: __,
113119
...inputWithoutCursorAndDirection
114-
} = input;
120+
} = opts.input;
115121
return [
122+
prefix,
116123
splitPath,
117124
{
118125
input: inputWithoutCursorAndDirection,
@@ -122,11 +129,12 @@ export function getQueryKeyInternal(
122129
}
123130

124131
return [
132+
prefix,
125133
splitPath,
126134
{
127-
...(typeof input !== 'undefined' &&
128-
input !== skipToken && { input: input }),
129-
...(type && type !== 'any' && { type: type }),
135+
...(typeof opts.input !== 'undefined' &&
136+
opts.input !== skipToken && { input: opts.input }),
137+
...(opts.type && opts.type !== 'any' && { type: opts.type }),
130138
},
131139
];
132140
}
@@ -136,11 +144,18 @@ export function getQueryKeyInternal(
136144
*/
137145
export function getMutationKeyInternal(
138146
path: readonly string[],
147+
opts: {
148+
prefix?: readonly string[];
149+
} = {},
139150
): TRPCMutationKey {
151+
const prefix = opts.prefix ?? [];
152+
140153
// some parts of the path may be dot-separated, split them up
141154
const splitPath = path.flatMap((part) => part.split('.'));
142155

143-
return splitPath.length ? [splitPath] : ([] as unknown as TRPCMutationKey);
156+
return splitPath.length
157+
? [prefix, splitPath]
158+
: ([prefix] as unknown as TRPCMutationKey);
144159
}
145160

146161
/**

packages/tanstack-react-query/test/__helpers.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { AnyTRPCRouter } from '@trpc/server';
1010
import * as React from 'react';
1111
import { createTRPCContext, createTRPCOptionsProxy } from '../src';
1212

13-
type TestReactResourceExtraOpts = { queryKeyPrefix?: string | string[] }
13+
type TestReactResourceExtraOpts = { queryKeyPrefix?: string | string[] };
1414

1515
export function testReactResource<TRouter extends AnyTRPCRouter>(
1616
appRouter: TRouter,
@@ -23,20 +23,26 @@ export function testReactResource<TRouter extends AnyTRPCRouter>(
2323
const optionsProxyClient = createTRPCOptionsProxy({
2424
client: getUntypedClient(ctx.client),
2525
queryClient,
26+
queryKeyPrefix: opts?.queryKeyPrefix,
2627
});
2728

2829
const optionsProxyServer = createTRPCOptionsProxy({
2930
router: appRouter,
3031
ctx: {},
3132
queryClient,
33+
queryKeyPrefix: opts?.queryKeyPrefix,
3234
});
3335

3436
const { TRPCProvider, useTRPC, useTRPCClient } = createTRPCContext<TRouter>();
3537

3638
function renderApp(ui: React.ReactNode) {
3739
return render(
3840
<QueryClientProvider client={queryClient}>
39-
<TRPCProvider trpcClient={ctx.client} queryClient={queryClient}>
41+
<TRPCProvider
42+
trpcClient={ctx.client}
43+
queryClient={queryClient}
44+
queryKeyPrefix={opts?.queryKeyPrefix}
45+
>
4046
{ui}
4147
</TRPCProvider>
4248
</QueryClientProvider>,
@@ -46,7 +52,11 @@ export function testReactResource<TRouter extends AnyTRPCRouter>(
4652
function rerenderApp(render: RenderResult, ui: React.ReactNode) {
4753
return render.rerender(
4854
<QueryClientProvider client={queryClient}>
49-
<TRPCProvider trpcClient={ctx.client} queryClient={queryClient}>
55+
<TRPCProvider
56+
trpcClient={ctx.client}
57+
queryClient={queryClient}
58+
queryKeyPrefix={opts?.queryKeyPrefix}
59+
>
5060
{ui}
5161
</TRPCProvider>
5262
</QueryClientProvider>,

0 commit comments

Comments
 (0)