galbe 0.1.6 → 0.1.7

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/src/parser.ts CHANGED
@@ -1,20 +1,24 @@
1
- import type { Static, TObject, TProperties } from '@sinclair/typebox'
1
+ import type { MaybeArray, STBody, Context } from './index'
2
2
  import type {
3
+ STStream,
4
+ STUrlForm,
5
+ STMultipartForm,
6
+ Static,
7
+ STProps,
8
+ STObject,
3
9
  MultipartFormData,
4
- MaybeArray,
5
- TBody,
6
- TMultipartForm,
7
- TUrlForm,
8
- TUrlFormParam,
9
- TMultipartFormParam,
10
- TStream,
11
- Context
12
- } from './index'
10
+ STUrlFormValues,
11
+ STMultipartFormValues,
12
+ STUnion,
13
+ STLiteral,
14
+ STArray,
15
+ STSchema
16
+ } from './schema'
13
17
 
14
- import { Kind, Optional } from '@sinclair/typebox'
15
- import { RequestError, Stream, T } from './index'
16
- import { validate } from './validator'
17
18
  import { readableStreamToArrayBuffer } from 'bun'
19
+ import { Kind, Optional, Stream } from './schema'
20
+ import { validate } from './validator'
21
+ import { RequestError, $T } from './index'
18
22
 
19
23
  const textDecoder = new TextDecoder()
20
24
  const textEncoder = new TextEncoder()
@@ -36,7 +40,7 @@ const MP_HEADER_RX = /^multipart\/form-data/
36
40
  export const requestBodyParser = async (
37
41
  body: ReadableStream | null,
38
42
  headers: { 'content-type'?: string; 'content-length'?: string },
39
- schema?: TBody
43
+ schema?: STBody
40
44
  ) => {
41
45
  const { 'content-type': contentType, 'content-length': _contentLength } = headers
42
46
  const kind = schema?.[Kind]
@@ -44,7 +48,7 @@ export const requestBodyParser = async (
44
48
  try {
45
49
  if (body === null) {
46
50
  if (schema) {
47
- if (kind === 'ByteArray') {
51
+ if (kind === 'byteArray') {
48
52
  if (Stream in schema) {
49
53
  return new ReadableStream({
50
54
  start(controller) {
@@ -72,20 +76,20 @@ export const requestBodyParser = async (
72
76
  } else return null
73
77
  }
74
78
  } else {
75
- if (kind === 'ByteArray') {
79
+ if (kind === 'byteArray') {
76
80
  if (isStream) return rsToAsyncIterator(body)
77
81
  const bytes = await readableStreamToArrayBuffer(body)
78
82
  return new Uint8Array(bytes)
79
- } else if (kind === 'String' && isStream) {
83
+ } else if (kind === 'string' && isStream) {
80
84
  return $streamToString(body)
81
85
  } else if (
82
- (!contentType?.match(FORM_HEADER_RX) && kind === 'UrlForm') ||
83
- (!contentType?.match(MP_HEADER_RX) && kind === 'MultipartForm')
86
+ (!contentType?.match(FORM_HEADER_RX) && kind === 'urlForm') ||
87
+ (!contentType?.match(MP_HEADER_RX) && kind === 'multipartForm')
84
88
  ) {
85
89
  let received = contentType?.match(FORM_HEADER_RX)
86
- ? 'UrlForm'
90
+ ? 'urlForm'
87
91
  : contentType?.match(MP_HEADER_RX)
88
- ? 'MultipartForm'
92
+ ? 'multipartForm'
89
93
  : contentType
90
94
  throw new RequestError({ status: 400, error: { body: `Expected ${kind}, received ${received}` } })
91
95
  } else if (!contentType || contentType === BA_HEADER) {
@@ -100,7 +104,7 @@ export const requestBodyParser = async (
100
104
  }
101
105
  } else if (contentType === JSON_HEADER) {
102
106
  if (!schema) {
103
- return await streamToString(body, T.Object(T.Any()))
107
+ return await streamToString(body, $T.object($T.any()))
104
108
  } else {
105
109
  const str = await streamToString(body)
106
110
  let json
@@ -124,21 +128,21 @@ export const requestBodyParser = async (
124
128
  if (!schema) {
125
129
  return await streamToUrlForm(body)
126
130
  } else {
127
- if (kind !== 'UrlForm')
128
- throw new RequestError({ status: 400, error: { body: `Expected ${kind}, received UrlForm` } })
129
- if (isStream) return $streamToUrlForm(body, schema as TStream<TUrlForm>)
130
- else return await streamToUrlForm(body, schema as TUrlForm)
131
+ if (kind !== 'urlForm')
132
+ throw new RequestError({ status: 400, error: { body: `Expected ${kind}, received urlForm` } })
133
+ if (isStream) return $streamToUrlForm(body, schema as STStream<STUrlForm>)
134
+ else return await streamToUrlForm(body, schema as STUrlForm)
131
135
  }
132
136
  } else if (contentType.match(MP_HEADER_RX)) {
133
137
  const boundary = contentType.match(/boundary\="?([^"]*)"?;?.*$/)?.[1] || ''
134
138
  if (!schema) {
135
139
  return await streamToMultipartForm(body, boundary)
136
140
  } else {
137
- if (kind !== 'MultipartForm')
141
+ if (kind !== 'multipartForm')
138
142
  throw new RequestError({ status: 400, error: { body: `Expected ${kind}, received MultipartForm` } })
139
- if (isStream) return $streamToMultipartForm(body, boundary, schema as TStream<TMultipartForm>)
143
+ if (isStream) return $streamToMultipartForm(body, boundary, schema as STStream<STMultipartForm>)
140
144
  else {
141
- return streamToMultipartForm(body, boundary, schema as TMultipartForm)
145
+ return streamToMultipartForm(body, boundary, schema as STMultipartForm)
142
146
  }
143
147
  }
144
148
  } else {
@@ -153,7 +157,7 @@ export const requestBodyParser = async (
153
157
  async function* $streamToString(body: ReadableStream) {
154
158
  for await (const chunk of body) yield textDecoder.decode(chunk)
155
159
  }
156
- const streamToString = async (body: ReadableStream, schema?: TBody): Promise<any> => {
160
+ const streamToString = async (body: ReadableStream, schema?: STBody): Promise<any> => {
157
161
  let res = ''
158
162
  for await (const chunk of $streamToString(body)) res += chunk
159
163
  if (schema) return validate(res, schema, true)
@@ -161,14 +165,14 @@ const streamToString = async (body: ReadableStream, schema?: TBody): Promise<any
161
165
  }
162
166
  async function* $streamToUrlForm(
163
167
  body: ReadableStream<Uint8Array>,
164
- schema?: TStream<TUrlForm>
168
+ schema?: STStream<STUrlForm>
165
169
  ): AsyncGenerator<[string, any]> {
166
170
  let rest: Uint8Array = new Uint8Array()
167
171
  let bK: Uint8Array = new Uint8Array()
168
172
  let bV: Uint8Array = new Uint8Array()
169
173
  let start = 0
170
174
  const required = Object.fromEntries(
171
- Object.entries(schema?.properties || {}).filter(([_, v]: [string, any]) => !(Optional in v))
175
+ Object.entries(schema?.props || {}).filter(([_, v]: [string, any]) => !v?.[Optional])
172
176
  )
173
177
  for await (const chunk of body) {
174
178
  start = 0
@@ -182,8 +186,7 @@ async function* $streamToUrlForm(
182
186
  decodeURIComponent(textDecoder.decode(bV))
183
187
  ]
184
188
  try {
185
- let s =
186
- schema?.properties?.[key]?.[Kind] === 'Array' ? schema?.properties?.[key].items : schema?.properties?.[key]
189
+ let s = schema?.props?.[key]?.[Kind] === 'array' ? schema?.props?.[key].items : schema?.props?.[key]
187
190
  val = s ? paramParser(val, s) : val
188
191
  } catch (error) {
189
192
  throw new RequestError({ status: 400, error: { body: { [key]: error } } })
@@ -214,7 +217,7 @@ async function* $streamToUrlForm(
214
217
  decodeURIComponent(textDecoder.decode(rest))
215
218
  ]
216
219
  try {
217
- let s = schema?.properties?.[key]?.[Kind] === 'Array' ? schema?.properties?.[key].items : schema?.properties?.[key]
220
+ let s = schema?.props?.[key]?.[Kind] === 'array' ? schema?.props?.[key].items : schema?.props?.[key]
218
221
  val = s ? paramParser(val, s) : val
219
222
  } catch (error) {
220
223
  throw new RequestError({ status: 400, error: { body: { [key]: error } } })
@@ -222,8 +225,7 @@ async function* $streamToUrlForm(
222
225
  delete required[key]
223
226
  yield [key, val]
224
227
  for (const [k, s] of Object.entries(required)) {
225
- //@ts-ignore
226
- if (s[Kind] === 'Array') {
228
+ if (s[Kind] === 'array') {
227
229
  yield [k, []]
228
230
  delete required[k]
229
231
  }
@@ -235,10 +237,10 @@ async function* $streamToUrlForm(
235
237
  error: { body: `Missing field${reqKeys.length > 1 ? 's' : ''}: ${reqKeys.join(', ')}` }
236
238
  })
237
239
  }
238
- const streamToUrlForm = async (body: ReadableStream<Uint8Array>, schema?: TUrlForm) => {
240
+ const streamToUrlForm = async (body: ReadableStream<Uint8Array>, schema?: STUrlForm) => {
239
241
  let entries = []
240
242
  const required = Object.fromEntries(
241
- Object.entries(schema?.properties || {}).filter(([_, v]: [string, any]) => !(Optional in v))
243
+ Object.entries(schema?.props || {}).filter(([_, v]: [string, any]) => !v?.[Optional])
242
244
  )
243
245
  let errors: Record<string, any> = {}
244
246
  for await (const chunk of $streamToUrlForm(body)) entries.push(chunk)
@@ -247,21 +249,20 @@ const streamToUrlForm = async (body: ReadableStream<Uint8Array>, schema?: TUrlFo
247
249
  if (e[0] in object) {
248
250
  if (Array.isArray(object[e[0]])) object[e[0]].push(e[1])
249
251
  else object[e[0]] = [object[e[0]], e[1]]
250
- } else object[e[0]] = schema?.properties?.[e[0]]?.[Kind] === 'Array' ? [e[1]] : e[1]
252
+ } else object[e[0]] = schema?.props?.[e[0]]?.[Kind] === 'array' ? [e[1]] : e[1]
251
253
  }
252
- if (schema?.properties)
254
+ if (schema?.props)
253
255
  for (let [k, v] of Object.entries(object)) {
254
256
  delete required[k]
255
257
  try {
256
- object[k] = schema?.properties && k in schema?.properties ? paramParser(v, schema?.properties[k]) : v
258
+ object[k] = schema?.props && k in schema?.props ? paramParser(v, schema?.props[k]) : v
257
259
  } catch (error) {
258
260
  errors[k] = k in errors ? [...errors[k], error] : error
259
261
  }
260
262
  }
261
263
  if (Object.keys(errors).length) throw new RequestError({ status: 400, error: { body: errors } })
262
264
  for (const [k, s] of Object.entries(required)) {
263
- //@ts-ignore
264
- if (s[Kind] === 'Array') {
265
+ if (s[Kind] === 'array') {
265
266
  object[k] = []
266
267
  delete required[k]
267
268
  }
@@ -274,14 +275,14 @@ const streamToUrlForm = async (body: ReadableStream<Uint8Array>, schema?: TUrlFo
274
275
  })
275
276
  return object
276
277
  }
277
- async function* $streamToMultipartForm(data: ReadableStream<Uint8Array>, boundary: string, schema?: TMultipartForm) {
278
+ async function* $streamToMultipartForm(data: ReadableStream<Uint8Array>, boundary: string, schema?: STMultipartForm) {
278
279
  const bound = textEncoder.encode(boundary)
279
280
  let rest = new Uint8Array()
280
281
  let bK: Uint8Array = new Uint8Array()
281
282
  let bV: Uint8Array = new Uint8Array()
282
283
  let start = 0
283
284
  const required = Object.fromEntries(
284
- Object.entries(schema?.properties || {}).filter(([_, v]: [string, any]) => !(Optional in v))
285
+ Object.entries(schema?.props || {}).filter(([_, v]: [string, any]) => !v?.[Optional])
285
286
  )
286
287
  for await (const chunk of data) {
287
288
  start = 0
@@ -346,8 +347,7 @@ async function* $streamToMultipartForm(data: ReadableStream<Uint8Array>, boundar
346
347
  }
347
348
  }
348
349
  for (const [k, s] of Object.entries(required)) {
349
- //@ts-ignore
350
- if (s[Kind] === 'Array') {
350
+ if (s[Kind] === 'array') {
351
351
  yield { headers: { name: k }, content: [] }
352
352
  delete required[k]
353
353
  }
@@ -381,59 +381,59 @@ const parseMultipartHeader = (header: string): { name: string; [key: string]: st
381
381
  const parseMultipartContent = (
382
382
  content: Uint8Array,
383
383
  headers: { name: string; type?: string },
384
- schema?: TMultipartForm
384
+ schema?: STMultipartForm
385
385
  ) => {
386
386
  const type = headers?.type ?? 'text/plain'
387
387
  let result: any = content
388
388
  if (type === 'text/plain') {
389
389
  const str = textDecoder.decode(content).trim()
390
- let s = schema?.properties?.[headers.name]
391
- return s ? paramParser(str, s?.[Kind] === 'Array' ? s?.items : s) : str
390
+ let s = schema?.props?.[headers.name]
391
+ return s ? paramParser(str, s?.[Kind] === 'array' ? s?.items : s) : str
392
392
  } else if (type === 'application/json') {
393
- if (!schema?.properties || !(headers.name in schema?.properties)) {
393
+ if (!schema?.props || !(headers.name in schema?.props)) {
394
394
  try {
395
395
  result = JSON.parse(textDecoder.decode(content).trim())
396
396
  } catch (err: any) {
397
397
  throw new RequestError({ status: 400, error: { body: { [headers.name]: err?.message || 'Parsing error' } } })
398
398
  }
399
- } else if (schema?.properties) {
400
- if (schema?.properties[headers.name][Kind] === 'Object') {
399
+ } else if (schema?.props) {
400
+ if (schema?.props[headers.name][Kind] === 'object') {
401
401
  try {
402
402
  result = JSON.parse(textDecoder.decode(content).trim())
403
403
  } catch (err: any) {
404
404
  throw new RequestError({ status: 400, error: { body: { [headers.name]: err?.message || 'Parsing error' } } })
405
405
  }
406
406
  try {
407
- validate(result, schema?.properties[headers.name])
407
+ validate(result, schema?.props[headers.name])
408
408
  } catch (err) {
409
409
  throw new RequestError({ status: 400, error: { body: { [headers.name]: err } } })
410
410
  }
411
- } else if (schema?.properties[headers.name][Kind] === 'ByteArray') {
411
+ } else if (schema?.props[headers.name][Kind] === 'byteArray') {
412
412
  return content
413
- } else if (schema?.properties[headers.name][Kind] === 'String') {
413
+ } else if (schema?.props[headers.name][Kind] === 'string') {
414
414
  result = textDecoder.decode(content).trim()
415
415
  } else {
416
416
  throw new RequestError({
417
417
  status: 400,
418
- error: { body: { [headers.name]: `Expect ${schema?.properties[headers.name][Kind]} found json` } }
418
+ error: { body: { [headers.name]: `Expect ${schema?.props[headers.name][Kind]} found json` } }
419
419
  })
420
420
  }
421
421
  }
422
- } else if (schema?.properties?.[headers.name]) {
422
+ } else if (schema?.props?.[headers.name]) {
423
423
  try {
424
- let s = schema?.properties[headers.name]
425
- validate(result, s?.[Kind] === 'Array' ? s?.items : s)
424
+ let s = schema?.props[headers.name]
425
+ validate(result, s?.[Kind] === 'array' ? s?.items : s)
426
426
  } catch (err) {
427
427
  throw new RequestError({ status: 400, error: { body: { [headers.name]: err } } })
428
428
  }
429
429
  }
430
430
  return result
431
431
  }
432
- const streamToMultipartForm = async (data: ReadableStream<Uint8Array>, boundary: string, schema?: TMultipartForm) => {
432
+ const streamToMultipartForm = async (data: ReadableStream<Uint8Array>, boundary: string, schema?: STMultipartForm) => {
433
433
  const res: Record<string, MultipartFormData> = {}
434
434
  const errors: Record<string, any> = {}
435
435
  const required = Object.fromEntries(
436
- Object.entries(schema?.properties || {}).filter(([_, v]: [string, any]) => !(Optional in v))
436
+ Object.entries(schema?.props || {}).filter(([_, v]: [string, any]) => !v?.[Optional])
437
437
  )
438
438
  for await (const chunk of $streamToMultipartForm(data, boundary)) {
439
439
  if (chunk.headers.name in res) {
@@ -441,29 +441,26 @@ const streamToMultipartForm = async (data: ReadableStream<Uint8Array>, boundary:
441
441
  res[chunk.headers.name].content = [res[chunk.headers.name].content]
442
442
  res[chunk.headers.name].content.push(chunk.content)
443
443
  } else {
444
- if (schema?.properties?.[chunk.headers.name]?.[Kind] === 'Array')
444
+ if (schema?.props?.[chunk.headers.name]?.[Kind] === 'array')
445
445
  res[chunk.headers.name] = { ...chunk, content: [chunk.content] }
446
446
  else res[chunk.headers.name] = chunk
447
447
  }
448
448
  delete required[chunk.headers.name]
449
449
 
450
- if (schema?.properties && chunk?.headers?.name in schema.properties) {
450
+ if (schema?.props && chunk?.headers?.name in schema.props) {
451
451
  try {
452
- if (
453
- Array.isArray(res[chunk.headers.name].content) &&
454
- schema?.properties?.[chunk.headers.name]?.[Kind] !== 'Array'
455
- )
452
+ if (Array.isArray(res[chunk.headers.name].content) && schema?.props?.[chunk.headers.name]?.[Kind] !== 'array')
456
453
  throw `Multiple values found`
457
454
  res[chunk.headers.name].content = validate(
458
455
  res[chunk.headers.name].content,
459
- schema?.properties[chunk.headers.name],
456
+ schema?.props[chunk.headers.name],
460
457
  true
461
458
  )
462
- if (schema.properties[chunk.headers.name][Kind] === 'Array')
459
+ if (schema.props[chunk.headers.name][Kind] === 'array')
463
460
  for (let [k, v] of Object.entries(res[chunk.headers.name].content)) {
464
461
  try {
465
462
  //@ts-ignore
466
- res[chunk.headers.name].content[k] = paramParser(v, schema.properties[chunk.headers.name].items)
463
+ res[chunk.headers.name].content[k] = paramParser(v, schema.props[chunk.headers.name].items)
467
464
  } catch (error) {
468
465
  errors[chunk.headers.name] = chunk.headers.name in errors ? [...errors[chunk.headers.name], error] : error
469
466
  }
@@ -479,8 +476,7 @@ const streamToMultipartForm = async (data: ReadableStream<Uint8Array>, boundary:
479
476
  error: { body: errors }
480
477
  })
481
478
  for (const [k, s] of Object.entries(required)) {
482
- //@ts-ignore
483
- if (s[Kind] === 'Array') {
479
+ if (s[Kind] === 'array') {
484
480
  res[k] = { headers: { name: k }, content: [] }
485
481
  delete required[k]
486
482
  }
@@ -493,19 +489,22 @@ const streamToMultipartForm = async (data: ReadableStream<Uint8Array>, boundary:
493
489
  })
494
490
  return res
495
491
  }
496
- const paramParser = (value: string | string[] | null, type: TMultipartFormParam): MaybeArray<Static<TUrlFormParam>> => {
492
+ const paramParser = (
493
+ value: string | string[] | null,
494
+ type: STMultipartFormValues
495
+ ): MaybeArray<Static<STUrlFormValues>> => {
497
496
  if (value === undefined) {
498
- if (type[Optional]) return type?.default
497
+ if (type?.[Optional]) return type?.default
499
498
  else throw `Required`
500
499
  } else if (value === null) return null
501
500
  else if (Array.isArray(value)) {
502
- if (type[Kind] !== 'Array') throw `Multiple values found`
501
+ if (type[Kind] !== 'array') throw `Multiple values found`
503
502
  validate(value, type)
504
503
  let pv = []
505
504
  let errors: Record<number, any> = {}
506
505
  for (let [idx, v] of value.entries()) {
507
506
  try {
508
- pv.push(paramParser(v, type.items as TMultipartFormParam) as Static<TUrlFormParam>)
507
+ pv.push(paramParser(v, type.items as STMultipartFormValues) as Static<STUrlFormValues>)
509
508
  } catch (error) {
510
509
  errors[idx] = error
511
510
  }
@@ -513,44 +512,46 @@ const paramParser = (value: string | string[] | null, type: TMultipartFormParam)
513
512
  if (Object.keys(errors).length) throw errors
514
513
  return pv
515
514
  } else {
516
- if (type[Kind] === 'Boolean') {
515
+ if (type[Kind] === 'boolean') {
517
516
  if (typeof value === 'boolean') return value
518
517
  if (value === 'true') return true
519
518
  if (value === 'false') return false
520
519
  else throw `${value} is not a valid boolean. Should be 'true' or 'false'`
521
- } else if (type[Kind] === 'Integer') {
520
+ } else if (type[Kind] === 'integer') {
522
521
  if (value === null || value === undefined) throw `${value} is not a valid integer`
523
522
  const parsedValue = parseInt(value, 10)
524
523
  if (isNaN(parsedValue) || String(parsedValue) !== String(value)) throw `${value} is not a valid integer`
525
524
  validate(parsedValue, type)
526
525
  return parsedValue
527
- } else if (type[Kind] === 'Number') {
526
+ } else if (type[Kind] === 'number') {
528
527
  if (value === null || value === undefined) throw `${value} is not a valid number`
529
528
  const parsedValue = Number(value)
530
529
  if (isNaN(parsedValue) || String(parsedValue) !== String(value)) throw `${value} is not a valid number`
531
530
  validate(parsedValue, type)
532
531
  return parsedValue
533
- } else if (type[Kind] === 'String') {
532
+ } else if (type[Kind] === 'string') {
534
533
  validate(value, type)
535
534
  return value
536
- } else if (type[Kind] === 'Literal') {
537
- if (value !== type.const) throw `${value} is not a valid value`
535
+ } else if (type[Kind] === 'literal') {
536
+ if (value !== type.value) throw `${value} is not a valid value`
538
537
  return value
539
- } else if (type[Kind] === 'Array') {
540
- return [paramParser(value, type.items as TMultipartFormParam) as Static<TUrlFormParam>]
541
- } else if (type[Kind] === 'ByteArray') {
538
+ } else if (type[Kind] === 'array') {
539
+ return [paramParser(value, type.items as STMultipartFormValues) as Static<STUrlFormValues>]
540
+ } else if (type[Kind] === 'byteArray') {
542
541
  return Uint8Array.from(value, c => c.charCodeAt(0))
543
- } else if (type[Kind] === 'Union') {
542
+ } else if (type[Kind] === 'union') {
544
543
  const union = Object.values(type.anyOf)
545
544
  for (const elt of union) {
546
545
  try {
547
- return paramParser(value, elt as TMultipartFormParam)
546
+ return paramParser(value, elt as STMultipartFormValues)
548
547
  } catch (err) {
549
548
  continue
550
549
  }
551
550
  }
552
- throw `${value} could not be parsed to any of ${union.map(u => u?.const ?? u[Kind]).join(', ')}`
553
- } else if (type[Kind] === 'Any') {
551
+ throw `${value} could not be parsed to any of ${union
552
+ .map(u => (u as STLiteral)?.value ?? (u as STSchema)[Kind])
553
+ .join(', ')}`
554
+ } else if (type[Kind] === 'any') {
554
555
  return value
555
556
  }
556
557
  throw `Unknown parsing type ${type[Kind]}`
@@ -570,12 +571,12 @@ export const requestPathParser = (input: string, path: string) => {
570
571
  return params
571
572
  }
572
573
 
573
- export const parseEntry = <T extends TProperties>(
574
+ export const parseEntry = <T extends STProps>(
574
575
  params: { [key: string]: string | string[] },
575
576
  schema: T,
576
577
  options?: { name?: string; i?: boolean }
577
- ): Static<TObject<T>> => {
578
- const parsedParams: Partial<Static<TObject<T>>> = {}
578
+ ): Static<STObject<T>> => {
579
+ const parsedParams: Partial<Static<STObject<T>>> = {}
579
580
  const errors: { [key: string]: string | string[] } = {}
580
581
 
581
582
  if (options?.i === true) {
@@ -588,9 +589,9 @@ export const parseEntry = <T extends TProperties>(
588
589
  Object.entries(schema).forEach(([key, s]) => {
589
590
  const k = options?.i === true ? key.toLowerCase() : key
590
591
  let v = params[k]
591
- if (s[Kind] === 'Array' && options?.name === 'query' && typeof v === 'string') v = v.split(',')
592
+ if (s[Kind] === 'array' && options?.name === 'query' && typeof v === 'string') v = v.split(',')
592
593
  try {
593
- let p = paramParser(v, s as TMultipartFormParam)
594
+ let p = paramParser(v, s as STMultipartFormValues)
594
595
  //@ts-ignore
595
596
  if (p !== undefined) parsedParams[k] = p
596
597
  } catch (errMsg) {
@@ -603,7 +604,7 @@ export const parseEntry = <T extends TProperties>(
603
604
  throw new RequestError({ status: 400, error: options?.name ? { [options.name]: errors } : errors })
604
605
  }
605
606
 
606
- return parsedParams as Static<TObject<T>>
607
+ return parsedParams as Static<STObject<T>>
607
608
  }
608
609
 
609
610
  const isIterator = (obj: any) => typeof obj?.next === 'function'
@@ -616,7 +617,6 @@ export const responseParser = (response: any, ctx: Context) => {
616
617
  if (response instanceof Response) return response
617
618
  else if (typeof response === 'string') {
618
619
  if (!details?.headers?.has('content-type')) details?.headers?.set('content-type', 'text/plain')
619
- //@ts-ignore
620
620
  return new Response(response, details)
621
621
  }
622
622
  if (response instanceof ReadableStream) {
@@ -641,12 +641,10 @@ export const responseParser = (response: any, ctx: Context) => {
641
641
  }
642
642
  })
643
643
  details.headers.set('Content-Type', 'text/event-stream')
644
- //@ts-ignore
645
644
  return new Response(rs, details)
646
645
  } else {
647
646
  try {
648
647
  if (!details?.headers?.has('content-type')) details?.headers?.set('content-type', 'application/json')
649
- //@ts-ignore
650
648
  return new Response(JSON.stringify(response), details)
651
649
  } catch (error) {
652
650
  console.error(error)
package/src/routes.ts CHANGED
@@ -8,6 +8,8 @@ import { Galbe } from './index'
8
8
  import { transformSync } from '@swc/core'
9
9
  import { Glob } from 'bun'
10
10
 
11
+ export const DEFAULT_ROUTE_PATTERN = 'src/**/*.route.{js,ts}'
12
+
11
13
  export type RouteMeta = {
12
14
  header: Record<string, boolean | string | string[]>
13
15
  routes: Record<string, Record<string, Record<string, boolean | string | string[]>>>
@@ -116,7 +118,7 @@ const importRoutes = async (filePath: string, galbe: Galbe) => {
116
118
  }
117
119
 
118
120
  export const defineRoutes = async (options: GalbeConfig, galbe: Galbe) => {
119
- const routes = options?.routes
121
+ const routes = options?.routes === true ? DEFAULT_ROUTE_PATTERN : options?.routes
120
122
  if (!routes) {
121
123
  console.log(`\x1b\[38;5;245m No route file defined\x1b[0m`)
122
124
  return