@trpc/tanstack-react-query 0.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/index.d.ts +9 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +11 -0
  6. package/dist/index.mjs +3 -0
  7. package/dist/internals/Context.d.ts +14 -0
  8. package/dist/internals/Context.d.ts.map +1 -0
  9. package/dist/internals/Context.js +52 -0
  10. package/dist/internals/Context.mjs +31 -0
  11. package/dist/internals/createOptionsProxy.d.ts +107 -0
  12. package/dist/internals/createOptionsProxy.d.ts.map +1 -0
  13. package/dist/internals/createOptionsProxy.js +99 -0
  14. package/dist/internals/createOptionsProxy.mjs +97 -0
  15. package/dist/internals/infiniteQueryOptions.d.ts +49 -0
  16. package/dist/internals/infiniteQueryOptions.d.ts.map +1 -0
  17. package/dist/internals/infiniteQueryOptions.js +39 -0
  18. package/dist/internals/infiniteQueryOptions.mjs +37 -0
  19. package/dist/internals/mutationOptions.d.ts +38 -0
  20. package/dist/internals/mutationOptions.d.ts.map +1 -0
  21. package/dist/internals/mutationOptions.js +38 -0
  22. package/dist/internals/mutationOptions.mjs +36 -0
  23. package/dist/internals/queryOptions.d.ts +61 -0
  24. package/dist/internals/queryOptions.d.ts.map +1 -0
  25. package/dist/internals/queryOptions.js +40 -0
  26. package/dist/internals/queryOptions.mjs +38 -0
  27. package/dist/internals/subscriptionOptions.d.ts +77 -0
  28. package/dist/internals/subscriptionOptions.d.ts.map +1 -0
  29. package/dist/internals/subscriptionOptions.js +173 -0
  30. package/dist/internals/subscriptionOptions.mjs +151 -0
  31. package/dist/internals/types.d.ts +41 -0
  32. package/dist/internals/types.d.ts.map +1 -0
  33. package/dist/internals/utils.d.ts +28 -0
  34. package/dist/internals/utils.d.ts.map +1 -0
  35. package/dist/internals/utils.js +112 -0
  36. package/dist/internals/utils.mjs +105 -0
  37. package/package.json +81 -0
  38. package/src/index.ts +25 -0
  39. package/src/internals/Context.tsx +46 -0
  40. package/src/internals/createOptionsProxy.ts +309 -0
  41. package/src/internals/infiniteQueryOptions.ts +233 -0
  42. package/src/internals/mutationOptions.ts +113 -0
  43. package/src/internals/queryOptions.ts +199 -0
  44. package/src/internals/subscriptionOptions.ts +286 -0
  45. package/src/internals/types.ts +47 -0
  46. package/src/internals/utils.ts +140 -0
@@ -0,0 +1,309 @@
1
+ import { type QueryClient, type QueryFilters } from '@tanstack/react-query';
2
+ import {
3
+ getUntypedClient,
4
+ TRPCUntypedClient,
5
+ type CreateTRPCClient,
6
+ type TRPCRequestOptions,
7
+ } from '@trpc/client';
8
+ import {
9
+ callProcedure,
10
+ type AnyProcedure,
11
+ type inferProcedureInput,
12
+ type inferRouterContext,
13
+ type inferTransformedProcedureOutput,
14
+ type ProcedureType,
15
+ } from '@trpc/server';
16
+ import { createRecursiveProxy } from '@trpc/server/unstable-core-do-not-import';
17
+ import type {
18
+ AnyRootTypes,
19
+ AnyRouter,
20
+ MaybePromise,
21
+ RouterRecord,
22
+ } from '@trpc/server/unstable-core-do-not-import';
23
+ import {
24
+ trpcInfiniteQueryOptions,
25
+ type TRPCInfiniteQueryOptions,
26
+ } from './infiniteQueryOptions';
27
+ import type { MutationOptionsOverride } from './mutationOptions';
28
+ import {
29
+ trpcMutationOptions,
30
+ type TRPCMutationOptions,
31
+ } from './mutationOptions';
32
+ import { trpcQueryOptions, type TRPCQueryOptions } from './queryOptions';
33
+ import {
34
+ trpcSubscriptionOptions,
35
+ type TRPCSubscriptionOptions,
36
+ } from './subscriptionOptions';
37
+ import type {
38
+ QueryType,
39
+ ResolverDef,
40
+ TRPCMutationKey,
41
+ TRPCQueryKey,
42
+ } from './types';
43
+ import {
44
+ getMutationKeyInternal,
45
+ getQueryKeyInternal,
46
+ unwrapLazyArg,
47
+ } from './utils';
48
+
49
+ export interface DecorateQueryKeyable {
50
+ /**
51
+ * Calculate the Tanstack Query Key for a Route
52
+ *
53
+ * @see https://tanstack.com/query/latest/docs/framework/react/guides/query-keys
54
+ */
55
+ queryKey: () => TRPCQueryKey;
56
+
57
+ /**
58
+ * Calculate a Tanstack Query Filter for a Route
59
+ *
60
+ * @see https://tanstack.com/query/latest/docs/framework/react/guides/filters
61
+ */
62
+ queryFilter: () => QueryFilters;
63
+ }
64
+
65
+ export type InferInput<
66
+ TProcedure extends
67
+ | DecorateQueryProcedure<any>
68
+ | DecorateMutationProcedure<any>,
69
+ > = TProcedure['~types']['input'];
70
+
71
+ export type InferOutput<
72
+ TProcedure extends
73
+ | DecorateQueryProcedure<any>
74
+ | DecorateMutationProcedure<any>,
75
+ > = TProcedure['~types']['output'];
76
+
77
+ export interface DecorateQueryProcedure<TDef extends ResolverDef> {
78
+ /**
79
+ * @internal prefer using InferInput and InferOutput to access types
80
+ */
81
+ '~types': {
82
+ input: TDef['input'];
83
+ output: TDef['output'];
84
+ };
85
+
86
+ /**
87
+ * @see https://tanstack.com/query/latest/docs/framework/react/reference/queryOptions#queryoptions
88
+ */
89
+ queryOptions: TRPCQueryOptions<TDef>;
90
+
91
+ /**
92
+ * @see https://tanstack.com/query/latest/docs/framework/react/reference/infiniteQueryOptions#infinitequeryoptions
93
+ */
94
+ infiniteQueryOptions: TRPCInfiniteQueryOptions<TDef>;
95
+
96
+ /**
97
+ * Calculate the Tanstack Query Key for a Query Procedure
98
+ *
99
+ * @see https://tanstack.com/query/latest/docs/framework/react/guides/query-keys
100
+ */
101
+ queryKey: (input?: TDef['input']) => TRPCQueryKey;
102
+
103
+ /**
104
+ * Calculate a Tanstack Query Filter for a Query Procedure
105
+ *
106
+ * @see https://tanstack.com/query/latest/docs/framework/react/guides/filters
107
+ */
108
+ queryFilter: (input?: TDef['input']) => QueryFilters;
109
+ }
110
+
111
+ export interface DecorateMutationProcedure<TDef extends ResolverDef> {
112
+ /**
113
+ * @internal prefer using InferInput and InferOutput to access types
114
+ */
115
+ '~types': {
116
+ input: TDef['input'];
117
+ output: TDef['output'];
118
+ };
119
+
120
+ /**
121
+ * @see
122
+ */
123
+ mutationOptions: TRPCMutationOptions<TDef>;
124
+
125
+ /**
126
+ * Calculate the Tanstack Mutation Key for a Mutation Procedure
127
+ */
128
+ mutationKey: () => TRPCMutationKey;
129
+ }
130
+
131
+ export interface DecorateSubscriptionProcedure<TDef extends ResolverDef> {
132
+ /**
133
+ * @see
134
+ */
135
+ subscriptionOptions: TRPCSubscriptionOptions<TDef>;
136
+ }
137
+
138
+ export type DecorateProcedure<
139
+ TType extends ProcedureType,
140
+ TDef extends ResolverDef,
141
+ > = TType extends 'query'
142
+ ? DecorateQueryProcedure<TDef>
143
+ : TType extends 'mutation'
144
+ ? DecorateMutationProcedure<TDef>
145
+ : TType extends 'subscription'
146
+ ? DecorateSubscriptionProcedure<TDef>
147
+ : never;
148
+
149
+ /**
150
+ * @internal
151
+ */
152
+ export type DecoratedProcedureUtilsRecord<
153
+ TRoot extends AnyRootTypes,
154
+ TRecord extends RouterRecord,
155
+ > = {
156
+ [TKey in keyof TRecord]: TRecord[TKey] extends infer $Value
157
+ ? $Value extends RouterRecord
158
+ ? DecoratedProcedureUtilsRecord<TRoot, $Value> & DecorateQueryKeyable
159
+ : $Value extends AnyProcedure
160
+ ? DecorateProcedure<
161
+ $Value['_def']['type'],
162
+ {
163
+ input: inferProcedureInput<$Value>;
164
+ output: inferTransformedProcedureOutput<TRoot, $Value>;
165
+ transformer: TRoot['transformer'];
166
+ errorShape: TRoot['errorShape'];
167
+ }
168
+ >
169
+ : never
170
+ : never;
171
+ };
172
+
173
+ export type TRPCOptionsProxy<TRouter extends AnyRouter> =
174
+ DecoratedProcedureUtilsRecord<
175
+ TRouter['_def']['_config']['$types'],
176
+ TRouter['_def']['record']
177
+ > &
178
+ DecorateQueryKeyable;
179
+
180
+ export interface TRPCOptionsProxyOptionsBase {
181
+ queryClient: QueryClient | (() => QueryClient);
182
+ overrides?: {
183
+ mutations?: MutationOptionsOverride;
184
+ };
185
+ }
186
+
187
+ export interface TRPCOptionsProxyOptionsInternal<TRouter extends AnyRouter> {
188
+ router: TRouter;
189
+ ctx:
190
+ | inferRouterContext<TRouter>
191
+ | (() => MaybePromise<inferRouterContext<TRouter>>);
192
+ }
193
+
194
+ export interface TRPCOptionsProxyOptionsExternal<TRouter extends AnyRouter> {
195
+ client: TRPCUntypedClient<TRouter> | CreateTRPCClient<TRouter>;
196
+ }
197
+
198
+ export type TRPCOptionsProxyOptions<TRouter extends AnyRouter> =
199
+ TRPCOptionsProxyOptionsBase &
200
+ (
201
+ | TRPCOptionsProxyOptionsInternal<TRouter>
202
+ | TRPCOptionsProxyOptionsExternal<TRouter>
203
+ );
204
+
205
+ type UtilsMethods =
206
+ | keyof DecorateQueryProcedure<any>
207
+ | keyof DecorateMutationProcedure<any>
208
+ | keyof DecorateSubscriptionProcedure<any>;
209
+
210
+ function getQueryType(method: UtilsMethods) {
211
+ const map: Partial<Record<UtilsMethods, QueryType>> = {
212
+ queryOptions: 'query',
213
+ infiniteQueryOptions: 'infinite',
214
+ subscriptionOptions: 'any',
215
+ mutationOptions: 'any',
216
+ };
217
+
218
+ return map[method];
219
+ }
220
+
221
+ export function createTRPCOptionsProxy<TRouter extends AnyRouter>(
222
+ opts: TRPCOptionsProxyOptions<TRouter>,
223
+ ): TRPCOptionsProxy<TRouter> {
224
+ const callIt = (type: ProcedureType): any => {
225
+ return (path: string, input: unknown, trpcOpts: TRPCRequestOptions) => {
226
+ if ('router' in opts) {
227
+ return Promise.resolve(unwrapLazyArg(opts.ctx)).then((ctx) =>
228
+ callProcedure({
229
+ procedures: opts.router._def.procedures,
230
+ path: path,
231
+ getRawInput: async () => input,
232
+ ctx: ctx,
233
+ type: type,
234
+ signal: undefined,
235
+ }),
236
+ );
237
+ }
238
+
239
+ const untypedClient =
240
+ opts.client instanceof TRPCUntypedClient
241
+ ? opts.client
242
+ : getUntypedClient(opts.client);
243
+
244
+ return untypedClient[type](path, input, trpcOpts);
245
+ };
246
+ };
247
+
248
+ return createRecursiveProxy(({ args, path: _path }) => {
249
+ const path = [..._path];
250
+ const utilName = path.pop() as UtilsMethods;
251
+ const [arg1, arg2] = args as any[];
252
+
253
+ const queryType = getQueryType(utilName);
254
+ const queryKey = getQueryKeyInternal(path, arg1, queryType ?? 'any');
255
+
256
+ const contextMap: Record<UtilsMethods, () => unknown> = {
257
+ '~types': undefined as any,
258
+
259
+ mutationKey: () => {
260
+ return getMutationKeyInternal(path);
261
+ },
262
+ queryKey: () => {
263
+ return queryKey;
264
+ },
265
+ queryFilter: (): QueryFilters => {
266
+ return {
267
+ queryKey: queryKey,
268
+ };
269
+ },
270
+ infiniteQueryOptions: () => {
271
+ return trpcInfiniteQueryOptions({
272
+ opts: arg2,
273
+ path,
274
+ queryClient: opts.queryClient,
275
+ queryKey: queryKey,
276
+ query: callIt('query'),
277
+ });
278
+ },
279
+ queryOptions: () => {
280
+ return trpcQueryOptions({
281
+ opts: arg2,
282
+ path,
283
+ queryClient: opts.queryClient,
284
+ queryKey: queryKey,
285
+ query: callIt('query'),
286
+ });
287
+ },
288
+ mutationOptions: () => {
289
+ return trpcMutationOptions({
290
+ opts: arg1,
291
+ path,
292
+ queryClient: opts.queryClient,
293
+ mutate: callIt('mutation'),
294
+ overrides: opts.overrides?.mutations,
295
+ });
296
+ },
297
+ subscriptionOptions: () => {
298
+ return trpcSubscriptionOptions({
299
+ opts: arg2,
300
+ path,
301
+ queryKey: queryKey,
302
+ subscribe: callIt('subscription'),
303
+ });
304
+ },
305
+ };
306
+
307
+ return contextMap[utilName]();
308
+ });
309
+ }
@@ -0,0 +1,233 @@
1
+ import type {
2
+ DataTag,
3
+ DefinedInitialDataInfiniteOptions,
4
+ InfiniteData,
5
+ QueryFunction,
6
+ UndefinedInitialDataInfiniteOptions,
7
+ UnusedSkipTokenInfiniteOptions,
8
+ } from '@tanstack/react-query';
9
+ import {
10
+ infiniteQueryOptions,
11
+ skipToken,
12
+ type QueryClient,
13
+ type SkipToken,
14
+ } from '@tanstack/react-query';
15
+ import type { TRPCClientErrorLike, TRPCUntypedClient } from '@trpc/client';
16
+ import type { DistributiveOmit } from '@trpc/server/unstable-core-do-not-import';
17
+ import type {
18
+ ExtractCursorType,
19
+ ResolverDef,
20
+ TRPCQueryBaseOptions,
21
+ TRPCQueryKey,
22
+ TRPCQueryOptionsResult,
23
+ } from './types';
24
+ import { createTRPCOptionsResult, getClientArgs } from './utils';
25
+
26
+ type ReservedOptions =
27
+ | 'queryKey'
28
+ | 'queryFn'
29
+ | 'queryHashFn'
30
+ | 'queryHash'
31
+ | 'initialPageParam';
32
+
33
+ interface UndefinedTRPCInfiniteQueryOptionsIn<
34
+ TInput,
35
+ TQueryFnData,
36
+ TData,
37
+ TError,
38
+ > extends DistributiveOmit<
39
+ UndefinedInitialDataInfiniteOptions<
40
+ TQueryFnData,
41
+ TError,
42
+ InfiniteData<TData, NonNullable<ExtractCursorType<TInput>> | null>,
43
+ TRPCQueryKey,
44
+ NonNullable<ExtractCursorType<TInput>> | null
45
+ >,
46
+ ReservedOptions
47
+ >,
48
+ TRPCQueryBaseOptions {
49
+ initialCursor?: NonNullable<ExtractCursorType<TInput>> | null;
50
+ }
51
+
52
+ interface UndefinedTRPCInfiniteQueryOptionsOut<
53
+ TInput,
54
+ TQueryFnData,
55
+ TData,
56
+ TError,
57
+ > extends DistributiveOmit<
58
+ UndefinedInitialDataInfiniteOptions<
59
+ TQueryFnData,
60
+ TError,
61
+ InfiniteData<TData, NonNullable<ExtractCursorType<TInput>> | null>,
62
+ TRPCQueryKey,
63
+ NonNullable<ExtractCursorType<TInput>> | null
64
+ >,
65
+ 'initialPageParam'
66
+ >,
67
+ TRPCQueryOptionsResult {
68
+ queryKey: DataTag<TRPCQueryKey, TData>;
69
+ initialPageParam: NonNullable<ExtractCursorType<TInput>> | null;
70
+ }
71
+
72
+ interface DefinedTRPCInfiniteQueryOptionsIn<TInput, TQueryFnData, TData, TError>
73
+ extends DistributiveOmit<
74
+ DefinedInitialDataInfiniteOptions<
75
+ TQueryFnData,
76
+ TError,
77
+ InfiniteData<TData, NonNullable<ExtractCursorType<TInput>> | null>,
78
+ TRPCQueryKey,
79
+ NonNullable<ExtractCursorType<TInput>> | null
80
+ >,
81
+ ReservedOptions
82
+ >,
83
+ TRPCQueryBaseOptions {
84
+ initialCursor?: NonNullable<ExtractCursorType<TInput>> | null;
85
+ }
86
+
87
+ interface DefinedTRPCInfiniteQueryOptionsOut<
88
+ TInput,
89
+ TQueryFnData,
90
+ TData,
91
+ TError,
92
+ > extends DistributiveOmit<
93
+ DefinedInitialDataInfiniteOptions<
94
+ TQueryFnData,
95
+ TError,
96
+ InfiniteData<TData, NonNullable<ExtractCursorType<TInput>> | null>,
97
+ TRPCQueryKey,
98
+ NonNullable<ExtractCursorType<TInput>> | null
99
+ >,
100
+ 'initialPageParam'
101
+ >,
102
+ TRPCQueryOptionsResult {
103
+ queryKey: DataTag<TRPCQueryKey, TData>;
104
+ initialPageParam: NonNullable<ExtractCursorType<TInput>> | null;
105
+ }
106
+
107
+ interface UnusedSkipTokenTRPCInfiniteQueryOptionsIn<
108
+ TInput,
109
+ TQueryFnData,
110
+ TData,
111
+ TError,
112
+ > extends DistributiveOmit<
113
+ UnusedSkipTokenInfiniteOptions<
114
+ TQueryFnData,
115
+ TError,
116
+ InfiniteData<TData, NonNullable<ExtractCursorType<TInput>> | null>,
117
+ TRPCQueryKey,
118
+ NonNullable<ExtractCursorType<TInput>> | null
119
+ >,
120
+ ReservedOptions
121
+ >,
122
+ TRPCQueryBaseOptions {
123
+ initialCursor?: NonNullable<ExtractCursorType<TInput>> | null;
124
+ }
125
+
126
+ interface UnusedSkipTokenTRPCInfiniteQueryOptionsOut<
127
+ TInput,
128
+ TQueryFnData,
129
+ TData,
130
+ TError,
131
+ > extends DistributiveOmit<
132
+ UnusedSkipTokenInfiniteOptions<
133
+ TQueryFnData,
134
+ TError,
135
+ InfiniteData<TData, NonNullable<ExtractCursorType<TInput>> | null>,
136
+ TRPCQueryKey,
137
+ NonNullable<ExtractCursorType<TInput>> | null
138
+ >,
139
+ 'initialPageParam'
140
+ >,
141
+ TRPCQueryOptionsResult {
142
+ queryKey: DataTag<TRPCQueryKey, TData>;
143
+ initialPageParam: NonNullable<ExtractCursorType<TInput>> | null;
144
+ }
145
+
146
+ export interface TRPCInfiniteQueryOptions<TDef extends ResolverDef> {
147
+ <TQueryFnData extends TDef['output'], TData = TQueryFnData>(
148
+ input: TDef['input'] | SkipToken,
149
+ opts: DefinedTRPCInfiniteQueryOptionsIn<
150
+ TDef['input'],
151
+ TQueryFnData,
152
+ TData,
153
+ TRPCClientErrorLike<TDef>
154
+ >,
155
+ ): DefinedTRPCInfiniteQueryOptionsOut<
156
+ TDef['input'],
157
+ TQueryFnData,
158
+ TData,
159
+ TRPCClientErrorLike<TDef>
160
+ >;
161
+ <TQueryFnData extends TDef['output'], TData = TQueryFnData>(
162
+ input: TDef['input'],
163
+ opts: UnusedSkipTokenTRPCInfiniteQueryOptionsIn<
164
+ TDef['input'],
165
+ TQueryFnData,
166
+ TData,
167
+ TRPCClientErrorLike<TDef>
168
+ >,
169
+ ): UnusedSkipTokenTRPCInfiniteQueryOptionsOut<
170
+ TDef['input'],
171
+ TQueryFnData,
172
+ TData,
173
+ TRPCClientErrorLike<TDef>
174
+ >;
175
+ <TQueryFnData extends TDef['output'], TData = TQueryFnData>(
176
+ input: TDef['input'] | SkipToken,
177
+ opts?: UndefinedTRPCInfiniteQueryOptionsIn<
178
+ TDef['input'],
179
+ TQueryFnData,
180
+ TData,
181
+ TRPCClientErrorLike<TDef>
182
+ >,
183
+ ): UndefinedTRPCInfiniteQueryOptionsOut<
184
+ TDef['input'],
185
+ TQueryFnData,
186
+ TData,
187
+ TRPCClientErrorLike<TDef>
188
+ >;
189
+ }
190
+
191
+ export function trpcInfiniteQueryOptions(args: {
192
+ query: typeof TRPCUntypedClient.prototype.query;
193
+ queryClient: QueryClient | (() => QueryClient);
194
+ path: readonly string[];
195
+ queryKey: TRPCQueryKey;
196
+ opts: UndefinedTRPCInfiniteQueryOptionsIn<unknown, unknown, unknown, unknown>;
197
+ }) {
198
+ const { query, path, queryKey, opts } = args;
199
+ const inputIsSkipToken = queryKey[1]?.input === skipToken;
200
+
201
+ const queryFn: QueryFunction<unknown, TRPCQueryKey, unknown> = async (
202
+ queryFnContext,
203
+ ) => {
204
+ const actualOpts = {
205
+ ...opts,
206
+ trpc: {
207
+ ...opts?.trpc,
208
+ ...(opts?.trpc?.abortOnUnmount
209
+ ? { signal: queryFnContext.signal }
210
+ : { signal: null }),
211
+ },
212
+ };
213
+
214
+ const result = await query(
215
+ ...getClientArgs(queryKey, actualOpts, {
216
+ direction: queryFnContext.direction,
217
+ pageParam: queryFnContext.pageParam,
218
+ }),
219
+ );
220
+
221
+ return result;
222
+ };
223
+
224
+ return Object.assign(
225
+ infiniteQueryOptions({
226
+ ...opts,
227
+ queryKey,
228
+ queryFn: inputIsSkipToken ? skipToken : queryFn,
229
+ initialPageParam: opts?.initialCursor ?? null,
230
+ }),
231
+ { trpc: createTRPCOptionsResult({ path }) },
232
+ );
233
+ }
@@ -0,0 +1,113 @@
1
+ import type { MutationFunction } from '@tanstack/react-query';
2
+ import {
3
+ type QueryClient,
4
+ type UseMutationOptions,
5
+ } from '@tanstack/react-query';
6
+ import type { TRPCClientErrorLike, TRPCUntypedClient } from '@trpc/client';
7
+ import type {
8
+ DistributiveOmit,
9
+ MaybePromise,
10
+ } from '@trpc/server/unstable-core-do-not-import';
11
+ import type {
12
+ ResolverDef,
13
+ TRPCMutationKey,
14
+ TRPCQueryBaseOptions,
15
+ TRPCQueryOptionsResult,
16
+ } from './types';
17
+ import {
18
+ createTRPCOptionsResult,
19
+ getClientArgs,
20
+ getMutationKeyInternal,
21
+ unwrapLazyArg,
22
+ } from './utils';
23
+
24
+ type ReservedOptions = 'mutationKey' | 'mutationFn';
25
+
26
+ interface TRPCMutationOptionsIn<TInput, TError, TOutput, TContext>
27
+ extends DistributiveOmit<
28
+ UseMutationOptions<TOutput, TError, TInput, TContext>,
29
+ ReservedOptions
30
+ >,
31
+ TRPCQueryBaseOptions {}
32
+
33
+ interface TRPCMutationOptionsOut<TInput, TError, TOutput, TContext>
34
+ extends UseMutationOptions<TOutput, TError, TInput, TContext>,
35
+ TRPCQueryOptionsResult {
36
+ mutationKey: TRPCMutationKey;
37
+ }
38
+
39
+ export interface TRPCMutationOptions<TDef extends ResolverDef> {
40
+ <TContext = unknown>(
41
+ opts?: TRPCMutationOptionsIn<
42
+ TDef['input'],
43
+ TRPCClientErrorLike<TDef>,
44
+ TDef['output'],
45
+ TContext
46
+ >,
47
+ ): TRPCMutationOptionsOut<
48
+ TDef['input'],
49
+ TRPCClientErrorLike<TDef>,
50
+ TDef['output'],
51
+ TContext
52
+ >;
53
+ }
54
+
55
+ /**
56
+ * @internal
57
+ */
58
+ export interface MutationOptionsOverride {
59
+ onSuccess: (opts: {
60
+ /**
61
+ * Calls the original function that was defined in the query's `onSuccess` option
62
+ */
63
+ originalFn: () => MaybePromise<unknown>;
64
+ queryClient: QueryClient;
65
+ /**
66
+ * Meta data passed in from the `useMutation()` hook
67
+ */
68
+ meta: Record<string, unknown>;
69
+ }) => MaybePromise<unknown>;
70
+ }
71
+
72
+ export function trpcMutationOptions(args: {
73
+ mutate: typeof TRPCUntypedClient.prototype.mutation;
74
+ queryClient: QueryClient | (() => QueryClient);
75
+ path: readonly string[];
76
+ opts: TRPCMutationOptionsIn<unknown, unknown, unknown, unknown> | undefined;
77
+ overrides: MutationOptionsOverride | undefined;
78
+ }): TRPCMutationOptionsOut<unknown, unknown, unknown, unknown> {
79
+ const { mutate, path, opts, overrides } = args;
80
+ const queryClient = unwrapLazyArg(args.queryClient);
81
+
82
+ const mutationKey = getMutationKeyInternal(path);
83
+
84
+ const defaultOpts = queryClient.defaultMutationOptions(
85
+ queryClient.getMutationDefaults(mutationKey),
86
+ );
87
+
88
+ const mutationSuccessOverride: MutationOptionsOverride['onSuccess'] =
89
+ overrides?.onSuccess ?? ((options) => options.originalFn());
90
+
91
+ const mutationFn: MutationFunction = async (input) => {
92
+ const result = await mutate(...getClientArgs([path, { input }], opts));
93
+
94
+ return result;
95
+ };
96
+
97
+ return {
98
+ ...opts,
99
+ mutationKey: mutationKey,
100
+ mutationFn,
101
+ onSuccess(...args) {
102
+ const originalFn = () =>
103
+ opts?.onSuccess?.(...args) ?? defaultOpts?.onSuccess?.(...args);
104
+
105
+ return mutationSuccessOverride({
106
+ originalFn,
107
+ queryClient,
108
+ meta: opts?.meta ?? defaultOpts?.meta ?? {},
109
+ });
110
+ },
111
+ trpc: createTRPCOptionsResult({ path }),
112
+ };
113
+ }