@trpc/react-query 11.0.0-alpha-tmp-subscription-connection-state.488 → 11.0.0-alpha-tmp-12-06-react.665

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 (73) hide show
  1. package/dist/bundle-analysis.json +59 -76
  2. package/dist/createTRPCReact.d.ts +47 -17
  3. package/dist/createTRPCReact.d.ts.map +1 -1
  4. package/dist/internals/context.d.ts +43 -21
  5. package/dist/internals/context.d.ts.map +1 -1
  6. package/dist/internals/getQueryKey.d.ts +2 -2
  7. package/dist/internals/getQueryKey.js +3 -3
  8. package/dist/internals/getQueryKey.mjs +3 -3
  9. package/dist/internals/trpcResult.d.ts +18 -0
  10. package/dist/internals/trpcResult.d.ts.map +1 -0
  11. package/dist/internals/trpcResult.js +63 -0
  12. package/dist/internals/trpcResult.mjs +40 -0
  13. package/dist/internals/useQueries.d.ts +1 -1
  14. package/dist/internals/useQueries.d.ts.map +1 -1
  15. package/dist/rsc.d.ts +1 -1
  16. package/dist/rsc.d.ts.map +1 -1
  17. package/dist/rsc.js +4 -4
  18. package/dist/rsc.mjs +4 -4
  19. package/dist/server/ssgProxy.d.ts +7 -24
  20. package/dist/server/ssgProxy.d.ts.map +1 -1
  21. package/dist/server/ssgProxy.js +21 -4
  22. package/dist/server/ssgProxy.mjs +21 -4
  23. package/dist/shared/hooks/createHooksInternal.d.ts +4 -2
  24. package/dist/shared/hooks/createHooksInternal.d.ts.map +1 -1
  25. package/dist/shared/hooks/createHooksInternal.js +160 -93
  26. package/dist/shared/hooks/createHooksInternal.mjs +156 -89
  27. package/dist/shared/hooks/types.d.ts +38 -159
  28. package/dist/shared/hooks/types.d.ts.map +1 -1
  29. package/dist/shared/index.js +0 -7
  30. package/dist/shared/index.mjs +0 -1
  31. package/dist/shared/polymorphism/mutationLike.d.ts.map +1 -1
  32. package/dist/shared/polymorphism/queryLike.d.ts.map +1 -1
  33. package/dist/shared/polymorphism/routerLike.d.ts.map +1 -1
  34. package/dist/shared/proxy/decorationProxy.js +1 -1
  35. package/dist/shared/proxy/decorationProxy.mjs +1 -1
  36. package/dist/shared/proxy/useQueriesProxy.d.ts.map +1 -1
  37. package/dist/shared/proxy/utilsProxy.d.ts +45 -20
  38. package/dist/shared/proxy/utilsProxy.d.ts.map +1 -1
  39. package/dist/shared/proxy/utilsProxy.js +4 -0
  40. package/dist/shared/proxy/utilsProxy.mjs +4 -0
  41. package/dist/shared/types.d.ts +60 -2
  42. package/dist/shared/types.d.ts.map +1 -1
  43. package/dist/utils/createUtilityFunctions.d.ts +2 -2
  44. package/dist/utils/createUtilityFunctions.d.ts.map +1 -1
  45. package/dist/utils/createUtilityFunctions.js +69 -3
  46. package/dist/utils/createUtilityFunctions.mjs +69 -3
  47. package/dist/utils/inferReactQueryProcedure.d.ts +2 -2
  48. package/dist/utils/inferReactQueryProcedure.d.ts.map +1 -1
  49. package/package.json +22 -19
  50. package/src/createTRPCReact.tsx +276 -65
  51. package/src/internals/context.tsx +105 -24
  52. package/src/internals/getQueryKey.ts +2 -2
  53. package/src/internals/trpcResult.ts +55 -0
  54. package/src/internals/useQueries.ts +36 -31
  55. package/src/rsc.tsx +6 -6
  56. package/src/server/ssgProxy.ts +23 -66
  57. package/src/shared/hooks/createHooksInternal.tsx +222 -151
  58. package/src/shared/hooks/types.ts +64 -348
  59. package/src/shared/polymorphism/mutationLike.ts +8 -6
  60. package/src/shared/polymorphism/queryLike.ts +12 -14
  61. package/src/shared/polymorphism/routerLike.ts +4 -4
  62. package/src/shared/proxy/useQueriesProxy.ts +4 -4
  63. package/src/shared/proxy/utilsProxy.ts +153 -25
  64. package/src/shared/types.ts +229 -1
  65. package/src/utils/createUtilityFunctions.ts +90 -2
  66. package/src/utils/inferReactQueryProcedure.ts +8 -6
  67. package/dist/internals/useHookResult.d.ts +0 -8
  68. package/dist/internals/useHookResult.d.ts.map +0 -1
  69. package/dist/internals/useHookResult.js +0 -35
  70. package/dist/internals/useHookResult.mjs +0 -14
  71. package/dist/shared/hooks/types.js +0 -133
  72. package/dist/shared/hooks/types.mjs +0 -126
  73. package/src/internals/useHookResult.ts +0 -17
@@ -1,14 +1,15 @@
1
1
  import {
2
2
  useInfiniteQuery as __useInfiniteQuery,
3
3
  useMutation as __useMutation,
4
+ usePrefetchInfiniteQuery as __usePrefetchInfiniteQuery,
4
5
  useQueries as __useQueries,
5
6
  useQuery as __useQuery,
6
7
  useSuspenseInfiniteQuery as __useSuspenseInfiniteQuery,
7
8
  useSuspenseQueries as __useSuspenseQueries,
8
9
  useSuspenseQuery as __useSuspenseQuery,
10
+ usePrefetchQuery as _usePrefetchQuery,
9
11
  hashKey,
10
12
  skipToken,
11
- useQueryClient,
12
13
  } from '@tanstack/react-query';
13
14
  import type { TRPCClientErrorLike } from '@trpc/client';
14
15
  import { createTRPCUntypedClient } from '@trpc/client';
@@ -23,7 +24,10 @@ import {
23
24
  getMutationKeyInternal,
24
25
  getQueryKeyInternal,
25
26
  } from '../../internals/getQueryKey';
26
- import { useHookResult } from '../../internals/useHookResult';
27
+ import {
28
+ buildQueryFromAsyncIterable,
29
+ useHookResult,
30
+ } from '../../internals/trpcResult';
27
31
  import type {
28
32
  TRPCUseQueries,
29
33
  TRPCUseSuspenseQueries,
@@ -31,33 +35,27 @@ import type {
31
35
  import { createUtilityFunctions } from '../../utils/createUtilityFunctions';
32
36
  import { createUseQueries } from '../proxy/useQueriesProxy';
33
37
  import type { CreateTRPCReactOptions, UseMutationOverride } from '../types';
34
- // import type { restartSubscriptionFn } from './types';
35
- import {
36
- getConnectingResult,
37
- getErrorResult,
38
- getIdleResult,
39
- getPendingResult,
40
- getStartingResult,
41
- type CreateClient,
42
- type TRPCProvider,
43
- type TRPCQueryOptions,
44
- type UseTRPCInfiniteQueryOptions,
45
- type UseTRPCInfiniteQueryResult,
46
- type UseTRPCMutationOptions,
47
- type UseTRPCMutationResult,
48
- type UseTRPCQueryOptions,
49
- type UseTRPCQueryResult,
50
- type UseTRPCSubscriptionOptions,
51
- type UseTRPCSubscriptionResult,
52
- type UseTRPCSuspenseInfiniteQueryOptions,
53
- type UseTRPCSuspenseInfiniteQueryResult,
54
- type UseTRPCSuspenseQueryOptions,
55
- type UseTRPCSuspenseQueryResult,
38
+ import type {
39
+ CreateClient,
40
+ TRPCProvider,
41
+ TRPCQueryOptions,
42
+ TRPCSubscriptionResult,
43
+ UseTRPCInfiniteQueryOptions,
44
+ UseTRPCInfiniteQueryResult,
45
+ UseTRPCMutationOptions,
46
+ UseTRPCMutationResult,
47
+ UseTRPCPrefetchInfiniteQueryOptions,
48
+ UseTRPCPrefetchQueryOptions,
49
+ UseTRPCQueryOptions,
50
+ UseTRPCQueryResult,
51
+ UseTRPCSubscriptionOptions,
52
+ UseTRPCSuspenseInfiniteQueryOptions,
53
+ UseTRPCSuspenseInfiniteQueryResult,
54
+ UseTRPCSuspenseQueryOptions,
55
+ UseTRPCSuspenseQueryResult,
56
56
  } from './types';
57
57
 
58
- const trackResult = <
59
- T extends UseTRPCSubscriptionResult<unknown, unknown, unknown>,
60
- >(
58
+ const trackResult = <T extends object>(
61
59
  result: T,
62
60
  onTrackResult: (key: keyof T) => void,
63
61
  ): T => {
@@ -143,7 +141,7 @@ export function createRootHooks<
143
141
 
144
142
  /**
145
143
  * Hack to make sure errors return `status`='error` when doing SSR
146
- * @link https://github.com/trpc/trpc/pull/1645
144
+ * @see https://github.com/trpc/trpc/pull/1645
147
145
  */
148
146
  function useSSRQueryOptionsIfNeeded<
149
147
  TOptions extends { retryOnMount?: boolean } | undefined,
@@ -213,26 +211,11 @@ export function createRootHooks<
213
211
  );
214
212
 
215
213
  if (isAsyncIterable(result)) {
216
- const queryCache = queryClient.getQueryCache();
217
-
218
- const query = queryCache.build(queryFunctionContext.queryKey, {
214
+ return buildQueryFromAsyncIterable(
215
+ result,
216
+ queryClient,
219
217
  queryKey,
220
- });
221
-
222
- query.setState({
223
- data: [],
224
- status: 'success',
225
- });
226
-
227
- const aggregate: unknown[] = [];
228
- for await (const value of result) {
229
- aggregate.push(value);
230
-
231
- query.setState({
232
- data: [...aggregate],
233
- });
234
- }
235
- return aggregate;
218
+ );
236
219
  }
237
220
  return result;
238
221
  },
@@ -247,6 +230,41 @@ export function createRootHooks<
247
230
  return hook;
248
231
  }
249
232
 
233
+ function usePrefetchQuery(
234
+ path: string[],
235
+ input: unknown,
236
+ opts?: UseTRPCPrefetchQueryOptions<unknown, unknown, TError>,
237
+ ): void {
238
+ const context = useContext();
239
+ const queryKey = getQueryKeyInternal(path, input, 'query');
240
+
241
+ const isInputSkipToken = input === skipToken;
242
+
243
+ const shouldAbortOnUnmount =
244
+ opts?.trpc?.abortOnUnmount ??
245
+ config?.abortOnUnmount ??
246
+ context.abortOnUnmount;
247
+
248
+ _usePrefetchQuery({
249
+ ...opts,
250
+ queryKey: queryKey as any,
251
+ queryFn: isInputSkipToken
252
+ ? input
253
+ : (queryFunctionContext) => {
254
+ const actualOpts = {
255
+ trpc: {
256
+ ...opts?.trpc,
257
+ ...(shouldAbortOnUnmount
258
+ ? { signal: queryFunctionContext.signal }
259
+ : {}),
260
+ },
261
+ };
262
+
263
+ return context.client.query(...getClientArgs(queryKey, actualOpts));
264
+ },
265
+ });
266
+ }
267
+
250
268
  function useSuspenseQuery(
251
269
  path: readonly string[],
252
270
  input: unknown,
@@ -266,7 +284,9 @@ export function createRootHooks<
266
284
  queryKey: queryKey as any,
267
285
  queryFn: (queryFunctionContext) => {
268
286
  const actualOpts = {
287
+ ...opts,
269
288
  trpc: {
289
+ ...opts?.trpc,
270
290
  ...(shouldAbortOnUnmount
271
291
  ? { signal: queryFunctionContext.signal }
272
292
  : { signal: null }),
@@ -290,8 +310,7 @@ export function createRootHooks<
290
310
  path: readonly string[],
291
311
  opts?: UseTRPCMutationOptions<unknown, TError, unknown, unknown>,
292
312
  ): UseTRPCMutationResult<unknown, TError, unknown, unknown> {
293
- const { client } = useContext();
294
- const queryClient = useQueryClient();
313
+ const { client, queryClient } = useContext();
295
314
 
296
315
  const mutationKey = getMutationKeyInternal(path);
297
316
 
@@ -332,80 +351,35 @@ export function createRootHooks<
332
351
  path: readonly string[],
333
352
  input: unknown,
334
353
  opts: UseTRPCSubscriptionOptions<unknown, TError>,
335
- ): UseTRPCSubscriptionResult<unknown, unknown, TError> {
354
+ ) {
336
355
  const enabled = opts?.enabled ?? input !== skipToken;
337
356
  const queryKey = hashKey(getQueryKeyInternal(path, input, 'any'));
357
+ const { client } = useContext();
338
358
 
339
- const trackedProps = React.useRef(
340
- new Set<keyof UseTRPCSubscriptionResult<unknown, unknown, TError>>([]),
341
- );
342
-
343
- const addTrackedProp = React.useCallback(
344
- (key: keyof UseTRPCSubscriptionResult<unknown, unknown, TError>) => {
345
- trackedProps.current.add(key);
346
- },
347
- [],
348
- );
349
-
350
- // const restart = React.useRef<restartSubscriptionFn<unknown>>(() => {
351
- // throw new Error('not implemented');
352
- // });
353
-
354
- const currentResult = React.useRef<
355
- UseTRPCSubscriptionResult<unknown, unknown, TError>
356
- >(
357
- enabled
358
- ? getStartingResult(/* restart.current */)
359
- : getIdleResult(/* restart.current */),
360
- );
361
-
362
- const [subscriptionState, setSubscriptionState] = React.useState(
363
- trackResult(currentResult.current, addTrackedProp),
364
- );
365
-
366
- const updateSubscriptionState = React.useCallback(
367
- (
368
- opts:
369
- | UseTRPCSubscriptionResult<unknown, unknown, TError>
370
- | ((
371
- prev: UseTRPCSubscriptionResult<unknown, unknown, TError>,
372
- ) => UseTRPCSubscriptionResult<unknown, unknown, TError>),
373
- ) => {
374
- const oldResult = currentResult.current;
375
-
376
- const newResult =
377
- typeof opts === 'function' ? opts(currentResult.current) : opts;
359
+ const optsRef = React.useRef<typeof opts>(opts);
360
+ optsRef.current = opts;
378
361
 
379
- currentResult.current = newResult;
362
+ type $Result = TRPCSubscriptionResult<unknown, TError>;
380
363
 
381
- let shouldUpdate = false;
364
+ const trackedProps = React.useRef(new Set<keyof $Result>([]));
382
365
 
383
- for (const key of trackedProps.current) {
384
- if (oldResult[key] !== newResult[key]) {
385
- shouldUpdate = true;
386
- break;
387
- }
388
- }
389
-
390
- if (shouldUpdate) {
391
- setSubscriptionState(trackResult(newResult, addTrackedProp));
392
- return;
393
- }
394
- },
395
- [addTrackedProp],
396
- );
366
+ const addTrackedProp = React.useCallback((key: keyof $Result) => {
367
+ trackedProps.current.add(key);
368
+ }, []);
397
369
 
398
- const { client } = useContext();
370
+ type Unsubscribe = () => void;
371
+ const currentSubscriptionRef = React.useRef<Unsubscribe | null>(null);
399
372
 
400
- const optsRef = React.useRef<typeof opts>(opts);
401
- optsRef.current = opts;
373
+ const reset = React.useCallback((): void => {
374
+ // unsubscribe from the previous subscription
375
+ currentSubscriptionRef.current?.();
402
376
 
403
- React.useEffect(() => {
377
+ updateState(getInitialState);
404
378
  if (!enabled) {
405
379
  return;
406
380
  }
407
- let isStopped = false;
408
381
 
382
+ let isStopped = false;
409
383
  const subscription = client.subscription(
410
384
  path.join('.'),
411
385
  input ?? undefined,
@@ -413,67 +387,113 @@ export function createRootHooks<
413
387
  onStarted: () => {
414
388
  if (!isStopped) {
415
389
  optsRef.current.onStarted?.();
390
+ updateState((prev) => ({
391
+ ...prev,
392
+ status: 'pending',
393
+ error: null,
394
+ }));
416
395
  }
417
396
  },
418
397
  onData: (data) => {
419
398
  if (!isStopped) {
420
- optsRef.current.onData(data);
421
-
422
- updateSubscriptionState((prev) => {
423
- if (prev.isPending) {
424
- return getPendingResult(prev, data);
425
- }
426
-
427
- return prev;
428
- });
399
+ optsRef.current.onData?.(data);
400
+ updateState((prev) => ({
401
+ ...prev,
402
+ status: 'pending',
403
+ data,
404
+ error: null,
405
+ }));
429
406
  }
430
407
  },
431
- onError: (err) => {
408
+ onError: (error) => {
432
409
  if (!isStopped) {
433
- optsRef.current.onError?.(err);
410
+ optsRef.current.onError?.(error);
411
+ updateState((prev) => ({
412
+ ...prev,
413
+ status: 'error',
414
+ error,
415
+ }));
434
416
  }
435
417
  },
436
- onStateChange: (state) => {
437
- if (state.state === 'idle') {
438
- updateSubscriptionState(getIdleResult(/* restart.current */));
439
-
440
- return;
441
- }
442
-
443
- if (state.state === 'connecting') {
444
- updateSubscriptionState((prev) => {
445
- return getConnectingResult(prev, state.data ?? null);
446
- });
447
-
448
- return;
449
- }
450
-
451
- if (state.state === 'pending') {
452
- updateSubscriptionState((prev) => getPendingResult(prev));
453
- }
454
-
455
- if (state.state === 'error') {
456
- updateSubscriptionState((prev) => {
457
- return getErrorResult(prev, state.data);
458
- });
459
- }
418
+ onConnectionStateChange: (result) => {
419
+ const delta = {
420
+ status: result.state,
421
+ error: result.error,
422
+ } as $Result;
423
+
424
+ updateState((prev) => {
425
+ return {
426
+ ...prev,
427
+ ...delta,
428
+ };
429
+ });
460
430
  },
461
431
  },
462
432
  );
463
433
 
464
- // const effectRestart = restart.current;
465
-
466
- return () => {
434
+ currentSubscriptionRef.current = () => {
467
435
  isStopped = true;
468
436
  subscription.unsubscribe();
469
-
470
- updateSubscriptionState(getIdleResult(/* effectRestart */));
471
437
  };
472
438
 
473
439
  // eslint-disable-next-line react-hooks/exhaustive-deps
474
440
  }, [queryKey, enabled]);
475
441
 
476
- return subscriptionState;
442
+ const getInitialState = React.useCallback((): $Result => {
443
+ return enabled
444
+ ? {
445
+ data: undefined,
446
+ error: null,
447
+ status: 'connecting',
448
+ reset,
449
+ }
450
+ : {
451
+ data: undefined,
452
+ error: null,
453
+ status: 'idle',
454
+ reset,
455
+ };
456
+ }, [enabled, reset]);
457
+
458
+ const resultRef = React.useRef<$Result>(getInitialState());
459
+
460
+ const [state, setState] = React.useState<$Result>(
461
+ trackResult(resultRef.current, addTrackedProp),
462
+ );
463
+
464
+ state.reset = reset;
465
+
466
+ const updateState = React.useCallback(
467
+ (callback: (prevState: $Result) => $Result) => {
468
+ const prev = resultRef.current;
469
+ const next = (resultRef.current = callback(prev));
470
+
471
+ let shouldUpdate = false;
472
+ for (const key of trackedProps.current) {
473
+ if (prev[key] !== next[key]) {
474
+ shouldUpdate = true;
475
+ break;
476
+ }
477
+ }
478
+ if (shouldUpdate) {
479
+ setState(trackResult(next, addTrackedProp));
480
+ }
481
+ },
482
+ [addTrackedProp],
483
+ );
484
+
485
+ React.useEffect(() => {
486
+ if (!enabled) {
487
+ return;
488
+ }
489
+ reset();
490
+
491
+ return () => {
492
+ currentSubscriptionRef.current?.();
493
+ };
494
+ }, [reset, enabled]);
495
+
496
+ return state;
477
497
  }
478
498
 
479
499
  function useInfiniteQuery(
@@ -550,6 +570,54 @@ export function createRootHooks<
550
570
  return hook;
551
571
  }
552
572
 
573
+ function usePrefetchInfiniteQuery(
574
+ path: string[],
575
+ input: unknown,
576
+ opts: UseTRPCPrefetchInfiniteQueryOptions<unknown, unknown, TError>,
577
+ ): void {
578
+ const context = useContext();
579
+ const queryKey = getQueryKeyInternal(path, input, 'infinite');
580
+
581
+ const defaultOpts = context.queryClient.getQueryDefaults(queryKey);
582
+
583
+ const isInputSkipToken = input === skipToken;
584
+
585
+ const ssrOpts = useSSRQueryOptionsIfNeeded(queryKey, {
586
+ ...defaultOpts,
587
+ ...opts,
588
+ });
589
+
590
+ // request option should take priority over global
591
+ const shouldAbortOnUnmount =
592
+ opts?.trpc?.abortOnUnmount ?? context.abortOnUnmount;
593
+
594
+ __usePrefetchInfiniteQuery({
595
+ ...opts,
596
+ initialPageParam: opts.initialCursor ?? null,
597
+ queryKey,
598
+ queryFn: isInputSkipToken
599
+ ? input
600
+ : (queryFunctionContext) => {
601
+ const actualOpts = {
602
+ ...ssrOpts,
603
+ trpc: {
604
+ ...ssrOpts?.trpc,
605
+ ...(shouldAbortOnUnmount
606
+ ? { signal: queryFunctionContext.signal }
607
+ : {}),
608
+ },
609
+ };
610
+
611
+ return context.client.query(
612
+ ...getClientArgs(queryKey, actualOpts, {
613
+ pageParam: queryFunctionContext.pageParam ?? opts.initialCursor,
614
+ direction: queryFunctionContext.direction,
615
+ }),
616
+ );
617
+ },
618
+ });
619
+ }
620
+
553
621
  function useSuspenseInfiniteQuery(
554
622
  path: readonly string[],
555
623
  input: unknown,
@@ -647,6 +715,7 @@ export function createRootHooks<
647
715
  {
648
716
  queries: queries.map((query) => ({
649
717
  ...query,
718
+ queryFn: query.queryFn,
650
719
  queryKey: (query as TRPCQueryOptions<any, any>).queryKey,
651
720
  })),
652
721
  },
@@ -662,12 +731,14 @@ export function createRootHooks<
662
731
  useContext,
663
732
  useUtils: useContext,
664
733
  useQuery,
734
+ usePrefetchQuery,
665
735
  useSuspenseQuery,
666
736
  useQueries,
667
737
  useSuspenseQueries,
668
738
  useMutation,
669
739
  useSubscription,
670
740
  useInfiniteQuery,
741
+ usePrefetchInfiniteQuery,
671
742
  useSuspenseInfiniteQuery,
672
743
  };
673
744
  }