@trpc/next 10.26.0 → 10.27.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/dist/app-dir/client.d.ts +4 -7
- package/dist/app-dir/client.d.ts.map +1 -1
- package/dist/app-dir/client.js +144 -54
- package/dist/app-dir/client.mjs +144 -56
- package/dist/app-dir/client.test.d.ts +2 -0
- package/dist/app-dir/client.test.d.ts.map +1 -0
- package/dist/app-dir/create-action-hook.d.ts +51 -0
- package/dist/app-dir/create-action-hook.d.ts.map +1 -0
- package/dist/app-dir/formDataToObject.d.ts +2 -0
- package/dist/app-dir/formDataToObject.d.ts.map +1 -0
- package/dist/app-dir/server.d.ts +21 -2
- package/dist/app-dir/server.d.ts.map +1 -1
- package/dist/app-dir/server.js +88 -0
- package/dist/app-dir/server.mjs +89 -2
- package/dist/app-dir/shared.d.ts +21 -1
- package/dist/app-dir/shared.d.ts.map +1 -1
- package/dist/shared-2ca37369.js +15 -0
- package/dist/shared-59b269d5.mjs +13 -0
- package/dist/shared-bc6a2699.js +14 -0
- package/package.json +10 -10
- package/src/app-dir/client.test.tsx +408 -0
- package/src/app-dir/client.ts +71 -63
- package/src/app-dir/create-action-hook.tsx +218 -0
- package/src/app-dir/formDataToObject.test.ts +58 -0
- package/src/app-dir/formDataToObject.ts +36 -0
- package/src/app-dir/server.ts +110 -4
- package/src/app-dir/shared.ts +32 -0
|
@@ -0,0 +1,408 @@
|
|
|
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
|
+
});
|
package/src/app-dir/client.ts
CHANGED
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CreateTRPCProxyClient,
|
|
2
3
|
clientCallTypeToProcedureType,
|
|
3
4
|
createTRPCUntypedClient,
|
|
4
5
|
} from '@trpc/client';
|
|
5
6
|
import { AnyRouter } from '@trpc/server';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
import { createRecursiveProxy } from '@trpc/server/shared';
|
|
8
|
+
import { CreateTRPCNextAppRouterOptions } from './shared';
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
// ts-prune-ignore-next
|
|
12
|
+
experimental_createActionHook,
|
|
13
|
+
// ts-prune-ignore-next
|
|
14
|
+
experimental_serverActionLink,
|
|
15
|
+
// ts-prune-ignore-next
|
|
16
|
+
type UseTRPCActionResult,
|
|
17
|
+
// ts-prune-ignore-next
|
|
18
|
+
type inferActionResultProps,
|
|
19
|
+
} from './create-action-hook';
|
|
20
|
+
|
|
21
|
+
// function normalizePromiseArray<TValue>(
|
|
22
|
+
// promise: Promise<TValue> | Promise<TValue>[],
|
|
23
|
+
// ) {
|
|
24
|
+
// if (Array.isArray(promise)) {
|
|
25
|
+
// return Promise.all(promise);
|
|
26
|
+
// }
|
|
27
|
+
// return promise;
|
|
28
|
+
// }
|
|
22
29
|
|
|
23
30
|
type QueryResult = {
|
|
24
31
|
data?: unknown;
|
|
@@ -31,63 +38,64 @@ export function experimental_createTRPCNextAppDirClient<
|
|
|
31
38
|
TRouter extends AnyRouter,
|
|
32
39
|
>(opts: CreateTRPCNextAppRouterOptions<TRouter>) {
|
|
33
40
|
const client = createTRPCUntypedClient<TRouter>(opts.config());
|
|
34
|
-
const useProxy = createUseProxy<TRouter>(client);
|
|
41
|
+
// const useProxy = createUseProxy<TRouter>(client);
|
|
35
42
|
|
|
36
43
|
const cache = new Map<string, QueryResult>();
|
|
37
|
-
return createFlatProxy<CreateTRPCNextAppRouter<TRouter>>((key) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// useEffect(() => {
|
|
49
|
-
// const promise = normalizePromiseArray(cb(useProxy));
|
|
50
|
-
|
|
51
|
-
// void promise.then(setData).catch((err) => {
|
|
52
|
-
// throw err;
|
|
53
|
-
// });
|
|
54
|
-
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
55
|
-
// }, []);
|
|
56
|
-
|
|
57
|
-
// return data;
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return createRecursiveProxy(({ path, args }) => {
|
|
62
|
-
const pathCopy = [key, ...path];
|
|
63
|
-
const procedureType = clientCallTypeToProcedureType(pathCopy.pop()!);
|
|
44
|
+
// return createFlatProxy<CreateTRPCNextAppRouter<TRouter>>((key) => {
|
|
45
|
+
// if (key === 'use') {
|
|
46
|
+
// return (
|
|
47
|
+
// cb: (
|
|
48
|
+
// t: UseProcedureRecord<TRouter>,
|
|
49
|
+
// ) => Promise<unknown> | Promise<unknown>[],
|
|
50
|
+
// ) => {
|
|
51
|
+
// const promise = normalizePromiseArray(cb(useProxy));
|
|
52
|
+
// throw promise;
|
|
53
|
+
// // const [data, setData] = useState<unknown | unknown[]>();
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const cached = cache.get(queryCacheKey);
|
|
55
|
+
// // useEffect(() => {
|
|
56
|
+
// // const promise = normalizePromiseArray(cb(useProxy));
|
|
68
57
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
58
|
+
// // void promise.then(setData).catch((err) => {
|
|
59
|
+
// // throw err;
|
|
60
|
+
// // });
|
|
61
|
+
// // // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
62
|
+
// // }, []);
|
|
73
63
|
|
|
74
|
-
|
|
64
|
+
// // return data;
|
|
65
|
+
// };
|
|
66
|
+
// }
|
|
75
67
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (procedureType !== 'query') {
|
|
81
|
-
return promise;
|
|
82
|
-
}
|
|
68
|
+
return createRecursiveProxy(({ path, args }) => {
|
|
69
|
+
// const pathCopy = [key, ...path];
|
|
70
|
+
const pathCopy = [...path];
|
|
71
|
+
const procedureType = clientCallTypeToProcedureType(pathCopy.pop()!);
|
|
83
72
|
|
|
73
|
+
if (procedureType === 'query') {
|
|
84
74
|
const queryCacheKey = JSON.stringify([path, args[0]]);
|
|
75
|
+
const cached = cache.get(queryCacheKey);
|
|
85
76
|
|
|
86
|
-
|
|
87
|
-
promise
|
|
88
|
-
}
|
|
77
|
+
if (cached?.promise) {
|
|
78
|
+
return cached.promise;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
89
81
|
|
|
82
|
+
const fullPath = pathCopy.join('.');
|
|
83
|
+
|
|
84
|
+
const promise: Promise<unknown> = (client as any)[procedureType](
|
|
85
|
+
fullPath,
|
|
86
|
+
...args,
|
|
87
|
+
);
|
|
88
|
+
if (procedureType !== 'query') {
|
|
90
89
|
return promise;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const queryCacheKey = JSON.stringify([path, args[0]]);
|
|
93
|
+
|
|
94
|
+
cache.set(queryCacheKey, {
|
|
95
|
+
promise,
|
|
91
96
|
});
|
|
92
|
-
|
|
97
|
+
|
|
98
|
+
return promise;
|
|
99
|
+
}) as CreateTRPCProxyClient<TRouter>;
|
|
100
|
+
// });
|
|
93
101
|
}
|