@trpc/next 11.0.0-alpha-tmp-export-from-main.213 → 11.0.0-alpha-tmp-export-from-main.217
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/dist/app-dir/client.js +3 -101
- package/dist/app-dir/client.mjs +4 -100
- package/dist/app-dir/create-action-hook.js +104 -0
- package/dist/app-dir/create-action-hook.mjs +101 -0
- package/dist/app-dir/formDataToObject.js +34 -0
- package/dist/app-dir/formDataToObject.mjs +32 -0
- package/dist/app-dir/links/nextCache.js +1 -3
- package/dist/app-dir/links/nextCache.mjs +1 -1
- package/dist/app-dir/links/nextHttp.js +1 -4
- package/dist/app-dir/links/nextHttp.mjs +1 -2
- package/dist/app-dir/server.js +3 -35
- package/dist/app-dir/server.mjs +2 -32
- package/dist/{shared-2f1ecbeb.mjs → app-dir/shared.mjs} +1 -1
- package/dist/createTRPCNext.js +38 -0
- package/dist/createTRPCNext.mjs +36 -0
- package/dist/index.js +4 -229
- package/dist/index.mjs +2 -207
- package/dist/withTRPC.js +178 -0
- package/dist/withTRPC.mjs +176 -0
- package/package.json +8 -8
- package/dist/shared-62d181e7.js +0 -19
- /package/dist/{shared-a452b80f.js → app-dir/shared.js} +0 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createFlatProxy } from '@trpc/core';
|
|
2
|
+
import { createRootHooks, createReactQueryUtils, createReactDecoration } from '@trpc/react-query/shared';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { withTRPC } from './withTRPC.mjs';
|
|
5
|
+
|
|
6
|
+
/* istanbul ignore file -- @preserve */ // We're testing this through E2E-testing
|
|
7
|
+
function createTRPCNext(opts) {
|
|
8
|
+
const hooks = createRootHooks(opts);
|
|
9
|
+
// TODO: maybe set TSSRContext to `never` when using `WithTRPCNoSSROptions`
|
|
10
|
+
const _withTRPC = withTRPC(opts);
|
|
11
|
+
return createFlatProxy((key)=>{
|
|
12
|
+
if (key === 'useContext' || key === 'useUtils') {
|
|
13
|
+
return ()=>{
|
|
14
|
+
const context = hooks.useUtils();
|
|
15
|
+
// create a stable reference of the utils context
|
|
16
|
+
return useMemo(()=>{
|
|
17
|
+
return createReactQueryUtils(context);
|
|
18
|
+
}, [
|
|
19
|
+
context
|
|
20
|
+
]);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (key === 'useQueries') {
|
|
24
|
+
return hooks.useQueries;
|
|
25
|
+
}
|
|
26
|
+
if (key === 'useSuspenseQueries') {
|
|
27
|
+
return hooks.useSuspenseQueries;
|
|
28
|
+
}
|
|
29
|
+
if (key === 'withTRPC') {
|
|
30
|
+
return _withTRPC;
|
|
31
|
+
}
|
|
32
|
+
return createReactDecoration(key, hooks);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { createTRPCNext };
|
package/dist/index.js
CHANGED
|
@@ -1,234 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
var withTRPC = require('./withTRPC.js');
|
|
4
|
+
var createTRPCNext = require('./createTRPCNext.js');
|
|
4
5
|
|
|
5
|
-
var reactQuery = require('@tanstack/react-query');
|
|
6
|
-
var client = require('@trpc/client');
|
|
7
|
-
var shared = require('@trpc/react-query/shared');
|
|
8
|
-
var React = require('react');
|
|
9
|
-
var core = require('@trpc/core');
|
|
10
6
|
|
|
11
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
12
7
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
var n = Object.create(null);
|
|
16
|
-
if (e) {
|
|
17
|
-
Object.keys(e).forEach(function (k) {
|
|
18
|
-
if (k !== 'default') {
|
|
19
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
20
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
21
|
-
enumerable: true,
|
|
22
|
-
get: function () { return e[k]; }
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
n["default"] = e;
|
|
28
|
-
return Object.freeze(n);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
32
|
-
|
|
33
|
-
function transformQueryOrMutationCacheErrors(result) {
|
|
34
|
-
const error = result.state.error;
|
|
35
|
-
if (error instanceof Error && error.name === 'TRPCClientError') {
|
|
36
|
-
const newError = {
|
|
37
|
-
message: error.message,
|
|
38
|
-
data: error.data,
|
|
39
|
-
shape: error.shape
|
|
40
|
-
};
|
|
41
|
-
return {
|
|
42
|
-
...result,
|
|
43
|
-
state: {
|
|
44
|
-
...result.state,
|
|
45
|
-
error: newError
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
51
|
-
function withTRPC(opts) {
|
|
52
|
-
const { config: getClientConfig } = opts;
|
|
53
|
-
return (AppOrPage)=>{
|
|
54
|
-
const trpc = shared.createRootHooks(opts);
|
|
55
|
-
const WithTRPC = (props)=>{
|
|
56
|
-
const [prepassProps] = React.useState(()=>{
|
|
57
|
-
if (props.trpc) {
|
|
58
|
-
return props.trpc;
|
|
59
|
-
}
|
|
60
|
-
const config = getClientConfig({});
|
|
61
|
-
const queryClient = shared.getQueryClient(config);
|
|
62
|
-
const trpcClient = trpc.createClient(config);
|
|
63
|
-
return {
|
|
64
|
-
abortOnUnmount: config.abortOnUnmount,
|
|
65
|
-
queryClient,
|
|
66
|
-
trpcClient,
|
|
67
|
-
ssrState: opts.ssr ? 'mounting' : false,
|
|
68
|
-
ssrContext: null
|
|
69
|
-
};
|
|
70
|
-
});
|
|
71
|
-
const { queryClient , trpcClient , ssrState , ssrContext } = prepassProps;
|
|
72
|
-
// allow normal components to be wrapped, not just app/pages
|
|
73
|
-
const hydratedState = trpc.useDehydratedState(trpcClient, props.pageProps?.trpcState);
|
|
74
|
-
return /*#__PURE__*/ React__default["default"].createElement(trpc.Provider, {
|
|
75
|
-
abortOnUnmount: prepassProps.abortOnUnmount ?? false,
|
|
76
|
-
client: trpcClient,
|
|
77
|
-
queryClient: queryClient,
|
|
78
|
-
ssrState: ssrState,
|
|
79
|
-
ssrContext: ssrContext
|
|
80
|
-
}, /*#__PURE__*/ React__default["default"].createElement(reactQuery.QueryClientProvider, {
|
|
81
|
-
client: queryClient
|
|
82
|
-
}, /*#__PURE__*/ React__default["default"].createElement(reactQuery.HydrationBoundary, {
|
|
83
|
-
state: hydratedState
|
|
84
|
-
}, /*#__PURE__*/ React__default["default"].createElement(AppOrPage, Object.assign({}, props)))));
|
|
85
|
-
};
|
|
86
|
-
if (AppOrPage.getInitialProps ?? opts.ssr) {
|
|
87
|
-
WithTRPC.getInitialProps = async (appOrPageCtx)=>{
|
|
88
|
-
const shouldSsr = async ()=>{
|
|
89
|
-
if (typeof opts.ssr === 'function') {
|
|
90
|
-
if (typeof window !== 'undefined') {
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
try {
|
|
94
|
-
return await opts.ssr({
|
|
95
|
-
ctx: appOrPageCtx.ctx
|
|
96
|
-
});
|
|
97
|
-
} catch (e) {
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return opts.ssr;
|
|
102
|
-
};
|
|
103
|
-
const ssr = await shouldSsr();
|
|
104
|
-
const AppTree = appOrPageCtx.AppTree;
|
|
105
|
-
// Determine if we are wrapping an App component or a Page component.
|
|
106
|
-
const isApp = !!appOrPageCtx.Component;
|
|
107
|
-
const ctx = isApp ? appOrPageCtx.ctx : appOrPageCtx;
|
|
108
|
-
// Run the wrapped component's getInitialProps function.
|
|
109
|
-
let pageProps = {};
|
|
110
|
-
if (AppOrPage.getInitialProps) {
|
|
111
|
-
const originalProps = await AppOrPage.getInitialProps(appOrPageCtx);
|
|
112
|
-
const originalPageProps = isApp ? originalProps.pageProps ?? {} : originalProps;
|
|
113
|
-
pageProps = {
|
|
114
|
-
...originalPageProps,
|
|
115
|
-
...pageProps
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
const getAppTreeProps = (props)=>isApp ? {
|
|
119
|
-
pageProps: props
|
|
120
|
-
} : props;
|
|
121
|
-
if (typeof window !== 'undefined' || !ssr) {
|
|
122
|
-
return getAppTreeProps(pageProps);
|
|
123
|
-
}
|
|
124
|
-
const config = getClientConfig({
|
|
125
|
-
ctx
|
|
126
|
-
});
|
|
127
|
-
const trpcClient = client.createTRPCUntypedClient(config);
|
|
128
|
-
const queryClient = shared.getQueryClient(config);
|
|
129
|
-
const trpcProp = {
|
|
130
|
-
config,
|
|
131
|
-
trpcClient,
|
|
132
|
-
queryClient,
|
|
133
|
-
ssrState: 'prepass',
|
|
134
|
-
ssrContext: ctx
|
|
135
|
-
};
|
|
136
|
-
const prepassProps = {
|
|
137
|
-
pageProps,
|
|
138
|
-
trpc: trpcProp
|
|
139
|
-
};
|
|
140
|
-
const reactDomServer = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('react-dom/server')); });
|
|
141
|
-
// Run the prepass step on AppTree. This will run all trpc queries on the server.
|
|
142
|
-
// multiple prepass ensures that we can do batching on the server
|
|
143
|
-
while(true){
|
|
144
|
-
// render full tree
|
|
145
|
-
reactDomServer.renderToString(/*#__PURE__*/ React.createElement(AppTree, prepassProps));
|
|
146
|
-
if (!queryClient.isFetching()) {
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
// wait until the query cache has settled it's promises
|
|
150
|
-
await new Promise((resolve)=>{
|
|
151
|
-
const unsub = queryClient.getQueryCache().subscribe((event)=>{
|
|
152
|
-
if (event?.query.getObserversCount() === 0) {
|
|
153
|
-
resolve();
|
|
154
|
-
unsub();
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
const dehydratedCache = reactQuery.dehydrate(queryClient, {
|
|
160
|
-
shouldDehydrateQuery (query) {
|
|
161
|
-
// filter out queries that are marked as trpc: { ssr: false } or are not enabled, but make sure errors are dehydrated
|
|
162
|
-
const isExcludedFromSSr = query.state.fetchStatus === 'idle' && query.state.status === 'pending';
|
|
163
|
-
return !isExcludedFromSSr;
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
// since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects
|
|
167
|
-
const dehydratedCacheWithErrors = {
|
|
168
|
-
...dehydratedCache,
|
|
169
|
-
queries: dehydratedCache.queries.map(transformQueryOrMutationCacheErrors),
|
|
170
|
-
mutations: dehydratedCache.mutations.map(transformQueryOrMutationCacheErrors)
|
|
171
|
-
};
|
|
172
|
-
// dehydrate query client's state and add it to the props
|
|
173
|
-
pageProps['trpcState'] = trpcClient.runtime.combinedTransformer.output.serialize(dehydratedCacheWithErrors);
|
|
174
|
-
const appTreeProps = getAppTreeProps(pageProps);
|
|
175
|
-
if ('responseMeta' in opts) {
|
|
176
|
-
const meta = opts.responseMeta?.({
|
|
177
|
-
ctx,
|
|
178
|
-
clientErrors: [
|
|
179
|
-
...dehydratedCache.queries,
|
|
180
|
-
...dehydratedCache.mutations
|
|
181
|
-
].map((v)=>v.state.error).flatMap((err)=>err instanceof Error && err.name === 'TRPCClientError' ? [
|
|
182
|
-
err
|
|
183
|
-
] : [])
|
|
184
|
-
}) ?? {};
|
|
185
|
-
for (const [key, value] of Object.entries(meta.headers ?? {})){
|
|
186
|
-
if (typeof value === 'string') {
|
|
187
|
-
ctx.res?.setHeader(key, value);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
if (meta.status && ctx.res) {
|
|
191
|
-
ctx.res.statusCode = meta.status;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return appTreeProps;
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
const displayName = AppOrPage.displayName ?? AppOrPage.name ?? 'Component';
|
|
198
|
-
WithTRPC.displayName = `withTRPC(${displayName})`;
|
|
199
|
-
return WithTRPC;
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/* istanbul ignore file -- @preserve */ // We're testing this through E2E-testing
|
|
204
|
-
function createTRPCNext(opts) {
|
|
205
|
-
const hooks = shared.createRootHooks(opts);
|
|
206
|
-
// TODO: maybe set TSSRContext to `never` when using `WithTRPCNoSSROptions`
|
|
207
|
-
const _withTRPC = withTRPC(opts);
|
|
208
|
-
return core.createFlatProxy((key)=>{
|
|
209
|
-
if (key === 'useContext' || key === 'useUtils') {
|
|
210
|
-
return ()=>{
|
|
211
|
-
const context = hooks.useUtils();
|
|
212
|
-
// create a stable reference of the utils context
|
|
213
|
-
return React.useMemo(()=>{
|
|
214
|
-
return shared.createReactQueryUtils(context);
|
|
215
|
-
}, [
|
|
216
|
-
context
|
|
217
|
-
]);
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
if (key === 'useQueries') {
|
|
221
|
-
return hooks.useQueries;
|
|
222
|
-
}
|
|
223
|
-
if (key === 'useSuspenseQueries') {
|
|
224
|
-
return hooks.useSuspenseQueries;
|
|
225
|
-
}
|
|
226
|
-
if (key === 'withTRPC') {
|
|
227
|
-
return _withTRPC;
|
|
228
|
-
}
|
|
229
|
-
return shared.createReactDecoration(key, hooks);
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
exports.createTRPCNext = createTRPCNext;
|
|
234
|
-
exports.withTRPC = withTRPC;
|
|
8
|
+
exports.withTRPC = withTRPC.withTRPC;
|
|
9
|
+
exports.createTRPCNext = createTRPCNext.createTRPCNext;
|
package/dist/index.mjs
CHANGED
|
@@ -1,207 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { createRootHooks, getQueryClient, createReactQueryUtils, createReactDecoration } from '@trpc/react-query/shared';
|
|
4
|
-
import React, { createElement, useState, useMemo } from 'react';
|
|
5
|
-
import { createFlatProxy } from '@trpc/core';
|
|
6
|
-
|
|
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
|
-
function withTRPC(opts) {
|
|
26
|
-
const { config: getClientConfig } = opts;
|
|
27
|
-
return (AppOrPage)=>{
|
|
28
|
-
const trpc = createRootHooks(opts);
|
|
29
|
-
const WithTRPC = (props)=>{
|
|
30
|
-
const [prepassProps] = useState(()=>{
|
|
31
|
-
if (props.trpc) {
|
|
32
|
-
return props.trpc;
|
|
33
|
-
}
|
|
34
|
-
const config = getClientConfig({});
|
|
35
|
-
const queryClient = getQueryClient(config);
|
|
36
|
-
const trpcClient = trpc.createClient(config);
|
|
37
|
-
return {
|
|
38
|
-
abortOnUnmount: config.abortOnUnmount,
|
|
39
|
-
queryClient,
|
|
40
|
-
trpcClient,
|
|
41
|
-
ssrState: opts.ssr ? 'mounting' : false,
|
|
42
|
-
ssrContext: null
|
|
43
|
-
};
|
|
44
|
-
});
|
|
45
|
-
const { queryClient , trpcClient , ssrState , ssrContext } = prepassProps;
|
|
46
|
-
// allow normal components to be wrapped, not just app/pages
|
|
47
|
-
const hydratedState = trpc.useDehydratedState(trpcClient, props.pageProps?.trpcState);
|
|
48
|
-
return /*#__PURE__*/ React.createElement(trpc.Provider, {
|
|
49
|
-
abortOnUnmount: prepassProps.abortOnUnmount ?? false,
|
|
50
|
-
client: trpcClient,
|
|
51
|
-
queryClient: queryClient,
|
|
52
|
-
ssrState: ssrState,
|
|
53
|
-
ssrContext: ssrContext
|
|
54
|
-
}, /*#__PURE__*/ React.createElement(QueryClientProvider, {
|
|
55
|
-
client: queryClient
|
|
56
|
-
}, /*#__PURE__*/ React.createElement(HydrationBoundary, {
|
|
57
|
-
state: hydratedState
|
|
58
|
-
}, /*#__PURE__*/ React.createElement(AppOrPage, Object.assign({}, props)))));
|
|
59
|
-
};
|
|
60
|
-
if (AppOrPage.getInitialProps ?? opts.ssr) {
|
|
61
|
-
WithTRPC.getInitialProps = async (appOrPageCtx)=>{
|
|
62
|
-
const shouldSsr = async ()=>{
|
|
63
|
-
if (typeof opts.ssr === 'function') {
|
|
64
|
-
if (typeof window !== 'undefined') {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
try {
|
|
68
|
-
return await opts.ssr({
|
|
69
|
-
ctx: appOrPageCtx.ctx
|
|
70
|
-
});
|
|
71
|
-
} catch (e) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return opts.ssr;
|
|
76
|
-
};
|
|
77
|
-
const ssr = await shouldSsr();
|
|
78
|
-
const AppTree = appOrPageCtx.AppTree;
|
|
79
|
-
// Determine if we are wrapping an App component or a Page component.
|
|
80
|
-
const isApp = !!appOrPageCtx.Component;
|
|
81
|
-
const ctx = isApp ? appOrPageCtx.ctx : appOrPageCtx;
|
|
82
|
-
// Run the wrapped component's getInitialProps function.
|
|
83
|
-
let pageProps = {};
|
|
84
|
-
if (AppOrPage.getInitialProps) {
|
|
85
|
-
const originalProps = await AppOrPage.getInitialProps(appOrPageCtx);
|
|
86
|
-
const originalPageProps = isApp ? originalProps.pageProps ?? {} : originalProps;
|
|
87
|
-
pageProps = {
|
|
88
|
-
...originalPageProps,
|
|
89
|
-
...pageProps
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
const getAppTreeProps = (props)=>isApp ? {
|
|
93
|
-
pageProps: props
|
|
94
|
-
} : props;
|
|
95
|
-
if (typeof window !== 'undefined' || !ssr) {
|
|
96
|
-
return getAppTreeProps(pageProps);
|
|
97
|
-
}
|
|
98
|
-
const config = getClientConfig({
|
|
99
|
-
ctx
|
|
100
|
-
});
|
|
101
|
-
const trpcClient = createTRPCUntypedClient(config);
|
|
102
|
-
const queryClient = getQueryClient(config);
|
|
103
|
-
const trpcProp = {
|
|
104
|
-
config,
|
|
105
|
-
trpcClient,
|
|
106
|
-
queryClient,
|
|
107
|
-
ssrState: 'prepass',
|
|
108
|
-
ssrContext: ctx
|
|
109
|
-
};
|
|
110
|
-
const prepassProps = {
|
|
111
|
-
pageProps,
|
|
112
|
-
trpc: trpcProp
|
|
113
|
-
};
|
|
114
|
-
const reactDomServer = await import('react-dom/server');
|
|
115
|
-
// Run the prepass step on AppTree. This will run all trpc queries on the server.
|
|
116
|
-
// multiple prepass ensures that we can do batching on the server
|
|
117
|
-
while(true){
|
|
118
|
-
// render full tree
|
|
119
|
-
reactDomServer.renderToString(/*#__PURE__*/ createElement(AppTree, prepassProps));
|
|
120
|
-
if (!queryClient.isFetching()) {
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
// wait until the query cache has settled it's promises
|
|
124
|
-
await new Promise((resolve)=>{
|
|
125
|
-
const unsub = queryClient.getQueryCache().subscribe((event)=>{
|
|
126
|
-
if (event?.query.getObserversCount() === 0) {
|
|
127
|
-
resolve();
|
|
128
|
-
unsub();
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
const dehydratedCache = dehydrate(queryClient, {
|
|
134
|
-
shouldDehydrateQuery (query) {
|
|
135
|
-
// filter out queries that are marked as trpc: { ssr: false } or are not enabled, but make sure errors are dehydrated
|
|
136
|
-
const isExcludedFromSSr = query.state.fetchStatus === 'idle' && query.state.status === 'pending';
|
|
137
|
-
return !isExcludedFromSSr;
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
// since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects
|
|
141
|
-
const dehydratedCacheWithErrors = {
|
|
142
|
-
...dehydratedCache,
|
|
143
|
-
queries: dehydratedCache.queries.map(transformQueryOrMutationCacheErrors),
|
|
144
|
-
mutations: dehydratedCache.mutations.map(transformQueryOrMutationCacheErrors)
|
|
145
|
-
};
|
|
146
|
-
// dehydrate query client's state and add it to the props
|
|
147
|
-
pageProps['trpcState'] = trpcClient.runtime.combinedTransformer.output.serialize(dehydratedCacheWithErrors);
|
|
148
|
-
const appTreeProps = getAppTreeProps(pageProps);
|
|
149
|
-
if ('responseMeta' in opts) {
|
|
150
|
-
const meta = opts.responseMeta?.({
|
|
151
|
-
ctx,
|
|
152
|
-
clientErrors: [
|
|
153
|
-
...dehydratedCache.queries,
|
|
154
|
-
...dehydratedCache.mutations
|
|
155
|
-
].map((v)=>v.state.error).flatMap((err)=>err instanceof Error && err.name === 'TRPCClientError' ? [
|
|
156
|
-
err
|
|
157
|
-
] : [])
|
|
158
|
-
}) ?? {};
|
|
159
|
-
for (const [key, value] of Object.entries(meta.headers ?? {})){
|
|
160
|
-
if (typeof value === 'string') {
|
|
161
|
-
ctx.res?.setHeader(key, value);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
if (meta.status && ctx.res) {
|
|
165
|
-
ctx.res.statusCode = meta.status;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return appTreeProps;
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
const displayName = AppOrPage.displayName ?? AppOrPage.name ?? 'Component';
|
|
172
|
-
WithTRPC.displayName = `withTRPC(${displayName})`;
|
|
173
|
-
return WithTRPC;
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/* istanbul ignore file -- @preserve */ // We're testing this through E2E-testing
|
|
178
|
-
function createTRPCNext(opts) {
|
|
179
|
-
const hooks = createRootHooks(opts);
|
|
180
|
-
// TODO: maybe set TSSRContext to `never` when using `WithTRPCNoSSROptions`
|
|
181
|
-
const _withTRPC = withTRPC(opts);
|
|
182
|
-
return createFlatProxy((key)=>{
|
|
183
|
-
if (key === 'useContext' || key === 'useUtils') {
|
|
184
|
-
return ()=>{
|
|
185
|
-
const context = hooks.useUtils();
|
|
186
|
-
// create a stable reference of the utils context
|
|
187
|
-
return useMemo(()=>{
|
|
188
|
-
return createReactQueryUtils(context);
|
|
189
|
-
}, [
|
|
190
|
-
context
|
|
191
|
-
]);
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
if (key === 'useQueries') {
|
|
195
|
-
return hooks.useQueries;
|
|
196
|
-
}
|
|
197
|
-
if (key === 'useSuspenseQueries') {
|
|
198
|
-
return hooks.useSuspenseQueries;
|
|
199
|
-
}
|
|
200
|
-
if (key === 'withTRPC') {
|
|
201
|
-
return _withTRPC;
|
|
202
|
-
}
|
|
203
|
-
return createReactDecoration(key, hooks);
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export { createTRPCNext, withTRPC };
|
|
1
|
+
export { withTRPC } from './withTRPC.mjs';
|
|
2
|
+
export { createTRPCNext } from './createTRPCNext.mjs';
|
package/dist/withTRPC.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var reactQuery = require('@tanstack/react-query');
|
|
4
|
+
var client = require('@trpc/client');
|
|
5
|
+
var shared = require('@trpc/react-query/shared');
|
|
6
|
+
var React = require('react');
|
|
7
|
+
|
|
8
|
+
function transformQueryOrMutationCacheErrors(result) {
|
|
9
|
+
const error = result.state.error;
|
|
10
|
+
if (error instanceof Error && error.name === 'TRPCClientError') {
|
|
11
|
+
const newError = {
|
|
12
|
+
message: error.message,
|
|
13
|
+
data: error.data,
|
|
14
|
+
shape: error.shape
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
...result,
|
|
18
|
+
state: {
|
|
19
|
+
...result.state,
|
|
20
|
+
error: newError
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
function withTRPC(opts) {
|
|
27
|
+
const { config: getClientConfig } = opts;
|
|
28
|
+
return (AppOrPage)=>{
|
|
29
|
+
const trpc = shared.createRootHooks(opts);
|
|
30
|
+
const WithTRPC = (props)=>{
|
|
31
|
+
const [prepassProps] = React.useState(()=>{
|
|
32
|
+
if (props.trpc) {
|
|
33
|
+
return props.trpc;
|
|
34
|
+
}
|
|
35
|
+
const config = getClientConfig({});
|
|
36
|
+
const queryClient = shared.getQueryClient(config);
|
|
37
|
+
const trpcClient = trpc.createClient(config);
|
|
38
|
+
return {
|
|
39
|
+
abortOnUnmount: config.abortOnUnmount,
|
|
40
|
+
queryClient,
|
|
41
|
+
trpcClient,
|
|
42
|
+
ssrState: opts.ssr ? 'mounting' : false,
|
|
43
|
+
ssrContext: null
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
const { queryClient , trpcClient , ssrState , ssrContext } = prepassProps;
|
|
47
|
+
// allow normal components to be wrapped, not just app/pages
|
|
48
|
+
const hydratedState = trpc.useDehydratedState(trpcClient, props.pageProps?.trpcState);
|
|
49
|
+
return /*#__PURE__*/ React.createElement(trpc.Provider, {
|
|
50
|
+
abortOnUnmount: prepassProps.abortOnUnmount ?? false,
|
|
51
|
+
client: trpcClient,
|
|
52
|
+
queryClient: queryClient,
|
|
53
|
+
ssrState: ssrState,
|
|
54
|
+
ssrContext: ssrContext
|
|
55
|
+
}, /*#__PURE__*/ React.createElement(reactQuery.QueryClientProvider, {
|
|
56
|
+
client: queryClient
|
|
57
|
+
}, /*#__PURE__*/ React.createElement(reactQuery.HydrationBoundary, {
|
|
58
|
+
state: hydratedState
|
|
59
|
+
}, /*#__PURE__*/ React.createElement(AppOrPage, Object.assign({}, props)))));
|
|
60
|
+
};
|
|
61
|
+
if (AppOrPage.getInitialProps ?? opts.ssr) {
|
|
62
|
+
WithTRPC.getInitialProps = async (appOrPageCtx)=>{
|
|
63
|
+
const shouldSsr = async ()=>{
|
|
64
|
+
if (typeof opts.ssr === 'function') {
|
|
65
|
+
if (typeof window !== 'undefined') {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
return await opts.ssr({
|
|
70
|
+
ctx: appOrPageCtx.ctx
|
|
71
|
+
});
|
|
72
|
+
} catch (e) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return opts.ssr;
|
|
77
|
+
};
|
|
78
|
+
const ssr = await shouldSsr();
|
|
79
|
+
const AppTree = appOrPageCtx.AppTree;
|
|
80
|
+
// Determine if we are wrapping an App component or a Page component.
|
|
81
|
+
const isApp = !!appOrPageCtx.Component;
|
|
82
|
+
const ctx = isApp ? appOrPageCtx.ctx : appOrPageCtx;
|
|
83
|
+
// Run the wrapped component's getInitialProps function.
|
|
84
|
+
let pageProps = {};
|
|
85
|
+
if (AppOrPage.getInitialProps) {
|
|
86
|
+
const originalProps = await AppOrPage.getInitialProps(appOrPageCtx);
|
|
87
|
+
const originalPageProps = isApp ? originalProps.pageProps ?? {} : originalProps;
|
|
88
|
+
pageProps = {
|
|
89
|
+
...originalPageProps,
|
|
90
|
+
...pageProps
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const getAppTreeProps = (props)=>isApp ? {
|
|
94
|
+
pageProps: props
|
|
95
|
+
} : props;
|
|
96
|
+
if (typeof window !== 'undefined' || !ssr) {
|
|
97
|
+
return getAppTreeProps(pageProps);
|
|
98
|
+
}
|
|
99
|
+
const config = getClientConfig({
|
|
100
|
+
ctx
|
|
101
|
+
});
|
|
102
|
+
const trpcClient = client.createTRPCUntypedClient(config);
|
|
103
|
+
const queryClient = shared.getQueryClient(config);
|
|
104
|
+
const trpcProp = {
|
|
105
|
+
config,
|
|
106
|
+
trpcClient,
|
|
107
|
+
queryClient,
|
|
108
|
+
ssrState: 'prepass',
|
|
109
|
+
ssrContext: ctx
|
|
110
|
+
};
|
|
111
|
+
const prepassProps = {
|
|
112
|
+
pageProps,
|
|
113
|
+
trpc: trpcProp
|
|
114
|
+
};
|
|
115
|
+
const reactDomServer = await import('react-dom/server');
|
|
116
|
+
// Run the prepass step on AppTree. This will run all trpc queries on the server.
|
|
117
|
+
// multiple prepass ensures that we can do batching on the server
|
|
118
|
+
while(true){
|
|
119
|
+
// render full tree
|
|
120
|
+
reactDomServer.renderToString(/*#__PURE__*/ React.createElement(AppTree, prepassProps));
|
|
121
|
+
if (!queryClient.isFetching()) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
// wait until the query cache has settled it's promises
|
|
125
|
+
await new Promise((resolve)=>{
|
|
126
|
+
const unsub = queryClient.getQueryCache().subscribe((event)=>{
|
|
127
|
+
if (event?.query.getObserversCount() === 0) {
|
|
128
|
+
resolve();
|
|
129
|
+
unsub();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const dehydratedCache = reactQuery.dehydrate(queryClient, {
|
|
135
|
+
shouldDehydrateQuery (query) {
|
|
136
|
+
// filter out queries that are marked as trpc: { ssr: false } or are not enabled, but make sure errors are dehydrated
|
|
137
|
+
const isExcludedFromSSr = query.state.fetchStatus === 'idle' && query.state.status === 'pending';
|
|
138
|
+
return !isExcludedFromSSr;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects
|
|
142
|
+
const dehydratedCacheWithErrors = {
|
|
143
|
+
...dehydratedCache,
|
|
144
|
+
queries: dehydratedCache.queries.map(transformQueryOrMutationCacheErrors),
|
|
145
|
+
mutations: dehydratedCache.mutations.map(transformQueryOrMutationCacheErrors)
|
|
146
|
+
};
|
|
147
|
+
// dehydrate query client's state and add it to the props
|
|
148
|
+
pageProps['trpcState'] = trpcClient.runtime.combinedTransformer.output.serialize(dehydratedCacheWithErrors);
|
|
149
|
+
const appTreeProps = getAppTreeProps(pageProps);
|
|
150
|
+
if ('responseMeta' in opts) {
|
|
151
|
+
const meta = opts.responseMeta?.({
|
|
152
|
+
ctx,
|
|
153
|
+
clientErrors: [
|
|
154
|
+
...dehydratedCache.queries,
|
|
155
|
+
...dehydratedCache.mutations
|
|
156
|
+
].map((v)=>v.state.error).flatMap((err)=>err instanceof Error && err.name === 'TRPCClientError' ? [
|
|
157
|
+
err
|
|
158
|
+
] : [])
|
|
159
|
+
}) ?? {};
|
|
160
|
+
for (const [key, value] of Object.entries(meta.headers ?? {})){
|
|
161
|
+
if (typeof value === 'string') {
|
|
162
|
+
ctx.res?.setHeader(key, value);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (meta.status && ctx.res) {
|
|
166
|
+
ctx.res.statusCode = meta.status;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return appTreeProps;
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const displayName = AppOrPage.displayName ?? AppOrPage.name ?? 'Component';
|
|
173
|
+
WithTRPC.displayName = `withTRPC(${displayName})`;
|
|
174
|
+
return WithTRPC;
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
exports.withTRPC = withTRPC;
|