@trpc/next 10.0.0-alpha.8 → 10.0.0-proxy-alpha.53

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 CHANGED
@@ -1,3 +1,86 @@
1
+ <p align="center">
2
+ <a href="https://trpc.io/"><img src="../../www/static/img/logo-text.svg" alt="tRPC" height="130"/></a>
3
+ </p>
4
+
5
+ <p align="center">
6
+ <strong>End-to-end typesafe APIs made easy</strong>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <!-- TODO: replace with new version GIF -->
11
+ <img src="https://storage.googleapis.com/trpc/trpcgif.gif" alt="Demo" />
12
+ </p>
13
+
1
14
  # `@trpc/next`
2
15
 
3
- https://trpc.io
16
+ > Connect a tRPC router to Next.js.
17
+
18
+ ## Documentation
19
+
20
+ Full documentation for `@trpc/next` can be found [here](https://trpc.io/docs/nextjs)
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ # npm
26
+ npm install @trpc/next @trpc/react react-query
27
+
28
+ # Yarn
29
+ yarn add @trpc/next @trpc/react react-query
30
+
31
+ # pnpm
32
+ pnpm add @trpc/next @trpc/react react-query
33
+ ```
34
+
35
+ ## Basic Example
36
+
37
+ Setup tRPC in `utils/trpc.ts`.
38
+
39
+ ```ts
40
+ import { setupTRPC } from '@trpc/next';
41
+ // Import the router type from your server file
42
+ import type { AppRouter } from '../pages/api/[trpc].ts';
43
+
44
+ export const trpc = setupTRPC<AppRouter>({
45
+ config() {
46
+ return {
47
+ url: 'http://localhost:3000/api/trpc',
48
+ };
49
+ },
50
+ ssr: true,
51
+ });
52
+ ```
53
+
54
+ Hook up tRPC inside `_app.tsx`.
55
+
56
+ ```ts
57
+ import { trpc } from '~/utils/trpc';
58
+
59
+ const App = ({ Component, pageProps }) => {
60
+ return <Component {...pageProps} />;
61
+ };
62
+
63
+ export default trpc.withTRPC(App);
64
+ ```
65
+
66
+ Now you can query your API in any component.
67
+
68
+ ```ts
69
+ import { trpc } from '~/utils/trpc';
70
+
71
+ export function Hello() {
72
+ const { data, error, status } = trpc.proxy.greeting.useQuery({
73
+ name: 'tRPC',
74
+ });
75
+
76
+ if (error) {
77
+ return <p>{error.message}</p>;
78
+ }
79
+
80
+ if (status !== 'success') {
81
+ return <p>Loading...</p>;
82
+ }
83
+
84
+ return <div>{data && <p>{data.greeting}</p>}</div>;
85
+ }
86
+ ```
package/dist/index.js CHANGED
@@ -2,255 +2,199 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
6
- var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
7
- var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
8
- var _defineProperty = require('@babel/runtime/helpers/defineProperty');
9
- var _regeneratorRuntime = require('@babel/runtime/regenerator');
5
+ var reactQuery = require('@tanstack/react-query');
10
6
  var react = require('@trpc/react');
11
7
  var React = require('react');
12
- var reactQuery = require('react-query');
13
8
  var ssrPrepass = require('react-ssr-prepass');
14
9
 
15
10
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
16
11
 
17
- var _toConsumableArray__default = /*#__PURE__*/_interopDefaultLegacy(_toConsumableArray);
18
- var _asyncToGenerator__default = /*#__PURE__*/_interopDefaultLegacy(_asyncToGenerator);
19
- var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray);
20
- var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
21
- var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime);
22
12
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
23
13
  var ssrPrepass__default = /*#__PURE__*/_interopDefaultLegacy(ssrPrepass);
24
14
 
25
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
15
+ function extends_() {
16
+ extends_ = Object.assign || function (target) {
17
+ for (var i = 1; i < arguments.length; i++) {
18
+ var source = arguments[i];
26
19
 
27
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
28
-
29
- function transformQueryOrMutationCacheErrors(result) {
30
- var error = result.state.error;
20
+ for (var key in source) {
21
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
22
+ target[key] = source[key];
23
+ }
24
+ }
25
+ }
31
26
 
32
- if (error instanceof Error && error.name === 'TRPCClientError') {
33
- var newError = {
34
- message: error.message,
35
- data: error.data,
36
- shape: error.shape
37
- };
38
- return _objectSpread(_objectSpread({}, result), {}, {
39
- state: _objectSpread(_objectSpread({}, result.state), {}, {
40
- error: newError
41
- })
42
- });
43
- }
27
+ return target;
28
+ };
44
29
 
45
- return result;
30
+ return extends_.apply(this, arguments);
46
31
  }
47
32
 
48
- function withTRPC(opts) {
49
- var getClientConfig = opts.config;
50
- return function (AppOrPage) {
51
- var trpc = react.createReactQueryHooks(opts);
52
-
53
- var WithTRPC = function WithTRPC(props) {
54
- var _props$pageProps;
55
-
56
- var _useState = React.useState(function () {
57
- if (props.trpc) {
58
- return props.trpc;
59
- }
33
+ function _extends() {
34
+ return extends_.apply(this, arguments);
35
+ }
60
36
 
61
- var config = getClientConfig({});
62
- var queryClient = new reactQuery.QueryClient(config.queryClientConfig);
63
- var trpcClient = trpc.createClient(config);
37
+ function transformQueryOrMutationCacheErrors(result) {
38
+ const error = result.state.error;
39
+ if (error instanceof Error && error.name === 'TRPCClientError') {
40
+ const newError = {
41
+ message: error.message,
42
+ data: error.data,
43
+ shape: error.shape
44
+ };
64
45
  return {
65
- queryClient: queryClient,
66
- trpcClient: trpcClient,
67
- isPrepass: false,
68
- ssrContext: null
46
+ ...result,
47
+ state: {
48
+ ...result.state,
49
+ error: newError
50
+ }
69
51
  };
70
- }),
71
- _useState2 = _slicedToArray__default["default"](_useState, 1),
72
- _useState2$ = _useState2[0],
73
- queryClient = _useState2$.queryClient,
74
- trpcClient = _useState2$.trpcClient,
75
- isPrepass = _useState2$.isPrepass,
76
- ssrContext = _useState2$.ssrContext;
77
-
78
- var hydratedState = trpc.useDehydratedState((_props$pageProps = props.pageProps) === null || _props$pageProps === void 0 ? void 0 : _props$pageProps.trpcState);
79
- return /*#__PURE__*/React__default["default"].createElement(trpc.Provider, {
80
- client: trpcClient,
81
- queryClient: queryClient,
82
- isPrepass: isPrepass,
83
- ssrContext: ssrContext
84
- }, /*#__PURE__*/React__default["default"].createElement(reactQuery.QueryClientProvider, {
85
- client: queryClient
86
- }, /*#__PURE__*/React__default["default"].createElement(reactQuery.Hydrate, {
87
- state: hydratedState
88
- }, /*#__PURE__*/React__default["default"].createElement(AppOrPage, props))));
89
- };
90
-
91
- if (AppOrPage.getInitialProps || opts.ssr) {
92
- WithTRPC.getInitialProps = /*#__PURE__*/function () {
93
- var _ref = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee(appOrPageCtx) {
94
- var _opts$responseMeta;
95
-
96
- var AppTree, isApp, ctx, pageProps, _originalProps$pagePr, originalProps, originalPageProps, getAppTreeProps, config, trpcClient, queryClient, trpcProp, prepassProps, dehydratedCache, dehydratedCacheWithErrors, appTreeProps, meta, _i, _Object$entries, _Object$entries$_i, key, value, _ctx$res;
97
-
98
- return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) {
99
- while (1) {
100
- switch (_context.prev = _context.next) {
101
- case 0:
102
- AppTree = appOrPageCtx.AppTree; // Determine if we are wrapping an App component or a Page component.
103
-
104
- isApp = !!appOrPageCtx.Component;
105
- ctx = isApp ? appOrPageCtx.ctx : appOrPageCtx; // Run the wrapped component's getInitialProps function.
106
-
107
- pageProps = {};
108
-
109
- if (!AppOrPage.getInitialProps) {
110
- _context.next = 10;
111
- break;
112
- }
113
-
114
- _context.next = 7;
115
- return AppOrPage.getInitialProps(appOrPageCtx);
116
-
117
- case 7:
118
- originalProps = _context.sent;
119
- originalPageProps = isApp ? (_originalProps$pagePr = originalProps.pageProps) !== null && _originalProps$pagePr !== void 0 ? _originalProps$pagePr : {} : originalProps;
120
- pageProps = _objectSpread(_objectSpread({}, originalPageProps), pageProps);
121
-
122
- case 10:
123
- getAppTreeProps = function getAppTreeProps(props) {
124
- return isApp ? {
125
- pageProps: props
52
+ }
53
+ return result;
54
+ }
55
+ function withTRPC(opts) {
56
+ const { config: getClientConfig } = opts;
57
+ return (AppOrPage)=>{
58
+ const trpc = react.createReactQueryHooks();
59
+ const WithTRPC = (props)=>{
60
+ const [{ queryClient , trpcClient , ssrState , ssrContext }] = React.useState(()=>{
61
+ if (props.trpc) {
62
+ return props.trpc;
63
+ }
64
+ const config = getClientConfig({});
65
+ const queryClient = new reactQuery.QueryClient(config.queryClientConfig);
66
+ const trpcClient = trpc.createClient(config);
67
+ return {
68
+ queryClient,
69
+ trpcClient,
70
+ ssrState: opts.ssr ? 'mounting' : false,
71
+ ssrContext: null
72
+ };
73
+ });
74
+ const hydratedState = trpc.useDehydratedState(trpcClient, props.pageProps?.trpcState);
75
+ return /*#__PURE__*/ React__default["default"].createElement(trpc.Provider, {
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.Hydrate, {
83
+ state: hydratedState
84
+ }, /*#__PURE__*/ React__default["default"].createElement(AppOrPage, _extends({}, props)))));
85
+ };
86
+ if (AppOrPage.getInitialProps || opts.ssr) {
87
+ WithTRPC.getInitialProps = async (appOrPageCtx)=>{
88
+ const AppTree = appOrPageCtx.AppTree;
89
+ // Determine if we are wrapping an App component or a Page component.
90
+ const isApp = !!appOrPageCtx.Component;
91
+ const ctx = isApp ? appOrPageCtx.ctx : appOrPageCtx;
92
+ // Run the wrapped component's getInitialProps function.
93
+ let pageProps = {};
94
+ if (AppOrPage.getInitialProps) {
95
+ const originalProps = await AppOrPage.getInitialProps(appOrPageCtx);
96
+ const originalPageProps = isApp ? originalProps.pageProps ?? {} : originalProps;
97
+ pageProps = {
98
+ ...originalPageProps,
99
+ ...pageProps
100
+ };
101
+ }
102
+ const getAppTreeProps = (props)=>isApp ? {
103
+ pageProps: props
126
104
  } : props;
127
- };
128
-
129
- if (!(typeof window !== 'undefined' || !opts.ssr)) {
130
- _context.next = 13;
131
- break;
132
- }
133
-
134
- return _context.abrupt("return", getAppTreeProps(pageProps));
135
-
136
- case 13:
137
- config = getClientConfig({
138
- ctx: ctx
139
- });
140
- trpcClient = react.createTRPCClient(config);
141
- queryClient = new reactQuery.QueryClient(config.queryClientConfig);
142
- trpcProp = {
143
- config: config,
144
- trpcClient: trpcClient,
145
- queryClient: queryClient,
146
- isPrepass: true,
105
+ if (typeof window !== 'undefined' || !opts.ssr) {
106
+ return getAppTreeProps(pageProps);
107
+ }
108
+ const config = getClientConfig({
109
+ ctx
110
+ });
111
+ const trpcClient = react.createTRPCClient(config);
112
+ const queryClient = new reactQuery.QueryClient(config.queryClientConfig);
113
+ const trpcProp = {
114
+ config,
115
+ trpcClient,
116
+ queryClient,
117
+ ssrState: 'prepass',
147
118
  ssrContext: ctx
148
- };
149
- prepassProps = {
150
- pageProps: pageProps,
119
+ };
120
+ const prepassProps = {
121
+ pageProps,
151
122
  trpc: trpcProp
152
- }; // Run the prepass step on AppTree. This will run all trpc queries on the server.
153
- // multiple prepass ensures that we can do batching on the server
154
-
155
- case 18:
156
-
157
- _context.next = 21;
158
- return ssrPrepass__default["default"]( /*#__PURE__*/React.createElement(AppTree, prepassProps));
159
-
160
- case 21:
161
- if (queryClient.isFetching()) {
162
- _context.next = 23;
163
- break;
164
- }
165
-
166
- return _context.abrupt("break", 27);
167
-
168
- case 23:
169
- _context.next = 25;
170
- return new Promise(function (resolve) {
171
- var unsub = queryClient.getQueryCache().subscribe(function (event) {
172
- if ((event === null || event === void 0 ? void 0 : event.query.getObserversCount()) === 0) {
173
- resolve();
174
- unsub();
175
- }
123
+ };
124
+ // Run the prepass step on AppTree. This will run all trpc queries on the server.
125
+ // multiple prepass ensures that we can do batching on the server
126
+ while(true){
127
+ // render full tree
128
+ await ssrPrepass__default["default"](/*#__PURE__*/ React.createElement(AppTree, prepassProps));
129
+ if (!queryClient.isFetching()) {
130
+ break;
131
+ }
132
+ // wait until the query cache has settled it's promises
133
+ await new Promise((resolve)=>{
134
+ const unsub = queryClient.getQueryCache().subscribe((event)=>{
135
+ if (event?.query.getObserversCount() === 0) {
136
+ resolve();
137
+ unsub();
138
+ }
139
+ });
176
140
  });
177
- });
178
-
179
- case 25:
180
- _context.next = 18;
181
- break;
182
-
183
- case 27:
184
- dehydratedCache = reactQuery.dehydrate(queryClient, {
185
- shouldDehydrateQuery: function shouldDehydrateQuery() {
186
- // makes sure errors are also dehydrated
187
- return true;
141
+ }
142
+ const dehydratedCache = reactQuery.dehydrate(queryClient, {
143
+ shouldDehydrateQuery () {
144
+ // makes sure errors are also dehydrated
145
+ return true;
188
146
  }
189
- }); // since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects
190
-
191
- dehydratedCacheWithErrors = _objectSpread(_objectSpread({}, dehydratedCache), {}, {
147
+ });
148
+ // since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects
149
+ const dehydratedCacheWithErrors = {
150
+ ...dehydratedCache,
192
151
  queries: dehydratedCache.queries.map(transformQueryOrMutationCacheErrors),
193
152
  mutations: dehydratedCache.mutations.map(transformQueryOrMutationCacheErrors)
194
- }); // dehydrate query client's state and add it to the props
195
-
196
- pageProps.trpcState = opts.transformer ? opts.transformer.serialize(dehydratedCacheWithErrors) : dehydratedCacheWithErrors;
197
- appTreeProps = getAppTreeProps(pageProps);
198
- meta = ((_opts$responseMeta = opts.responseMeta) === null || _opts$responseMeta === void 0 ? void 0 : _opts$responseMeta.call(opts, {
199
- ctx: ctx,
200
- clientErrors: [].concat(_toConsumableArray__default["default"](dehydratedCache.queries), _toConsumableArray__default["default"](dehydratedCache.mutations)).map(function (v) {
201
- return v.state.error;
202
- }).flatMap(function (err) {
203
- return err instanceof Error && err.name === 'TRPCClientError' ? [err] : [];
204
- })
205
- })) || {};
206
-
207
- for (_i = 0, _Object$entries = Object.entries(meta.headers || {}); _i < _Object$entries.length; _i++) {
208
- _Object$entries$_i = _slicedToArray__default["default"](_Object$entries[_i], 2), key = _Object$entries$_i[0], value = _Object$entries$_i[1];
209
-
153
+ };
154
+ // dehydrate query client's state and add it to the props
155
+ pageProps.trpcState = trpcClient.runtime.transformer.serialize(dehydratedCacheWithErrors);
156
+ const appTreeProps = getAppTreeProps(pageProps);
157
+ const meta = opts.responseMeta?.({
158
+ ctx,
159
+ clientErrors: [
160
+ ...dehydratedCache.queries,
161
+ ...dehydratedCache.mutations,
162
+ ].map((v)=>v.state.error).flatMap((err)=>err instanceof Error && err.name === 'TRPCClientError' ? [
163
+ err
164
+ ] : [])
165
+ }) || {};
166
+ for (const [key, value] of Object.entries(meta.headers || {})){
210
167
  if (typeof value === 'string') {
211
- (_ctx$res = ctx.res) === null || _ctx$res === void 0 ? void 0 : _ctx$res.setHeader(key, value);
168
+ ctx.res?.setHeader(key, value);
212
169
  }
213
- }
214
-
215
- if (meta.status && ctx.res) {
170
+ }
171
+ if (meta.status && ctx.res) {
216
172
  ctx.res.statusCode = meta.status;
217
- }
218
-
219
- return _context.abrupt("return", appTreeProps);
220
-
221
- case 35:
222
- case "end":
223
- return _context.stop();
224
- }
225
- }
226
- }, _callee);
227
- }));
228
-
229
- return function (_x) {
230
- return _ref.apply(this, arguments);
231
- };
232
- }();
233
- }
234
-
235
- var displayName = AppOrPage.displayName || AppOrPage.name || 'Component';
236
- WithTRPC.displayName = "withTRPC(".concat(displayName, ")");
237
- return WithTRPC;
238
- };
173
+ }
174
+ return appTreeProps;
175
+ };
176
+ }
177
+ const displayName = AppOrPage.displayName || AppOrPage.name || 'Component';
178
+ WithTRPC.displayName = `withTRPC(${displayName})`;
179
+ return WithTRPC;
180
+ };
239
181
  }
240
182
 
241
183
  function setupTRPC(opts) {
242
- var hooks = react.createReactQueryHooks(opts);
243
-
244
- var _withTRPC = withTRPC(opts);
245
-
246
- return {
247
- useContext: hooks.useContext,
248
- useInfiniteQuery: hooks.useInfiniteQuery,
249
- useMutation: hooks.useMutation,
250
- useQuery: hooks.useQuery,
251
- useSubscription: hooks.useSubscription,
252
- withTRPC: _withTRPC
253
- };
184
+ const hooks = react.createReactQueryHooks();
185
+ const proxy = react.createReactQueryHooksProxy(hooks);
186
+ // TODO: maybe set TSSRContext to `never` when using `WithTRPCNoSSROptions`
187
+ const _withTRPC = withTRPC(opts);
188
+ return {
189
+ proxy,
190
+ useContext: hooks.useContext,
191
+ useInfiniteQuery: hooks.useInfiniteQuery,
192
+ useMutation: hooks.useMutation,
193
+ useQuery: hooks.useQuery,
194
+ useSubscription: hooks.useSubscription,
195
+ withTRPC: _withTRPC,
196
+ queries: hooks.queries
197
+ };
254
198
  }
255
199
 
256
200
  exports.setupTRPC = setupTRPC;