Skip to content

Commit 77b2713

Browse files
committed
feat: add MaybeNull validator
1 parent 5a28cd7 commit 77b2713

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

src/type-system/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Type, Kind } from '@sinclair/typebox'
1+
import { Type, Kind, Static } from '@sinclair/typebox'
22
import type {
33
ArrayOptions,
44
DateOptions,
@@ -492,12 +492,21 @@ export const ElysiaType = {
492492
})
493493
.Encode((value) => value) as unknown as TUnsafe<File[]>,
494494

495+
/**
496+
* @deprecated Use MaybeNull instead which is OpenAPI 3.0 compliant. Will be removed in the next major release
497+
*/
495498
Nullable: <T extends TSchema>(schema: T, options?: SchemaOptions) =>
496499
t.Union([schema, t.Null()], {
497500
...options,
498501
nullable: true
499502
}),
500503

504+
MaybeNull: <T extends TSchema>(schema: T): TUnsafe<Static<T> | null> =>
505+
Type.Unsafe({
506+
...schema,
507+
nullable: true,
508+
}),
509+
501510
/**
502511
* Allow Optional, Nullable and Undefined
503512
*/
@@ -660,6 +669,7 @@ t.Files = (arg) => {
660669
}
661670

662671
t.Nullable = ElysiaType.Nullable
672+
t.MaybeNull = ElysiaType.MaybeNull
663673
t.MaybeEmpty = ElysiaType.MaybeEmpty
664674
t.Cookie = ElysiaType.Cookie
665675
t.Date = ElysiaType.Date
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { describe, expect, it } from 'bun:test'
2+
import Elysia, { t } from '../../src'
3+
import { post } from '../utils'
4+
5+
describe('TypeSystem - MaybeNull', () => {
6+
it('OpenAPI compliant', () => {
7+
const schema = t.MaybeNull(t.String());
8+
9+
expect(schema).toMatchObject({
10+
type: "string",
11+
nullable: true
12+
});
13+
14+
const objSchema = t.Object({
15+
name: t.MaybeNull(t.String())
16+
});
17+
18+
expect(objSchema).toMatchObject({
19+
type: "object",
20+
properties: {
21+
name: {
22+
type: "string",
23+
nullable: true
24+
}
25+
},
26+
});
27+
});
28+
29+
it('Validate', async () => {
30+
const app = new Elysia().post('/', ({ body }) => body, {
31+
body: t.Object({
32+
name: t.Nullable(t.String())
33+
})
34+
})
35+
36+
const res1 = await app.handle(
37+
post('/', {
38+
name: '123'
39+
})
40+
)
41+
expect(res1.status).toBe(200)
42+
expect(await res1.json()).toEqual({ name: '123' })
43+
44+
const res2 = await app.handle(post('/', {
45+
name: null
46+
}))
47+
expect(res2.status).toBe(200)
48+
expect(await res2.json()).toEqual({ name: null })
49+
50+
const res3 = await app.handle(post('/', {}))
51+
expect(res3.status).toBe(422)
52+
});
53+
})

0 commit comments

Comments
 (0)