@trpc/next 10.27.3 → 10.28.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trpc/next",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.28.0",
|
|
4
4
|
"description": "The tRPC Next.js library",
|
|
5
5
|
"author": "KATT",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,13 +51,14 @@
|
|
|
51
51
|
"src",
|
|
52
52
|
"README.md",
|
|
53
53
|
"package.json",
|
|
54
|
-
"app-dir"
|
|
54
|
+
"app-dir",
|
|
55
|
+
"!**/*.test.*"
|
|
55
56
|
],
|
|
56
57
|
"peerDependencies": {
|
|
57
58
|
"@tanstack/react-query": "^4.18.0",
|
|
58
|
-
"@trpc/client": "10.
|
|
59
|
-
"@trpc/react-query": "10.
|
|
60
|
-
"@trpc/server": "10.
|
|
59
|
+
"@trpc/client": "10.28.0",
|
|
60
|
+
"@trpc/react-query": "10.28.0",
|
|
61
|
+
"@trpc/server": "10.28.0",
|
|
61
62
|
"next": "*",
|
|
62
63
|
"react": ">=16.8.0",
|
|
63
64
|
"react-dom": ">=16.8.0"
|
|
@@ -67,9 +68,9 @@
|
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|
|
69
70
|
"@tanstack/react-query": "^4.18.0",
|
|
70
|
-
"@trpc/client": "10.
|
|
71
|
-
"@trpc/react-query": "10.
|
|
72
|
-
"@trpc/server": "10.
|
|
71
|
+
"@trpc/client": "10.28.0",
|
|
72
|
+
"@trpc/react-query": "10.28.0",
|
|
73
|
+
"@trpc/server": "10.28.0",
|
|
73
74
|
"@types/express": "^4.17.17",
|
|
74
75
|
"@types/node": "^18.7.20",
|
|
75
76
|
"@types/react": "^18.2.6",
|
|
@@ -86,5 +87,8 @@
|
|
|
86
87
|
"publishConfig": {
|
|
87
88
|
"access": "public"
|
|
88
89
|
},
|
|
89
|
-
"
|
|
90
|
+
"funding": [
|
|
91
|
+
"https://trpc.io/sponsor"
|
|
92
|
+
],
|
|
93
|
+
"gitHead": "7aadb24ce0bc20ae27f32bd80891ef6da5885e5e"
|
|
90
94
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../src/app-dir/client.test.tsx"],"names":[],"mappings":""}
|
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
import { render, waitFor } from '@testing-library/react';
|
|
2
|
-
import userEvent from '@testing-library/user-event';
|
|
3
|
-
import { initTRPC } from '@trpc/server';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import superjson from 'superjson';
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
import {
|
|
8
|
-
UseTRPCActionResult,
|
|
9
|
-
experimental_createActionHook,
|
|
10
|
-
experimental_serverActionLink,
|
|
11
|
-
} from './create-action-hook';
|
|
12
|
-
import { experimental_createServerActionHandler } from './server';
|
|
13
|
-
|
|
14
|
-
describe('without transformer', () => {
|
|
15
|
-
const instance = initTRPC
|
|
16
|
-
.context<{
|
|
17
|
-
foo: string;
|
|
18
|
-
}>()
|
|
19
|
-
.create({});
|
|
20
|
-
const { procedure } = instance;
|
|
21
|
-
|
|
22
|
-
const createAction = experimental_createServerActionHandler(instance, {
|
|
23
|
-
createContext() {
|
|
24
|
-
return {
|
|
25
|
-
foo: 'bar',
|
|
26
|
-
};
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const useAction = experimental_createActionHook({
|
|
31
|
-
links: [experimental_serverActionLink()],
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('server actions smoke test', async () => {
|
|
35
|
-
const action = createAction(procedure.mutation((opts) => opts.ctx));
|
|
36
|
-
expect(await action()).toMatchInlineSnapshot(`
|
|
37
|
-
Object {
|
|
38
|
-
"result": Object {
|
|
39
|
-
"data": Object {
|
|
40
|
-
"foo": "bar",
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
}
|
|
44
|
-
`);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('normalize FormData', async () => {
|
|
48
|
-
const action = createAction(
|
|
49
|
-
procedure
|
|
50
|
-
.input(
|
|
51
|
-
z.object({
|
|
52
|
-
text: z.string(),
|
|
53
|
-
}),
|
|
54
|
-
)
|
|
55
|
-
.mutation((opts) => `hello ${opts.input.text}` as const),
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
expect(
|
|
59
|
-
await action({
|
|
60
|
-
text: 'there',
|
|
61
|
-
}),
|
|
62
|
-
).toMatchInlineSnapshot(`
|
|
63
|
-
Object {
|
|
64
|
-
"result": Object {
|
|
65
|
-
"data": "hello there",
|
|
66
|
-
},
|
|
67
|
-
}
|
|
68
|
-
`);
|
|
69
|
-
|
|
70
|
-
const formData = new FormData();
|
|
71
|
-
formData.append('text', 'there');
|
|
72
|
-
expect(await action(formData)).toMatchInlineSnapshot(`
|
|
73
|
-
Object {
|
|
74
|
-
"result": Object {
|
|
75
|
-
"data": "hello there",
|
|
76
|
-
},
|
|
77
|
-
}
|
|
78
|
-
`);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test('an actual client', async () => {
|
|
82
|
-
const action = createAction(
|
|
83
|
-
procedure
|
|
84
|
-
.input(
|
|
85
|
-
z.object({
|
|
86
|
-
text: z.string(),
|
|
87
|
-
}),
|
|
88
|
-
)
|
|
89
|
-
.mutation((opts) => `hello ${opts.input.text}` as const),
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
const allStates: Omit<
|
|
93
|
-
UseTRPCActionResult<any>,
|
|
94
|
-
'mutate' | 'mutateAsync'
|
|
95
|
-
>[] = [] as any[];
|
|
96
|
-
|
|
97
|
-
function MyComponent() {
|
|
98
|
-
const mutation = useAction(action);
|
|
99
|
-
const { mutate, mutateAsync, ...other } = mutation;
|
|
100
|
-
allStates.push(other);
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<>
|
|
104
|
-
<button
|
|
105
|
-
role="trigger"
|
|
106
|
-
onClick={() => {
|
|
107
|
-
mutation.mutate({
|
|
108
|
-
text: 'world',
|
|
109
|
-
});
|
|
110
|
-
}}
|
|
111
|
-
>
|
|
112
|
-
click me
|
|
113
|
-
</button>
|
|
114
|
-
</>
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// mount it
|
|
119
|
-
const utils = render(<MyComponent />);
|
|
120
|
-
|
|
121
|
-
// get the contents of pre
|
|
122
|
-
expect(allStates.at(-1)).toMatchInlineSnapshot(`
|
|
123
|
-
Object {
|
|
124
|
-
"status": "idle",
|
|
125
|
-
}
|
|
126
|
-
`);
|
|
127
|
-
|
|
128
|
-
// click the button
|
|
129
|
-
userEvent.click(utils.getByRole('trigger'));
|
|
130
|
-
|
|
131
|
-
// wait to finish
|
|
132
|
-
await waitFor(() => {
|
|
133
|
-
assert(allStates.at(-1)?.status === 'success');
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
expect(allStates).toMatchInlineSnapshot(`
|
|
137
|
-
Array [
|
|
138
|
-
Object {
|
|
139
|
-
"status": "idle",
|
|
140
|
-
},
|
|
141
|
-
Object {
|
|
142
|
-
"status": "loading",
|
|
143
|
-
},
|
|
144
|
-
Object {
|
|
145
|
-
"data": "hello world",
|
|
146
|
-
"status": "success",
|
|
147
|
-
},
|
|
148
|
-
]
|
|
149
|
-
`);
|
|
150
|
-
|
|
151
|
-
const lastState = allStates.at(-1);
|
|
152
|
-
assert(lastState?.status === 'success');
|
|
153
|
-
expect(lastState.data).toMatchInlineSnapshot(`"hello world"`);
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
describe('with transformer', () => {
|
|
158
|
-
const instance = initTRPC
|
|
159
|
-
.context<{
|
|
160
|
-
foo: string;
|
|
161
|
-
}>()
|
|
162
|
-
.create({
|
|
163
|
-
transformer: superjson,
|
|
164
|
-
});
|
|
165
|
-
const { procedure } = instance;
|
|
166
|
-
|
|
167
|
-
const createAction = experimental_createServerActionHandler(instance, {
|
|
168
|
-
createContext() {
|
|
169
|
-
return {
|
|
170
|
-
foo: 'bar',
|
|
171
|
-
};
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const useAction = experimental_createActionHook({
|
|
176
|
-
links: [experimental_serverActionLink()],
|
|
177
|
-
transformer: superjson,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
test('pass a Date', async () => {
|
|
181
|
-
const action = createAction(
|
|
182
|
-
procedure
|
|
183
|
-
.input(
|
|
184
|
-
z.object({
|
|
185
|
-
date: z.date(),
|
|
186
|
-
}),
|
|
187
|
-
)
|
|
188
|
-
.mutation((opts) => opts.input.date),
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
const allStates: Omit<
|
|
192
|
-
UseTRPCActionResult<any>,
|
|
193
|
-
'mutate' | 'mutateAsync'
|
|
194
|
-
>[] = [] as any[];
|
|
195
|
-
|
|
196
|
-
function MyComponent() {
|
|
197
|
-
const mutation = useAction(action);
|
|
198
|
-
const { mutate, mutateAsync, ...other } = mutation;
|
|
199
|
-
allStates.push(other);
|
|
200
|
-
|
|
201
|
-
return (
|
|
202
|
-
<>
|
|
203
|
-
<button
|
|
204
|
-
role="trigger"
|
|
205
|
-
onClick={() => {
|
|
206
|
-
mutation.mutate({
|
|
207
|
-
date: new Date(0),
|
|
208
|
-
});
|
|
209
|
-
}}
|
|
210
|
-
>
|
|
211
|
-
click me
|
|
212
|
-
</button>
|
|
213
|
-
</>
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// mount it
|
|
218
|
-
const utils = render(<MyComponent />);
|
|
219
|
-
|
|
220
|
-
// get the contents of pre
|
|
221
|
-
expect(allStates.at(-1)).toMatchInlineSnapshot(`
|
|
222
|
-
Object {
|
|
223
|
-
"status": "idle",
|
|
224
|
-
}
|
|
225
|
-
`);
|
|
226
|
-
|
|
227
|
-
// click the button
|
|
228
|
-
userEvent.click(utils.getByRole('trigger'));
|
|
229
|
-
|
|
230
|
-
// wait to finish
|
|
231
|
-
await waitFor(() => {
|
|
232
|
-
assert(allStates.at(-1)?.status === 'success');
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
expect(allStates).toMatchInlineSnapshot(`
|
|
236
|
-
Array [
|
|
237
|
-
Object {
|
|
238
|
-
"status": "idle",
|
|
239
|
-
},
|
|
240
|
-
Object {
|
|
241
|
-
"status": "loading",
|
|
242
|
-
},
|
|
243
|
-
Object {
|
|
244
|
-
"data": 1970-01-01T00:00:00.000Z,
|
|
245
|
-
"status": "success",
|
|
246
|
-
},
|
|
247
|
-
]
|
|
248
|
-
`);
|
|
249
|
-
|
|
250
|
-
const lastState = allStates.at(-1);
|
|
251
|
-
assert(lastState?.status === 'success');
|
|
252
|
-
expect(lastState.data).toMatchInlineSnapshot('1970-01-01T00:00:00.000Z');
|
|
253
|
-
expect(lastState.data).toBeInstanceOf(Date);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
test('FormData', async () => {
|
|
257
|
-
const action = createAction(
|
|
258
|
-
procedure
|
|
259
|
-
.input(
|
|
260
|
-
z.object({
|
|
261
|
-
text: z.string(),
|
|
262
|
-
}),
|
|
263
|
-
)
|
|
264
|
-
.mutation((opts) => opts.input.text),
|
|
265
|
-
);
|
|
266
|
-
|
|
267
|
-
const allStates: Omit<
|
|
268
|
-
UseTRPCActionResult<any>,
|
|
269
|
-
'mutate' | 'mutateAsync'
|
|
270
|
-
>[] = [] as any[];
|
|
271
|
-
|
|
272
|
-
function MyComponent() {
|
|
273
|
-
const mutation = useAction(action);
|
|
274
|
-
const { mutate, mutateAsync, ...other } = mutation;
|
|
275
|
-
allStates.push(other);
|
|
276
|
-
|
|
277
|
-
return (
|
|
278
|
-
<>
|
|
279
|
-
<form
|
|
280
|
-
onSubmit={(e) => {
|
|
281
|
-
e.preventDefault();
|
|
282
|
-
|
|
283
|
-
const formData = new FormData(e.currentTarget);
|
|
284
|
-
mutation.mutate(formData);
|
|
285
|
-
}}
|
|
286
|
-
>
|
|
287
|
-
<input type="text" name="text" defaultValue="world" />
|
|
288
|
-
<button role="trigger" type="submit">
|
|
289
|
-
click me
|
|
290
|
-
</button>
|
|
291
|
-
</form>
|
|
292
|
-
</>
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// mount it
|
|
297
|
-
const utils = render(<MyComponent />);
|
|
298
|
-
|
|
299
|
-
// get the contents of pre
|
|
300
|
-
expect(allStates.at(-1)).toMatchInlineSnapshot(`
|
|
301
|
-
Object {
|
|
302
|
-
"status": "idle",
|
|
303
|
-
}
|
|
304
|
-
`);
|
|
305
|
-
|
|
306
|
-
// click the button
|
|
307
|
-
userEvent.click(utils.getByRole('trigger'));
|
|
308
|
-
|
|
309
|
-
// wait to finish
|
|
310
|
-
await waitFor(() => {
|
|
311
|
-
assert(allStates.at(-1)?.status === 'success');
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
expect(allStates).toMatchInlineSnapshot(`
|
|
315
|
-
Array [
|
|
316
|
-
Object {
|
|
317
|
-
"status": "idle",
|
|
318
|
-
},
|
|
319
|
-
Object {
|
|
320
|
-
"status": "loading",
|
|
321
|
-
},
|
|
322
|
-
Object {
|
|
323
|
-
"data": "world",
|
|
324
|
-
"status": "success",
|
|
325
|
-
},
|
|
326
|
-
]
|
|
327
|
-
`);
|
|
328
|
-
|
|
329
|
-
const lastState = allStates.at(-1);
|
|
330
|
-
assert(lastState?.status === 'success');
|
|
331
|
-
expect(lastState.data).toMatchInlineSnapshot('"world"');
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
describe('type tests', () => {
|
|
336
|
-
const ignoreErrors = async (fn: () => Promise<unknown> | unknown) => {
|
|
337
|
-
try {
|
|
338
|
-
await fn();
|
|
339
|
-
} catch {
|
|
340
|
-
// ignore
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
const instance = initTRPC
|
|
345
|
-
.context<{
|
|
346
|
-
foo: string;
|
|
347
|
-
}>()
|
|
348
|
-
.create({});
|
|
349
|
-
const { procedure } = instance;
|
|
350
|
-
|
|
351
|
-
const createAction = experimental_createServerActionHandler(instance, {
|
|
352
|
-
createContext() {
|
|
353
|
-
return {
|
|
354
|
-
foo: 'bar',
|
|
355
|
-
};
|
|
356
|
-
},
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
const useAction = experimental_createActionHook({
|
|
360
|
-
links: [experimental_serverActionLink()],
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
test('assert input is sent', async () => {
|
|
364
|
-
ignoreErrors(async () => {
|
|
365
|
-
const action = createAction(
|
|
366
|
-
procedure.input(z.string()).mutation((opts) => opts.input),
|
|
367
|
-
);
|
|
368
|
-
const hook = useAction(action);
|
|
369
|
-
// @ts-expect-error this requires an input
|
|
370
|
-
await action();
|
|
371
|
-
// @ts-expect-error this requires an input
|
|
372
|
-
hook.mutate();
|
|
373
|
-
|
|
374
|
-
// @ts-expect-error this requires an input
|
|
375
|
-
await hook.mutateAsync();
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
test('assert types is correct', async () => {
|
|
380
|
-
ignoreErrors(async () => {
|
|
381
|
-
const action = createAction(
|
|
382
|
-
procedure.input(z.date().optional()).mutation((opts) => opts.input),
|
|
383
|
-
);
|
|
384
|
-
const hook = useAction(action);
|
|
385
|
-
// @ts-expect-error wrong type
|
|
386
|
-
await action('bleh');
|
|
387
|
-
// @ts-expect-error wrong type
|
|
388
|
-
hook.mutate('bleh');
|
|
389
|
-
|
|
390
|
-
hook.mutate();
|
|
391
|
-
await action();
|
|
392
|
-
});
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
test('assert no input', async () => {
|
|
396
|
-
ignoreErrors(async () => {
|
|
397
|
-
const action = createAction(procedure.mutation((opts) => opts.input));
|
|
398
|
-
const hook = useAction(action);
|
|
399
|
-
// @ts-expect-error this takes no input
|
|
400
|
-
await action(null);
|
|
401
|
-
// @ts-expect-error this takes no input
|
|
402
|
-
hook.mutate(null);
|
|
403
|
-
|
|
404
|
-
// @ts-expect-error this takes no input
|
|
405
|
-
await hook.mutateAsync(null);
|
|
406
|
-
});
|
|
407
|
-
});
|
|
408
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { formDataToObject } from './formDataToObject';
|
|
2
|
-
|
|
3
|
-
test('basic', () => {
|
|
4
|
-
const formData = new FormData();
|
|
5
|
-
|
|
6
|
-
formData.append('foo', 'bar');
|
|
7
|
-
|
|
8
|
-
expect(formDataToObject(formData)).toEqual({
|
|
9
|
-
foo: 'bar',
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('multiple values on the same key', () => {
|
|
14
|
-
const formData = new FormData();
|
|
15
|
-
|
|
16
|
-
formData.append('foo', 'bar');
|
|
17
|
-
formData.append('foo', 'baz');
|
|
18
|
-
|
|
19
|
-
expect(formDataToObject(formData)).toEqual({
|
|
20
|
-
foo: ['bar', 'baz'],
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('deep key', () => {
|
|
25
|
-
const formData = new FormData();
|
|
26
|
-
|
|
27
|
-
formData.append('foo.bar.baz', 'qux');
|
|
28
|
-
|
|
29
|
-
expect(formDataToObject(formData)).toEqual({
|
|
30
|
-
foo: {
|
|
31
|
-
bar: {
|
|
32
|
-
baz: 'qux',
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('array', () => {
|
|
39
|
-
const formData = new FormData();
|
|
40
|
-
|
|
41
|
-
formData.append('foo[0]', 'bar');
|
|
42
|
-
formData.append('foo[1]', 'baz');
|
|
43
|
-
|
|
44
|
-
expect(formDataToObject(formData)).toEqual({
|
|
45
|
-
foo: ['bar', 'baz'],
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test('array with dot notation', () => {
|
|
50
|
-
const formData = new FormData();
|
|
51
|
-
|
|
52
|
-
formData.append('foo.0', 'bar');
|
|
53
|
-
formData.append('foo.1', 'baz');
|
|
54
|
-
|
|
55
|
-
expect(formDataToObject(formData)).toEqual({
|
|
56
|
-
foo: ['bar', 'baz'],
|
|
57
|
-
});
|
|
58
|
-
});
|