@orpc/server 0.0.0-next.83ec2e8 → 0.0.0-next.842d6b5

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 (122) hide show
  1. package/README.md +127 -0
  2. package/dist/adapters/aws-lambda/index.d.mts +46 -0
  3. package/dist/adapters/aws-lambda/index.d.ts +46 -0
  4. package/dist/adapters/aws-lambda/index.mjs +42 -0
  5. package/dist/adapters/bun-ws/index.d.mts +36 -0
  6. package/dist/adapters/bun-ws/index.d.ts +36 -0
  7. package/dist/adapters/bun-ws/index.mjs +47 -0
  8. package/dist/adapters/crossws/index.d.mts +33 -0
  9. package/dist/adapters/crossws/index.d.ts +33 -0
  10. package/dist/adapters/crossws/index.mjs +45 -0
  11. package/dist/adapters/fetch/index.d.mts +79 -0
  12. package/dist/adapters/fetch/index.d.ts +79 -0
  13. package/dist/adapters/fetch/index.mjs +110 -0
  14. package/dist/adapters/message-port/index.d.mts +31 -0
  15. package/dist/adapters/message-port/index.d.ts +31 -0
  16. package/dist/adapters/message-port/index.mjs +39 -0
  17. package/dist/adapters/node/index.d.mts +78 -0
  18. package/dist/adapters/node/index.d.ts +78 -0
  19. package/dist/adapters/node/index.mjs +96 -0
  20. package/dist/adapters/standard/index.d.mts +21 -0
  21. package/dist/adapters/standard/index.d.ts +21 -0
  22. package/dist/adapters/standard/index.mjs +8 -0
  23. package/dist/adapters/standard-peer/index.d.mts +18 -0
  24. package/dist/adapters/standard-peer/index.d.ts +18 -0
  25. package/dist/adapters/standard-peer/index.mjs +7 -0
  26. package/dist/adapters/websocket/index.d.mts +54 -0
  27. package/dist/adapters/websocket/index.d.ts +54 -0
  28. package/dist/adapters/websocket/index.mjs +67 -0
  29. package/dist/adapters/ws/index.d.mts +31 -0
  30. package/dist/adapters/ws/index.d.ts +31 -0
  31. package/dist/adapters/ws/index.mjs +37 -0
  32. package/dist/helpers/index.d.mts +134 -0
  33. package/dist/helpers/index.d.ts +134 -0
  34. package/dist/helpers/index.mjs +188 -0
  35. package/dist/hibernation/index.d.mts +44 -0
  36. package/dist/hibernation/index.d.ts +44 -0
  37. package/dist/hibernation/index.mjs +65 -0
  38. package/dist/index.d.mts +803 -0
  39. package/dist/index.d.ts +803 -0
  40. package/dist/index.mjs +489 -0
  41. package/dist/plugins/index.d.mts +169 -0
  42. package/dist/plugins/index.d.ts +169 -0
  43. package/dist/plugins/index.mjs +285 -0
  44. package/dist/shared/server.B7b2w3_i.d.ts +12 -0
  45. package/dist/shared/server.BEFBl-Cb.d.mts +12 -0
  46. package/dist/shared/server.BU4WI18A.d.mts +32 -0
  47. package/dist/shared/server.BW-nUGgA.mjs +36 -0
  48. package/dist/shared/server.Bmh5xd4n.d.ts +74 -0
  49. package/dist/shared/server.BohymmQ6.mjs +219 -0
  50. package/dist/shared/server.CQr6WNc2.mjs +408 -0
  51. package/dist/shared/server.CYNGeoCm.d.mts +194 -0
  52. package/dist/shared/server.CYNGeoCm.d.ts +194 -0
  53. package/dist/shared/server.D0H-iaY3.d.ts +32 -0
  54. package/dist/shared/server.DZ5BIITo.mjs +9 -0
  55. package/dist/shared/server.DhJj-1X9.d.mts +42 -0
  56. package/dist/shared/server.UVMTOWrk.mjs +26 -0
  57. package/dist/shared/server.gqRxT-yN.d.mts +74 -0
  58. package/dist/shared/server.jMTkVNIb.d.ts +42 -0
  59. package/package.json +94 -19
  60. package/dist/chunk-TDFYNRZV.js +0 -190
  61. package/dist/chunk-TDFYNRZV.js.map +0 -1
  62. package/dist/fetch.js +0 -681
  63. package/dist/fetch.js.map +0 -1
  64. package/dist/index.js +0 -394
  65. package/dist/index.js.map +0 -1
  66. package/dist/src/adapters/fetch.d.ts +0 -42
  67. package/dist/src/adapters/fetch.d.ts.map +0 -1
  68. package/dist/src/builder.d.ts +0 -49
  69. package/dist/src/builder.d.ts.map +0 -1
  70. package/dist/src/index.d.ts +0 -15
  71. package/dist/src/index.d.ts.map +0 -1
  72. package/dist/src/middleware.d.ts +0 -26
  73. package/dist/src/middleware.d.ts.map +0 -1
  74. package/dist/src/procedure-builder.d.ts +0 -31
  75. package/dist/src/procedure-builder.d.ts.map +0 -1
  76. package/dist/src/procedure-caller.d.ts +0 -19
  77. package/dist/src/procedure-caller.d.ts.map +0 -1
  78. package/dist/src/procedure-implementer.d.ts +0 -18
  79. package/dist/src/procedure-implementer.d.ts.map +0 -1
  80. package/dist/src/procedure.d.ts +0 -29
  81. package/dist/src/procedure.d.ts.map +0 -1
  82. package/dist/src/router-builder.d.ts +0 -22
  83. package/dist/src/router-builder.d.ts.map +0 -1
  84. package/dist/src/router-caller.d.ts +0 -22
  85. package/dist/src/router-caller.d.ts.map +0 -1
  86. package/dist/src/router-implementer.d.ts +0 -20
  87. package/dist/src/router-implementer.d.ts.map +0 -1
  88. package/dist/src/router.d.ts +0 -20
  89. package/dist/src/router.d.ts.map +0 -1
  90. package/dist/src/types.d.ts +0 -8
  91. package/dist/src/types.d.ts.map +0 -1
  92. package/dist/src/utils.d.ts +0 -3
  93. package/dist/src/utils.d.ts.map +0 -1
  94. package/dist/tsconfig.tsbuildinfo +0 -1
  95. package/src/adapters/fetch.test.ts +0 -629
  96. package/src/adapters/fetch.ts +0 -290
  97. package/src/builder.test.ts +0 -371
  98. package/src/builder.ts +0 -238
  99. package/src/index.ts +0 -16
  100. package/src/middleware.test.ts +0 -260
  101. package/src/middleware.ts +0 -136
  102. package/src/procedure-builder.test.ts +0 -223
  103. package/src/procedure-builder.ts +0 -158
  104. package/src/procedure-caller.test.ts +0 -171
  105. package/src/procedure-caller.ts +0 -138
  106. package/src/procedure-implementer.test.ts +0 -220
  107. package/src/procedure-implementer.ts +0 -102
  108. package/src/procedure.test.ts +0 -317
  109. package/src/procedure.ts +0 -237
  110. package/src/router-builder.test.ts +0 -106
  111. package/src/router-builder.ts +0 -122
  112. package/src/router-caller.test.ts +0 -126
  113. package/src/router-caller.ts +0 -64
  114. package/src/router-implementer.test.ts +0 -116
  115. package/src/router-implementer.ts +0 -113
  116. package/src/router.test-d.ts +0 -48
  117. package/src/router.test.ts +0 -142
  118. package/src/router.ts +0 -91
  119. package/src/types.test.ts +0 -18
  120. package/src/types.ts +0 -13
  121. package/src/utils.test.ts +0 -16
  122. package/src/utils.ts +0 -16
@@ -1,629 +0,0 @@
1
- import { ORPC_HEADER, ORPC_HEADER_VALUE } from '@orpc/contract'
2
- import { oz } from '@orpc/zod'
3
- import { describe, expect, it } from 'vitest'
4
- import { z } from 'zod'
5
- import { ORPCError, os } from '..'
6
- import { createFetchHandler } from './fetch'
7
-
8
- const router = os.router({
9
- throw: os.func(() => {
10
- throw new Error('test')
11
- }),
12
- ping: os.func(() => {
13
- return 'ping'
14
- }),
15
- ping2: os.route({ method: 'GET', path: '/ping2' }).func(() => {
16
- return 'ping2'
17
- }),
18
- })
19
-
20
- const handler = createFetchHandler({ router })
21
-
22
- describe('simple', () => {
23
- const osw = os.context<{ auth?: boolean }>()
24
- const router = osw.router({
25
- ping: osw.func(async () => 'pong'),
26
- ping2: osw
27
- .route({ method: 'GET', path: '/ping2' })
28
- .func(async () => 'pong2'),
29
- })
30
- const handler = createFetchHandler({
31
- router,
32
- })
33
-
34
- it('200: public url', async () => {
35
- const response = await handler({
36
- prefix: '/orpc',
37
- request: new Request('http://localhost/orpc/ping', {
38
- method: 'POST',
39
- }),
40
- context: () => ({ auth: true }),
41
- })
42
-
43
- expect(response.status).toBe(200)
44
- expect(await response.json()).toEqual('pong')
45
-
46
- const response2 = await handler({
47
- prefix: '/orpc',
48
- request: new Request('http://localhost/orpc/ping2', {
49
- method: 'GET',
50
- }),
51
- context: { auth: true },
52
- })
53
-
54
- expect(response2.status).toBe(200)
55
- expect(await response2.json()).toEqual('pong2')
56
- })
57
-
58
- it('200: internal url', async () => {
59
- const response = await handler({
60
- request: new Request('http://localhost/ping'),
61
- context: { auth: true },
62
- })
63
-
64
- expect(response.status).toBe(200)
65
- expect(await response.json()).toEqual('pong')
66
-
67
- const response2 = await handler({
68
- prefix: '/orpc',
69
- request: new Request('http://localhost/orpc/ping2'),
70
- context: { auth: true },
71
- })
72
-
73
- expect(response2.status).toBe(200)
74
- expect(await response2.json()).toEqual('pong2')
75
- })
76
-
77
- it('404', async () => {
78
- const response = await handler({
79
- prefix: '/orpc',
80
- request: new Request('http://localhost/orpc/pingp', {
81
- method: 'POST',
82
- }),
83
- context: { auth: true },
84
- })
85
-
86
- expect(response.status).toBe(404)
87
- })
88
- })
89
-
90
- describe('procedure throw error', () => {
91
- it('unknown error', async () => {
92
- const response = await handler({
93
- request: new Request('https://local.com/throw', { method: 'POST' }),
94
- })
95
-
96
- expect(response.status).toBe(500)
97
- expect(await response.json()).toEqual({
98
- code: 'INTERNAL_SERVER_ERROR',
99
- status: 500,
100
- message: 'Internal server error',
101
- })
102
- })
103
-
104
- it('orpc error', async () => {
105
- const router = os.router({
106
- ping: os.func(() => {
107
- throw new ORPCError({ code: 'TIMEOUT' })
108
- }),
109
- })
110
-
111
- const handler = createFetchHandler({ router })
112
-
113
- const response = await handler({
114
- request: new Request('https://local.com/ping', { method: 'POST' }),
115
- })
116
-
117
- expect(response.status).toBe(408)
118
- expect(await response.json()).toEqual({
119
- code: 'TIMEOUT',
120
- status: 408,
121
- message: '',
122
- })
123
- })
124
-
125
- it('orpc error with data', async () => {
126
- const router = os.router({
127
- ping: os.func(() => {
128
- throw new ORPCError({
129
- code: 'PAYLOAD_TOO_LARGE',
130
- message: 'test',
131
- data: { max: '10mb' },
132
- })
133
- }),
134
- })
135
-
136
- const handler = createFetchHandler({ router })
137
-
138
- const response = await handler({
139
- request: new Request('https://local.com/ping', { method: 'POST' }),
140
- })
141
-
142
- expect(response.status).toBe(413)
143
- expect(await response.json()).toEqual({
144
- code: 'PAYLOAD_TOO_LARGE',
145
- status: 413,
146
- message: 'test',
147
- data: { max: '10mb' },
148
- })
149
- })
150
-
151
- it('orpc error with custom status', async () => {
152
- const router = os.router({
153
- ping: os.func(() => {
154
- throw new ORPCError({
155
- code: 'PAYLOAD_TOO_LARGE',
156
- status: 100,
157
- })
158
- }),
159
-
160
- ping2: os.func(() => {
161
- throw new ORPCError({
162
- code: 'PAYLOAD_TOO_LARGE',
163
- status: 488,
164
- })
165
- }),
166
- })
167
-
168
- const handler = createFetchHandler({ router })
169
-
170
- const response = await handler({
171
- request: new Request('https://local.com/ping', { method: 'POST' }),
172
- })
173
-
174
- expect(response.status).toBe(500)
175
- expect(await response.json()).toEqual({
176
- code: 'INTERNAL_SERVER_ERROR',
177
- status: 500,
178
- message: 'Internal server error',
179
- })
180
-
181
- const response2 = await handler({
182
- request: new Request('https://local.com/ping2', { method: 'POST' }),
183
- })
184
-
185
- expect(response2.status).toBe(488)
186
- expect(await response2.json()).toEqual({
187
- code: 'PAYLOAD_TOO_LARGE',
188
- status: 488,
189
- message: '',
190
- })
191
- })
192
-
193
- it('input validation error', async () => {
194
- const router = os.router({
195
- ping: os
196
- .input(z.object({}))
197
- .output(z.string())
198
- .func(() => {
199
- return 'unnoq'
200
- }),
201
- })
202
-
203
- const handler = createFetchHandler({ router })
204
-
205
- const response = await handler({
206
- request: new Request('https://local.com/ping', { method: 'POST' }),
207
- })
208
-
209
- expect(response.status).toBe(400)
210
- expect(await response.json()).toEqual({
211
- code: 'BAD_REQUEST',
212
- status: 400,
213
- message: 'Validation input failed',
214
- issues: [
215
- {
216
- code: 'invalid_type',
217
- expected: 'object',
218
- message: 'Required',
219
- path: [],
220
- received: 'undefined',
221
- },
222
- ],
223
- })
224
- })
225
-
226
- it('output validation error', async () => {
227
- const router = os.router({
228
- ping: os
229
- .input(z.string())
230
- .output(z.string())
231
- .func(() => {
232
- return 12344 as any
233
- }),
234
- })
235
-
236
- const handler = createFetchHandler({ router })
237
-
238
- const response = await handler({
239
- request: new Request('https://local.com/ping', {
240
- method: 'POST',
241
- body: '"hi"',
242
- }),
243
- })
244
-
245
- expect(response.status).toBe(500)
246
- expect(await response.json()).toEqual({
247
- code: 'INTERNAL_SERVER_ERROR',
248
- status: 500,
249
- message: 'Validation output failed',
250
- })
251
- })
252
- })
253
-
254
- describe('hooks', () => {
255
- it('on success', async () => {
256
- const onSuccess = vi.fn()
257
- const onError = vi.fn()
258
- const onFinish = vi.fn()
259
-
260
- const handler = createFetchHandler({
261
- router,
262
- hooks: async (context, hooks) => {
263
- try {
264
- const response = await hooks.next()
265
- onSuccess(response)
266
- return response
267
- }
268
- catch (e) {
269
- onError(e)
270
- throw e
271
- }
272
- finally {
273
- onFinish()
274
- }
275
- },
276
- })
277
-
278
- await handler({
279
- prefix: '/orpc',
280
- request: new Request('http://localhost/orpc/ping', {
281
- method: 'POST',
282
- }),
283
- })
284
-
285
- expect(onSuccess).toHaveBeenCalledTimes(1)
286
- expect(onError).toHaveBeenCalledTimes(0)
287
- expect(onFinish).toHaveBeenCalledTimes(1)
288
-
289
- expect(onSuccess.mock.calls[0]?.[0]).toBeInstanceOf(Response)
290
- expect(onFinish.mock.calls[0]?.[1]).toBe(undefined)
291
- })
292
-
293
- it('on failed', async () => {
294
- const onSuccess = vi.fn()
295
- const onError = vi.fn()
296
- const onFinish = vi.fn()
297
-
298
- const handler = createFetchHandler({
299
- router,
300
- hooks: async (context, hooks) => {
301
- try {
302
- const response = await hooks.next()
303
- onSuccess(response)
304
- return response
305
- }
306
- catch (e) {
307
- onError(e)
308
- throw e
309
- }
310
- finally {
311
- onFinish()
312
- }
313
- },
314
- })
315
-
316
- await handler({
317
- prefix: '/orpc',
318
- request: new Request('http://localhost/orpc/throw', {
319
- method: 'POST',
320
- }),
321
- })
322
-
323
- expect(onSuccess).toHaveBeenCalledTimes(0)
324
- expect(onError).toHaveBeenCalledTimes(1)
325
- expect(onFinish).toHaveBeenCalledTimes(1)
326
-
327
- expect(onError.mock.calls[0]?.[0]).toBeInstanceOf(Error)
328
- expect(onError.mock.calls[0]?.[0]?.message).toBe('test')
329
- expect(onFinish.mock.calls[0]?.[0]).toBe(undefined)
330
- })
331
- })
332
-
333
- describe('file upload', () => {
334
- const router = os.router({
335
- signal: os.input(z.instanceof(Blob)).func((input) => {
336
- return input
337
- }),
338
- multiple: os
339
- .input(
340
- z.object({ first: z.instanceof(Blob), second: z.instanceof(Blob) }),
341
- )
342
- .func((input) => {
343
- return input
344
- }),
345
- })
346
-
347
- const handler = createFetchHandler({ router })
348
-
349
- const blob1 = new Blob(['hello'], { type: 'text/plain;charset=utf-8' })
350
- const blob2 = new Blob(['"world"'], { type: 'image/png' })
351
- const blob3 = new Blob(['unnoq'], { type: 'application/octet-stream' })
352
-
353
- it('single file', async () => {
354
- const rForm = new FormData()
355
- rForm.set('meta', JSON.stringify([]))
356
- rForm.set('maps', JSON.stringify([[]]))
357
- rForm.set('0', blob3)
358
-
359
- const response = await handler({
360
- prefix: '/orpc',
361
- request: new Request('http://localhost/orpc/signal', {
362
- method: 'POST',
363
- body: rForm,
364
- headers: {
365
- [ORPC_HEADER]: ORPC_HEADER_VALUE,
366
- },
367
- }),
368
- })
369
-
370
- expect(response.status).toBe(200)
371
- const form = await response.formData()
372
-
373
- const file0 = form.get('0') as File
374
- expect(file0).toBeInstanceOf(File)
375
- expect(file0.name).toBe('blob')
376
- expect(file0.type).toBe('application/octet-stream')
377
- expect(await file0.text()).toBe('unnoq')
378
- })
379
-
380
- it('multiple file', async () => {
381
- const form = new FormData()
382
- form.set('data', JSON.stringify({ first: blob1, second: blob2 }))
383
- form.set('meta', JSON.stringify([]))
384
- form.set('maps', JSON.stringify([['first'], ['second']]))
385
- form.set('0', blob1)
386
- form.set('1', blob2)
387
-
388
- const response = await handler({
389
- prefix: '/orpc',
390
- request: new Request('http://localhost/orpc/multiple', {
391
- method: 'POST',
392
- body: form,
393
- headers: {
394
- [ORPC_HEADER]: ORPC_HEADER_VALUE,
395
- },
396
- }),
397
- })
398
-
399
- expect(response.status).toBe(200)
400
-
401
- const form_ = await response.formData()
402
- const file0 = form_.get('0') as File
403
- const file1 = form_.get('1') as File
404
-
405
- expect(file0).toBeInstanceOf(File)
406
- expect(file0.name).toBe('blob')
407
- expect(file0.type).toBe('text/plain;charset=utf-8')
408
- expect(await file0.text()).toBe('hello')
409
-
410
- expect(file1).toBeInstanceOf(File)
411
- expect(file1.name).toBe('blob')
412
- expect(file1.type).toBe('image/png')
413
- expect(await file1.text()).toBe('"world"')
414
- })
415
- })
416
-
417
- describe('accept header', () => {
418
- const router = os.router({
419
- ping: os.func(async () => 'pong'),
420
- })
421
- const handler = createFetchHandler({
422
- router,
423
- })
424
-
425
- it('application/json', async () => {
426
- const response = await handler({
427
- prefix: '/orpc',
428
- request: new Request('http://localhost/orpc/ping', {
429
- method: 'POST',
430
- headers: {
431
- Accept: 'application/json',
432
- },
433
- }),
434
- })
435
-
436
- expect(response.headers.get('Content-Type')).toEqual('application/json')
437
-
438
- expect(await response.json()).toEqual('pong')
439
- })
440
-
441
- it('multipart/form-data', async () => {
442
- const response = await handler({
443
- prefix: '/orpc',
444
- request: new Request('http://localhost/orpc/ping', {
445
- method: 'POST',
446
- headers: {
447
- Accept: 'multipart/form-data',
448
- },
449
- }),
450
- })
451
-
452
- expect(response.headers.get('Content-Type')).toContain(
453
- 'multipart/form-data',
454
- )
455
-
456
- const form = await response.formData()
457
- expect(form.get('')).toEqual('pong')
458
- })
459
-
460
- it('application/x-www-form-urlencoded', async () => {
461
- const response = await handler({
462
- prefix: '/orpc',
463
- request: new Request('http://localhost/orpc/ping', {
464
- method: 'POST',
465
- headers: {
466
- Accept: 'application/x-www-form-urlencoded',
467
- },
468
- }),
469
- })
470
-
471
- expect(response.headers.get('Content-Type')).toEqual(
472
- 'application/x-www-form-urlencoded',
473
- )
474
-
475
- const params = new URLSearchParams(await response.text())
476
- expect(params.get('')).toEqual('pong')
477
- })
478
-
479
- it('*/*', async () => {
480
- const response = await handler({
481
- prefix: '/orpc',
482
- request: new Request('http://localhost/orpc/ping', {
483
- method: 'POST',
484
- headers: {
485
- Accept: '*/*',
486
- },
487
- }),
488
- })
489
-
490
- expect(response.headers.get('Content-Type')).toEqual('application/json')
491
- expect(await response.json()).toEqual('pong')
492
- })
493
-
494
- it('invalid', async () => {
495
- const response = await handler({
496
- prefix: '/orpc',
497
- request: new Request('http://localhost/orpc/ping', {
498
- method: 'POST',
499
- headers: {
500
- Accept: 'invalid',
501
- },
502
- }),
503
- })
504
-
505
- expect(response.headers.get('Content-Type')).toEqual('application/json')
506
- expect(await response.json()).toEqual({
507
- code: 'NOT_ACCEPTABLE',
508
- message: 'Unsupported content-type: invalid',
509
- status: 406,
510
- })
511
- })
512
- })
513
-
514
- describe('dynamic params', () => {
515
- const router = os.router({
516
- deep: os
517
- .route({
518
- method: 'POST',
519
- path: '/{id}/{id2}',
520
- })
521
- .input(
522
- z.object({
523
- id: z.number(),
524
- id2: z.string(),
525
- file: oz.file(),
526
- }),
527
- )
528
- .func(input => input),
529
-
530
- find: os
531
- .route({
532
- method: 'GET',
533
- path: '/{id}',
534
- })
535
- .input(
536
- z.object({
537
- id: z.number(),
538
- }),
539
- )
540
- .func(input => input),
541
- })
542
-
543
- const handlers = [
544
- createFetchHandler({
545
- router,
546
- }),
547
- createFetchHandler({
548
- router,
549
- serverless: true,
550
- }),
551
- ]
552
-
553
- it.each(handlers)('should handle dynamic params', async (handler) => {
554
- const response = await handler({
555
- request: new Request('http://localhost/123'),
556
- })
557
-
558
- expect(response.status).toEqual(200)
559
- expect(response.headers.get('Content-Type')).toEqual('application/json')
560
- expect(await response.json()).toEqual({ id: 123 })
561
- })
562
-
563
- it.each(handlers)('should handle deep dynamic params', async (handler) => {
564
- const form = new FormData()
565
- form.append('file', new Blob(['hello']), 'hello.txt')
566
-
567
- const response = await handler({
568
- request: new Request('http://localhost/123/dfdsfds', {
569
- method: 'POST',
570
- body: form,
571
- }),
572
- })
573
-
574
- expect(response.status).toEqual(200)
575
- const rForm = await response.formData()
576
- expect(rForm.get('id')).toEqual('123')
577
- expect(rForm.get('id2')).toEqual('dfdsfds')
578
- })
579
- })
580
-
581
- describe('can control method on POST request', () => {
582
- const router = os.router({
583
- update: os
584
- .route({
585
- method: 'PUT',
586
- path: '/{id}',
587
- })
588
- .input(
589
- z.object({
590
- id: z.number(),
591
- file: oz.file(),
592
- }),
593
- )
594
- .func(input => input),
595
- })
596
-
597
- const handlers = [
598
- createFetchHandler({
599
- router,
600
- }),
601
- createFetchHandler({
602
- router,
603
- serverless: true,
604
- }),
605
- ]
606
-
607
- it.each(handlers)('work', async (handler) => {
608
- const form = new FormData()
609
- form.set('file', new File(['hello'], 'hello.txt'))
610
-
611
- const response = await handler({
612
- request: new Request('http://localhost/123', {
613
- method: 'POST',
614
- body: form,
615
- }),
616
- })
617
-
618
- expect(response.status).toEqual(404)
619
-
620
- const response2 = await handler({
621
- request: new Request('http://localhost/123?method=PUT', {
622
- method: 'POST',
623
- body: form,
624
- }),
625
- })
626
-
627
- expect(response2.status).toEqual(200)
628
- })
629
- })