Skip to content

Commit 9605f4e

Browse files
committed
🎉 feat: reference model
1 parent 77e89f7 commit 9605f4e

File tree

11 files changed

+610
-138
lines changed

11 files changed

+610
-138
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 0.2.0-rc.0 - 23 Jan 2023
2+
Feature:
3+
- Add support for reference model via `.setModel`
4+
- Add support for OpenAPI's `definitions` field
5+
16
# 0.2.0-beta.2 - 22 Jan 2023
27
Feature:
38
- Add support for custom openapi field using `schema.detail`

bun.lockb

0 Bytes
Binary file not shown.

example/schema.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
1-
import { Elysia, t, SCHEMA } from '../src'
1+
import { Elysia, t, SCHEMA, DEFS } from '../src'
22

33
const app = new Elysia()
4-
// Strictly validate response
5-
.get('/', () => 'hi', {
6-
schema: {
4+
.setModel(
5+
'a',
6+
t.Object({
77
response: t.String()
8-
}
9-
})
8+
})
9+
)
10+
.setModel(
11+
'b',
12+
t.Object({
13+
response: t.Number()
14+
})
15+
)
16+
// Strictly validate response
17+
.get('/', () => 'hi')
1018
// Strictly validate body and response
11-
.post('/', ({ body }) => body.id, {
19+
.post('/', ({ body, query }) => body.id, {
1220
schema: {
1321
body: t.Object({
1422
id: t.Number(),
1523
username: t.String(),
1624
profile: t.Object({
1725
name: t.String()
1826
})
19-
}),
20-
response: {
21-
200: t.Number()
22-
}
27+
})
2328
}
2429
})
2530
// Strictly validate query, params, and body
@@ -71,4 +76,7 @@ const app = new Elysia()
7176
)
7277
.listen(8080)
7378

74-
type A = typeof app['store'][typeof SCHEMA]['/query/:id']['GET']['query']
79+
type A = typeof app['store'][typeof SCHEMA]['/']['POST']['query']
80+
type B = typeof app['store'][typeof DEFS]
81+
82+
// const a = app.getModel('b')

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "elysia",
33
"description": "Fast, and friendly Bun web framework",
4-
"version": "0.2.0-beta.2",
4+
"version": "0.2.0-rc.0",
55
"author": {
66
"name": "saltyAom",
77
"url": "https://github.com/SaltyAom",

src/context.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import { Elysia } from '.'
22
import type { TypedRoute } from './types'
33

4+
type UnwrapFn<T> = T extends (...params: any) => any ? ReturnType<T> : T
5+
46
export interface Context<
57
Route extends TypedRoute = TypedRoute,
68
Store extends Elysia['store'] = Elysia['store']
79
> {
810
request: Request
9-
query: Route['query'] extends undefined
11+
query: UnwrapFn<Route['query']> extends undefined
1012
? Record<string, unknown>
11-
: Route['query']
12-
params: Route['params']
13-
body: Route['body']
13+
: UnwrapFn<Route['query']>
14+
params: UnwrapFn<Route['params']>
15+
body: UnwrapFn<Route['body']>
1416
store: Store
1517

1618
set: {

src/index.ts

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import {
88
mergeHook,
99
mergeDeep,
1010
createValidationError,
11+
getSchemaValidator,
1112
SCHEMA,
12-
getSchemaValidator
13+
DEFS,
14+
getResponseSchemaValidator
1315
} from './utils'
1416
import { registerSchemaPath } from './schema'
1517
import { mapErrorCode, mapErrorStatus } from './error'
@@ -44,8 +46,10 @@ import type {
4446
NoReturnHandler,
4547
ElysiaRoute,
4648
MaybePromise,
47-
IsNever
49+
IsNever,
50+
InferSchema
4851
} from './types'
52+
import { type TSchema } from '@sinclair/typebox'
4953

5054
/**
5155
* ### Elysia Server
@@ -65,7 +69,8 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
6569
config: ElysiaConfig
6670

6771
store: Instance['store'] = {
68-
[SCHEMA]: {}
72+
[SCHEMA]: {},
73+
[DEFS]: {}
6974
}
7075
// Will be applied to Context
7176
protected decorators: Record<string, unknown> | null = null
@@ -99,7 +104,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
99104
}
100105

101106
private _addHandler<
102-
Schema extends TypedSchema = TypedSchema,
107+
Schema extends TypedSchema,
103108
Path extends string = string
104109
>(
105110
method: HTTPMethod,
@@ -116,28 +121,36 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
116121
hooks: mergeHook(clone(this.event), hook as RegisteredHook)
117122
})
118123

124+
const defs = this.store[DEFS]
125+
119126
const body = getSchemaValidator(
120-
hook?.schema?.body ?? this.$schema?.body
127+
hook?.schema?.body ?? this.$schema?.body,
128+
defs
121129
)
122130
const header = getSchemaValidator(
123131
hook?.schema?.headers ?? this.$schema?.headers,
132+
defs,
124133
true
125134
)
126135
const params = getSchemaValidator(
127-
hook?.schema?.params ?? this.$schema?.params
136+
hook?.schema?.params ?? this.$schema?.params,
137+
defs
128138
)
129139
const query = getSchemaValidator(
130-
hook?.schema?.query ?? this.$schema?.query
140+
hook?.schema?.query ?? this.$schema?.query,
141+
defs
131142
)
132-
const response = getSchemaValidator(
133-
hook?.schema?.response ?? this.$schema?.response
143+
const response = getResponseSchemaValidator(
144+
hook?.schema?.response ?? this.$schema?.response,
145+
defs
134146
)
135147

136148
registerSchemaPath({
137149
schema: this.store[SCHEMA],
138150
hook,
139151
method,
140-
path
152+
path,
153+
models: this.store[DEFS]
141154
})
142155

143156
const validator =
@@ -639,7 +652,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
639652
* ```
640653
*/
641654
get<
642-
Schema extends TypedSchema = TypedSchema,
655+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
643656
Path extends string = string,
644657
Response = unknown
645658
>(
@@ -671,7 +684,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
671684
* ```
672685
*/
673686
post<
674-
Schema extends TypedSchema = {},
687+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
675688
Path extends string = string,
676689
Response = unknown
677690
>(
@@ -703,7 +716,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
703716
* ```
704717
*/
705718
put<
706-
Schema extends TypedSchema = {},
719+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
707720
Path extends string = string,
708721
Response = unknown
709722
>(
@@ -735,7 +748,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
735748
* ```
736749
*/
737750
patch<
738-
Schema extends TypedSchema = {},
751+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
739752
Path extends string = string,
740753
Response = unknown
741754
>(
@@ -767,7 +780,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
767780
* ```
768781
*/
769782
delete<
770-
Schema extends TypedSchema = {},
783+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
771784
Path extends string = string,
772785
Response = unknown
773786
>(
@@ -799,7 +812,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
799812
* ```
800813
*/
801814
options<
802-
Schema extends TypedSchema = {},
815+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
803816
Path extends string = string,
804817
Response = unknown
805818
>(
@@ -826,7 +839,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
826839
* ```
827840
*/
828841
all<
829-
Schema extends TypedSchema = {},
842+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
830843
Path extends string = string,
831844
Response = unknown
832845
>(
@@ -858,7 +871,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
858871
* ```
859872
*/
860873
head<
861-
Schema extends TypedSchema = {},
874+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
862875
Path extends string = string,
863876
Response = unknown
864877
>(
@@ -890,7 +903,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
890903
* ```
891904
*/
892905
trace<
893-
Schema extends TypedSchema = {},
906+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
894907
Path extends string = string,
895908
Response = unknown
896909
>(
@@ -922,7 +935,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
922935
* ```
923936
*/
924937
connect<
925-
Schema extends TypedSchema = {},
938+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
926939
Path extends string = string,
927940
Response = unknown
928941
>(
@@ -955,7 +968,7 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
955968
*/
956969
route<
957970
Method extends HTTPMethod = HTTPMethod,
958-
Schema extends TypedSchema = {},
971+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
959972
Path extends string = string,
960973
Response = unknown
961974
>(
@@ -1104,21 +1117,22 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
11041117
* ```
11051118
*/
11061119
schema<
1107-
Schema extends TypedSchema = TypedSchema,
1120+
Schema extends InferSchema<Instance> = InferSchema<Instance>,
11081121
NewInstance = Elysia<{
11091122
request: Instance['request']
11101123
store: Instance['store']
11111124
schema: MergeSchema<Schema, Instance['schema']>
11121125
}>
11131126
>(schema: Schema): NewInstance {
1127+
const defs = this.store[DEFS]
1128+
11141129
this.$schema = {
1115-
body: getSchemaValidator(schema?.body),
1116-
headers: getSchemaValidator(schema?.headers),
1117-
params: getSchemaValidator(schema?.params),
1118-
query: getSchemaValidator(schema?.query),
1119-
response: getSchemaValidator(
1120-
schema?.response?.['200'] ?? schema.response
1121-
)
1130+
body: getSchemaValidator(schema.body, defs),
1131+
headers: getSchemaValidator(schema?.headers, defs, true),
1132+
params: getSchemaValidator(schema?.params, defs),
1133+
query: getSchemaValidator(schema?.query, defs),
1134+
// @ts-ignore
1135+
response: getSchemaValidator(schema?.response, defs)
11221136
}
11231137

11241138
return this as unknown as NewInstance
@@ -1421,13 +1435,28 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
14211435
get modules() {
14221436
return Promise.all(this.lazyLoadModules)
14231437
}
1438+
1439+
setModel<Recorder extends Record<string, TSchema>>(
1440+
record: Recorder
1441+
): Elysia<{
1442+
store: Instance['store'] & {
1443+
[Defs in typeof DEFS]: Recorder
1444+
}
1445+
request: Instance['request']
1446+
schema: Instance['schema']
1447+
}> {
1448+
Object.assign(this.store[DEFS], record)
1449+
1450+
return this as unknown as any
1451+
}
14241452
}
14251453

14261454
export { Elysia, Router }
14271455
export { Type as t } from '@sinclair/typebox'
14281456

14291457
export {
14301458
SCHEMA,
1459+
DEFS,
14311460
getPath,
14321461
createValidationError,
14331462
getSchemaValidator

0 commit comments

Comments
 (0)