@trpc/next 11.0.0-alpha-tmp-nosideeffects.257 → 11.0.0-alpha-tmp-02-08-tmp.274
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.
- package/README.md +1 -1
- package/dist/app-dir/create-action-hook.d.ts +2 -2
- package/dist/app-dir/create-action-hook.d.ts.map +1 -1
- package/dist/app-dir/links/nextCache.d.ts +2 -2
- package/dist/app-dir/links/nextCache.d.ts.map +1 -1
- package/dist/app-dir/server.d.ts +2 -2
- package/dist/app-dir/server.d.ts.map +1 -1
- package/dist/app-dir/shared.d.ts +8 -3
- package/dist/app-dir/shared.d.ts.map +1 -1
- package/dist/app-dir/types.d.ts +21 -9
- package/dist/app-dir/types.d.ts.map +1 -1
- package/dist/bundle-analysis.json +158 -0
- package/dist/createTRPCNext.d.ts +2 -2
- package/dist/createTRPCNext.d.ts.map +1 -1
- package/dist/ssrPrepass.d.ts +3 -0
- package/dist/ssrPrepass.d.ts.map +1 -0
- package/dist/ssrPrepass.js +139 -0
- package/dist/ssrPrepass.mjs +137 -0
- package/dist/withTRPC.d.ts +29 -3
- package/dist/withTRPC.d.ts.map +1 -1
- package/dist/withTRPC.js +7 -130
- package/dist/withTRPC.mjs +9 -132
- package/package.json +14 -8
- package/src/app-dir/create-action-hook.tsx +2 -2
- package/src/app-dir/links/nextCache.ts +2 -2
- package/src/app-dir/server.ts +2 -2
- package/src/app-dir/shared.ts +9 -3
- package/src/app-dir/types.ts +27 -13
- package/src/createTRPCNext.tsx +2 -5
- package/src/ssrPrepass.ts +185 -0
- package/src/withTRPC.tsx +39 -185
- package/ssrPrepass/index.d.ts +1 -0
- package/ssrPrepass/index.js +1 -0
package/dist/withTRPC.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Heavily based on urql's ssr
|
|
3
|
+
* https://github.com/FormidableLabs/urql/blob/main/packages/next-urql/src/with-urql-client.ts
|
|
4
|
+
*/
|
|
5
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
6
|
+
import type { CreateTRPCClientOptions, TRPCUntypedClient } from '@trpc/client';
|
|
2
7
|
import { type TransformerOptions } from '@trpc/client/unstable-internals';
|
|
3
8
|
import type { TRPCClientError } from '@trpc/react-query';
|
|
4
9
|
import type { CreateTRPCReactOptions, CreateTRPCReactQueryClientConfig } from '@trpc/react-query/shared';
|
|
5
|
-
import type { AnyRouter,
|
|
10
|
+
import type { AnyRouter, inferClientTypes, ResponseMeta } from '@trpc/server/unstable-core-do-not-import';
|
|
6
11
|
import type { NextComponentType, NextPageContext } from 'next/dist/shared/lib/utils';
|
|
7
12
|
export type WithTRPCConfig<TRouter extends AnyRouter> = CreateTRPCClientOptions<TRouter> & CreateTRPCReactQueryClientConfig & {
|
|
8
13
|
abortOnUnmount?: boolean;
|
|
@@ -11,8 +16,17 @@ type WithTRPCOptions<TRouter extends AnyRouter> = CreateTRPCReactOptions<TRouter
|
|
|
11
16
|
config: (info: {
|
|
12
17
|
ctx?: NextPageContext;
|
|
13
18
|
}) => WithTRPCConfig<TRouter>;
|
|
14
|
-
} & TransformerOptions<
|
|
19
|
+
} & TransformerOptions<inferClientTypes<TRouter>>;
|
|
20
|
+
export type TRPCPrepassHelper = (opts: {
|
|
21
|
+
parent: WithTRPCSSROptions<AnyRouter>;
|
|
22
|
+
WithTRPC: NextComponentType<any, any, any>;
|
|
23
|
+
AppOrPage: NextComponentType<any, any, any>;
|
|
24
|
+
}) => void;
|
|
15
25
|
export type WithTRPCSSROptions<TRouter extends AnyRouter> = WithTRPCOptions<TRouter> & {
|
|
26
|
+
/**
|
|
27
|
+
* If you enable this, you also need to add a `ssrPrepass`-prop
|
|
28
|
+
* @link https://trpc.io/docs/client/nextjs/ssr
|
|
29
|
+
*/
|
|
16
30
|
ssr: true | ((opts: {
|
|
17
31
|
ctx: NextPageContext;
|
|
18
32
|
}) => boolean | Promise<boolean>);
|
|
@@ -20,10 +34,22 @@ export type WithTRPCSSROptions<TRouter extends AnyRouter> = WithTRPCOptions<TRou
|
|
|
20
34
|
ctx: NextPageContext;
|
|
21
35
|
clientErrors: TRPCClientError<TRouter>[];
|
|
22
36
|
}) => ResponseMeta;
|
|
37
|
+
/**
|
|
38
|
+
* use `import { ssrPrepass } from '@trpc/next/ssrPrepass'`
|
|
39
|
+
* @link https://trpc.io/docs/client/nextjs/ssr
|
|
40
|
+
*/
|
|
41
|
+
ssrPrepass: TRPCPrepassHelper;
|
|
23
42
|
};
|
|
24
43
|
export type WithTRPCNoSSROptions<TRouter extends AnyRouter> = WithTRPCOptions<TRouter> & {
|
|
25
44
|
ssr?: false;
|
|
26
45
|
};
|
|
46
|
+
export type TRPCPrepassProps<TRouter extends AnyRouter, TSSRContext extends NextPageContext = NextPageContext> = {
|
|
47
|
+
config: WithTRPCConfig<TRouter>;
|
|
48
|
+
queryClient: QueryClient;
|
|
49
|
+
trpcClient: TRPCUntypedClient<TRouter>;
|
|
50
|
+
ssrState: 'prepass';
|
|
51
|
+
ssrContext: TSSRContext;
|
|
52
|
+
};
|
|
27
53
|
export declare function withTRPC<TRouter extends AnyRouter, TSSRContext extends NextPageContext = NextPageContext>(opts: WithTRPCNoSSROptions<TRouter> | WithTRPCSSROptions<TRouter>): (AppOrPage: NextComponentType<any, any, any>) => NextComponentType;
|
|
28
54
|
export {};
|
|
29
55
|
//# sourceMappingURL=withTRPC.d.ts.map
|
package/dist/withTRPC.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withTRPC.d.ts","sourceRoot":"","sources":["../src/withTRPC.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"withTRPC.d.ts","sourceRoot":"","sources":["../src/withTRPC.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAE/E,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EACV,sBAAsB,EACtB,gCAAgC,EACjC,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACb,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAEV,iBAAiB,EACjB,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAIpC,MAAM,MAAM,cAAc,CAAC,OAAO,SAAS,SAAS,IAClD,uBAAuB,CAAC,OAAO,CAAC,GAC9B,gCAAgC,GAAG;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEN,KAAK,eAAe,CAAC,OAAO,SAAS,SAAS,IAC5C,sBAAsB,CAAC,OAAO,CAAC,GAAG;IAChC,MAAM,EAAE,CAAC,IAAI,EAAE;QAAE,GAAG,CAAC,EAAE,eAAe,CAAA;KAAE,KAAK,cAAc,CAAC,OAAO,CAAC,CAAC;CACtE,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;AAEpD,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE;IACrC,MAAM,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACtC,QAAQ,EAAE,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3C,SAAS,EAAE,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;CAC7C,KAAK,IAAI,CAAC;AACX,MAAM,MAAM,kBAAkB,CAAC,OAAO,SAAS,SAAS,IACtD,eAAe,CAAC,OAAO,CAAC,GAAG;IACzB;;;OAGG;IACH,GAAG,EACC,IAAI,GACJ,CAAC,CAAC,IAAI,EAAE;QAAE,GAAG,EAAE,eAAe,CAAA;KAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE;QACpB,GAAG,EAAE,eAAe,CAAC;QACrB,YAAY,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;KAC1C,KAAK,YAAY,CAAC;IACnB;;;OAGG;IACH,UAAU,EAAE,iBAAiB,CAAC;CAC/B,CAAC;AAEJ,MAAM,MAAM,oBAAoB,CAAC,OAAO,SAAS,SAAS,IACxD,eAAe,CAAC,OAAO,CAAC,GAAG;IACzB,GAAG,CAAC,EAAE,KAAK,CAAC;CACb,CAAC;AAEJ,MAAM,MAAM,gBAAgB,CAC1B,OAAO,SAAS,SAAS,EACzB,WAAW,SAAS,eAAe,GAAG,eAAe,IACnD;IACF,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IAChC,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,EAAE,WAAW,CAAC;CACzB,CAAC;AAEF,wBAAgB,QAAQ,CACtB,OAAO,SAAS,SAAS,EACzB,WAAW,SAAS,eAAe,GAAG,eAAe,EACrD,IAAI,EAAE,oBAAoB,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC,eAO9C,kBAAkB,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,KAAG,iBAAiB,CAsExE"}
|
package/dist/withTRPC.js
CHANGED
|
@@ -1,35 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var reactQuery = require('@tanstack/react-query');
|
|
4
|
-
var client = require('@trpc/client');
|
|
5
4
|
var unstableInternals = require('@trpc/client/unstable-internals');
|
|
6
5
|
var shared = require('@trpc/react-query/shared');
|
|
7
6
|
var React = require('react');
|
|
8
7
|
|
|
9
|
-
function transformQueryOrMutationCacheErrors(result) {
|
|
10
|
-
const error = result.state.error;
|
|
11
|
-
if (error instanceof Error && error.name === 'TRPCClientError') {
|
|
12
|
-
const newError = {
|
|
13
|
-
message: error.message,
|
|
14
|
-
data: error.data,
|
|
15
|
-
shape: error.shape
|
|
16
|
-
};
|
|
17
|
-
return {
|
|
18
|
-
...result,
|
|
19
|
-
state: {
|
|
20
|
-
...result.state,
|
|
21
|
-
error: newError
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
return result;
|
|
26
|
-
}
|
|
27
8
|
function withTRPC(opts) {
|
|
28
9
|
const { config: getClientConfig } = opts;
|
|
29
10
|
const transformer = unstableInternals.getTransformer(opts.transformer);
|
|
30
11
|
return (AppOrPage)=>{
|
|
31
12
|
const trpc = shared.createRootHooks(opts);
|
|
32
|
-
const WithTRPC =
|
|
13
|
+
const WithTRPC = (props)=>{
|
|
33
14
|
const [prepassProps] = React.useState(()=>{
|
|
34
15
|
if (props.trpc) {
|
|
35
16
|
return props.trpc;
|
|
@@ -70,116 +51,12 @@ function withTRPC(opts) {
|
|
|
70
51
|
state: hydratedState
|
|
71
52
|
}, /*#__PURE__*/ React.createElement(AppOrPage, Object.assign({}, props)))));
|
|
72
53
|
};
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
try {
|
|
81
|
-
return await opts.ssr({
|
|
82
|
-
ctx: appOrPageCtx.ctx
|
|
83
|
-
});
|
|
84
|
-
} catch (e) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return opts.ssr;
|
|
89
|
-
};
|
|
90
|
-
const ssr = await shouldSsr();
|
|
91
|
-
const AppTree = appOrPageCtx.AppTree;
|
|
92
|
-
// Determine if we are wrapping an App component or a Page component.
|
|
93
|
-
const isApp = !!appOrPageCtx.Component;
|
|
94
|
-
const ctx = isApp ? appOrPageCtx.ctx : appOrPageCtx;
|
|
95
|
-
// Run the wrapped component's getInitialProps function.
|
|
96
|
-
let pageProps = {};
|
|
97
|
-
if (AppOrPage.getInitialProps) {
|
|
98
|
-
const originalProps = await AppOrPage.getInitialProps(appOrPageCtx);
|
|
99
|
-
const originalPageProps = isApp ? originalProps.pageProps ?? {} : originalProps;
|
|
100
|
-
pageProps = {
|
|
101
|
-
...originalPageProps,
|
|
102
|
-
...pageProps
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
const getAppTreeProps = (props)=>isApp ? {
|
|
106
|
-
pageProps: props
|
|
107
|
-
} : props;
|
|
108
|
-
if (typeof window !== 'undefined' || !ssr) {
|
|
109
|
-
return getAppTreeProps(pageProps);
|
|
110
|
-
}
|
|
111
|
-
const config = getClientConfig({
|
|
112
|
-
ctx
|
|
113
|
-
});
|
|
114
|
-
const trpcClient = client.createTRPCUntypedClient(config);
|
|
115
|
-
const queryClient = shared.getQueryClient(config);
|
|
116
|
-
const trpcProp = {
|
|
117
|
-
config,
|
|
118
|
-
trpcClient,
|
|
119
|
-
queryClient,
|
|
120
|
-
ssrState: 'prepass',
|
|
121
|
-
ssrContext: ctx
|
|
122
|
-
};
|
|
123
|
-
const prepassProps = {
|
|
124
|
-
pageProps,
|
|
125
|
-
trpc: trpcProp
|
|
126
|
-
};
|
|
127
|
-
const reactDomServer = /** __@PURE__ */ await import('react-dom/server');
|
|
128
|
-
// Run the prepass step on AppTree. This will run all trpc queries on the server.
|
|
129
|
-
// multiple prepass ensures that we can do batching on the server
|
|
130
|
-
while(true){
|
|
131
|
-
// render full tree
|
|
132
|
-
reactDomServer.renderToString(/*#__PURE__*/ React.createElement(AppTree, prepassProps));
|
|
133
|
-
if (!queryClient.isFetching()) {
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
// wait until the query cache has settled it's promises
|
|
137
|
-
await new Promise((resolve)=>{
|
|
138
|
-
const unsub = queryClient.getQueryCache().subscribe((event)=>{
|
|
139
|
-
if (event?.query.getObserversCount() === 0) {
|
|
140
|
-
resolve();
|
|
141
|
-
unsub();
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
const dehydratedCache = reactQuery.dehydrate(queryClient, {
|
|
147
|
-
shouldDehydrateQuery (query) {
|
|
148
|
-
// filter out queries that are marked as trpc: { ssr: false } or are not enabled, but make sure errors are dehydrated
|
|
149
|
-
const isExcludedFromSSr = query.state.fetchStatus === 'idle' && query.state.status === 'pending';
|
|
150
|
-
return !isExcludedFromSSr;
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
// since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects
|
|
154
|
-
const dehydratedCacheWithErrors = {
|
|
155
|
-
...dehydratedCache,
|
|
156
|
-
queries: dehydratedCache.queries.map(transformQueryOrMutationCacheErrors),
|
|
157
|
-
mutations: dehydratedCache.mutations.map(transformQueryOrMutationCacheErrors)
|
|
158
|
-
};
|
|
159
|
-
// dehydrate query client's state and add it to the props
|
|
160
|
-
pageProps['trpcState'] = transformer.input.serialize(dehydratedCacheWithErrors);
|
|
161
|
-
const appTreeProps = getAppTreeProps(pageProps);
|
|
162
|
-
if ('responseMeta' in opts) {
|
|
163
|
-
const meta = opts.responseMeta?.({
|
|
164
|
-
ctx,
|
|
165
|
-
clientErrors: [
|
|
166
|
-
...dehydratedCache.queries,
|
|
167
|
-
...dehydratedCache.mutations
|
|
168
|
-
].map((v)=>v.state.error).flatMap((err)=>err instanceof Error && err.name === 'TRPCClientError' ? [
|
|
169
|
-
err
|
|
170
|
-
] : [])
|
|
171
|
-
}) ?? {};
|
|
172
|
-
for (const [key, value] of Object.entries(meta.headers ?? {})){
|
|
173
|
-
if (typeof value === 'string') {
|
|
174
|
-
ctx.res?.setHeader(key, value);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (meta.status && ctx.res) {
|
|
178
|
-
ctx.res.statusCode = meta.status;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return appTreeProps;
|
|
182
|
-
};
|
|
54
|
+
if (opts.ssr) {
|
|
55
|
+
opts.ssrPrepass({
|
|
56
|
+
parent: opts,
|
|
57
|
+
AppOrPage,
|
|
58
|
+
WithTRPC
|
|
59
|
+
});
|
|
183
60
|
}
|
|
184
61
|
const displayName = AppOrPage.displayName ?? AppOrPage.name ?? 'Component';
|
|
185
62
|
WithTRPC.displayName = `withTRPC(${displayName})`;
|
package/dist/withTRPC.mjs
CHANGED
|
@@ -1,33 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createTRPCUntypedClient } from '@trpc/client';
|
|
1
|
+
import { QueryClientProvider, HydrationBoundary } from '@tanstack/react-query';
|
|
3
2
|
import { getTransformer } from '@trpc/client/unstable-internals';
|
|
4
3
|
import { createRootHooks, getQueryClient } from '@trpc/react-query/shared';
|
|
5
|
-
import React, {
|
|
4
|
+
import React, { useState } from 'react';
|
|
6
5
|
|
|
7
|
-
function transformQueryOrMutationCacheErrors(result) {
|
|
8
|
-
const error = result.state.error;
|
|
9
|
-
if (error instanceof Error && error.name === 'TRPCClientError') {
|
|
10
|
-
const newError = {
|
|
11
|
-
message: error.message,
|
|
12
|
-
data: error.data,
|
|
13
|
-
shape: error.shape
|
|
14
|
-
};
|
|
15
|
-
return {
|
|
16
|
-
...result,
|
|
17
|
-
state: {
|
|
18
|
-
...result.state,
|
|
19
|
-
error: newError
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
return result;
|
|
24
|
-
}
|
|
25
6
|
function withTRPC(opts) {
|
|
26
7
|
const { config: getClientConfig } = opts;
|
|
27
8
|
const transformer = getTransformer(opts.transformer);
|
|
28
9
|
return (AppOrPage)=>{
|
|
29
10
|
const trpc = createRootHooks(opts);
|
|
30
|
-
const WithTRPC =
|
|
11
|
+
const WithTRPC = (props)=>{
|
|
31
12
|
const [prepassProps] = useState(()=>{
|
|
32
13
|
if (props.trpc) {
|
|
33
14
|
return props.trpc;
|
|
@@ -68,116 +49,12 @@ function withTRPC(opts) {
|
|
|
68
49
|
state: hydratedState
|
|
69
50
|
}, /*#__PURE__*/ React.createElement(AppOrPage, Object.assign({}, props)))));
|
|
70
51
|
};
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
try {
|
|
79
|
-
return await opts.ssr({
|
|
80
|
-
ctx: appOrPageCtx.ctx
|
|
81
|
-
});
|
|
82
|
-
} catch (e) {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return opts.ssr;
|
|
87
|
-
};
|
|
88
|
-
const ssr = await shouldSsr();
|
|
89
|
-
const AppTree = appOrPageCtx.AppTree;
|
|
90
|
-
// Determine if we are wrapping an App component or a Page component.
|
|
91
|
-
const isApp = !!appOrPageCtx.Component;
|
|
92
|
-
const ctx = isApp ? appOrPageCtx.ctx : appOrPageCtx;
|
|
93
|
-
// Run the wrapped component's getInitialProps function.
|
|
94
|
-
let pageProps = {};
|
|
95
|
-
if (AppOrPage.getInitialProps) {
|
|
96
|
-
const originalProps = await AppOrPage.getInitialProps(appOrPageCtx);
|
|
97
|
-
const originalPageProps = isApp ? originalProps.pageProps ?? {} : originalProps;
|
|
98
|
-
pageProps = {
|
|
99
|
-
...originalPageProps,
|
|
100
|
-
...pageProps
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
const getAppTreeProps = (props)=>isApp ? {
|
|
104
|
-
pageProps: props
|
|
105
|
-
} : props;
|
|
106
|
-
if (typeof window !== 'undefined' || !ssr) {
|
|
107
|
-
return getAppTreeProps(pageProps);
|
|
108
|
-
}
|
|
109
|
-
const config = getClientConfig({
|
|
110
|
-
ctx
|
|
111
|
-
});
|
|
112
|
-
const trpcClient = createTRPCUntypedClient(config);
|
|
113
|
-
const queryClient = getQueryClient(config);
|
|
114
|
-
const trpcProp = {
|
|
115
|
-
config,
|
|
116
|
-
trpcClient,
|
|
117
|
-
queryClient,
|
|
118
|
-
ssrState: 'prepass',
|
|
119
|
-
ssrContext: ctx
|
|
120
|
-
};
|
|
121
|
-
const prepassProps = {
|
|
122
|
-
pageProps,
|
|
123
|
-
trpc: trpcProp
|
|
124
|
-
};
|
|
125
|
-
const reactDomServer = /** __@PURE__ */ await import('react-dom/server');
|
|
126
|
-
// Run the prepass step on AppTree. This will run all trpc queries on the server.
|
|
127
|
-
// multiple prepass ensures that we can do batching on the server
|
|
128
|
-
while(true){
|
|
129
|
-
// render full tree
|
|
130
|
-
reactDomServer.renderToString(/*#__PURE__*/ createElement(AppTree, prepassProps));
|
|
131
|
-
if (!queryClient.isFetching()) {
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
// wait until the query cache has settled it's promises
|
|
135
|
-
await new Promise((resolve)=>{
|
|
136
|
-
const unsub = queryClient.getQueryCache().subscribe((event)=>{
|
|
137
|
-
if (event?.query.getObserversCount() === 0) {
|
|
138
|
-
resolve();
|
|
139
|
-
unsub();
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
const dehydratedCache = dehydrate(queryClient, {
|
|
145
|
-
shouldDehydrateQuery (query) {
|
|
146
|
-
// filter out queries that are marked as trpc: { ssr: false } or are not enabled, but make sure errors are dehydrated
|
|
147
|
-
const isExcludedFromSSr = query.state.fetchStatus === 'idle' && query.state.status === 'pending';
|
|
148
|
-
return !isExcludedFromSSr;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
// since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects
|
|
152
|
-
const dehydratedCacheWithErrors = {
|
|
153
|
-
...dehydratedCache,
|
|
154
|
-
queries: dehydratedCache.queries.map(transformQueryOrMutationCacheErrors),
|
|
155
|
-
mutations: dehydratedCache.mutations.map(transformQueryOrMutationCacheErrors)
|
|
156
|
-
};
|
|
157
|
-
// dehydrate query client's state and add it to the props
|
|
158
|
-
pageProps['trpcState'] = transformer.input.serialize(dehydratedCacheWithErrors);
|
|
159
|
-
const appTreeProps = getAppTreeProps(pageProps);
|
|
160
|
-
if ('responseMeta' in opts) {
|
|
161
|
-
const meta = opts.responseMeta?.({
|
|
162
|
-
ctx,
|
|
163
|
-
clientErrors: [
|
|
164
|
-
...dehydratedCache.queries,
|
|
165
|
-
...dehydratedCache.mutations
|
|
166
|
-
].map((v)=>v.state.error).flatMap((err)=>err instanceof Error && err.name === 'TRPCClientError' ? [
|
|
167
|
-
err
|
|
168
|
-
] : [])
|
|
169
|
-
}) ?? {};
|
|
170
|
-
for (const [key, value] of Object.entries(meta.headers ?? {})){
|
|
171
|
-
if (typeof value === 'string') {
|
|
172
|
-
ctx.res?.setHeader(key, value);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
if (meta.status && ctx.res) {
|
|
176
|
-
ctx.res.statusCode = meta.status;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return appTreeProps;
|
|
180
|
-
};
|
|
52
|
+
if (opts.ssr) {
|
|
53
|
+
opts.ssrPrepass({
|
|
54
|
+
parent: opts,
|
|
55
|
+
AppOrPage,
|
|
56
|
+
WithTRPC
|
|
57
|
+
});
|
|
181
58
|
}
|
|
182
59
|
const displayName = AppOrPage.displayName ?? AppOrPage.name ?? 'Component';
|
|
183
60
|
WithTRPC.displayName = `withTRPC(${displayName})`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trpc/next",
|
|
3
|
-
"version": "11.0.0-alpha-tmp-
|
|
3
|
+
"version": "11.0.0-alpha-tmp-02-08-tmp.274+fc6e807b1",
|
|
4
4
|
"description": "The tRPC Next.js library",
|
|
5
5
|
"author": "KATT",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,6 +55,11 @@
|
|
|
55
55
|
"import": "./dist/app-dir/server.mjs",
|
|
56
56
|
"require": "./dist/app-dir/server.js",
|
|
57
57
|
"default": "./dist/app-dir/server.js"
|
|
58
|
+
},
|
|
59
|
+
"./ssrPrepass": {
|
|
60
|
+
"import": "./dist/ssrPrepass.mjs",
|
|
61
|
+
"require": "./dist/ssrPrepass.js",
|
|
62
|
+
"default": "./dist/ssrPrepass.js"
|
|
58
63
|
}
|
|
59
64
|
},
|
|
60
65
|
"files": [
|
|
@@ -63,13 +68,14 @@
|
|
|
63
68
|
"README.md",
|
|
64
69
|
"package.json",
|
|
65
70
|
"app-dir",
|
|
71
|
+
"ssrPrepass",
|
|
66
72
|
"!**/*.test.*"
|
|
67
73
|
],
|
|
68
74
|
"peerDependencies": {
|
|
69
75
|
"@tanstack/react-query": "^5.0.0",
|
|
70
|
-
"@trpc/client": "11.0.0-alpha-tmp-
|
|
71
|
-
"@trpc/react-query": "11.0.0-alpha-tmp-
|
|
72
|
-
"@trpc/server": "11.0.0-alpha-tmp-
|
|
76
|
+
"@trpc/client": "11.0.0-alpha-tmp-02-08-tmp.274+fc6e807b1",
|
|
77
|
+
"@trpc/react-query": "11.0.0-alpha-tmp-02-08-tmp.274+fc6e807b1",
|
|
78
|
+
"@trpc/server": "11.0.0-alpha-tmp-02-08-tmp.274+fc6e807b1",
|
|
73
79
|
"next": "*",
|
|
74
80
|
"react": ">=16.8.0",
|
|
75
81
|
"react-dom": ">=16.8.0"
|
|
@@ -84,9 +90,9 @@
|
|
|
84
90
|
},
|
|
85
91
|
"devDependencies": {
|
|
86
92
|
"@tanstack/react-query": "^5.0.0",
|
|
87
|
-
"@trpc/client": "11.0.0-alpha-tmp-
|
|
88
|
-
"@trpc/react-query": "11.0.0-alpha-tmp-
|
|
89
|
-
"@trpc/server": "11.0.0-alpha-tmp-
|
|
93
|
+
"@trpc/client": "11.0.0-alpha-tmp-02-08-tmp.274+fc6e807b1",
|
|
94
|
+
"@trpc/react-query": "11.0.0-alpha-tmp-02-08-tmp.274+fc6e807b1",
|
|
95
|
+
"@trpc/server": "11.0.0-alpha-tmp-02-08-tmp.274+fc6e807b1",
|
|
90
96
|
"@types/express": "^4.17.17",
|
|
91
97
|
"@types/node": "^20.10.0",
|
|
92
98
|
"@types/react": "^18.2.33",
|
|
@@ -106,5 +112,5 @@
|
|
|
106
112
|
"funding": [
|
|
107
113
|
"https://trpc.io/sponsor"
|
|
108
114
|
],
|
|
109
|
-
"gitHead": "
|
|
115
|
+
"gitHead": "fc6e807b19d0b6fc726daa0a58ff5fcefcbef3d2"
|
|
110
116
|
}
|
|
@@ -11,8 +11,8 @@ import type {
|
|
|
11
11
|
import { getTransformer } from '@trpc/client/unstable-internals';
|
|
12
12
|
import { observable } from '@trpc/server/observable';
|
|
13
13
|
import type {
|
|
14
|
+
inferClientTypes,
|
|
14
15
|
InferrableClientTypes,
|
|
15
|
-
inferRootTypes,
|
|
16
16
|
MaybePromise,
|
|
17
17
|
ProcedureOptions,
|
|
18
18
|
Simplify,
|
|
@@ -80,7 +80,7 @@ export function experimental_serverActionLink<
|
|
|
80
80
|
? [
|
|
81
81
|
TypeError<'Generic parameter missing in `experimental_createActionHook<HERE>()` or experimental_serverActionLink<HERE>()'>,
|
|
82
82
|
]
|
|
83
|
-
:
|
|
83
|
+
: inferClientTypes<TInferrable>['transformer'] extends true
|
|
84
84
|
? [
|
|
85
85
|
opts: TransformerOptions<{
|
|
86
86
|
transformer: true;
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { observable } from '@trpc/server/observable';
|
|
10
10
|
import type {
|
|
11
11
|
AnyRouter,
|
|
12
|
-
|
|
12
|
+
inferClientTypes,
|
|
13
13
|
inferRouterContext,
|
|
14
14
|
} from '@trpc/server/unstable-core-do-not-import';
|
|
15
15
|
import { callProcedure } from '@trpc/server/unstable-core-do-not-import';
|
|
@@ -21,7 +21,7 @@ type NextCacheLinkOptions<TRouter extends AnyRouter> = {
|
|
|
21
21
|
createContext: () => Promise<inferRouterContext<TRouter>>;
|
|
22
22
|
/** how many seconds the cache should hold before revalidating */
|
|
23
23
|
revalidate?: number | false;
|
|
24
|
-
} & TransformerOptions<
|
|
24
|
+
} & TransformerOptions<inferClientTypes<TRouter>>;
|
|
25
25
|
|
|
26
26
|
// ts-prune-ignore-next
|
|
27
27
|
export function experimental_nextCacheLink<TRouter extends AnyRouter>(
|
package/src/app-dir/server.ts
CHANGED
|
@@ -7,8 +7,8 @@ import type {
|
|
|
7
7
|
AnyProcedure,
|
|
8
8
|
AnyRootTypes,
|
|
9
9
|
AnyRouter,
|
|
10
|
+
inferClientTypes,
|
|
10
11
|
inferProcedureInput,
|
|
11
|
-
inferRootTypes,
|
|
12
12
|
MaybePromise,
|
|
13
13
|
RootConfig,
|
|
14
14
|
Simplify,
|
|
@@ -95,7 +95,7 @@ export function experimental_createServerActionHandler<
|
|
|
95
95
|
return function createServerAction<TProc extends AnyProcedure>(
|
|
96
96
|
proc: TProc,
|
|
97
97
|
): TRPCActionHandler<
|
|
98
|
-
Simplify<inferActionDef<
|
|
98
|
+
Simplify<inferActionDef<inferClientTypes<TInstance>, TProc>>
|
|
99
99
|
> {
|
|
100
100
|
return async function actionHandler(
|
|
101
101
|
rawInput: FormData | inferProcedureInput<TProc>,
|
package/src/app-dir/shared.ts
CHANGED
|
@@ -4,12 +4,13 @@ import type {
|
|
|
4
4
|
TRPCUntypedClient,
|
|
5
5
|
} from '@trpc/client';
|
|
6
6
|
import type {
|
|
7
|
-
|
|
7
|
+
AnyClientTypes,
|
|
8
8
|
AnyProcedure,
|
|
9
9
|
AnyQueryProcedure,
|
|
10
10
|
AnyRootTypes,
|
|
11
11
|
AnyRouter,
|
|
12
12
|
inferProcedureInput,
|
|
13
|
+
inferTransformedProcedureOutput,
|
|
13
14
|
ProtectedIntersection,
|
|
14
15
|
RouterRecord,
|
|
15
16
|
} from '@trpc/server/unstable-core-do-not-import';
|
|
@@ -26,7 +27,12 @@ export type UseProcedureRecord<
|
|
|
26
27
|
? $Value extends RouterRecord
|
|
27
28
|
? UseProcedureRecord<TRoot, $Value>
|
|
28
29
|
: $Value extends AnyQueryProcedure
|
|
29
|
-
? Resolver<
|
|
30
|
+
? Resolver<{
|
|
31
|
+
input: inferProcedureInput<$Value>;
|
|
32
|
+
output: inferTransformedProcedureOutput<TRoot, $Value>;
|
|
33
|
+
errorShape: TRoot['errorShape'];
|
|
34
|
+
transformer: TRoot['transformer'];
|
|
35
|
+
}>
|
|
30
36
|
: never
|
|
31
37
|
: never;
|
|
32
38
|
};
|
|
@@ -114,7 +120,7 @@ export interface ActionHandlerDef {
|
|
|
114
120
|
* @internal
|
|
115
121
|
*/
|
|
116
122
|
export type inferActionDef<
|
|
117
|
-
TRoot extends
|
|
123
|
+
TRoot extends AnyClientTypes,
|
|
118
124
|
TProc extends AnyProcedure,
|
|
119
125
|
> = {
|
|
120
126
|
input: inferProcedureInput<TProc>;
|
package/src/app-dir/types.ts
CHANGED
|
@@ -1,33 +1,39 @@
|
|
|
1
1
|
import type { Resolver } from '@trpc/client';
|
|
2
2
|
import type {
|
|
3
|
-
AnyMutationProcedure,
|
|
4
3
|
AnyProcedure,
|
|
5
|
-
AnyQueryProcedure,
|
|
6
4
|
AnyRootTypes,
|
|
7
|
-
AnySubscriptionProcedure,
|
|
8
5
|
inferProcedureInput,
|
|
6
|
+
inferTransformedProcedureOutput,
|
|
7
|
+
ProcedureType,
|
|
9
8
|
RouterRecord,
|
|
10
9
|
} from '@trpc/server/unstable-core-do-not-import';
|
|
11
10
|
|
|
11
|
+
type ResolverDef = {
|
|
12
|
+
input: any;
|
|
13
|
+
output: any;
|
|
14
|
+
transformer: boolean;
|
|
15
|
+
errorShape: any;
|
|
16
|
+
};
|
|
17
|
+
|
|
12
18
|
export type DecorateProcedureServer<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
> =
|
|
19
|
+
TType extends ProcedureType,
|
|
20
|
+
TDef extends ResolverDef,
|
|
21
|
+
> = TType extends 'query'
|
|
16
22
|
? {
|
|
17
|
-
query: Resolver<
|
|
23
|
+
query: Resolver<TDef>;
|
|
18
24
|
revalidate: (
|
|
19
|
-
input?:
|
|
25
|
+
input?: TDef['input'],
|
|
20
26
|
) => Promise<
|
|
21
27
|
{ revalidated: false; error: string } | { revalidated: true }
|
|
22
28
|
>;
|
|
23
29
|
}
|
|
24
|
-
:
|
|
30
|
+
: TType extends 'mutation'
|
|
25
31
|
? {
|
|
26
|
-
mutate: Resolver<
|
|
32
|
+
mutate: Resolver<TDef>;
|
|
27
33
|
}
|
|
28
|
-
:
|
|
34
|
+
: TType extends 'subscription'
|
|
29
35
|
? {
|
|
30
|
-
subscribe: Resolver<
|
|
36
|
+
subscribe: Resolver<TDef>;
|
|
31
37
|
}
|
|
32
38
|
: never;
|
|
33
39
|
|
|
@@ -39,7 +45,15 @@ export type NextAppDirDecorateRouterRecord<
|
|
|
39
45
|
? $Value extends RouterRecord
|
|
40
46
|
? NextAppDirDecorateRouterRecord<TRoot, $Value>
|
|
41
47
|
: $Value extends AnyProcedure
|
|
42
|
-
? DecorateProcedureServer<
|
|
48
|
+
? DecorateProcedureServer<
|
|
49
|
+
$Value['_def']['type'],
|
|
50
|
+
{
|
|
51
|
+
input: inferProcedureInput<$Value>;
|
|
52
|
+
output: inferTransformedProcedureOutput<TRoot, $Value>;
|
|
53
|
+
errorShape: TRoot['errorShape'];
|
|
54
|
+
transformer: TRoot['transformer'];
|
|
55
|
+
}
|
|
56
|
+
>
|
|
43
57
|
: never
|
|
44
58
|
: never;
|
|
45
59
|
};
|
package/src/createTRPCNext.tsx
CHANGED
|
@@ -49,23 +49,20 @@ export interface CreateTRPCNextBase<
|
|
|
49
49
|
export type CreateTRPCNext<
|
|
50
50
|
TRouter extends AnyRouter,
|
|
51
51
|
TSSRContext extends NextPageContext,
|
|
52
|
-
TFlags,
|
|
53
52
|
> = ProtectedIntersection<
|
|
54
53
|
CreateTRPCNextBase<TRouter, TSSRContext>,
|
|
55
54
|
DecorateRouterRecord<
|
|
56
55
|
TRouter['_def']['_config']['$types'],
|
|
57
|
-
TRouter['_def']['record']
|
|
58
|
-
TFlags
|
|
56
|
+
TRouter['_def']['record']
|
|
59
57
|
>
|
|
60
58
|
>;
|
|
61
59
|
|
|
62
60
|
export function createTRPCNext<
|
|
63
61
|
TRouter extends AnyRouter,
|
|
64
62
|
TSSRContext extends NextPageContext = NextPageContext,
|
|
65
|
-
TFlags = null,
|
|
66
63
|
>(
|
|
67
64
|
opts: WithTRPCNoSSROptions<TRouter> | WithTRPCSSROptions<TRouter>,
|
|
68
|
-
): CreateTRPCNext<TRouter, TSSRContext
|
|
65
|
+
): CreateTRPCNext<TRouter, TSSRContext> {
|
|
69
66
|
const hooks = createRootHooks<TRouter, TSSRContext>(opts);
|
|
70
67
|
|
|
71
68
|
// TODO: maybe set TSSRContext to `never` when using `WithTRPCNoSSROptions`
|