galbe 0.12.0 → 0.12.2
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/bin/commands/generate/code/openapi.parser.ts +2 -2
- package/package.json +6 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -23
- package/.github/workflows/build_test.yml +0 -17
- package/.github/workflows/deploy_website.yml +0 -20
- package/.github/workflows/release.yml +0 -39
- package/.prettierrc +0 -10
- package/bun.lock +0 -904
- package/bunfig.toml +0 -2
- package/docs/CONTRIBUTING.md +0 -105
- package/docs/cli.md +0 -343
- package/docs/configuration.md +0 -80
- package/docs/context.md +0 -104
- package/docs/error-handler.md +0 -54
- package/docs/getting-started.md +0 -164
- package/docs/handler.md +0 -119
- package/docs/hooks.md +0 -90
- package/docs/plugins.md +0 -146
- package/docs/router.md +0 -10
- package/docs/routes.md +0 -133
- package/docs/schemas.md +0 -327
- package/test/hooks.test.ts +0 -200
- package/test/parser.test.ts +0 -1358
- package/test/plugins.test.ts +0 -239
- package/test/requests.test.ts +0 -917
- package/test/resources/image.png +0 -0
- package/test/resources/object.badSyntax.json +0 -8
- package/test/resources/object.json +0 -8
- package/test/resources/object.missing.json +0 -6
- package/test/resources/static/chameleon.png +0 -0
- package/test/resources/static/index.html +0 -13
- package/test/resources/static/sub/index.html +0 -13
- package/test/resources/static/sub/other.html +0 -13
- package/test/resources/test.route.comment.ts +0 -58
- package/test/resources/test.route.empty.ts +0 -9
- package/test/responses.test.ts +0 -483
- package/test/routeFiles.test.ts +0 -239
- package/test/router.test.ts +0 -231
- package/test/test.utils.ts +0 -109
- package/test/types.test.ts +0 -909
- package/tsconfig.json +0 -23
package/test/types.test.ts
DELETED
|
@@ -1,909 +0,0 @@
|
|
|
1
|
-
import { $T, Galbe } from '../src'
|
|
2
|
-
import type { Static } from '../src/schema'
|
|
3
|
-
import { describe, test, expect, beforeAll } from 'bun:test'
|
|
4
|
-
import { formdata } from './test.utils'
|
|
5
|
-
|
|
6
|
-
// Test utils
|
|
7
|
-
type Equal<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false
|
|
8
|
-
type Expect<T extends true> = T
|
|
9
|
-
type Extends<A, B> = A extends B ? true : false
|
|
10
|
-
|
|
11
|
-
// Basic Schema types
|
|
12
|
-
|
|
13
|
-
const any = $T.any()
|
|
14
|
-
const nil = $T.null()
|
|
15
|
-
const bool = $T.boolean()
|
|
16
|
-
const num = $T.number()
|
|
17
|
-
const int = $T.integer()
|
|
18
|
-
const str = $T.string()
|
|
19
|
-
const literal = $T.literal('foo')
|
|
20
|
-
const ba = $T.byteArray()
|
|
21
|
-
const obj = $T.object()
|
|
22
|
-
|
|
23
|
-
type _any = Expect<Extends<Static<typeof any>, any>>
|
|
24
|
-
type _nil = Expect<Extends<Static<typeof nil>, null>>
|
|
25
|
-
type _bool = Expect<Extends<Static<typeof bool>, boolean>>
|
|
26
|
-
type _num = Expect<Extends<Static<typeof num>, number>>
|
|
27
|
-
type _int = Expect<Extends<Static<typeof int>, number>>
|
|
28
|
-
type _str = Expect<Extends<Static<typeof str>, string>>
|
|
29
|
-
type _literal = Expect<Extends<Static<typeof literal>, 'foo'>>
|
|
30
|
-
type _ba = Expect<Extends<Static<typeof ba>, Uint8Array<ArrayBufferLike>>>
|
|
31
|
-
type _obj = Expect<Extends<Static<typeof obj>, Record<string | number, any>>>
|
|
32
|
-
|
|
33
|
-
// Basic schema wrappers
|
|
34
|
-
|
|
35
|
-
const opt_str = $T.optional($T.string())
|
|
36
|
-
const null_str = $T.nullable($T.string())
|
|
37
|
-
const nullish_str = $T.nullish($T.string())
|
|
38
|
-
|
|
39
|
-
type _opt_str = Expect<Extends<Static<typeof opt_str>, string | undefined>>
|
|
40
|
-
type _null_str = Expect<Extends<Static<typeof null_str>, string | null>>
|
|
41
|
-
type _nullish_str = Expect<Extends<Static<typeof nullish_str>, string | null | undefined>>
|
|
42
|
-
|
|
43
|
-
// Array schema type
|
|
44
|
-
|
|
45
|
-
const arr_nil = $T.array($T.null())
|
|
46
|
-
const arr_bool = $T.array($T.boolean())
|
|
47
|
-
const arr_num = $T.array($T.number())
|
|
48
|
-
const arr_int = $T.array($T.integer())
|
|
49
|
-
const arr_str = $T.array($T.string())
|
|
50
|
-
const arr_obj = $T.array($T.object({ foo: $T.literal(42) }))
|
|
51
|
-
const arr_arr = $T.array($T.array($T.literal('hello')))
|
|
52
|
-
|
|
53
|
-
const arr_union = $T.array($T.union([$T.literal('hello'), $T.literal('mom')]))
|
|
54
|
-
const arr_intersection = $T.array($T.intersection([$T.object({ foo: $T.string() }), $T.object({ bar: $T.number() })]))
|
|
55
|
-
|
|
56
|
-
type _arr_nil = Expect<Extends<Static<typeof arr_nil>, null[]>>
|
|
57
|
-
type _arr_bool = Expect<Extends<Static<typeof arr_bool>, boolean[]>>
|
|
58
|
-
type _arr_num = Expect<Extends<Static<typeof arr_num>, number[]>>
|
|
59
|
-
type _arr_int = Expect<Extends<Static<typeof arr_int>, number[]>>
|
|
60
|
-
type _arr_str = Expect<Extends<Static<typeof arr_str>, string[]>>
|
|
61
|
-
type _arr_obj = Expect<Extends<Static<typeof arr_obj>, { foo: 42 }[]>>
|
|
62
|
-
type _arr_arr = Expect<Extends<Static<typeof arr_arr>, 'hello'[][]>>
|
|
63
|
-
|
|
64
|
-
type _arr_union = Expect<Extends<Static<typeof arr_union>, ('hello' | 'mom')[]>>
|
|
65
|
-
type _arr_intersection = Expect<Extends<Static<typeof arr_intersection>, ({ foo: string } & { bar: number })[]>>
|
|
66
|
-
|
|
67
|
-
// Object schema type
|
|
68
|
-
|
|
69
|
-
const obj_1 = $T.object({
|
|
70
|
-
any: $T.any(),
|
|
71
|
-
nil: $T.null(),
|
|
72
|
-
bool: $T.boolean(),
|
|
73
|
-
num: $T.number(),
|
|
74
|
-
int: $T.integer(),
|
|
75
|
-
str: $T.string(),
|
|
76
|
-
literal: $T.literal('foo'),
|
|
77
|
-
ba: $T.byteArray(),
|
|
78
|
-
arr: $T.array($T.string()),
|
|
79
|
-
obj: $T.object({
|
|
80
|
-
foo: $T.string(),
|
|
81
|
-
}),
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
type _obj_1 = Expect<
|
|
85
|
-
Equal<
|
|
86
|
-
Static<typeof obj_1>,
|
|
87
|
-
{
|
|
88
|
-
literal: 'foo'
|
|
89
|
-
any: any
|
|
90
|
-
nil: null
|
|
91
|
-
bool: boolean
|
|
92
|
-
num: number
|
|
93
|
-
int: number
|
|
94
|
-
str: string
|
|
95
|
-
ba: Uint8Array<ArrayBufferLike>
|
|
96
|
-
arr: string[]
|
|
97
|
-
obj: {
|
|
98
|
-
foo: string
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
>
|
|
102
|
-
>
|
|
103
|
-
|
|
104
|
-
// Union type
|
|
105
|
-
|
|
106
|
-
const union_str_number = $T.union([$T.string(), $T.number()])
|
|
107
|
-
const union_str_any = $T.union([$T.string(), $T.any()])
|
|
108
|
-
const union_union_number = $T.union([$T.union([$T.literal('foo'), $T.literal('bar')]), $T.literal('baz')])
|
|
109
|
-
const union_intersection = $T.union([
|
|
110
|
-
$T.intersection([$T.object({ foo: $T.literal(42) }), $T.object({ bar: $T.number() })]),
|
|
111
|
-
$T.object({ test: $T.literal('test') }),
|
|
112
|
-
])
|
|
113
|
-
|
|
114
|
-
type _union_str_number = Expect<Extends<Static<typeof union_str_number>, string | number>>
|
|
115
|
-
type _union_str_any = Expect<Extends<Static<typeof union_str_any>, any>>
|
|
116
|
-
type _union_union_number = Expect<Extends<Static<typeof union_union_number>, 'foo' | 'bar' | 'baz'>>
|
|
117
|
-
type _union_intersection = Expect<
|
|
118
|
-
Extends<Static<typeof union_intersection>, ({ foo: 42 } & { bar: number }) | { test: 'test' }>
|
|
119
|
-
>
|
|
120
|
-
|
|
121
|
-
// Intersection type
|
|
122
|
-
|
|
123
|
-
const intersection_obj_obj = $T.intersection([$T.object({ foo: $T.string() }), $T.object({ bar: $T.boolean() })])
|
|
124
|
-
const intersection_union_obj = $T.intersection([
|
|
125
|
-
$T.union([$T.object({ foo: $T.string() }), $T.object({ bar: $T.boolean() })]),
|
|
126
|
-
$T.object({ baz: $T.literal(42) }),
|
|
127
|
-
])
|
|
128
|
-
const intersection_intersection_obj = $T.intersection([
|
|
129
|
-
$T.intersection([$T.object({ foo: $T.string() }), $T.object({ bar: $T.boolean() })]),
|
|
130
|
-
$T.object({ baz: $T.literal('42') }),
|
|
131
|
-
])
|
|
132
|
-
|
|
133
|
-
type _intersection_obj_obj = Expect<Extends<Static<typeof intersection_obj_obj>, { foo: string } & { bar: boolean }>>
|
|
134
|
-
type _intersection_union_obj = Expect<
|
|
135
|
-
Extends<Static<typeof intersection_union_obj>, ({ foo: string } | { bar: boolean }) & { baz: 42 }>
|
|
136
|
-
>
|
|
137
|
-
type _intersection_intersection_obj = Expect<
|
|
138
|
-
Extends<Static<typeof intersection_intersection_obj>, { foo: string } & { bar: boolean } & { baz: '42' }>
|
|
139
|
-
>
|
|
140
|
-
|
|
141
|
-
// Stream types
|
|
142
|
-
|
|
143
|
-
const stream_ba = $T.stream($T.byteArray())
|
|
144
|
-
const stream_str = $T.stream($T.string())
|
|
145
|
-
const stream_obj = $T.stream(
|
|
146
|
-
$T.object({ foo: $T.literal('hi'), bar: $T.number(), obj: $T.object({ nested: $T.boolean() }) })
|
|
147
|
-
)
|
|
148
|
-
const stream_multipart = $T.stream(
|
|
149
|
-
$T.multipartForm({ foo: $T.literal('hi'), bar: $T.number(), obj: $T.object({ nested: $T.boolean() }) })
|
|
150
|
-
)
|
|
151
|
-
const stream_union = $T.stream($T.union([$T.object({ foo: $T.string() }), $T.object({ bar: $T.boolean() })]))
|
|
152
|
-
const stream_intersection = $T.stream(
|
|
153
|
-
$T.intersection([$T.object({ foo: $T.string() }), $T.object({ bar: $T.boolean() })])
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
type _stream_ba = Expect<Extends<Static<typeof stream_ba>, AsyncGenerator<Uint8Array<ArrayBufferLike>>>>
|
|
157
|
-
type _stream_str = Expect<Extends<Static<typeof stream_str>, AsyncGenerator<string>>>
|
|
158
|
-
type _stream_obj = Expect<
|
|
159
|
-
Extends<
|
|
160
|
-
Static<typeof stream_obj>,
|
|
161
|
-
AsyncGenerator<
|
|
162
|
-
| ['foo', 'hi']
|
|
163
|
-
| ['bar', number]
|
|
164
|
-
| [
|
|
165
|
-
'obj',
|
|
166
|
-
{
|
|
167
|
-
nested: boolean
|
|
168
|
-
}
|
|
169
|
-
]
|
|
170
|
-
>
|
|
171
|
-
>
|
|
172
|
-
>
|
|
173
|
-
type _stream_multipart = Expect<
|
|
174
|
-
Extends<
|
|
175
|
-
Static<typeof stream_multipart>,
|
|
176
|
-
AsyncGenerator<
|
|
177
|
-
| {
|
|
178
|
-
headers: {
|
|
179
|
-
type?: string
|
|
180
|
-
name: 'foo'
|
|
181
|
-
filename?: string
|
|
182
|
-
}
|
|
183
|
-
content: 'hi'
|
|
184
|
-
}
|
|
185
|
-
| {
|
|
186
|
-
headers: {
|
|
187
|
-
type?: string
|
|
188
|
-
name: 'bar'
|
|
189
|
-
filename?: string
|
|
190
|
-
}
|
|
191
|
-
content: number
|
|
192
|
-
}
|
|
193
|
-
| {
|
|
194
|
-
headers: {
|
|
195
|
-
type?: string
|
|
196
|
-
name: 'obj'
|
|
197
|
-
filename?: string
|
|
198
|
-
}
|
|
199
|
-
content: {
|
|
200
|
-
nested: boolean
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
>
|
|
204
|
-
>
|
|
205
|
-
>
|
|
206
|
-
type _stream_union = Expect<Extends<Static<typeof stream_union>, AsyncGenerator<['foo', string] | ['bar', boolean]>>>
|
|
207
|
-
type _stream_intersection = Expect<
|
|
208
|
-
Extends<Static<typeof stream_intersection>, AsyncGenerator<['foo', string] | ['bar', boolean]>>
|
|
209
|
-
>
|
|
210
|
-
|
|
211
|
-
// Endpoints
|
|
212
|
-
|
|
213
|
-
const g = new Galbe()
|
|
214
|
-
|
|
215
|
-
// Path params
|
|
216
|
-
|
|
217
|
-
g.get('/params/noschema/:param1/and/:param2', ctx => {
|
|
218
|
-
const { params } = ctx
|
|
219
|
-
type _ep_params = Expect<Equal<typeof params, { param1: string; param2: string }>>
|
|
220
|
-
ctx.set.status = typeof params.param1 === 'string' && typeof params.param2 === 'string' ? 200 : 500
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
g.get(
|
|
224
|
-
'/params/schema/:bool/:num/:int/:str/:literal',
|
|
225
|
-
{ params: { bool: $T.boolean(), num: $T.number(), int: $T.integer(), str: $T.string(), literal: $T.literal(42) } },
|
|
226
|
-
ctx => {
|
|
227
|
-
const { params } = ctx
|
|
228
|
-
type _ep_params = Expect<
|
|
229
|
-
Equal<typeof params, { bool: boolean; num: number; int: number; str: string; literal: 42 }>
|
|
230
|
-
>
|
|
231
|
-
ctx.set.status =
|
|
232
|
-
typeof params.bool === 'boolean' &&
|
|
233
|
-
typeof params.num === 'number' &&
|
|
234
|
-
typeof params.int === 'number' &&
|
|
235
|
-
typeof params.str === 'string' &&
|
|
236
|
-
params.literal === 42
|
|
237
|
-
? 200
|
|
238
|
-
: 500
|
|
239
|
-
}
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
// Query params
|
|
243
|
-
|
|
244
|
-
g.get('/query', ctx => {
|
|
245
|
-
const { query } = ctx
|
|
246
|
-
type _ep_params = Expect<Equal<typeof query, Record<string | number | symbol, any>>>
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
g.get(
|
|
250
|
-
'/query/schema',
|
|
251
|
-
{
|
|
252
|
-
query: {
|
|
253
|
-
bool: $T.boolean(),
|
|
254
|
-
num: $T.number(),
|
|
255
|
-
int: $T.integer(),
|
|
256
|
-
str: $T.string(),
|
|
257
|
-
literal: $T.literal('foo'),
|
|
258
|
-
opt: $T.optional($T.literal('opt')),
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
ctx => {
|
|
262
|
-
const { query } = ctx
|
|
263
|
-
type _ep_query = Expect<
|
|
264
|
-
Equal<typeof query, { bool: boolean; num: number; int: number; str: string; literal: 'foo'; opt?: 'opt' }>
|
|
265
|
-
>
|
|
266
|
-
ctx.set.status =
|
|
267
|
-
typeof query.bool === 'boolean' &&
|
|
268
|
-
typeof query.num === 'number' &&
|
|
269
|
-
typeof query.int === 'number' &&
|
|
270
|
-
typeof query.str === 'string' &&
|
|
271
|
-
(query.opt !== undefined ? query.opt === 'opt' : true) &&
|
|
272
|
-
query.literal === 'foo'
|
|
273
|
-
? 200
|
|
274
|
-
: 500
|
|
275
|
-
}
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
// Body
|
|
279
|
-
|
|
280
|
-
// Null bodies
|
|
281
|
-
g.get('/body', ctx => {
|
|
282
|
-
const { body } = ctx
|
|
283
|
-
type _ep_body = Expect<Equal<typeof body, null>>
|
|
284
|
-
ctx.set.status = body === null ? 200 : 500
|
|
285
|
-
})
|
|
286
|
-
g.get('/body/schema', { body: $T.string() }, ctx => {
|
|
287
|
-
const { body } = ctx
|
|
288
|
-
type _ep_body = Expect<Equal<typeof body, null>>
|
|
289
|
-
ctx.set.status = body === null ? 200 : 500
|
|
290
|
-
})
|
|
291
|
-
g.options('/body', ctx => {
|
|
292
|
-
const { body } = ctx
|
|
293
|
-
type _ep_body = Expect<Equal<typeof body, null>>
|
|
294
|
-
ctx.set.status = body === null ? 200 : 500
|
|
295
|
-
})
|
|
296
|
-
g.options('/body/schema', { body: $T.string() }, ctx => {
|
|
297
|
-
const { body } = ctx
|
|
298
|
-
type _ep_body = Expect<Equal<typeof body, null>>
|
|
299
|
-
ctx.set.status = body === null ? 200 : 500
|
|
300
|
-
})
|
|
301
|
-
g.head('/body', ctx => {
|
|
302
|
-
const { body } = ctx
|
|
303
|
-
type _ep_body = Expect<Equal<typeof body, null>>
|
|
304
|
-
ctx.set.status = body === null ? 200 : 500
|
|
305
|
-
})
|
|
306
|
-
g.head('/body/schema', { body: $T.string() }, ctx => {
|
|
307
|
-
const { body } = ctx
|
|
308
|
-
type _ep_body = Expect<Equal<typeof body, null>>
|
|
309
|
-
ctx.set.status = body === null ? 200 : 500
|
|
310
|
-
})
|
|
311
|
-
|
|
312
|
-
g.post('/body/post', ctx => {
|
|
313
|
-
const { body } = ctx
|
|
314
|
-
type _ep_body = Expect<Equal<typeof body, any>>
|
|
315
|
-
})
|
|
316
|
-
g.patch('/body/patch', ctx => {
|
|
317
|
-
const { body } = ctx
|
|
318
|
-
type _ep_body = Expect<Equal<typeof body, any>>
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
g.post('/body/post', { body: $T.null() }, ctx => {
|
|
322
|
-
const { body } = ctx
|
|
323
|
-
type _ep_body = Expect<Equal<typeof body, null>>
|
|
324
|
-
ctx.set.status = body === null ? 200 : 500
|
|
325
|
-
})
|
|
326
|
-
g.patch('/body/patch', { body: $T.null() }, ctx => {
|
|
327
|
-
const { body } = ctx
|
|
328
|
-
type _ep_body = Expect<Equal<typeof body, null>>
|
|
329
|
-
ctx.set.status = body === null ? 200 : 500
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
// Body ByteArray
|
|
333
|
-
|
|
334
|
-
g.post('/body/ba', { body: { byteArray: $T.byteArray() } }, ctx => {
|
|
335
|
-
const { body, contentType } = ctx
|
|
336
|
-
type _ep_body = Expect<Equal<typeof body, Uint8Array<ArrayBufferLike>>>
|
|
337
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'byteArray'>>
|
|
338
|
-
ctx.set.status = body instanceof Uint8Array ? 200 : 500
|
|
339
|
-
})
|
|
340
|
-
|
|
341
|
-
g.post('/body/ba/stream', { body: { byteArray: $T.stream($T.byteArray()) } }, async ctx => {
|
|
342
|
-
const { body, contentType } = ctx
|
|
343
|
-
type _ep_body = Expect<Extends<typeof body, AsyncGenerator<Uint8Array<ArrayBufferLike>>>>
|
|
344
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'byteArray'>>
|
|
345
|
-
for await (const bp of body) {
|
|
346
|
-
if (body instanceof Uint8Array) ctx.set.status = 500
|
|
347
|
-
}
|
|
348
|
-
})
|
|
349
|
-
|
|
350
|
-
// Body Text
|
|
351
|
-
|
|
352
|
-
g.post('/body/text/str', { body: { text: $T.string() } }, ctx => {
|
|
353
|
-
const { body, contentType } = ctx
|
|
354
|
-
type _ep_body = Expect<Equal<typeof body, string>>
|
|
355
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'text'>>
|
|
356
|
-
ctx.set.status = typeof body === 'string' ? 200 : 500
|
|
357
|
-
})
|
|
358
|
-
|
|
359
|
-
g.post('/body/text/literal', { body: { text: $T.literal('foo') } }, ctx => {
|
|
360
|
-
const { body, contentType } = ctx
|
|
361
|
-
type _ep_body = Expect<Equal<typeof body, 'foo'>>
|
|
362
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'text'>>
|
|
363
|
-
ctx.set.status = body === 'foo' ? 200 : 500
|
|
364
|
-
})
|
|
365
|
-
|
|
366
|
-
g.post('/body/text/bool', { body: { text: $T.boolean() } }, ctx => {
|
|
367
|
-
const { body, contentType } = ctx
|
|
368
|
-
type _ep_body = Expect<Equal<typeof body, boolean>>
|
|
369
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'text'>>
|
|
370
|
-
ctx.set.status = typeof body === 'boolean' ? 200 : 500
|
|
371
|
-
})
|
|
372
|
-
|
|
373
|
-
g.post('/body/text/num', { body: { text: $T.number() } }, ctx => {
|
|
374
|
-
const { body, contentType } = ctx
|
|
375
|
-
type _ep_body = Expect<Equal<typeof body, number>>
|
|
376
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'text'>>
|
|
377
|
-
ctx.set.status = typeof body === 'number' ? 200 : 500
|
|
378
|
-
})
|
|
379
|
-
|
|
380
|
-
g.post('/body/text/int', { body: { text: $T.integer() } }, ctx => {
|
|
381
|
-
const { body, contentType } = ctx
|
|
382
|
-
type _ep_body = Expect<Equal<typeof body, number>>
|
|
383
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'text'>>
|
|
384
|
-
ctx.set.status = typeof body === 'number' ? 200 : 500
|
|
385
|
-
})
|
|
386
|
-
|
|
387
|
-
g.post('/body/text/union', { body: { text: $T.union([$T.literal('foo'), $T.number()]) } }, ctx => {
|
|
388
|
-
const { body, contentType } = ctx
|
|
389
|
-
type _ep_body = Expect<Equal<typeof body, 'foo' | number>>
|
|
390
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'text'>>
|
|
391
|
-
ctx.set.status = body === 'foo' || typeof body === 'number' ? 200 : 500
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
g.post('/body/text/stream', { body: { text: $T.stream($T.string()) } }, async ctx => {
|
|
395
|
-
const { body, contentType } = ctx
|
|
396
|
-
type _ep_body = Expect<Extends<typeof body, AsyncGenerator<string>>>
|
|
397
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'text'>>
|
|
398
|
-
for await (const chunk of body) if (typeof chunk !== 'string') ctx.set.status = 500
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
// Body Json
|
|
402
|
-
|
|
403
|
-
g.post('/body/json/bool', { body: { json: $T.boolean() } }, ctx => {
|
|
404
|
-
const { body, contentType } = ctx
|
|
405
|
-
type _ep_body = Expect<Extends<typeof body, boolean>>
|
|
406
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'json'>>
|
|
407
|
-
ctx.set.status = typeof body === 'boolean' ? 200 : 500
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
g.post('/body/json/num', { body: { json: $T.number() } }, ctx => {
|
|
411
|
-
const { body, contentType } = ctx
|
|
412
|
-
type _ep_body = Expect<Extends<typeof body, number>>
|
|
413
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'json'>>
|
|
414
|
-
ctx.set.status = typeof body === 'number' ? 200 : 500
|
|
415
|
-
})
|
|
416
|
-
|
|
417
|
-
g.post('/body/json/int', { body: { json: $T.integer() } }, ctx => {
|
|
418
|
-
const { body, contentType } = ctx
|
|
419
|
-
type _ep_body = Expect<Extends<typeof body, number>>
|
|
420
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'json'>>
|
|
421
|
-
ctx.set.status = typeof body === 'number' ? 200 : 500
|
|
422
|
-
})
|
|
423
|
-
|
|
424
|
-
g.post('/body/json/str', { body: { json: $T.string() } }, ctx => {
|
|
425
|
-
const { body, contentType } = ctx
|
|
426
|
-
type _ep_body = Expect<Extends<typeof body, string>>
|
|
427
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'json'>>
|
|
428
|
-
ctx.set.status = typeof body === 'string' ? 200 : 500
|
|
429
|
-
})
|
|
430
|
-
|
|
431
|
-
g.post('/body/json/arr', { body: { json: $T.array($T.string()) } }, ctx => {
|
|
432
|
-
const { body, contentType } = ctx
|
|
433
|
-
type _ep_body = Expect<Extends<typeof body, string[]>>
|
|
434
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'json'>>
|
|
435
|
-
ctx.set.status = Array.isArray(body) && body.every(i => typeof i === 'string') ? 200 : 500
|
|
436
|
-
})
|
|
437
|
-
|
|
438
|
-
g.post('/body/json/union', { body: { json: $T.union([$T.boolean(), $T.string()]) } }, ctx => {
|
|
439
|
-
const { body, contentType } = ctx
|
|
440
|
-
type _ep_body = Expect<Extends<typeof body, boolean | string>>
|
|
441
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'json'>>
|
|
442
|
-
ctx.set.status = typeof body === 'string' || typeof body === 'boolean' ? 200 : 500
|
|
443
|
-
})
|
|
444
|
-
|
|
445
|
-
g.post('/body/json/obj', { body: { json: $T.object({ foo: $T.string() }) } }, ctx => {
|
|
446
|
-
const { body, contentType } = ctx
|
|
447
|
-
type _ep_body = Expect<Extends<typeof body, { foo: string }>>
|
|
448
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'json'>>
|
|
449
|
-
ctx.set.status = typeof body.foo === 'string' ? 200 : 500
|
|
450
|
-
})
|
|
451
|
-
|
|
452
|
-
// Body UrlForm
|
|
453
|
-
|
|
454
|
-
g.post(
|
|
455
|
-
'/body/urlForm',
|
|
456
|
-
{ body: { urlForm: $T.object({ foo: $T.string(), bar: $T.number(), opt: $T.optional($T.literal('opt')) }) } },
|
|
457
|
-
ctx => {
|
|
458
|
-
const { body, contentType } = ctx
|
|
459
|
-
type _ep_body = Expect<Equal<typeof body, { foo: string; bar: number; opt?: 'opt' }>>
|
|
460
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'urlForm'>>
|
|
461
|
-
ctx.set.status =
|
|
462
|
-
typeof body.foo === 'string' && typeof body.bar === 'number' && (body.opt ? body.opt === 'opt' : true) ? 200 : 500
|
|
463
|
-
}
|
|
464
|
-
)
|
|
465
|
-
|
|
466
|
-
g.post(
|
|
467
|
-
'/body/urlForm/union',
|
|
468
|
-
{ body: { urlForm: $T.union([$T.object({ foo: $T.string() }), $T.object({ bar: $T.boolean() })]) } },
|
|
469
|
-
ctx => {
|
|
470
|
-
const { body, contentType } = ctx
|
|
471
|
-
type _ep_body = Expect<Extends<typeof body, { foo: string } | { bar: boolean }>>
|
|
472
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'urlForm'>>
|
|
473
|
-
//@ts-ignore
|
|
474
|
-
typeof body.foo ? typeof body.foo === 'string' : true && body.bar ? typeof body.bar === 'number' : true ? 200 : 500
|
|
475
|
-
}
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
g.post(
|
|
479
|
-
'/body/urlForm/stream',
|
|
480
|
-
{ body: { urlForm: $T.stream($T.object({ foo: $T.string(), bar: $T.number() })) } },
|
|
481
|
-
async ctx => {
|
|
482
|
-
const { body, contentType } = ctx
|
|
483
|
-
type _ep_body = Expect<Extends<typeof body, AsyncGenerator<['foo', string] | ['bar', number]>>>
|
|
484
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'urlForm'>>
|
|
485
|
-
for await (const [k, v] of body) {
|
|
486
|
-
if (k === 'foo' && typeof v !== 'string') ctx.set.status = 500
|
|
487
|
-
if (k === 'bar' && typeof v !== 'number') ctx.set.status = 500
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
)
|
|
491
|
-
|
|
492
|
-
// Body MultipartForm
|
|
493
|
-
|
|
494
|
-
g.post(
|
|
495
|
-
'/body/multipart',
|
|
496
|
-
{
|
|
497
|
-
body: { multipart: $T.multipartForm({ foo: $T.string(), bar: $T.number(), opt: $T.optional($T.literal('opt')) }) },
|
|
498
|
-
},
|
|
499
|
-
ctx => {
|
|
500
|
-
const { body, contentType } = ctx
|
|
501
|
-
type _ep_body = Expect<
|
|
502
|
-
Equal<
|
|
503
|
-
typeof body,
|
|
504
|
-
{
|
|
505
|
-
foo: {
|
|
506
|
-
headers: {
|
|
507
|
-
type?: string
|
|
508
|
-
name: 'foo'
|
|
509
|
-
filename?: string
|
|
510
|
-
}
|
|
511
|
-
content: string
|
|
512
|
-
}
|
|
513
|
-
bar: {
|
|
514
|
-
headers: {
|
|
515
|
-
type?: string
|
|
516
|
-
name: 'bar'
|
|
517
|
-
filename?: string
|
|
518
|
-
}
|
|
519
|
-
content: number
|
|
520
|
-
}
|
|
521
|
-
opt: {
|
|
522
|
-
headers: {
|
|
523
|
-
type?: string
|
|
524
|
-
name: 'opt'
|
|
525
|
-
filename?: string
|
|
526
|
-
}
|
|
527
|
-
content: 'opt' | undefined
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
>
|
|
531
|
-
>
|
|
532
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'multipart'>>
|
|
533
|
-
if (body.foo) {
|
|
534
|
-
if (body.foo.headers?.type && typeof body.foo.headers?.type !== 'string') ctx.set.status = 500
|
|
535
|
-
if (body.foo.headers?.filename && typeof body.foo.headers?.filename !== 'string') ctx.set.status = 500
|
|
536
|
-
if (body.foo.headers.name !== 'foo') ctx.set.status = 500
|
|
537
|
-
if (typeof body.foo.content !== 'string') ctx.set.status = 500
|
|
538
|
-
}
|
|
539
|
-
if (body.bar) {
|
|
540
|
-
if (body.bar.headers?.type && typeof body.bar.headers?.type !== 'string') ctx.set.status = 500
|
|
541
|
-
if (body.bar.headers?.filename && typeof body.bar.headers?.filename !== 'string') ctx.set.status = 500
|
|
542
|
-
if (body.bar.headers.name !== 'bar') ctx.set.status = 500
|
|
543
|
-
if (typeof body.bar.content !== 'number') ctx.set.status = 500
|
|
544
|
-
}
|
|
545
|
-
if (body.opt) {
|
|
546
|
-
if (body.opt.headers?.type && typeof body.opt.headers?.type !== 'string') ctx.set.status = 500
|
|
547
|
-
if (body.opt.headers?.filename && typeof body.opt.headers?.filename !== 'string') ctx.set.status = 500
|
|
548
|
-
if (body.opt.headers.name !== 'opt') ctx.set.status = 500
|
|
549
|
-
if (body.opt.content && body.opt.content !== 'opt') ctx.set.status = 500
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
)
|
|
553
|
-
|
|
554
|
-
g.post(
|
|
555
|
-
'/body/multipart/stream',
|
|
556
|
-
{
|
|
557
|
-
body: {
|
|
558
|
-
multipart: $T.stream(
|
|
559
|
-
$T.multipartForm({ foo: $T.string(), bar: $T.number(), opt: $T.optional($T.literal('opt')) })
|
|
560
|
-
),
|
|
561
|
-
},
|
|
562
|
-
},
|
|
563
|
-
async ctx => {
|
|
564
|
-
const { body, contentType } = ctx
|
|
565
|
-
type _ep_body = Expect<
|
|
566
|
-
Extends<
|
|
567
|
-
typeof body,
|
|
568
|
-
AsyncGenerator<
|
|
569
|
-
| {
|
|
570
|
-
headers: {
|
|
571
|
-
type?: string
|
|
572
|
-
name: 'foo'
|
|
573
|
-
filename?: string
|
|
574
|
-
}
|
|
575
|
-
content: string
|
|
576
|
-
}
|
|
577
|
-
| {
|
|
578
|
-
headers: {
|
|
579
|
-
type?: string
|
|
580
|
-
name: 'bar'
|
|
581
|
-
filename?: string
|
|
582
|
-
}
|
|
583
|
-
content: number
|
|
584
|
-
}
|
|
585
|
-
| {
|
|
586
|
-
headers: {
|
|
587
|
-
type?: string
|
|
588
|
-
name: 'opt'
|
|
589
|
-
filename?: string
|
|
590
|
-
}
|
|
591
|
-
content: 'opt' | undefined
|
|
592
|
-
}
|
|
593
|
-
>
|
|
594
|
-
>
|
|
595
|
-
>
|
|
596
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'multipart'>>
|
|
597
|
-
for await (const mp of body) {
|
|
598
|
-
if (mp.headers.name === 'foo') {
|
|
599
|
-
if (mp.headers?.type && typeof mp.headers?.type !== 'string') ctx.set.status = 500
|
|
600
|
-
if (mp.headers?.filename && typeof mp.headers?.filename !== 'string') ctx.set.status = 500
|
|
601
|
-
if (mp.headers.name !== 'foo') ctx.set.status = 500
|
|
602
|
-
if (typeof mp.content !== 'string') ctx.set.status = 500
|
|
603
|
-
}
|
|
604
|
-
if (mp.headers.name === 'bar') {
|
|
605
|
-
if (mp.headers?.type && typeof mp.headers?.type !== 'string') ctx.set.status = 500
|
|
606
|
-
if (mp.headers?.filename && typeof mp.headers?.filename !== 'string') ctx.set.status = 500
|
|
607
|
-
if (mp.headers.name !== 'bar') ctx.set.status = 500
|
|
608
|
-
if (typeof mp.content !== 'number') ctx.set.status = 500
|
|
609
|
-
}
|
|
610
|
-
if (mp.headers.name === 'opt') {
|
|
611
|
-
if (mp.headers?.type && typeof mp.headers?.type !== 'string') ctx.set.status = 500
|
|
612
|
-
if (mp.headers?.filename && typeof mp.headers?.filename !== 'string') ctx.set.status = 500
|
|
613
|
-
if (mp.headers.name !== 'opt') ctx.set.status = 500
|
|
614
|
-
if (mp.content && mp.content !== 'opt') ctx.set.status = 500
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
)
|
|
619
|
-
|
|
620
|
-
// Body Default
|
|
621
|
-
|
|
622
|
-
g.post('/body/default', { body: { default: $T.any() } }, ctx => {
|
|
623
|
-
const { body, contentType } = ctx
|
|
624
|
-
type _ep_body = Expect<Equal<typeof body, any>>
|
|
625
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'default'>>
|
|
626
|
-
})
|
|
627
|
-
|
|
628
|
-
g.post('/body/default/ba', { body: { default: $T.byteArray() } }, ctx => {
|
|
629
|
-
const { body, contentType } = ctx
|
|
630
|
-
type _ep_body = Expect<Equal<typeof body, Uint8Array<ArrayBufferLike>>>
|
|
631
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'default'>>
|
|
632
|
-
})
|
|
633
|
-
|
|
634
|
-
g.post('/body/default/str', { body: { default: $T.string() } }, ctx => {
|
|
635
|
-
const { body, contentType } = ctx
|
|
636
|
-
type _ep_body = Expect<Equal<typeof body, string>>
|
|
637
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'default'>>
|
|
638
|
-
})
|
|
639
|
-
|
|
640
|
-
g.post('/body/default/stream/ba', { body: { default: $T.stream($T.byteArray()) } }, ctx => {
|
|
641
|
-
const { body, contentType } = ctx
|
|
642
|
-
type _ep_body = Expect<Equal<typeof body, AsyncGenerator<Uint8Array<ArrayBufferLike>>>>
|
|
643
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'default'>>
|
|
644
|
-
})
|
|
645
|
-
|
|
646
|
-
g.post('/body/default/stream/str', { body: { default: $T.stream($T.string()) } }, ctx => {
|
|
647
|
-
const { body, contentType } = ctx
|
|
648
|
-
type _ep_body = Expect<Equal<typeof body, AsyncGenerator<string>>>
|
|
649
|
-
type _ep_contentType = Expect<Extends<typeof contentType, 'default'>>
|
|
650
|
-
})
|
|
651
|
-
|
|
652
|
-
const port = 7362
|
|
653
|
-
describe('types', () => {
|
|
654
|
-
beforeAll(async () => {
|
|
655
|
-
await g.listen(port)
|
|
656
|
-
})
|
|
657
|
-
|
|
658
|
-
test('endpoint request static types match runtime types', async () => {
|
|
659
|
-
type Case = {
|
|
660
|
-
body?: any
|
|
661
|
-
method: string
|
|
662
|
-
type?: string
|
|
663
|
-
path: string
|
|
664
|
-
expected: number
|
|
665
|
-
}
|
|
666
|
-
const cases: Case[] = [
|
|
667
|
-
{ method: 'get', path: '/params/noschema/foo/and/42', expected: 200 },
|
|
668
|
-
{ method: 'get', path: '/params/schema/true/0/1/foo/42', expected: 200 },
|
|
669
|
-
{ method: 'get', path: '/params/schema/foo/0/1/foo/42', expected: 400 },
|
|
670
|
-
{ method: 'get', path: '/params/schema/true/x/1/foo/42', expected: 400 },
|
|
671
|
-
{ method: 'get', path: '/params/schema/true/0/y/foo/42', expected: 400 },
|
|
672
|
-
{ method: 'get', path: '/params/schema/true/0/y/foo/43', expected: 400 },
|
|
673
|
-
|
|
674
|
-
{ method: 'get', path: '/query', expected: 200 },
|
|
675
|
-
{ method: 'get', path: '/query?anything=42', expected: 200 },
|
|
676
|
-
{ method: 'get', path: '/query/schema?bool=true&num=42&int=0&str=bar&literal=foo', expected: 200 },
|
|
677
|
-
{ method: 'get', path: '/query/schema?bool=false&num=36&int=1&str=foo&literal=foo&opt=opt', expected: 200 },
|
|
678
|
-
{ method: 'get', path: '/query/schema?bool=foo&num=42&int=0&str=bar&literal=foo&opt=opt', expected: 400 },
|
|
679
|
-
{ method: 'get', path: '/query/schema?bool=true&num=foo&int=0&str=bar&literal=foo&opt=opt', expected: 400 },
|
|
680
|
-
{ method: 'get', path: '/query/schema?bool=true&num=1&int=true&str=bar&literal=foo&opt=opt', expected: 400 },
|
|
681
|
-
{ method: 'get', path: '/query/schema?bool=true&num=1&int=0&literal=foo&opt=opt', expected: 400 },
|
|
682
|
-
{ method: 'get', path: '/query/schema?bool=true&num=1&int=0&str=str&literal=bar&opt=opt', expected: 400 },
|
|
683
|
-
{ method: 'get', path: '/query/schema?bool=true&num=1&int=0&str=str&literal=foo&opt=noop', expected: 400 },
|
|
684
|
-
|
|
685
|
-
{ method: 'get', path: '/body', body: null, expected: 200 },
|
|
686
|
-
{ method: 'get', path: '/body/schema', body: null, expected: 200 },
|
|
687
|
-
{ method: 'option', path: '/body', body: null, expected: 200 },
|
|
688
|
-
{ method: 'option', path: '/body/schema', body: null, expected: 200 },
|
|
689
|
-
{ method: 'head', path: '/body', body: null, expected: 200 },
|
|
690
|
-
{ method: 'head', path: '/body/schema', body: null, expected: 200 },
|
|
691
|
-
{ method: 'post', path: '/body/post', body: null, expected: 200 },
|
|
692
|
-
{ method: 'patch', path: '/body/patch', body: null, expected: 200 },
|
|
693
|
-
{ method: 'post', path: '/body/post', body: null, expected: 200 },
|
|
694
|
-
{ method: 'patch', path: '/body/patch', body: null, expected: 200 },
|
|
695
|
-
|
|
696
|
-
{ method: 'post', path: '/body/ba', type: 'application/octet-stream', body: new Uint8Array([]), expected: 200 },
|
|
697
|
-
{
|
|
698
|
-
method: 'post',
|
|
699
|
-
path: '/body/ba/stream',
|
|
700
|
-
type: 'application/octet-stream',
|
|
701
|
-
body: new Uint8Array([]),
|
|
702
|
-
expected: 200,
|
|
703
|
-
},
|
|
704
|
-
|
|
705
|
-
{ method: 'post', path: '/body/text/str', type: 'text/plain', body: 'hello', expected: 200 },
|
|
706
|
-
{ method: 'post', path: '/body/text/str', type: 'text/plain', body: null, expected: 200 },
|
|
707
|
-
|
|
708
|
-
{ method: 'post', path: '/body/text/literal', type: 'text/plain', body: 'foo', expected: 200 },
|
|
709
|
-
{ method: 'post', path: '/body/text/literal', type: 'text/plain', body: 'bar', expected: 400 },
|
|
710
|
-
|
|
711
|
-
{ method: 'post', path: '/body/text/bool', type: 'text/plain', body: 'true', expected: 200 },
|
|
712
|
-
{ method: 'post', path: '/body/text/bool', type: 'text/plain', body: 'false', expected: 200 },
|
|
713
|
-
{ method: 'post', path: '/body/text/bool', type: 'text/plain', body: '0', expected: 400 },
|
|
714
|
-
|
|
715
|
-
{ method: 'post', path: '/body/text/num', type: 'text/plain', body: '0', expected: 200 },
|
|
716
|
-
{ method: 'post', path: '/body/text/num', type: 'text/plain', body: '-42', expected: 200 },
|
|
717
|
-
{ method: 'post', path: '/body/text/num', type: 'text/plain', body: '42.42', expected: 200 },
|
|
718
|
-
{ method: 'post', path: '/body/text/num', type: 'text/plain', body: 'true', expected: 400 },
|
|
719
|
-
{ method: 'post', path: '/body/text/num', type: 'text/plain', body: null, expected: 400 },
|
|
720
|
-
|
|
721
|
-
{ method: 'post', path: '/body/text/int', type: 'text/plain', body: '0', expected: 200 },
|
|
722
|
-
{ method: 'post', path: '/body/text/int', type: 'text/plain', body: '-42', expected: 200 },
|
|
723
|
-
{ method: 'post', path: '/body/text/int', type: 'text/plain', body: '42.42', expected: 400 },
|
|
724
|
-
{ method: 'post', path: '/body/text/int', type: 'text/plain', body: 'true', expected: 400 },
|
|
725
|
-
{ method: 'post', path: '/body/text/int', type: 'text/plain', body: null, expected: 400 },
|
|
726
|
-
|
|
727
|
-
{ method: 'post', path: '/body/text/union', type: 'text/plain', body: 'foo', expected: 200 },
|
|
728
|
-
{ method: 'post', path: '/body/text/union', type: 'text/plain', body: '42', expected: 200 },
|
|
729
|
-
{ method: 'post', path: '/body/text/union', type: 'text/plain', body: 'hello', expected: 400 },
|
|
730
|
-
{ method: 'post', path: '/body/text/stream', type: 'text/plain', body: '42424242', expected: 200 },
|
|
731
|
-
{ method: 'post', path: '/body/text/stream', type: 'text/plain', body: null, expected: 200 },
|
|
732
|
-
|
|
733
|
-
{ method: 'post', path: '/body/json/bool', type: 'application/json', body: 'true', expected: 200 },
|
|
734
|
-
{ method: 'post', path: '/body/json/bool', type: 'application/json', body: 'false', expected: 200 },
|
|
735
|
-
{ method: 'post', path: '/body/json/bool', type: 'application/json', body: '0', expected: 400 },
|
|
736
|
-
{ method: 'post', path: '/body/json/bool', type: 'application/json', body: '', expected: 400 },
|
|
737
|
-
{ method: 'post', path: '/body/json/bool', type: 'application/json', body: null, expected: 400 },
|
|
738
|
-
|
|
739
|
-
{ method: 'post', path: '/body/json/num', type: 'application/json', body: '1', expected: 200 },
|
|
740
|
-
{ method: 'post', path: '/body/json/num', type: 'application/json', body: '1.5', expected: 200 },
|
|
741
|
-
{ method: 'post', path: '/body/json/num', type: 'application/json', body: 'foo', expected: 400 },
|
|
742
|
-
{ method: 'post', path: '/body/json/num', type: 'application/json', body: '', expected: 400 },
|
|
743
|
-
{ method: 'post', path: '/body/json/num', type: 'application/json', body: null, expected: 400 },
|
|
744
|
-
|
|
745
|
-
{ method: 'post', path: '/body/json/int', type: 'application/json', body: '1', expected: 200 },
|
|
746
|
-
{ method: 'post', path: '/body/json/int', type: 'application/json', body: '1.5', expected: 400 },
|
|
747
|
-
{ method: 'post', path: '/body/json/int', type: 'application/json', body: 'foo', expected: 400 },
|
|
748
|
-
{ method: 'post', path: '/body/json/int', type: 'application/json', body: '', expected: 400 },
|
|
749
|
-
{ method: 'post', path: '/body/json/int', type: 'application/json', body: null, expected: 400 },
|
|
750
|
-
|
|
751
|
-
{ method: 'post', path: '/body/json/str', type: 'application/json', body: '"foo"', expected: 200 },
|
|
752
|
-
{ method: 'post', path: '/body/json/str', type: 'application/json', body: 'foo', expected: 400 },
|
|
753
|
-
{ method: 'post', path: '/body/json/str', type: 'application/json', body: '', expected: 400 },
|
|
754
|
-
{ method: 'post', path: '/body/json/str', type: 'application/json', body: null, expected: 400 },
|
|
755
|
-
|
|
756
|
-
{ method: 'post', path: '/body/json/arr', type: 'application/json', body: '[]', expected: 200 },
|
|
757
|
-
{ method: 'post', path: '/body/json/arr', type: 'application/json', body: '["foo","bar"]', expected: 200 },
|
|
758
|
-
{ method: 'post', path: '/body/json/arr', type: 'application/json', body: '["foo","bar",42]', expected: 400 },
|
|
759
|
-
{ method: 'post', path: '/body/json/arr', type: 'application/json', body: '', expected: 400 },
|
|
760
|
-
{ method: 'post', path: '/body/json/arr', type: 'application/json', body: null, expected: 400 },
|
|
761
|
-
|
|
762
|
-
{ method: 'post', path: '/body/json/union', type: 'application/json', body: '"foo"', expected: 200 },
|
|
763
|
-
{ method: 'post', path: '/body/json/union', type: 'application/json', body: '""', expected: 200 },
|
|
764
|
-
{ method: 'post', path: '/body/json/union', type: 'application/json', body: 'true', expected: 200 },
|
|
765
|
-
{ method: 'post', path: '/body/json/union', type: 'application/json', body: 'false', expected: 200 },
|
|
766
|
-
{ method: 'post', path: '/body/json/union', type: 'application/json', body: '42', expected: 400 },
|
|
767
|
-
{ method: 'post', path: '/body/json/union', type: 'application/json', body: '', expected: 400 },
|
|
768
|
-
{ method: 'post', path: '/body/json/union', type: 'application/json', body: null, expected: 400 },
|
|
769
|
-
|
|
770
|
-
{ method: 'post', path: '/body/json/obj', type: 'application/json', body: '{"foo":"bar"}', expected: 200 },
|
|
771
|
-
{ method: 'post', path: '/body/json/obj', type: 'application/json', body: '{"foo":42}', expected: 400 },
|
|
772
|
-
{ method: 'post', path: '/body/json/obj', type: 'application/json', body: '{}', expected: 400 },
|
|
773
|
-
{ method: 'post', path: '/body/json/obj', type: 'application/json', body: '', expected: 400 },
|
|
774
|
-
{ method: 'post', path: '/body/json/obj', type: 'application/json', body: null, expected: 400 },
|
|
775
|
-
|
|
776
|
-
{
|
|
777
|
-
method: 'post',
|
|
778
|
-
path: '/body/urlForm',
|
|
779
|
-
type: 'application/x-www-form-urlencoded',
|
|
780
|
-
body: 'foo=foo&bar=42&opt=opt',
|
|
781
|
-
expected: 200,
|
|
782
|
-
},
|
|
783
|
-
{
|
|
784
|
-
method: 'post',
|
|
785
|
-
path: '/body/urlForm',
|
|
786
|
-
type: 'application/x-www-form-urlencoded',
|
|
787
|
-
body: 'foo=bar&bar=0',
|
|
788
|
-
expected: 200,
|
|
789
|
-
},
|
|
790
|
-
{
|
|
791
|
-
method: 'post',
|
|
792
|
-
path: '/body/urlForm',
|
|
793
|
-
type: 'application/x-www-form-urlencoded',
|
|
794
|
-
body: 'foo=test&bar=no',
|
|
795
|
-
expected: 400,
|
|
796
|
-
},
|
|
797
|
-
{
|
|
798
|
-
method: 'post',
|
|
799
|
-
path: '/body/urlForm',
|
|
800
|
-
type: 'application/x-www-form-urlencoded',
|
|
801
|
-
body: 'foo=test&bar=1&opt=no',
|
|
802
|
-
expected: 400,
|
|
803
|
-
},
|
|
804
|
-
{
|
|
805
|
-
method: 'post',
|
|
806
|
-
path: '/body/urlForm',
|
|
807
|
-
type: 'application/x-www-form-urlencoded',
|
|
808
|
-
body: 'foo=test',
|
|
809
|
-
expected: 400,
|
|
810
|
-
},
|
|
811
|
-
{
|
|
812
|
-
method: 'post',
|
|
813
|
-
path: '/body/urlForm',
|
|
814
|
-
type: 'application/x-www-form-urlencoded',
|
|
815
|
-
body: '',
|
|
816
|
-
expected: 400,
|
|
817
|
-
},
|
|
818
|
-
{
|
|
819
|
-
method: 'post',
|
|
820
|
-
path: '/body/urlForm',
|
|
821
|
-
type: 'application/x-www-form-urlencoded',
|
|
822
|
-
body: null,
|
|
823
|
-
expected: 400,
|
|
824
|
-
},
|
|
825
|
-
|
|
826
|
-
{
|
|
827
|
-
method: 'post',
|
|
828
|
-
path: '/body/multipart',
|
|
829
|
-
body: formdata({ foo: 'foo', bar: '42', opt: 'opt' }),
|
|
830
|
-
expected: 200,
|
|
831
|
-
},
|
|
832
|
-
{
|
|
833
|
-
method: 'post',
|
|
834
|
-
path: '/body/multipart',
|
|
835
|
-
body: formdata({ foo: 'foo', bar: '42' }),
|
|
836
|
-
expected: 200,
|
|
837
|
-
},
|
|
838
|
-
{
|
|
839
|
-
method: 'post',
|
|
840
|
-
path: '/body/multipart',
|
|
841
|
-
body: formdata({ bar: '42' }),
|
|
842
|
-
expected: 400,
|
|
843
|
-
},
|
|
844
|
-
{
|
|
845
|
-
method: 'post',
|
|
846
|
-
path: '/body/multipart',
|
|
847
|
-
body: formdata({ foo: 'foo', bar: 'bar' }),
|
|
848
|
-
expected: 400,
|
|
849
|
-
},
|
|
850
|
-
{
|
|
851
|
-
method: 'post',
|
|
852
|
-
path: '/body/multipart',
|
|
853
|
-
body: formdata({}),
|
|
854
|
-
expected: 400,
|
|
855
|
-
},
|
|
856
|
-
{
|
|
857
|
-
method: 'post',
|
|
858
|
-
path: '/body/multipart',
|
|
859
|
-
body: null,
|
|
860
|
-
expected: 400,
|
|
861
|
-
},
|
|
862
|
-
|
|
863
|
-
{
|
|
864
|
-
method: 'post',
|
|
865
|
-
path: '/body/multipart/stream',
|
|
866
|
-
body: formdata({ foo: 'foo', bar: '42', opt: 'opt' }),
|
|
867
|
-
expected: 200,
|
|
868
|
-
},
|
|
869
|
-
{
|
|
870
|
-
method: 'post',
|
|
871
|
-
path: '/body/multipart/stream',
|
|
872
|
-
body: formdata({ foo: 'foo', bar: '42' }),
|
|
873
|
-
expected: 200,
|
|
874
|
-
},
|
|
875
|
-
{
|
|
876
|
-
method: 'post',
|
|
877
|
-
path: '/body/multipart/stream',
|
|
878
|
-
body: formdata({ bar: '42' }),
|
|
879
|
-
expected: 400,
|
|
880
|
-
},
|
|
881
|
-
{
|
|
882
|
-
method: 'post',
|
|
883
|
-
path: '/body/multipart/stream',
|
|
884
|
-
body: formdata({ foo: 'foo', bar: 'bar' }),
|
|
885
|
-
expected: 400,
|
|
886
|
-
},
|
|
887
|
-
{
|
|
888
|
-
method: 'post',
|
|
889
|
-
path: '/body/multipart/stream',
|
|
890
|
-
body: formdata({}),
|
|
891
|
-
expected: 400,
|
|
892
|
-
},
|
|
893
|
-
{
|
|
894
|
-
method: 'post',
|
|
895
|
-
path: '/body/multipart/stream',
|
|
896
|
-
body: null,
|
|
897
|
-
expected: 400,
|
|
898
|
-
},
|
|
899
|
-
]
|
|
900
|
-
for (let { method, path, type, body, expected } of cases) {
|
|
901
|
-
let resp = await fetch(`http://localhost:${port}/${path}`, {
|
|
902
|
-
method: method.toUpperCase(),
|
|
903
|
-
body,
|
|
904
|
-
headers: { ...(type ? { 'content-type': type } : {}) },
|
|
905
|
-
})
|
|
906
|
-
expect(resp.status).toBe(expected)
|
|
907
|
-
}
|
|
908
|
-
})
|
|
909
|
-
})
|