@trpc/react-query 11.0.0-alpha-tmp-rethrow-next-errors.386 → 11.0.0-alpha-tmp-app-router-example.367

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.
@@ -1,7 +1,7 @@
1
1
  {
2
- "bundleSize": 29431,
3
- "bundleOrigSize": 63440,
4
- "bundleReduction": 53.61,
2
+ "bundleSize": 32108,
3
+ "bundleOrigSize": 68254,
4
+ "bundleReduction": 52.96,
5
5
  "modules": [
6
6
  {
7
7
  "id": "/src/shared/hooks/createHooksInternal.tsx",
@@ -14,7 +14,7 @@
14
14
  "dependents": [
15
15
  "/src/createTRPCReact.tsx"
16
16
  ],
17
- "percent": 46.7,
17
+ "percent": 42.8,
18
18
  "reduction": 12.84
19
19
  },
20
20
  {
@@ -29,7 +29,7 @@
29
29
  "/src/createTRPCQueryUtils.tsx",
30
30
  "/src/shared/hooks/createHooksInternal.tsx"
31
31
  ],
32
- "percent": 12.85,
32
+ "percent": 11.78,
33
33
  "reduction": 6.34
34
34
  },
35
35
  {
@@ -43,7 +43,7 @@
43
43
  "dependents": [
44
44
  "/src/server/index.ts"
45
45
  ],
46
- "percent": 12.48,
46
+ "percent": 11.44,
47
47
  "reduction": 50.38
48
48
  },
49
49
  {
@@ -59,9 +59,21 @@
59
59
  "dependents": [
60
60
  "/src/shared/index.ts"
61
61
  ],
62
- "percent": 9.75,
62
+ "percent": 8.94,
63
63
  "reduction": 74.38
64
64
  },
65
+ {
66
+ "id": "/src/rsc.tsx",
67
+ "size": 2677,
68
+ "origSize": 4814,
69
+ "renderedExports": [
70
+ "createHydrationHelpers"
71
+ ],
72
+ "removedExports": [],
73
+ "dependents": [],
74
+ "percent": 8.34,
75
+ "reduction": 44.39
76
+ },
65
77
  {
66
78
  "id": "/src/internals/getQueryKey.ts",
67
79
  "size": 1999,
@@ -73,12 +85,13 @@
73
85
  "removedExports": [],
74
86
  "dependents": [
75
87
  "/src/index.ts",
88
+ "/src/rsc.tsx",
76
89
  "/src/server/ssgProxy.ts",
77
90
  "/src/shared/proxy/utilsProxy.ts",
78
91
  "/src/shared/proxy/useQueriesProxy.ts",
79
92
  "/src/shared/hooks/createHooksInternal.tsx"
80
93
  ],
81
- "percent": 6.79,
94
+ "percent": 6.23,
82
95
  "reduction": 42.49
83
96
  },
84
97
  {
@@ -93,7 +106,7 @@
93
106
  "dependents": [
94
107
  "/src/index.ts"
95
108
  ],
96
- "percent": 2.89,
109
+ "percent": 2.65,
97
110
  "reduction": 89.28
98
111
  },
99
112
  {
@@ -107,7 +120,7 @@
107
120
  "dependents": [
108
121
  "/src/shared/index.ts"
109
122
  ],
110
- "percent": 2.74,
123
+ "percent": 2.51,
111
124
  "reduction": 23.16
112
125
  },
113
126
  {
@@ -122,7 +135,7 @@
122
135
  "/src/shared/index.ts",
123
136
  "/src/shared/hooks/createHooksInternal.tsx"
124
137
  ],
125
- "percent": 1.93,
138
+ "percent": 1.77,
126
139
  "reduction": 82.03
127
140
  },
128
141
  {
@@ -138,7 +151,7 @@
138
151
  "/src/shared/hooks/createHooksInternal.tsx",
139
152
  "/src/utils/createUtilityFunctions.ts"
140
153
  ],
141
- "percent": 1.61,
154
+ "percent": 1.47,
142
155
  "reduction": 17.31
143
156
  },
144
157
  {
@@ -152,7 +165,7 @@
152
165
  "dependents": [
153
166
  "/src/shared/hooks/createHooksInternal.tsx"
154
167
  ],
155
- "percent": 0.75,
168
+ "percent": 0.69,
156
169
  "reduction": 36.21
157
170
  },
158
171
  {
@@ -166,7 +179,7 @@
166
179
  "dependents": [
167
180
  "/src/index.ts"
168
181
  ],
169
- "percent": 0.55,
182
+ "percent": 0.5,
170
183
  "reduction": 66.6
171
184
  },
172
185
  {
@@ -184,7 +197,7 @@
184
197
  "/src/shared/proxy/utilsProxy.ts",
185
198
  "/src/shared/hooks/createHooksInternal.tsx"
186
199
  ],
187
- "percent": 0.52,
200
+ "percent": 0.48,
188
201
  "reduction": 97.59
189
202
  },
190
203
  {
@@ -198,7 +211,7 @@
198
211
  "dependents": [
199
212
  "/src/shared/index.ts"
200
213
  ],
201
- "percent": 0.44,
214
+ "percent": 0.4,
202
215
  "reduction": 74.9
203
216
  },
204
217
  {
@@ -236,5 +249,5 @@
236
249
  "reduction": 100
237
250
  }
238
251
  ],
239
- "moduleCount": 16
252
+ "moduleCount": 17
240
253
  }
package/dist/rsc.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ import { type QueryClient } from '@tanstack/react-query';
2
+ import { TRPCClientError } from '@trpc/client';
3
+ import { inferTransformedProcedureOutput } from '@trpc/server';
4
+ import { AnyRootTypes, inferRouterRootTypes, type AnyRouter, type inferProcedureInput, type RouterRecord } from '@trpc/server/unstable-core-do-not-import';
5
+ import type { AnyProcedure, inferProcedureOutput, RouterCaller, TypeError } from '@trpc/server/unstable-core-do-not-import';
6
+ import * as React from 'react';
7
+ import { TRPCFetchInfiniteQueryOptions, TRPCFetchQueryOptions } from './shared';
8
+ type DecorateProcedure<TRoot extends AnyRootTypes, TProcedure extends AnyProcedure> = {
9
+ (input: inferProcedureInput<TProcedure>): Promise<inferProcedureOutput<TProcedure>>;
10
+ prefetch: (input: inferProcedureInput<TProcedure>, opts?: TRPCFetchQueryOptions<inferTransformedProcedureOutput<TRoot, TProcedure>, TRPCClientError<TRoot>>) => Promise<void>;
11
+ prefetchInfinite: (input: inferProcedureInput<TProcedure>, opts?: TRPCFetchInfiniteQueryOptions<inferProcedureInput<TProcedure>, inferTransformedProcedureOutput<TRoot, TProcedure>, TRPCClientError<TRoot>>) => Promise<void>;
12
+ };
13
+ type DecorateRouterRecord<TRoot extends AnyRootTypes, TRecord extends RouterRecord> = {
14
+ [TKey in keyof TRecord]: TRecord[TKey] extends AnyProcedure ? DecorateProcedure<TRoot, TRecord[TKey]> : TRecord[TKey] extends RouterRecord ? DecorateRouterRecord<TRoot, TRecord[TKey]> : never;
15
+ };
16
+ type Caller<TRouter extends AnyRouter> = ReturnType<RouterCaller<inferRouterRootTypes<TRouter>, TRouter['_def']['record']>>;
17
+ export declare function createHydrationHelpers<TRouter extends AnyRouter>(caller: AnyRouter extends TRouter ? TypeError<'Generic parameter missing in `createHydrationHelpers<HERE>`'> : Caller<TRouter>, getQueryClient: () => QueryClient): {
18
+ /***
19
+ * Wrapped caller with prefetch helpers
20
+ * Can be used as a regular [server-side caller](https://trpc.io/docs/server/server-side-calls)
21
+ * or using prefetch helpers to put the promise into the QueryClient cache
22
+ * @example
23
+ * ```ts
24
+ * const data = await trpc.post.get("postId");
25
+ *
26
+ * // or
27
+ * void trpc.post.get.prefetch("postId");
28
+ * ```
29
+ */
30
+ trpc: DecorateRouterRecord<inferRouterRootTypes<TRouter>, TRouter["_def"]["record"]>;
31
+ /**
32
+ * HoC to hydrate the query client for a client component
33
+ * to pick up the prefetched promise and skip an initial
34
+ * client-side fetch.
35
+ * @example
36
+ * ```tsx
37
+ * // MyRSC.tsx
38
+ * const MyRSC = ({ params }) => {
39
+ * void trpc.post.get.prefetch(params.postId);
40
+ *
41
+ * return (
42
+ * <HydrateClient>
43
+ * <MyCC postId={params.postId} />
44
+ * </HydrateClient>
45
+ * );
46
+ * };
47
+ *
48
+ * // MyCC.tsx
49
+ * "use client"
50
+ * const MyCC = ({ postId }) => {
51
+ * const { data: post } = trpc.post.get.useQuery(postId);
52
+ * return <div>{post.title}</div>;
53
+ * };
54
+ * ```
55
+ */
56
+ HydrateClient: (props: {
57
+ children: React.ReactNode;
58
+ }) => React.JSX.Element;
59
+ };
60
+ export {};
61
+ //# sourceMappingURL=rsc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rsc.d.ts","sourceRoot":"","sources":["../src/rsc.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,YAAY,EAEZ,oBAAoB,EAEpB,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,YAAY,EAClB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,SAAS,EACV,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAIhF,KAAK,iBAAiB,CACpB,KAAK,SAAS,YAAY,EAC1B,UAAU,SAAS,YAAY,IAC7B;IACF,CAAC,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,GAAG,OAAO,CAC/C,oBAAoB,CAAC,UAAU,CAAC,CACjC,CAAC;IACF,QAAQ,EAAE,CACR,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EACtC,IAAI,CAAC,EAAE,qBAAqB,CAC1B,+BAA+B,CAAC,KAAK,EAAE,UAAU,CAAC,EAClD,eAAe,CAAC,KAAK,CAAC,CACvB,KACE,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,gBAAgB,EAAE,CAChB,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EACtC,IAAI,CAAC,EAAE,6BAA6B,CAClC,mBAAmB,CAAC,UAAU,CAAC,EAC/B,+BAA+B,CAAC,KAAK,EAAE,UAAU,CAAC,EAClD,eAAe,CAAC,KAAK,CAAC,CACvB,KACE,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,KAAK,oBAAoB,CACvB,KAAK,SAAS,YAAY,EAC1B,OAAO,SAAS,YAAY,IAC1B;KACD,IAAI,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,YAAY,GACvD,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,SAAS,YAAY,GAClC,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,GAC1C,KAAK;CACV,CAAC;AAEF,KAAK,MAAM,CAAC,OAAO,SAAS,SAAS,IAAI,UAAU,CACjD,YAAY,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CACvE,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,OAAO,SAAS,SAAS,EAC9D,MAAM,EAAE,SAAS,SAAS,OAAO,GAC7B,SAAS,CAAC,6DAA6D,CAAC,GACxE,MAAM,CAAC,OAAO,CAAC,EACnB,cAAc,EAAE,MAAM,WAAW;IAqD/B;;;;;;;;;;;OAWG;;IAEH;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;2BAlDyB;QAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;KAAE;EAqD5D"}
package/dist/rsc.js ADDED
@@ -0,0 +1,106 @@
1
+ 'use strict';
2
+
3
+ var reactQuery = require('@tanstack/react-query');
4
+ var unstableCoreDoNotImport = require('@trpc/server/unstable-core-do-not-import');
5
+ var React = require('react');
6
+ var getQueryKey = require('./internals/getQueryKey.js');
7
+
8
+ function _interopNamespaceDefault(e) {
9
+ var n = Object.create(null);
10
+ if (e) {
11
+ Object.keys(e).forEach(function (k) {
12
+ if (k !== 'default') {
13
+ var d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: function () { return e[k]; }
17
+ });
18
+ }
19
+ });
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+
25
+ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
26
+
27
+ const HELPERS = [
28
+ 'prefetch',
29
+ 'prefetchInfinite'
30
+ ];
31
+ function createHydrationHelpers(caller, getQueryClient) {
32
+ const wrappedProxy = unstableCoreDoNotImport.createRecursiveProxy(async ({ path , args })=>{
33
+ const proc = path.reduce((acc, key)=>// @ts-expect-error - ??
34
+ HELPERS.includes(key) ? acc : acc[key], caller);
35
+ const input = args[0];
36
+ const promise = proc(input);
37
+ const helper = path.pop();
38
+ if (helper === 'prefetch') {
39
+ const args1 = args[1];
40
+ return getQueryClient().prefetchQuery({
41
+ ...args1,
42
+ queryKey: getQueryKey.getQueryKeyInternal(path, input, 'query'),
43
+ queryFn: ()=>promise
44
+ });
45
+ }
46
+ if (helper === 'prefetchInfinite') {
47
+ const args11 = args[1];
48
+ return getQueryClient().prefetchInfiniteQuery({
49
+ ...args11,
50
+ queryKey: getQueryKey.getQueryKeyInternal(path, input, 'infinite'),
51
+ queryFn: ()=>promise,
52
+ initialPageParam: args11?.initialCursor ?? null
53
+ });
54
+ }
55
+ return promise;
56
+ });
57
+ function HydrateClient(props) {
58
+ const dehydratedState = reactQuery.dehydrate(getQueryClient());
59
+ // TODO: transform?? We can't transform promises i don't think...
60
+ // since that is handled by React internally
61
+ return /*#__PURE__*/ React__namespace.createElement(reactQuery.HydrationBoundary, {
62
+ state: dehydratedState
63
+ }, props.children);
64
+ }
65
+ return {
66
+ /***
67
+ * Wrapped caller with prefetch helpers
68
+ * Can be used as a regular [server-side caller](https://trpc.io/docs/server/server-side-calls)
69
+ * or using prefetch helpers to put the promise into the QueryClient cache
70
+ * @example
71
+ * ```ts
72
+ * const data = await trpc.post.get("postId");
73
+ *
74
+ * // or
75
+ * void trpc.post.get.prefetch("postId");
76
+ * ```
77
+ */ trpc: wrappedProxy,
78
+ /**
79
+ * HoC to hydrate the query client for a client component
80
+ * to pick up the prefetched promise and skip an initial
81
+ * client-side fetch.
82
+ * @example
83
+ * ```tsx
84
+ * // MyRSC.tsx
85
+ * const MyRSC = ({ params }) => {
86
+ * void trpc.post.get.prefetch(params.postId);
87
+ *
88
+ * return (
89
+ * <HydrateClient>
90
+ * <MyCC postId={params.postId} />
91
+ * </HydrateClient>
92
+ * );
93
+ * };
94
+ *
95
+ * // MyCC.tsx
96
+ * "use client"
97
+ * const MyCC = ({ postId }) => {
98
+ * const { data: post } = trpc.post.get.useQuery(postId);
99
+ * return <div>{post.title}</div>;
100
+ * };
101
+ * ```
102
+ */ HydrateClient
103
+ };
104
+ }
105
+
106
+ exports.createHydrationHelpers = createHydrationHelpers;
package/dist/rsc.mjs ADDED
@@ -0,0 +1,85 @@
1
+ import { dehydrate, HydrationBoundary } from '@tanstack/react-query';
2
+ import { createRecursiveProxy } from '@trpc/server/unstable-core-do-not-import';
3
+ import * as React from 'react';
4
+ import { getQueryKeyInternal } from './internals/getQueryKey.mjs';
5
+
6
+ const HELPERS = [
7
+ 'prefetch',
8
+ 'prefetchInfinite'
9
+ ];
10
+ function createHydrationHelpers(caller, getQueryClient) {
11
+ const wrappedProxy = createRecursiveProxy(async ({ path , args })=>{
12
+ const proc = path.reduce((acc, key)=>// @ts-expect-error - ??
13
+ HELPERS.includes(key) ? acc : acc[key], caller);
14
+ const input = args[0];
15
+ const promise = proc(input);
16
+ const helper = path.pop();
17
+ if (helper === 'prefetch') {
18
+ const args1 = args[1];
19
+ return getQueryClient().prefetchQuery({
20
+ ...args1,
21
+ queryKey: getQueryKeyInternal(path, input, 'query'),
22
+ queryFn: ()=>promise
23
+ });
24
+ }
25
+ if (helper === 'prefetchInfinite') {
26
+ const args11 = args[1];
27
+ return getQueryClient().prefetchInfiniteQuery({
28
+ ...args11,
29
+ queryKey: getQueryKeyInternal(path, input, 'infinite'),
30
+ queryFn: ()=>promise,
31
+ initialPageParam: args11?.initialCursor ?? null
32
+ });
33
+ }
34
+ return promise;
35
+ });
36
+ function HydrateClient(props) {
37
+ const dehydratedState = dehydrate(getQueryClient());
38
+ // TODO: transform?? We can't transform promises i don't think...
39
+ // since that is handled by React internally
40
+ return /*#__PURE__*/ React.createElement(HydrationBoundary, {
41
+ state: dehydratedState
42
+ }, props.children);
43
+ }
44
+ return {
45
+ /***
46
+ * Wrapped caller with prefetch helpers
47
+ * Can be used as a regular [server-side caller](https://trpc.io/docs/server/server-side-calls)
48
+ * or using prefetch helpers to put the promise into the QueryClient cache
49
+ * @example
50
+ * ```ts
51
+ * const data = await trpc.post.get("postId");
52
+ *
53
+ * // or
54
+ * void trpc.post.get.prefetch("postId");
55
+ * ```
56
+ */ trpc: wrappedProxy,
57
+ /**
58
+ * HoC to hydrate the query client for a client component
59
+ * to pick up the prefetched promise and skip an initial
60
+ * client-side fetch.
61
+ * @example
62
+ * ```tsx
63
+ * // MyRSC.tsx
64
+ * const MyRSC = ({ params }) => {
65
+ * void trpc.post.get.prefetch(params.postId);
66
+ *
67
+ * return (
68
+ * <HydrateClient>
69
+ * <MyCC postId={params.postId} />
70
+ * </HydrateClient>
71
+ * );
72
+ * };
73
+ *
74
+ * // MyCC.tsx
75
+ * "use client"
76
+ * const MyCC = ({ postId }) => {
77
+ * const { data: post } = trpc.post.get.useQuery(postId);
78
+ * return <div>{post.title}</div>;
79
+ * };
80
+ * ```
81
+ */ HydrateClient
82
+ };
83
+ }
84
+
85
+ export { createHydrationHelpers };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/react-query",
3
- "version": "11.0.0-alpha-tmp-rethrow-next-errors.386+a4f5d8541",
3
+ "version": "11.0.0-alpha-tmp-app-router-example.367+bc87f071f",
4
4
  "description": "The tRPC React library",
5
5
  "author": "KATT",
6
6
  "license": "MIT",
@@ -27,6 +27,11 @@
27
27
  "require": "./dist/index.js",
28
28
  "default": "./dist/index.js"
29
29
  },
30
+ "./rsc": {
31
+ "import": "./dist/rsc.mjs",
32
+ "require": "./dist/rsc.js",
33
+ "default": "./dist/rsc.js"
34
+ },
30
35
  "./server": {
31
36
  "import": "./dist/server/index.mjs",
32
37
  "require": "./dist/server/index.js",
@@ -43,6 +48,7 @@
43
48
  "src",
44
49
  "README.md",
45
50
  "package.json",
51
+ "rsc",
46
52
  "server",
47
53
  "shared",
48
54
  "!**/*.test.*"
@@ -57,16 +63,16 @@
57
63
  }
58
64
  },
59
65
  "peerDependencies": {
60
- "@tanstack/react-query": "^5.25.0",
61
- "@trpc/client": "11.0.0-alpha-tmp-rethrow-next-errors.386+a4f5d8541",
62
- "@trpc/server": "11.0.0-alpha-tmp-rethrow-next-errors.386+a4f5d8541",
66
+ "@tanstack/react-query": "^5.40.0",
67
+ "@trpc/client": "11.0.0-alpha-tmp-app-router-example.367+bc87f071f",
68
+ "@trpc/server": "11.0.0-alpha-tmp-app-router-example.367+bc87f071f",
63
69
  "react": ">=18.2.0",
64
70
  "react-dom": ">=18.2.0"
65
71
  },
66
72
  "devDependencies": {
67
- "@tanstack/react-query": "^5.25.0",
68
- "@trpc/client": "11.0.0-alpha-tmp-rethrow-next-errors.386+a4f5d8541",
69
- "@trpc/server": "11.0.0-alpha-tmp-rethrow-next-errors.386+a4f5d8541",
73
+ "@tanstack/react-query": "^5.40.0",
74
+ "@trpc/client": "11.0.0-alpha-tmp-app-router-example.367+bc87f071f",
75
+ "@trpc/server": "11.0.0-alpha-tmp-app-router-example.367+bc87f071f",
70
76
  "@types/express": "^4.17.17",
71
77
  "@types/node": "^20.10.0",
72
78
  "@types/react": "^18.3.1",
@@ -86,5 +92,5 @@
86
92
  "funding": [
87
93
  "https://trpc.io/sponsor"
88
94
  ],
89
- "gitHead": "a4f5d854168964a872610d94d4aa359789db760b"
95
+ "gitHead": "bc87f071fdececce20027eb8ed6deb422a3523d8"
90
96
  }
package/rsc/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from '../dist/rsc';
package/rsc/index.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/rsc');
package/src/rsc.tsx ADDED
@@ -0,0 +1,165 @@
1
+ import {
2
+ dehydrate,
3
+ HydrationBoundary,
4
+ type QueryClient,
5
+ } from '@tanstack/react-query';
6
+ import { TRPCClientError } from '@trpc/client';
7
+ import { inferTransformedProcedureOutput } from '@trpc/server';
8
+ import {
9
+ AnyRootTypes,
10
+ createRecursiveProxy,
11
+ inferRouterRootTypes,
12
+ Maybe,
13
+ type AnyRouter,
14
+ type inferProcedureInput,
15
+ type RouterRecord,
16
+ } from '@trpc/server/unstable-core-do-not-import';
17
+ import type {
18
+ AnyProcedure,
19
+ inferProcedureOutput,
20
+ RouterCaller,
21
+ TypeError,
22
+ } from '@trpc/server/unstable-core-do-not-import';
23
+ import * as React from 'react';
24
+ import { getQueryKeyInternal } from './internals/getQueryKey';
25
+ import { TRPCFetchInfiniteQueryOptions, TRPCFetchQueryOptions } from './shared';
26
+
27
+ const HELPERS = ['prefetch', 'prefetchInfinite'];
28
+
29
+ type DecorateProcedure<
30
+ TRoot extends AnyRootTypes,
31
+ TProcedure extends AnyProcedure,
32
+ > = {
33
+ (input: inferProcedureInput<TProcedure>): Promise<
34
+ inferProcedureOutput<TProcedure>
35
+ >;
36
+ prefetch: (
37
+ input: inferProcedureInput<TProcedure>,
38
+ opts?: TRPCFetchQueryOptions<
39
+ inferTransformedProcedureOutput<TRoot, TProcedure>,
40
+ TRPCClientError<TRoot>
41
+ >,
42
+ ) => Promise<void>;
43
+ prefetchInfinite: (
44
+ input: inferProcedureInput<TProcedure>,
45
+ opts?: TRPCFetchInfiniteQueryOptions<
46
+ inferProcedureInput<TProcedure>,
47
+ inferTransformedProcedureOutput<TRoot, TProcedure>,
48
+ TRPCClientError<TRoot>
49
+ >,
50
+ ) => Promise<void>;
51
+ };
52
+
53
+ type DecorateRouterRecord<
54
+ TRoot extends AnyRootTypes,
55
+ TRecord extends RouterRecord,
56
+ > = {
57
+ [TKey in keyof TRecord]: TRecord[TKey] extends AnyProcedure
58
+ ? DecorateProcedure<TRoot, TRecord[TKey]>
59
+ : TRecord[TKey] extends RouterRecord
60
+ ? DecorateRouterRecord<TRoot, TRecord[TKey]>
61
+ : never;
62
+ };
63
+
64
+ type Caller<TRouter extends AnyRouter> = ReturnType<
65
+ RouterCaller<inferRouterRootTypes<TRouter>, TRouter['_def']['record']>
66
+ >;
67
+
68
+ export function createHydrationHelpers<TRouter extends AnyRouter>(
69
+ caller: AnyRouter extends TRouter
70
+ ? TypeError<'Generic parameter missing in `createHydrationHelpers<HERE>`'>
71
+ : Caller<TRouter>,
72
+ getQueryClient: () => QueryClient,
73
+ ) {
74
+ type RootTypes = inferRouterRootTypes<TRouter>;
75
+ const wrappedProxy = createRecursiveProxy(async ({ path, args }) => {
76
+ const proc = path.reduce(
77
+ (acc, key) =>
78
+ // @ts-expect-error - ??
79
+ HELPERS.includes(key) ? acc : acc[key],
80
+ caller,
81
+ ) as unknown as DecorateProcedure<RootTypes, AnyProcedure>;
82
+
83
+ const input = args[0];
84
+ const promise = proc(input);
85
+
86
+ const helper = path.pop()!;
87
+ if (helper === 'prefetch') {
88
+ const args1 = args[1] as Maybe<
89
+ TRPCFetchInfiniteQueryOptions<any, any, any>
90
+ >;
91
+ return getQueryClient().prefetchQuery({
92
+ ...args1,
93
+ queryKey: getQueryKeyInternal(path, input, 'query'),
94
+ queryFn: () => promise,
95
+ });
96
+ }
97
+ if (helper === 'prefetchInfinite') {
98
+ const args1 = args[1] as Maybe<
99
+ TRPCFetchInfiniteQueryOptions<any, any, any>
100
+ >;
101
+ return getQueryClient().prefetchInfiniteQuery({
102
+ ...args1,
103
+ queryKey: getQueryKeyInternal(path, input, 'infinite'),
104
+ queryFn: () => promise,
105
+ initialPageParam: args1?.initialCursor ?? null,
106
+ });
107
+ }
108
+
109
+ return promise;
110
+ }) as DecorateRouterRecord<RootTypes, TRouter['_def']['record']>;
111
+
112
+ function HydrateClient(props: { children: React.ReactNode }) {
113
+ const dehydratedState = dehydrate(getQueryClient());
114
+ // TODO: transform?? We can't transform promises i don't think...
115
+ // since that is handled by React internally
116
+
117
+ return (
118
+ <HydrationBoundary state={dehydratedState}>
119
+ {props.children}
120
+ </HydrationBoundary>
121
+ );
122
+ }
123
+
124
+ return {
125
+ /***
126
+ * Wrapped caller with prefetch helpers
127
+ * Can be used as a regular [server-side caller](https://trpc.io/docs/server/server-side-calls)
128
+ * or using prefetch helpers to put the promise into the QueryClient cache
129
+ * @example
130
+ * ```ts
131
+ * const data = await trpc.post.get("postId");
132
+ *
133
+ * // or
134
+ * void trpc.post.get.prefetch("postId");
135
+ * ```
136
+ */
137
+ trpc: wrappedProxy,
138
+ /**
139
+ * HoC to hydrate the query client for a client component
140
+ * to pick up the prefetched promise and skip an initial
141
+ * client-side fetch.
142
+ * @example
143
+ * ```tsx
144
+ * // MyRSC.tsx
145
+ * const MyRSC = ({ params }) => {
146
+ * void trpc.post.get.prefetch(params.postId);
147
+ *
148
+ * return (
149
+ * <HydrateClient>
150
+ * <MyCC postId={params.postId} />
151
+ * </HydrateClient>
152
+ * );
153
+ * };
154
+ *
155
+ * // MyCC.tsx
156
+ * "use client"
157
+ * const MyCC = ({ postId }) => {
158
+ * const { data: post } = trpc.post.get.useQuery(postId);
159
+ * return <div>{post.title}</div>;
160
+ * };
161
+ * ```
162
+ */
163
+ HydrateClient,
164
+ };
165
+ }