Skip to content

Commit a9b2020

Browse files
committed
🧹 chore: resolve merge conflict
2 parents 447ac89 + 3d61804 commit a9b2020

File tree

8 files changed

+180
-53
lines changed

8 files changed

+180
-53
lines changed

example/a.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
11
import { Elysia } from '../src'
22

33
const app = new Elysia({ precompile: true })
4-
.post('/json', ({ body }) => body, {
5-
parse: 'json'
4+
.get('/', function* () {
5+
yield "a"
6+
yield "b"
7+
yield "c"
8+
}, {
9+
mapResponse({ response }) {
10+
console.log({ response })
11+
}
612
})
713
.listen(3000)
8-
9-
console.log(app.routes[0].composed.toString())
10-
11-
const response = await app
12-
.handle(
13-
new Request('http://localhost:3000/json', {
14-
method: 'POST',
15-
body: JSON.stringify({ name: 'Aru' })
16-
})
17-
)
18-
.then((x) => x.json())
19-
20-
21-
// console.log(app.fetch.toString())

src/index.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5748,11 +5748,18 @@ export default class Elysia<
57485748
case 'object':
57495749
const parsedSchemas = {} as Record<string, TSchema>
57505750

5751-
Object.entries(name).forEach(([key, value]) => {
5752-
if (!(key in this.definitions.type))
5753-
parsedSchemas[key] = this.definitions.type[key] =
5754-
coerce(value) as TSchema
5755-
})
5751+
const kvs = Object.entries(name)
5752+
5753+
for (const [key, value] of kvs) {
5754+
if (key in this.definitions.type) continue
5755+
5756+
parsedSchemas[key] = this.definitions.type[key] = coerce(
5757+
value
5758+
) as TSchema
5759+
5760+
parsedSchemas[key].$id ??= `#/components/schemas/${key}`
5761+
}
5762+
57565763
// @ts-expect-error
57575764
this.definitions.typebox = t.Module({
57585765
...(this.definitions.typebox['$defs'] as TModule<{}>),
@@ -5767,6 +5774,21 @@ export default class Elysia<
57675774
this.definitions.typebox = t.Module(result as any)
57685775

57695776
return this as any
5777+
5778+
case 'string':
5779+
if (!model) break
5780+
5781+
const newModel = {
5782+
...model,
5783+
id: model.$id ?? `#/components/schemas/${name}`
5784+
}
5785+
5786+
this.definitions.type[name] = model
5787+
this.definitions.typebox = t.Module({
5788+
...(this.definitions.typebox['$defs'] as TModule<{}>),
5789+
...newModel
5790+
} as any)
5791+
return this as any
57705792
}
57715793

57725794
;(this.definitions.type as Record<string, TSchema>)[name] = model!

src/type-system.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { TypeRegistry, Type, FormatRegistry } from '@sinclair/typebox'
12
import {
23
ArrayOptions,
34
DateOptions,
@@ -6,24 +7,17 @@ import {
67
TArray,
78
TDate,
89
TUnsafe,
9-
TypeRegistry,
1010
TInteger,
1111
IntegerOptions,
12-
Unsafe
13-
} from '@sinclair/typebox'
14-
import {
15-
Type,
16-
type SchemaOptions,
17-
// type TNull,
18-
// type TUnion,
19-
type TSchema,
20-
// type TUndefined,
12+
Unsafe,
13+
Static,
14+
SchemaOptions,
15+
TSchema,
2116
TProperties,
2217
ObjectOptions,
2318
TObject,
2419
TNumber,
25-
TBoolean,
26-
FormatRegistry
20+
TBoolean
2721
} from '@sinclair/typebox'
2822

2923
import {
@@ -391,9 +385,9 @@ export const ElysiaType = {
391385
},
392386
Date: (property?: DateOptions) => {
393387
const schema = Type.Date(property)
394-
const _default = property?.default ?
395-
new Date(property.default) : // in case the default is an ISO string or milliseconds from epoch
396-
undefined;
388+
const _default = property?.default
389+
? new Date(property.default) // in case the default is an ISO string or milliseconds from epoch
390+
: undefined
397391
return t
398392
.Transform(
399393
t.Union(
@@ -744,6 +738,9 @@ t.Files = (arg = {}) =>
744738
}
745739
})
746740

741+
// t.Ref = <T extends TSchema>(schema: T) =>
742+
// Type.Unsafe<Static<T>>(Type.Ref(schema.$id!))
743+
747744
t.Nullable = (schema) => ElysiaType.Nullable(schema)
748745
t.MaybeEmpty = ElysiaType.MaybeEmpty as any
749746

src/types.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,9 @@ type OptionalField = {
337337
[OptionalKind]: 'Optional'
338338
}
339339

340+
type TrimArrayName<T extends string> =
341+
T extends `${infer Name}[]` ? Name : T
342+
340343
export type UnwrapSchema<
341344
Schema extends TSchema | string | undefined,
342345
Definitions extends DefinitionBase['typebox'] = TModule<{}>
@@ -346,9 +349,17 @@ export type UnwrapSchema<
346349
? Schema extends OptionalField
347350
? Prettify<Partial<Static<Schema>>>
348351
: StaticDecode<Schema>
349-
: Schema extends string
350-
? StaticDecode<TImport<UnwrapTypeModule<Definitions>, Schema>>
351-
: unknown
352+
: Schema extends `${infer Key}[]`
353+
? Definitions extends Record<Key, infer NamedSchema>
354+
? Array<NamedSchema>
355+
: StaticDecode<TImport<UnwrapTypeModule<Definitions>, TrimArrayName<Schema>>>[]
356+
: Schema extends string
357+
? Definitions extends Record<Schema, infer NamedSchema>
358+
? NamedSchema
359+
: StaticDecode<
360+
TImport<UnwrapTypeModule<Definitions>, Schema>
361+
>
362+
: unknown
352363

353364
export type UnwrapBodySchema<
354365
Schema extends TSchema | string | undefined,
@@ -359,9 +370,15 @@ export type UnwrapBodySchema<
359370
? Schema extends OptionalField
360371
? Prettify<Partial<Static<Schema>>> | null
361372
: StaticDecode<Schema>
362-
: Schema extends string
363-
? Static<TImport<UnwrapTypeModule<Definitions>, Schema>>
364-
: unknown
373+
: Schema extends `${infer Key}[]`
374+
? Definitions extends Record<Key, infer NamedSchema>
375+
? Array<NamedSchema>
376+
: Static<TImport<UnwrapTypeModule<Definitions>, TrimArrayName<Schema>>>[]
377+
: Schema extends string
378+
? Definitions extends Record<Schema, infer NamedSchema>
379+
? NamedSchema
380+
: Static<TImport<UnwrapTypeModule<Definitions>, Schema>>
381+
: unknown
365382

366383
export type IsNull<T> = [T] extends [null] ? true : false
367384

@@ -528,16 +545,17 @@ export type HTTPMethod =
528545
| 'ALL'
529546

530547
export interface InputSchema<Name extends string = string> {
531-
body?: TSchema | Name
548+
body?: TSchema | Name | `${Name}[]`
532549
headers?: TObject | TNull | TUndefined | Name
533550
query?: TObject | TNull | TUndefined | Name
534551
params?: TObject | TNull | TUndefined | Name
535552
cookie?: TObject | TNull | TUndefined | Name
536553
response?:
537554
| TSchema
538555
| Record<number, TSchema>
556+
| `${Name}[]`
539557
| Name
540-
| Record<number, Name | TSchema>
558+
| Record<number, `${Name}[]` | Name | TSchema>
541559
}
542560

543561
export interface MergeSchema<

src/utils.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -591,14 +591,17 @@ export const getSchemaValidator = <T extends TSchema | string | undefined>(
591591
}
592592
): T extends TSchema ? TypeCheck<TSchema> : undefined => {
593593
if (!s) return undefined as any
594-
if (typeof s === 'string' && !(s in models)) return undefined as any
595594

596595
let schema: TSchema =
597596
typeof s === 'string'
598-
? // @ts-expect-error
599-
((modules as TModule<{}, {}>).Import(s) ?? models[s])
597+
? s.endsWith('[]') ?
598+
t.Array(t.Ref(models[s.substring(0, s.length - 2)])) :
599+
// @ts-expect-error
600+
((modules as TModule<{}, {}>).Import(s) ?? models[s])
600601
: s
601602

603+
if (!schema) return undefined as any
604+
602605
if (coerce || additionalCoerce) {
603606
if (coerce)
604607
schema = replaceSchemaType(schema, [
@@ -757,14 +760,16 @@ export const getResponseSchemaValidator = (
757760
}
758761
): Record<number, TypeCheck<any>> | undefined => {
759762
if (!s) return
760-
if (typeof s === 'string' && !(s in models)) return
761763

762764
const maybeSchemaOrRecord =
763765
typeof s === 'string'
764-
? // @ts-ignore
766+
?
767+
s.endsWith('[]') ? t.Array(t.Ref(models[s.substring(0, s.length - 2)])) : // @ts-ignore
765768
((modules as TModule<{}, {}>).Import(s) ?? models[s])
766769
: s
767770

771+
if (!maybeSchemaOrRecord) return
772+
768773
const compile = (schema: TSchema, references?: TSchema[]) => {
769774
if (dynamic)
770775
return {
@@ -789,12 +794,14 @@ export const getResponseSchemaValidator = (
789794
return compiledValidator
790795
}
791796

797+
const modelValues = Object.values(models)
798+
792799
if (Kind in maybeSchemaOrRecord) {
793800
if ('additionalProperties' in maybeSchemaOrRecord === false)
794801
maybeSchemaOrRecord.additionalProperties = additionalProperties
795802

796803
return {
797-
200: compile(maybeSchemaOrRecord, Object.values(models))
804+
200: compile(maybeSchemaOrRecord, modelValues)
798805
}
799806
}
800807

@@ -812,7 +819,7 @@ export const getResponseSchemaValidator = (
812819
// Inherits model maybe already compiled
813820
record[+status] =
814821
Kind in schema
815-
? compile(schema, Object.values(models))
822+
? compile(schema, modelValues)
816823
: schema
817824
}
818825

@@ -828,7 +835,7 @@ export const getResponseSchemaValidator = (
828835
// Inherits model maybe already compiled
829836
record[+status] =
830837
Kind in maybeNameOrSchema
831-
? compile(maybeNameOrSchema, Object.values(models))
838+
? compile(maybeNameOrSchema, modelValues)
832839
: maybeNameOrSchema
833840
})
834841

test/extends/models.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ describe('Model', () => {
124124
data: t.Number()
125125
})
126126
})
127+
.post('/arr', ({ body }) => body, {
128+
response: 'number[]',
129+
body: 'number[]',
130+
})
127131

128132
const correct = await app.handle(
129133
new Request('http://localhost/', {
@@ -139,6 +143,19 @@ describe('Model', () => {
139143

140144
expect(correct.status).toBe(200)
141145

146+
const correctArr = await app.handle(
147+
new Request('http://localhost/arr', {
148+
method: 'POST',
149+
headers: {
150+
'content-type': 'application/json'
151+
},
152+
body: JSON.stringify([1, 2])
153+
})
154+
)
155+
156+
expect(correctArr.status).toBe(200)
157+
158+
142159
const wrong = await app.handle(
143160
new Request('http://localhost/', {
144161
method: 'POST',
@@ -152,6 +169,20 @@ describe('Model', () => {
152169
)
153170

154171
expect(wrong.status).toBe(422)
172+
173+
const wrongArr = await app.handle(
174+
new Request('http://localhost/arr', {
175+
method: 'POST',
176+
headers: {
177+
'content-type': 'application/json'
178+
},
179+
body: JSON.stringify({
180+
data: true
181+
})
182+
})
183+
)
184+
185+
expect(wrongArr.status).toBe(422)
155186
})
156187

157188
it('remap', async () => {

test/plugins/plugin.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { req } from '../utils'
66
describe('Plugin', () => {
77
it('await async nested plugin', async () => {
88
const yay = async () => {
9-
await Bun.sleep(1_000)
9+
await Bun.sleep(2)
1010

1111
return new Elysia({ name: 'yay' }).get('/yay', 'yay')
1212
}

0 commit comments

Comments
 (0)