@orpc/server 0.0.0-next.b15d206 → 0.0.0-next.c29cb6d

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.
Files changed (80) hide show
  1. package/dist/chunk-YAVPFNPF.js +182 -0
  2. package/dist/fetch.js +237 -632
  3. package/dist/index.js +402 -278
  4. package/dist/src/builder.d.ts +26 -40
  5. package/dist/src/fetch/composite-handler.d.ts +8 -0
  6. package/dist/src/fetch/index.d.ts +6 -0
  7. package/dist/src/fetch/orpc-handler.d.ts +20 -0
  8. package/dist/src/fetch/orpc-payload-codec.d.ts +9 -0
  9. package/dist/src/fetch/orpc-procedure-matcher.d.ts +12 -0
  10. package/dist/src/fetch/super-json.d.ts +12 -0
  11. package/dist/src/fetch/types.d.ts +16 -0
  12. package/dist/src/hidden.d.ts +6 -0
  13. package/dist/src/implementer-chainable.d.ts +10 -0
  14. package/dist/src/index.d.ts +11 -3
  15. package/dist/src/lazy-decorated.d.ts +10 -0
  16. package/dist/src/lazy-utils.d.ts +4 -0
  17. package/dist/src/lazy.d.ts +18 -0
  18. package/dist/src/middleware-decorated.d.ts +8 -0
  19. package/dist/src/middleware.d.ts +3 -6
  20. package/dist/src/procedure-builder.d.ts +15 -24
  21. package/dist/src/procedure-client.d.ts +34 -0
  22. package/dist/src/procedure-decorated.d.ts +14 -0
  23. package/dist/src/procedure-implementer.d.ts +13 -13
  24. package/dist/src/procedure.d.ts +18 -24
  25. package/dist/src/router-builder.d.ts +24 -17
  26. package/dist/src/router-client.d.ts +25 -0
  27. package/dist/src/router-implementer.d.ts +18 -17
  28. package/dist/src/router.d.ts +11 -15
  29. package/dist/src/types.d.ts +8 -4
  30. package/package.json +13 -21
  31. package/dist/chunk-TDFYNRZV.js +0 -190
  32. package/dist/chunk-TDFYNRZV.js.map +0 -1
  33. package/dist/fetch.js.map +0 -1
  34. package/dist/index.js.map +0 -1
  35. package/dist/src/adapters/fetch.d.ts +0 -42
  36. package/dist/src/adapters/fetch.d.ts.map +0 -1
  37. package/dist/src/builder.d.ts.map +0 -1
  38. package/dist/src/index.d.ts.map +0 -1
  39. package/dist/src/middleware.d.ts.map +0 -1
  40. package/dist/src/procedure-builder.d.ts.map +0 -1
  41. package/dist/src/procedure-caller.d.ts +0 -19
  42. package/dist/src/procedure-caller.d.ts.map +0 -1
  43. package/dist/src/procedure-implementer.d.ts.map +0 -1
  44. package/dist/src/procedure.d.ts.map +0 -1
  45. package/dist/src/router-builder.d.ts.map +0 -1
  46. package/dist/src/router-caller.d.ts +0 -22
  47. package/dist/src/router-caller.d.ts.map +0 -1
  48. package/dist/src/router-implementer.d.ts.map +0 -1
  49. package/dist/src/router.d.ts.map +0 -1
  50. package/dist/src/types.d.ts.map +0 -1
  51. package/dist/src/utils.d.ts.map +0 -1
  52. package/dist/tsconfig.tsbuildinfo +0 -1
  53. package/src/adapters/fetch.test.ts +0 -629
  54. package/src/adapters/fetch.ts +0 -290
  55. package/src/builder.test.ts +0 -371
  56. package/src/builder.ts +0 -238
  57. package/src/index.ts +0 -16
  58. package/src/middleware.test.ts +0 -260
  59. package/src/middleware.ts +0 -136
  60. package/src/procedure-builder.test.ts +0 -223
  61. package/src/procedure-builder.ts +0 -158
  62. package/src/procedure-caller.test.ts +0 -171
  63. package/src/procedure-caller.ts +0 -138
  64. package/src/procedure-implementer.test.ts +0 -220
  65. package/src/procedure-implementer.ts +0 -102
  66. package/src/procedure.test.ts +0 -317
  67. package/src/procedure.ts +0 -237
  68. package/src/router-builder.test.ts +0 -106
  69. package/src/router-builder.ts +0 -122
  70. package/src/router-caller.test.ts +0 -126
  71. package/src/router-caller.ts +0 -64
  72. package/src/router-implementer.test.ts +0 -116
  73. package/src/router-implementer.ts +0 -113
  74. package/src/router.test-d.ts +0 -48
  75. package/src/router.test.ts +0 -142
  76. package/src/router.ts +0 -91
  77. package/src/types.test.ts +0 -18
  78. package/src/types.ts +0 -13
  79. package/src/utils.test.ts +0 -16
  80. package/src/utils.ts +0 -16
@@ -1,220 +0,0 @@
1
- import type { DecoratedProcedure, Meta, MiddlewareMeta } from '.'
2
- import { DecoratedContractProcedure } from '@orpc/contract'
3
- import { z } from 'zod'
4
- import { isProcedure, os } from '.'
5
- import { ProcedureImplementer } from './procedure-implementer'
6
-
7
- const p1 = new DecoratedContractProcedure({
8
- InputSchema: undefined,
9
- OutputSchema: undefined,
10
- method: undefined,
11
- path: undefined,
12
- })
13
- const implementer1 = new ProcedureImplementer<
14
- { auth: boolean },
15
- undefined,
16
- undefined,
17
- undefined
18
- >({ contract: p1 })
19
-
20
- const schema1 = z.object({ id: z.string() })
21
- const schema2 = z.object({ name: z.string() })
22
-
23
- const p2 = new DecoratedContractProcedure({
24
- InputSchema: schema1,
25
- OutputSchema: schema2,
26
- method: 'GET',
27
- path: '/test',
28
- })
29
-
30
- const implementer2 = new ProcedureImplementer<
31
- { auth: boolean },
32
- undefined,
33
- typeof schema1,
34
- typeof schema2
35
- >({ contract: p2 })
36
-
37
- describe('use middleware', () => {
38
- it('infer types', () => {
39
- const i = implementer1
40
- .use((input, context, meta) => {
41
- expectTypeOf(input).toEqualTypeOf<unknown>()
42
- expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
43
- expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
44
-
45
- return meta.next({
46
- context: {
47
- userId: '1',
48
- },
49
- })
50
- })
51
- .use((input, context, meta) => {
52
- expectTypeOf(input).toEqualTypeOf<unknown>()
53
- expectTypeOf(context).toEqualTypeOf<
54
- { userId: string } & { auth: boolean }
55
- >()
56
- expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
57
-
58
- return meta.next({})
59
- })
60
-
61
- expectTypeOf(i).toEqualTypeOf<
62
- ProcedureImplementer<
63
- { auth: boolean },
64
- { userId: string },
65
- undefined,
66
- undefined
67
- >
68
- >()
69
- })
70
-
71
- it('map middleware input', () => {
72
- // @ts-expect-error mismatch input
73
- implementer2.use((input: { postId: string }) => {
74
- return { context: { a: 'a' } }
75
- })
76
-
77
- implementer2.use(
78
- (input: { postId: string }, _, meta) => {
79
- return meta.next({ context: { a: 'a' } })
80
- },
81
- // @ts-expect-error mismatch input
82
- input => ({ postId: 12455 }),
83
- )
84
-
85
- implementer2.use(
86
- (input: { postId: string }, context, meta) => meta.next({}),
87
- input => ({ postId: '12455' }),
88
- )
89
-
90
- const i = implementer2.use(
91
- (input: { id: number }, _, meta) => {
92
- return meta.next({
93
- context: {
94
- userIdd: '1',
95
- },
96
- })
97
- },
98
- input => ({ id: Number.parseInt(input.id) }),
99
- )
100
-
101
- expectTypeOf(i).toEqualTypeOf<
102
- ProcedureImplementer<
103
- { auth: boolean },
104
- { userIdd: string },
105
- typeof schema1,
106
- typeof schema2
107
- >
108
- >()
109
- })
110
- })
111
-
112
- describe('output schema', () => {
113
- it('auto infer output schema if output schema is not specified', async () => {
114
- const sr = os.func(() => ({ a: 1 }))
115
-
116
- const result = await sr.zz$p.func({}, undefined, {
117
- method: 'GET',
118
- path: '/',
119
- } as any)
120
-
121
- expectTypeOf(result).toEqualTypeOf<{ a: number }>()
122
- })
123
-
124
- it('not infer output schema if output schema is specified', async () => {
125
- const srb1 = new ProcedureImplementer({
126
- contract: new DecoratedContractProcedure({
127
- OutputSchema: z.unknown(),
128
- InputSchema: undefined,
129
- }),
130
- })
131
-
132
- const sr = srb1.func(() => ({ b: 1 }))
133
-
134
- const result = await sr.zz$p.func({}, {}, {
135
- method: 'GET',
136
- path: '/',
137
- } as any)
138
-
139
- expectTypeOf(result).toEqualTypeOf<unknown>()
140
- })
141
- })
142
-
143
- describe('handler', () => {
144
- it('infer types', () => {
145
- const handler = implementer1.func((input, context, meta) => {
146
- expectTypeOf(input).toEqualTypeOf<unknown>()
147
- expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
148
- expectTypeOf(meta).toEqualTypeOf<Meta>()
149
-
150
- return {
151
- name: 'unnoq',
152
- }
153
- })
154
-
155
- expectTypeOf(handler).toEqualTypeOf<
156
- DecoratedProcedure<
157
- { auth: boolean },
158
- undefined,
159
- undefined,
160
- undefined,
161
- { name: string }
162
- >
163
- >()
164
- expect(isProcedure(handler)).toBe(true)
165
-
166
- implementer2.func((input, context, meta) => {
167
- expectTypeOf(input).toEqualTypeOf<{ id: string }>()
168
- expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
169
- expectTypeOf(meta).toEqualTypeOf<Meta>()
170
-
171
- return {
172
- name: 'unnoq',
173
- }
174
- })
175
-
176
- // @ts-expect-error mismatch output
177
- implementer2.func(() => {})
178
- })
179
-
180
- it('combine middlewares', () => {
181
- const mid1 = os.middleware((input, context, meta) => {
182
- return meta.next({
183
- context: {
184
- userId: '1',
185
- },
186
- })
187
- })
188
-
189
- const mid2 = os.middleware((input, context, meta) => {
190
- return meta.next({ })
191
- })
192
-
193
- const handler = implementer2
194
- .use(mid1)
195
- .use(mid2)
196
- .func((input, context, meta) => {
197
- expectTypeOf(input).toEqualTypeOf<{ id: string }>()
198
- expectTypeOf(context).toEqualTypeOf<
199
- { auth: boolean } & { userId: string }
200
- >()
201
- expectTypeOf(meta).toEqualTypeOf<Meta>()
202
-
203
- return {
204
- name: 'unnoq',
205
- }
206
- })
207
-
208
- expectTypeOf(handler).toEqualTypeOf<
209
- DecoratedProcedure<
210
- { auth: boolean },
211
- { userId: string },
212
- typeof schema1,
213
- typeof schema2,
214
- { name: string }
215
- >
216
- >()
217
-
218
- expect(handler.zz$p.middlewares).toEqual([mid1, mid2])
219
- })
220
- })
@@ -1,102 +0,0 @@
1
- import type { ContractProcedure, Schema, SchemaInput, SchemaOutput } from '@orpc/contract'
2
- import type { Context, MergeContext } from './types'
3
- import {
4
- decorateMiddleware,
5
- type MapInputMiddleware,
6
- type Middleware,
7
- } from './middleware'
8
- import {
9
- type DecoratedProcedure,
10
- decorateProcedure,
11
- type ProcedureFunc,
12
- } from './procedure'
13
-
14
- export class ProcedureImplementer<
15
- TContext extends Context,
16
- TExtraContext extends Context,
17
- TInputSchema extends Schema,
18
- TOutputSchema extends Schema,
19
- > {
20
- constructor(
21
- public zz$pi: {
22
- contract: ContractProcedure<TInputSchema, TOutputSchema>
23
- middlewares?: Middleware<any, any, any, any>[]
24
- },
25
- ) {}
26
-
27
- use<
28
- UExtraContext extends
29
- | Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
30
- | undefined = undefined,
31
- >(
32
- middleware: Middleware<
33
- MergeContext<TContext, TExtraContext>,
34
- UExtraContext,
35
- SchemaOutput<TInputSchema>,
36
- SchemaInput<TOutputSchema>
37
- >,
38
- ): ProcedureImplementer<
39
- TContext,
40
- MergeContext<TExtraContext, UExtraContext>,
41
- TInputSchema,
42
- TOutputSchema
43
- >
44
-
45
- use<
46
- UExtraContext extends
47
- | Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
48
- | undefined = undefined,
49
- UMappedInput = unknown,
50
- >(
51
- middleware: Middleware<
52
- MergeContext<TContext, TExtraContext>,
53
- UExtraContext,
54
- UMappedInput,
55
- SchemaInput<TOutputSchema>
56
- >,
57
- mapInput: MapInputMiddleware<SchemaOutput<TInputSchema>, UMappedInput>,
58
- ): ProcedureImplementer<
59
- TContext,
60
- MergeContext<TExtraContext, UExtraContext>,
61
- TInputSchema,
62
- TOutputSchema
63
- >
64
-
65
- use(
66
- middleware: Middleware<any, any, any, any>,
67
- mapInput?: MapInputMiddleware<any, any>,
68
- ): ProcedureImplementer<any, any, any, any> {
69
- const middleware_ = mapInput
70
- ? decorateMiddleware(middleware).mapInput(mapInput)
71
- : middleware
72
-
73
- return new ProcedureImplementer({
74
- ...this.zz$pi,
75
- middlewares: [...(this.zz$pi.middlewares ?? []), middleware_],
76
- })
77
- }
78
-
79
- func<UFuncOutput extends SchemaOutput<TOutputSchema>>(
80
- func: ProcedureFunc<
81
- TContext,
82
- TExtraContext,
83
- TInputSchema,
84
- TOutputSchema,
85
- UFuncOutput
86
- >,
87
- ): DecoratedProcedure<
88
- TContext,
89
- TExtraContext,
90
- TInputSchema,
91
- TOutputSchema,
92
- UFuncOutput
93
- > {
94
- return decorateProcedure({
95
- zz$p: {
96
- middlewares: this.zz$pi.middlewares,
97
- contract: this.zz$pi.contract,
98
- func,
99
- },
100
- })
101
- }
102
- }
@@ -1,317 +0,0 @@
1
- import type { MiddlewareMeta } from '.'
2
- import { ContractProcedure, DecoratedContractProcedure } from '@orpc/contract'
3
- import { z } from 'zod'
4
- import { os } from '.'
5
- import {
6
- type DecoratedProcedure,
7
- decorateProcedure,
8
- isProcedure,
9
- Procedure,
10
- } from './procedure'
11
-
12
- it('isProcedure', () => {
13
- expect(
14
- isProcedure(
15
- decorateProcedure(
16
- new Procedure({
17
- contract: new ContractProcedure({
18
- InputSchema: undefined,
19
- OutputSchema: undefined,
20
- }),
21
- func: () => {},
22
- }),
23
- ),
24
- ),
25
- ).toBe(true)
26
- expect({
27
- zz$p: {
28
- contract: new DecoratedContractProcedure({
29
- InputSchema: undefined,
30
- OutputSchema: undefined,
31
- }),
32
- func: () => {},
33
- },
34
- }).toSatisfy(isProcedure)
35
-
36
- expect({
37
- zz$p: {
38
- contract: new DecoratedContractProcedure({
39
- InputSchema: undefined,
40
- OutputSchema: undefined,
41
- }),
42
- },
43
- }).not.toSatisfy(isProcedure)
44
-
45
- expect({
46
- zz$p: {
47
- handler: () => {},
48
- },
49
- }).not.toSatisfy(isProcedure)
50
-
51
- expect({}).not.toSatisfy(isProcedure)
52
- expect(12233).not.toSatisfy(isProcedure)
53
- expect('12233').not.toSatisfy(isProcedure)
54
- expect(undefined).not.toSatisfy(isProcedure)
55
- expect(null).not.toSatisfy(isProcedure)
56
- })
57
-
58
- describe('route method', () => {
59
- it('sets route options correctly', () => {
60
- const p = os.context<{ auth: boolean }>().func(() => {
61
- return 'test'
62
- })
63
-
64
- const p2 = p.route({ path: '/test', method: 'GET' })
65
-
66
- expect(p2.zz$p.contract.zz$cp.path).toBe('/test')
67
- expect(p2.zz$p.contract.zz$cp.method).toBe('GET')
68
- })
69
-
70
- it('preserves existing context and handler', () => {
71
- const handler = () => 'test'
72
- const p = os.context<{ auth: boolean }>().func(handler)
73
-
74
- const p2 = p.route({ path: '/test' })
75
-
76
- expect(p2.zz$p.func).toBe(handler)
77
- // Context type is preserved through the route method
78
- expectTypeOf(p2).toEqualTypeOf<
79
- DecoratedProcedure<
80
- { auth: boolean },
81
- undefined,
82
- undefined,
83
- undefined,
84
- string
85
- >
86
- >()
87
- })
88
-
89
- it('works with prefix method', () => {
90
- const p = os
91
- .context<{ auth: boolean }>()
92
- .route({ path: '/api', method: 'POST' })
93
- .func(() => 'test')
94
-
95
- const p2 = p.prefix('/v1')
96
-
97
- expect(p2.zz$p.contract.zz$cp.path).toBe('/v1/api')
98
- expect(p2.zz$p.contract.zz$cp.method).toBe('POST')
99
- })
100
-
101
- it('works with middleware', () => {
102
- const mid = os.middleware((_, __, meta) => meta.next({ context: { userId: '1' } }))
103
-
104
- const p = os
105
- .context<{ auth: boolean }>()
106
- .route({ path: '/test' })
107
- .use(mid)
108
- .func((input, context) => {
109
- expectTypeOf(context).toEqualTypeOf<
110
- { auth: boolean } & { userId: string }
111
- >()
112
- return 'test'
113
- })
114
-
115
- expect(p.zz$p.contract.zz$cp.path).toBe('/test')
116
- expect(p.zz$p.middlewares).toEqual([mid])
117
- })
118
-
119
- it('overrides existing route options', () => {
120
- const p = os
121
- .context<{ auth: boolean }>()
122
- .route({ path: '/test1', method: 'GET' })
123
- .func(() => 'test')
124
-
125
- const p2 = p.route({ path: '/test2', method: 'POST' })
126
-
127
- expect(p2.zz$p.contract.zz$cp.path).toBe('/test2')
128
- expect(p2.zz$p.contract.zz$cp.method).toBe('POST')
129
- })
130
-
131
- it('preserves input/output schemas', () => {
132
- const inputSchema = z.object({ id: z.number() })
133
- const outputSchema = z.string()
134
- const p = os
135
- .context<{ auth: boolean }>()
136
- .input(inputSchema)
137
- .output(outputSchema)
138
- .route({ path: '/test' })
139
- .func((input) => {
140
- expectTypeOf(input).toEqualTypeOf<{ id: number }>()
141
- return 'test'
142
- })
143
-
144
- const p2 = p.route({ path: '/test2' })
145
-
146
- // Type checking that schemas are preserved
147
- expectTypeOf(p2).toEqualTypeOf<
148
- DecoratedProcedure<
149
- { auth: boolean },
150
- undefined,
151
- typeof inputSchema,
152
- typeof outputSchema,
153
- string
154
- >
155
- >()
156
- })
157
- })
158
-
159
- it('prefix method', () => {
160
- const p = os.context<{ auth: boolean }>().func(() => {
161
- return 'unnoq'
162
- })
163
-
164
- const p2 = p.prefix('/test')
165
-
166
- expect(p2.zz$p.contract.zz$cp.path).toBe(undefined)
167
-
168
- const p3 = os
169
- .context<{ auth: boolean }>()
170
- .route({ path: '/test1' })
171
- .func(() => {
172
- return 'unnoq'
173
- })
174
-
175
- const p4 = p3.prefix('/test')
176
- expect(p4.zz$p.contract.zz$cp.path).toBe('/test/test1')
177
- })
178
-
179
- describe('use middleware', () => {
180
- it('infer types', () => {
181
- const p1 = os
182
- .context<{ auth: boolean }>()
183
- .use((_, __, meta) => {
184
- return meta.next({ context: { postId: 'string' } })
185
- })
186
- .func(() => {
187
- return 'unnoq'
188
- })
189
-
190
- const p2 = p1
191
- .use((input, context, meta) => {
192
- expectTypeOf(input).toEqualTypeOf<unknown>()
193
- expectTypeOf(context).toEqualTypeOf<
194
- { auth: boolean } & { postId: string }
195
- >()
196
- expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<string>>()
197
-
198
- return meta.next({
199
- context: {
200
- userId: '1',
201
- },
202
- })
203
- })
204
- .use((input, context, meta) => {
205
- expectTypeOf(input).toEqualTypeOf<unknown>()
206
- expectTypeOf(context).toEqualTypeOf<
207
- { userId: string } & { postId: string } & { auth: boolean }
208
- >()
209
- expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<string>>()
210
-
211
- return meta.next({})
212
- })
213
-
214
- expectTypeOf(p2).toEqualTypeOf<
215
- DecoratedProcedure<
216
- { auth: boolean },
217
- { postId: string } & { userId: string },
218
- undefined,
219
- undefined,
220
- string
221
- >
222
- >()
223
- })
224
-
225
- it('can map input', () => {
226
- const mid = os.middleware((input: { id: number }, __, meta) => {
227
- return meta.next({})
228
- })
229
-
230
- os.input(z.object({ postId: z.number() })).use(mid, (input) => {
231
- expectTypeOf(input).toEqualTypeOf<{ postId: number }>()
232
-
233
- return {
234
- id: input.postId,
235
- }
236
- })
237
-
238
- // @ts-expect-error mismatch input
239
- os.input(z.object({ postId: z.number() })).use(mid)
240
-
241
- // @ts-expect-error mismatch input
242
- os.input(z.object({ postId: z.number() })).use(mid, (input) => {
243
- return {
244
- wrong: input.postId,
245
- }
246
- })
247
- })
248
-
249
- it('add middlewares to beginning', () => {
250
- const mid1 = vi.fn()
251
- const mid2 = vi.fn()
252
- const mid3 = vi.fn()
253
-
254
- const p1 = os.use(mid1).func(() => 'unnoq')
255
- const p2 = p1.use(mid2).use(mid3)
256
-
257
- expect(p2.zz$p.middlewares).toEqual([mid3, mid2, mid1])
258
- })
259
- })
260
-
261
- describe('server action', () => {
262
- it('only accept undefined context', () => {
263
- expectTypeOf(os.func(() => {})).toMatchTypeOf<(...args: any[]) => any>()
264
- expectTypeOf(
265
- os.context<{ auth: boolean } | undefined>().func(() => {}),
266
- ).toMatchTypeOf<(...args: any[]) => any>()
267
- expectTypeOf(
268
- os.context<{ auth: boolean }>().func(() => {}),
269
- ).not.toMatchTypeOf<(...args: any[]) => any>()
270
- })
271
-
272
- it('infer types', () => {
273
- const p = os
274
- .input(z.object({ id: z.number() }))
275
- .output(z.string())
276
- .func(() => 'string')
277
-
278
- expectTypeOf(p).toMatchTypeOf<
279
- (input: { id: number } | FormData) => Promise<string>
280
- >()
281
-
282
- const p2 = os.input(z.object({ id: z.number() })).func(() => 12333)
283
-
284
- expectTypeOf(p2).toMatchTypeOf<
285
- (input: { id: number } | FormData) => Promise<number>
286
- >()
287
- })
288
-
289
- it('works with input', async () => {
290
- const p = os
291
- .input(z.object({ id: z.number(), date: z.date() }))
292
- .func(async (input, context) => {
293
- expect(context).toBe(undefined)
294
- return input
295
- })
296
-
297
- expect(await p({ id: 123, date: new Date('2022-01-01') })).toEqual({
298
- id: 123,
299
- date: new Date('2022-01-01'),
300
- })
301
- })
302
-
303
- it('can deserialize form data', async () => {
304
- const p = os
305
- .input(z.object({ id: z.number(), nested: z.object({ date: z.date() }) }))
306
- .func(async input => input)
307
-
308
- const form = new FormData()
309
- form.append('id', '123')
310
- form.append('nested[date]', '2022-01-01')
311
-
312
- expect(await p(form)).toEqual({
313
- id: 123,
314
- nested: { date: new Date('2022-01-01') },
315
- })
316
- })
317
- })