@trpc/react-query 10.0.0-proxy-beta.21

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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +88 -0
  3. package/dist/createHooksInternal-b47ee704.mjs +392 -0
  4. package/dist/createHooksInternal-e8214d72.js +400 -0
  5. package/dist/createTRPCReact.d.ts +38 -0
  6. package/dist/createTRPCReact.d.ts.map +1 -0
  7. package/dist/getArrayQueryKey-062214e0.mjs +19 -0
  8. package/dist/getArrayQueryKey-a2092b3c.js +21 -0
  9. package/dist/index.d.ts +4 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +58 -0
  12. package/dist/index.mjs +47 -0
  13. package/dist/internals/context.d.ts +99 -0
  14. package/dist/internals/context.d.ts.map +1 -0
  15. package/dist/internals/getArrayQueryKey.d.ts +9 -0
  16. package/dist/internals/getArrayQueryKey.d.ts.map +1 -0
  17. package/dist/internals/getQueryKey.d.ts +6 -0
  18. package/dist/internals/getQueryKey.d.ts.map +1 -0
  19. package/dist/interop.d.ts +10 -0
  20. package/dist/interop.d.ts.map +1 -0
  21. package/dist/queryClient-0569f6e0.mjs +7 -0
  22. package/dist/queryClient-83576230.js +9 -0
  23. package/dist/shared/hooks/createHooksInternal.d.ts +115 -0
  24. package/dist/shared/hooks/createHooksInternal.d.ts.map +1 -0
  25. package/dist/shared/index.d.ts +6 -0
  26. package/dist/shared/index.d.ts.map +1 -0
  27. package/dist/shared/index.js +18 -0
  28. package/dist/shared/index.mjs +7 -0
  29. package/dist/shared/proxy/decorationProxy.d.ts +8 -0
  30. package/dist/shared/proxy/decorationProxy.d.ts.map +1 -0
  31. package/dist/shared/proxy/utilsProxy.d.ts +80 -0
  32. package/dist/shared/proxy/utilsProxy.d.ts.map +1 -0
  33. package/dist/shared/queryClient.d.ts +16 -0
  34. package/dist/shared/queryClient.d.ts.map +1 -0
  35. package/dist/shared/types.d.ts +26 -0
  36. package/dist/shared/types.d.ts.map +1 -0
  37. package/dist/ssg/index.d.ts +5 -0
  38. package/dist/ssg/index.d.ts.map +1 -0
  39. package/dist/ssg/index.js +126 -0
  40. package/dist/ssg/index.mjs +121 -0
  41. package/dist/ssg/ssg.d.ts +23 -0
  42. package/dist/ssg/ssg.d.ts.map +1 -0
  43. package/dist/ssg/ssgProxy.d.ts +36 -0
  44. package/dist/ssg/ssgProxy.d.ts.map +1 -0
  45. package/package.json +75 -0
  46. package/shared/index.d.ts +1 -0
  47. package/shared/index.js +1 -0
  48. package/src/createTRPCReact.tsx +164 -0
  49. package/src/index.ts +4 -0
  50. package/src/internals/context.tsx +235 -0
  51. package/src/internals/getArrayQueryKey.test.ts +41 -0
  52. package/src/internals/getArrayQueryKey.ts +18 -0
  53. package/src/internals/getQueryKey.ts +10 -0
  54. package/src/interop.ts +25 -0
  55. package/src/shared/hooks/createHooksInternal.tsx +664 -0
  56. package/src/shared/index.ts +8 -0
  57. package/src/shared/proxy/decorationProxy.ts +33 -0
  58. package/src/shared/proxy/utilsProxy.ts +266 -0
  59. package/src/shared/queryClient.ts +20 -0
  60. package/src/shared/types.ts +27 -0
  61. package/src/ssg/index.ts +4 -0
  62. package/src/ssg/ssg.ts +138 -0
  63. package/src/ssg/ssgProxy.ts +105 -0
  64. package/ssg/index.d.ts +1 -0
  65. package/ssg/index.js +1 -0
@@ -0,0 +1,664 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import {
3
+ DehydratedState,
4
+ UseInfiniteQueryOptions,
5
+ UseInfiniteQueryResult,
6
+ UseMutationOptions,
7
+ UseMutationResult,
8
+ UseQueryOptions,
9
+ UseQueryResult,
10
+ useInfiniteQuery as __useInfiniteQuery,
11
+ useMutation as __useMutation,
12
+ useQuery as __useQuery,
13
+ hashQueryKey,
14
+ useQueryClient,
15
+ } from '@tanstack/react-query';
16
+ import {
17
+ CreateTRPCClientOptions,
18
+ TRPCClient,
19
+ TRPCClientErrorLike,
20
+ TRPCRequestOptions,
21
+ createTRPCClient,
22
+ } from '@trpc/client';
23
+ import type {
24
+ AnyRouter,
25
+ ProcedureRecord,
26
+ inferHandlerInput,
27
+ inferProcedureClientError,
28
+ inferProcedureInput,
29
+ inferProcedureOutput,
30
+ inferSubscriptionOutput,
31
+ } from '@trpc/server';
32
+ import { inferObservableValue } from '@trpc/server/observable';
33
+ import React, {
34
+ ReactNode,
35
+ useCallback,
36
+ useEffect,
37
+ useMemo,
38
+ useRef,
39
+ useState,
40
+ } from 'react';
41
+ import {
42
+ SSRState,
43
+ TRPCContext,
44
+ TRPCContextProps,
45
+ TRPCContextState,
46
+ } from '../../internals/context';
47
+ import { getArrayQueryKey } from '../../internals/getArrayQueryKey';
48
+ import { CreateTRPCReactOptions, UseMutationOverride } from '../types';
49
+
50
+ export type OutputWithCursor<TData, TCursor = any> = {
51
+ cursor: TCursor | null;
52
+ data: TData;
53
+ };
54
+
55
+ export interface TRPCReactRequestOptions
56
+ // For RQ, we use their internal AbortSignals instead of letting the user pass their own
57
+ extends Omit<TRPCRequestOptions, 'signal'> {
58
+ /**
59
+ * Opt out of SSR for this query by passing `ssr: false`
60
+ */
61
+ ssr?: boolean;
62
+ /**
63
+ * Opt out or into aborting request on unmount
64
+ */
65
+ abortOnUnmount?: boolean;
66
+ }
67
+
68
+ export interface TRPCUseQueryBaseOptions {
69
+ /**
70
+ * tRPC-related options
71
+ */
72
+ trpc?: TRPCReactRequestOptions;
73
+ }
74
+
75
+ export type { TRPCContext, TRPCContextState } from '../../internals/context';
76
+
77
+ export interface UseTRPCQueryOptions<TPath, TInput, TOutput, TData, TError>
78
+ extends UseQueryOptions<TOutput, TError, TData, [TPath, TInput]>,
79
+ TRPCUseQueryBaseOptions {}
80
+
81
+ export interface UseTRPCInfiniteQueryOptions<TPath, TInput, TOutput, TError>
82
+ extends UseInfiniteQueryOptions<
83
+ TOutput,
84
+ TError,
85
+ TOutput,
86
+ TOutput,
87
+ [TPath, TInput]
88
+ >,
89
+ TRPCUseQueryBaseOptions {}
90
+
91
+ export interface UseTRPCMutationOptions<
92
+ TInput,
93
+ TError,
94
+ TOutput,
95
+ TContext = unknown,
96
+ > extends UseMutationOptions<TOutput, TError, TInput, TContext>,
97
+ TRPCUseQueryBaseOptions {}
98
+
99
+ export interface UseTRPCSubscriptionOptions<TOutput, TError> {
100
+ enabled?: boolean;
101
+ onStarted?: () => void;
102
+ onData: (data: TOutput) => void;
103
+ onError?: (err: TError) => void;
104
+ }
105
+
106
+ function getClientArgs<TPathAndInput extends unknown[], TOptions>(
107
+ pathAndInput: TPathAndInput,
108
+ opts: TOptions,
109
+ ) {
110
+ const [path, input] = pathAndInput;
111
+ return [path, input, (opts as any)?.trpc] as const;
112
+ }
113
+
114
+ type inferInfiniteQueryNames<TObj extends ProcedureRecord> = {
115
+ [TPath in keyof TObj]: inferProcedureInput<TObj[TPath]> extends {
116
+ cursor?: any;
117
+ }
118
+ ? TPath
119
+ : never;
120
+ }[keyof TObj];
121
+
122
+ type inferProcedures<TObj extends ProcedureRecord> = {
123
+ [TPath in keyof TObj]: {
124
+ input: inferProcedureInput<TObj[TPath]>;
125
+ output: inferProcedureOutput<TObj[TPath]>;
126
+ };
127
+ };
128
+
129
+ export interface TRPCProviderProps<TRouter extends AnyRouter, TSSRContext>
130
+ extends TRPCContextProps<TRouter, TSSRContext> {
131
+ children: ReactNode;
132
+ }
133
+
134
+ export type TRPCProvider<TRouter extends AnyRouter, TSSRContext> = (
135
+ props: TRPCProviderProps<TRouter, TSSRContext>,
136
+ ) => JSX.Element;
137
+
138
+ export type UseDehydratedState<TRouter extends AnyRouter> = (
139
+ client: TRPCClient<TRouter>,
140
+ trpcState: DehydratedState | undefined,
141
+ ) => DehydratedState | undefined;
142
+
143
+ export type CreateClient<TRouter extends AnyRouter> = (
144
+ opts: CreateTRPCClientOptions<TRouter>,
145
+ ) => TRPCClient<TRouter>;
146
+
147
+ interface TRPCHookResult {
148
+ trpc: {
149
+ path: string;
150
+ };
151
+ }
152
+
153
+ /**
154
+ * @internal
155
+ */
156
+ export type UseTRPCQueryResult<TData, TError> = UseQueryResult<TData, TError> &
157
+ TRPCHookResult;
158
+
159
+ /**
160
+ * @internal
161
+ */
162
+ export type UseTRPCInfiniteQueryResult<TData, TError> = UseInfiniteQueryResult<
163
+ TData,
164
+ TError
165
+ > &
166
+ TRPCHookResult;
167
+
168
+ /**
169
+ * @internal
170
+ */
171
+ export type UseTRPCMutationResult<TData, TError, TVariables, TContext> =
172
+ UseMutationResult<TData, TError, TVariables, TContext> & TRPCHookResult;
173
+
174
+ /**
175
+ * Makes a stable reference of the `trpc` prop
176
+ */
177
+ function useHookResult(value: TRPCHookResult['trpc']): TRPCHookResult['trpc'] {
178
+ const ref = useRef(value);
179
+ ref.current.path = value.path;
180
+ return ref.current;
181
+ }
182
+ /**
183
+ * Create strongly typed react hooks
184
+ * @internal
185
+ */
186
+ export function createHooksInternal<
187
+ TRouter extends AnyRouter,
188
+ TSSRContext = unknown,
189
+ >(config?: CreateTRPCReactOptions<TRouter>) {
190
+ const mutationSuccessOverride: UseMutationOverride['onSuccess'] =
191
+ config?.unstable_overrides?.useMutation?.onSuccess ??
192
+ ((options) => options.originalFn());
193
+
194
+ type TQueries = TRouter['_def']['queries'];
195
+ type TSubscriptions = TRouter['_def']['subscriptions'];
196
+ type TMutations = TRouter['_def']['mutations'];
197
+
198
+ type TError = TRPCClientErrorLike<TRouter>;
199
+ type TInfiniteQueryNames = inferInfiniteQueryNames<TQueries>;
200
+
201
+ type TQueryValues = inferProcedures<TQueries>;
202
+ type TMutationValues = inferProcedures<TMutations>;
203
+
204
+ type ProviderContext = TRPCContextState<TRouter, TSSRContext>;
205
+ const Context = TRPCContext as React.Context<ProviderContext>;
206
+
207
+ const createClient: CreateClient<TRouter> = (opts) => {
208
+ return createTRPCClient(opts);
209
+ };
210
+
211
+ const TRPCProvider: TRPCProvider<TRouter, TSSRContext> = (props) => {
212
+ const { abortOnUnmount = false, client, queryClient, ssrContext } = props;
213
+ const [ssrState, setSSRState] = useState<SSRState>(props.ssrState ?? false);
214
+ useEffect(() => {
215
+ // Only updating state to `mounted` if we are using SSR.
216
+ // This makes it so we don't have an unnecessary re-render when opting out of SSR.
217
+ setSSRState((state) => (state ? 'mounted' : false));
218
+ }, []);
219
+ return (
220
+ <Context.Provider
221
+ value={{
222
+ abortOnUnmount,
223
+ queryClient,
224
+ client,
225
+ ssrContext: ssrContext || null,
226
+ ssrState,
227
+ fetchQuery: useCallback(
228
+ (pathAndInput, opts) => {
229
+ return queryClient.fetchQuery(
230
+ getArrayQueryKey(pathAndInput),
231
+ () =>
232
+ (client as any).query(...getClientArgs(pathAndInput, opts)),
233
+ opts,
234
+ );
235
+ },
236
+ [client, queryClient],
237
+ ),
238
+ fetchInfiniteQuery: useCallback(
239
+ (pathAndInput, opts) => {
240
+ return queryClient.fetchInfiniteQuery(
241
+ getArrayQueryKey(pathAndInput),
242
+ ({ pageParam }) => {
243
+ const [path, input] = pathAndInput;
244
+ const actualInput = { ...(input as any), cursor: pageParam };
245
+ return (client as any).query(
246
+ ...getClientArgs([path, actualInput], opts),
247
+ );
248
+ },
249
+ opts,
250
+ );
251
+ },
252
+ [client, queryClient],
253
+ ),
254
+ prefetchQuery: useCallback(
255
+ (pathAndInput, opts) => {
256
+ return queryClient.prefetchQuery(
257
+ getArrayQueryKey(pathAndInput),
258
+ () =>
259
+ (client as any).query(...getClientArgs(pathAndInput, opts)),
260
+ opts,
261
+ );
262
+ },
263
+ [client, queryClient],
264
+ ),
265
+ prefetchInfiniteQuery: useCallback(
266
+ (pathAndInput, opts) => {
267
+ return queryClient.prefetchInfiniteQuery(
268
+ getArrayQueryKey(pathAndInput),
269
+ ({ pageParam }) => {
270
+ const [path, input] = pathAndInput;
271
+ const actualInput = { ...(input as any), cursor: pageParam };
272
+ return (client as any).query(
273
+ ...getClientArgs([path, actualInput], opts),
274
+ );
275
+ },
276
+ opts,
277
+ );
278
+ },
279
+ [client, queryClient],
280
+ ),
281
+ invalidateQueries: useCallback(
282
+ (...args: any[]) => {
283
+ const [queryKey, ...rest] = args;
284
+ return queryClient.invalidateQueries(
285
+ getArrayQueryKey(queryKey),
286
+ ...rest,
287
+ );
288
+ },
289
+ [queryClient],
290
+ ),
291
+ refetchQueries: useCallback(
292
+ (...args: any[]) => {
293
+ const [queryKey, ...rest] = args;
294
+
295
+ return queryClient.refetchQueries(
296
+ getArrayQueryKey(queryKey),
297
+ ...rest,
298
+ );
299
+ },
300
+ [queryClient],
301
+ ),
302
+ cancelQuery: useCallback(
303
+ (pathAndInput) => {
304
+ return queryClient.cancelQueries(getArrayQueryKey(pathAndInput));
305
+ },
306
+ [queryClient],
307
+ ),
308
+ setQueryData: useCallback(
309
+ (...args) => {
310
+ const [queryKey, ...rest] = args;
311
+ return queryClient.setQueryData(
312
+ getArrayQueryKey(queryKey),
313
+ ...rest,
314
+ );
315
+ },
316
+ [queryClient],
317
+ ),
318
+ getQueryData: useCallback(
319
+ (...args) => {
320
+ const [queryKey, ...rest] = args;
321
+
322
+ return queryClient.getQueryData(
323
+ getArrayQueryKey(queryKey),
324
+ ...rest,
325
+ );
326
+ },
327
+ [queryClient],
328
+ ),
329
+ setInfiniteQueryData: useCallback(
330
+ (...args) => {
331
+ const [queryKey, ...rest] = args;
332
+
333
+ return queryClient.setQueryData(
334
+ getArrayQueryKey(queryKey),
335
+ ...rest,
336
+ );
337
+ },
338
+ [queryClient],
339
+ ),
340
+ getInfiniteQueryData: useCallback(
341
+ (...args) => {
342
+ const [queryKey, ...rest] = args;
343
+
344
+ return queryClient.getQueryData(
345
+ getArrayQueryKey(queryKey),
346
+ ...rest,
347
+ );
348
+ },
349
+ [queryClient],
350
+ ),
351
+ }}
352
+ >
353
+ {props.children}
354
+ </Context.Provider>
355
+ );
356
+ };
357
+
358
+ function useContext() {
359
+ return React.useContext(Context);
360
+ }
361
+
362
+ /**
363
+ * Hack to make sure errors return `status`='error` when doing SSR
364
+ * @link https://github.com/trpc/trpc/pull/1645
365
+ */
366
+ function useSSRQueryOptionsIfNeeded<
367
+ TOptions extends { retryOnMount?: boolean } | undefined,
368
+ >(pathAndInput: unknown[], opts: TOptions): TOptions {
369
+ const { queryClient, ssrState } = useContext();
370
+ return ssrState &&
371
+ ssrState !== 'mounted' &&
372
+ queryClient.getQueryCache().find(getArrayQueryKey(pathAndInput))?.state
373
+ .status === 'error'
374
+ ? {
375
+ retryOnMount: false,
376
+ ...opts,
377
+ }
378
+ : opts;
379
+ }
380
+
381
+ function useQuery<
382
+ TPath extends keyof TQueryValues & string,
383
+ TQueryFnData = TQueryValues[TPath]['output'],
384
+ TData = TQueryValues[TPath]['output'],
385
+ >(
386
+ pathAndInput: [path: TPath, ...args: inferHandlerInput<TQueries[TPath]>],
387
+ opts?: UseTRPCQueryOptions<
388
+ TPath,
389
+ TQueryValues[TPath]['input'],
390
+ TQueryFnData,
391
+ TData,
392
+ TError
393
+ >,
394
+ ): UseTRPCQueryResult<TData, TError> {
395
+ const { abortOnUnmount, client, ssrState, queryClient, prefetchQuery } =
396
+ useContext();
397
+
398
+ if (
399
+ typeof window === 'undefined' &&
400
+ ssrState === 'prepass' &&
401
+ opts?.trpc?.ssr !== false &&
402
+ opts?.enabled !== false &&
403
+ !queryClient.getQueryCache().find(getArrayQueryKey(pathAndInput))
404
+ ) {
405
+ void prefetchQuery(pathAndInput as any, opts as any);
406
+ }
407
+ const ssrOpts = useSSRQueryOptionsIfNeeded(pathAndInput, opts);
408
+ // request option should take priority over global
409
+ const shouldAbortOnUnmount = opts?.trpc?.abortOnUnmount ?? abortOnUnmount;
410
+
411
+ const hook = __useQuery(
412
+ getArrayQueryKey(pathAndInput) as any,
413
+ (queryFunctionContext) => {
414
+ const actualOpts = {
415
+ ...ssrOpts,
416
+ trpc: {
417
+ ...ssrOpts?.trpc,
418
+ ...(shouldAbortOnUnmount
419
+ ? { signal: queryFunctionContext.signal }
420
+ : {}),
421
+ },
422
+ };
423
+
424
+ return (client as any).query(
425
+ ...getClientArgs(pathAndInput, actualOpts),
426
+ );
427
+ },
428
+ ssrOpts,
429
+ ) as UseTRPCQueryResult<TData, TError>;
430
+ hook.trpc = useHookResult({
431
+ path: pathAndInput[0],
432
+ });
433
+
434
+ return hook;
435
+ }
436
+
437
+ function useMutation<
438
+ TPath extends keyof TMutationValues & string,
439
+ TContext = unknown,
440
+ >(
441
+ path: TPath | [TPath],
442
+ opts?: UseTRPCMutationOptions<
443
+ TMutationValues[TPath]['input'],
444
+ TError,
445
+ TMutationValues[TPath]['output'],
446
+ TContext
447
+ >,
448
+ ): UseTRPCMutationResult<
449
+ TMutationValues[TPath]['output'],
450
+ TError,
451
+ TMutationValues[TPath]['input'],
452
+ TContext
453
+ > {
454
+ const { client } = useContext();
455
+ const queryClient = useQueryClient();
456
+
457
+ const hook = __useMutation(
458
+ (input) => {
459
+ const actualPath = Array.isArray(path) ? path[0] : path;
460
+
461
+ return (client.mutation as any)(
462
+ ...getClientArgs([actualPath, input], opts),
463
+ );
464
+ },
465
+ {
466
+ ...opts,
467
+ onSuccess(...args) {
468
+ const originalFn = () => opts?.onSuccess?.(...args);
469
+ return mutationSuccessOverride({ originalFn, queryClient });
470
+ },
471
+ },
472
+ ) as UseTRPCMutationResult<
473
+ TMutationValues[TPath]['output'],
474
+ TError,
475
+ TMutationValues[TPath]['input'],
476
+ TContext
477
+ >;
478
+
479
+ hook.trpc = useHookResult({
480
+ path: Array.isArray(path) ? path[0] : path,
481
+ });
482
+
483
+ return hook;
484
+ }
485
+
486
+ /* istanbul ignore next */
487
+ /**
488
+ * ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
489
+ * **Experimental.** API might change without major version bump
490
+ * ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠
491
+ */
492
+ function useSubscription<
493
+ TPath extends keyof TSubscriptions & string,
494
+ TOutput extends inferSubscriptionOutput<TRouter, TPath>,
495
+ >(
496
+ pathAndInput: [
497
+ path: TPath,
498
+ ...args: inferHandlerInput<TSubscriptions[TPath]>,
499
+ ],
500
+ opts: UseTRPCSubscriptionOptions<
501
+ inferObservableValue<inferProcedureOutput<TSubscriptions[TPath]>>,
502
+ inferProcedureClientError<TSubscriptions[TPath]>
503
+ >,
504
+ ) {
505
+ const enabled = opts?.enabled ?? true;
506
+ const queryKey = hashQueryKey(pathAndInput);
507
+ const { client } = useContext();
508
+
509
+ return useEffect(() => {
510
+ if (!enabled) {
511
+ return;
512
+ }
513
+ const [path, input] = pathAndInput;
514
+ let isStopped = false;
515
+ const subscription = client.subscription<
516
+ TRouter['_def']['subscriptions'],
517
+ TPath,
518
+ TOutput,
519
+ inferProcedureInput<TRouter['_def']['subscriptions'][TPath]>
520
+ >(path, (input ?? undefined) as any, {
521
+ onStarted: () => {
522
+ if (!isStopped) {
523
+ opts.onStarted?.();
524
+ }
525
+ },
526
+ onData: (data) => {
527
+ if (!isStopped) {
528
+ opts.onData(data);
529
+ }
530
+ },
531
+ onError: (err) => {
532
+ if (!isStopped) {
533
+ opts.onError?.(err);
534
+ }
535
+ },
536
+ });
537
+ return () => {
538
+ isStopped = true;
539
+ subscription.unsubscribe();
540
+ };
541
+ // eslint-disable-next-line react-hooks/exhaustive-deps
542
+ }, [queryKey, enabled]);
543
+ }
544
+
545
+ function useInfiniteQuery<TPath extends TInfiniteQueryNames & string>(
546
+ pathAndInput: [
547
+ path: TPath,
548
+ input: Omit<TQueryValues[TPath]['input'], 'cursor'>,
549
+ ],
550
+ opts?: UseTRPCInfiniteQueryOptions<
551
+ TPath,
552
+ Omit<TQueryValues[TPath]['input'], 'cursor'>,
553
+ TQueryValues[TPath]['output'],
554
+ TError
555
+ >,
556
+ ): UseTRPCInfiniteQueryResult<TQueryValues[TPath]['output'], TError> {
557
+ const [path, input] = pathAndInput;
558
+ const {
559
+ client,
560
+ ssrState,
561
+ prefetchInfiniteQuery,
562
+ queryClient,
563
+ abortOnUnmount,
564
+ } = useContext();
565
+
566
+ if (
567
+ typeof window === 'undefined' &&
568
+ ssrState === 'prepass' &&
569
+ opts?.trpc?.ssr !== false &&
570
+ opts?.enabled !== false &&
571
+ !queryClient.getQueryCache().find(getArrayQueryKey(pathAndInput))
572
+ ) {
573
+ void prefetchInfiniteQuery(pathAndInput as any, opts as any);
574
+ }
575
+
576
+ const ssrOpts = useSSRQueryOptionsIfNeeded(pathAndInput, opts);
577
+
578
+ // request option should take priority over global
579
+ const shouldAbortOnUnmount = opts?.trpc?.abortOnUnmount ?? abortOnUnmount;
580
+
581
+ const hook = __useInfiniteQuery(
582
+ getArrayQueryKey(pathAndInput) as any,
583
+ (queryFunctionContext) => {
584
+ const actualOpts = {
585
+ ...ssrOpts,
586
+ trpc: {
587
+ ...ssrOpts?.trpc,
588
+ ...(shouldAbortOnUnmount
589
+ ? { signal: queryFunctionContext.signal }
590
+ : {}),
591
+ },
592
+ };
593
+
594
+ const actualInput = {
595
+ ...((input as any) ?? {}),
596
+ cursor: queryFunctionContext.pageParam,
597
+ };
598
+
599
+ return (client as any).query(
600
+ ...getClientArgs([path, actualInput], actualOpts),
601
+ );
602
+ },
603
+ ssrOpts,
604
+ ) as UseTRPCInfiniteQueryResult<TQueryValues[TPath]['output'], TError>;
605
+
606
+ hook.trpc = useHookResult({
607
+ path,
608
+ });
609
+ return hook;
610
+ }
611
+ const useDehydratedState: UseDehydratedState<TRouter> = (
612
+ client,
613
+ trpcState,
614
+ ) => {
615
+ const transformed: DehydratedState | undefined = useMemo(() => {
616
+ if (!trpcState) {
617
+ return trpcState;
618
+ }
619
+
620
+ return client.runtime.transformer.deserialize(trpcState);
621
+ }, [trpcState, client]);
622
+ return transformed;
623
+ };
624
+
625
+ return {
626
+ Provider: TRPCProvider,
627
+ createClient,
628
+ useContext,
629
+ useQuery,
630
+ useMutation,
631
+ useSubscription,
632
+ useDehydratedState,
633
+ useInfiniteQuery,
634
+ };
635
+ }
636
+
637
+ /**
638
+ * Hack to infer the type of `createReactQueryHooks`
639
+ * @link https://stackoverflow.com/a/59072991
640
+ */
641
+ class GnClass<TRouter extends AnyRouter, TSSRContext = unknown> {
642
+ fn() {
643
+ return createHooksInternal<TRouter, TSSRContext>();
644
+ }
645
+ }
646
+
647
+ type returnTypeInferer<TType> = TType extends (
648
+ a: Record<string, string>,
649
+ ) => infer U
650
+ ? U
651
+ : never;
652
+ type fooType<TRouter extends AnyRouter, TSSRContext = unknown> = GnClass<
653
+ TRouter,
654
+ TSSRContext
655
+ >['fn'];
656
+
657
+ /**
658
+ * Infer the type of a `createReactQueryHooks` function
659
+ * @internal
660
+ */
661
+ export type CreateReactQueryHooks<
662
+ TRouter extends AnyRouter,
663
+ TSSRContext = unknown,
664
+ > = returnTypeInferer<fooType<TRouter, TSSRContext>>;
@@ -0,0 +1,8 @@
1
+ export * from './proxy/decorationProxy';
2
+ export * from './proxy/utilsProxy';
3
+ export type {
4
+ DecorateProcedure,
5
+ DecoratedProcedureRecord,
6
+ } from '../createTRPCReact';
7
+ export * from './hooks/createHooksInternal';
8
+ export * from './queryClient';
@@ -0,0 +1,33 @@
1
+ import { AnyRouter } from '@trpc/server';
2
+ import { createRecursiveProxy } from '@trpc/server/shared';
3
+ import { getQueryKey } from '../../internals/getQueryKey';
4
+ import { CreateReactQueryHooks } from '../hooks/createHooksInternal';
5
+
6
+ /**
7
+ * Create proxy for decorating procedures
8
+ * @internal
9
+ */
10
+ export function createReactProxyDecoration<
11
+ TRouter extends AnyRouter,
12
+ TSSRContext = unknown,
13
+ >(name: string, hooks: CreateReactQueryHooks<TRouter, TSSRContext>) {
14
+ return createRecursiveProxy((opts) => {
15
+ const args = opts.args;
16
+
17
+ const pathCopy = [name, ...opts.path];
18
+
19
+ // The last arg is for instance `.useMutation` or `.useQuery()`
20
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21
+ const lastArg = pathCopy.pop()!;
22
+
23
+ // The `path` ends up being something like `post.byId`
24
+ const path = pathCopy.join('.');
25
+ if (lastArg === 'useMutation') {
26
+ return (hooks as any)[lastArg](path, ...args);
27
+ }
28
+ const [input, ...rest] = args;
29
+
30
+ const queryKey = getQueryKey(path, input);
31
+ return (hooks as any)[lastArg](queryKey, ...rest);
32
+ });
33
+ }