@nmtjs/type 0.4.7 → 0.5.0
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/dist/compiler.js +84 -38
- package/dist/compiler.js.map +1 -1
- package/dist/formats.js +1 -1
- package/dist/formats.js.map +1 -1
- package/dist/index.js +53 -22
- package/dist/index.js.map +1 -1
- package/dist/schemas/discriminated-union.js +9 -0
- package/dist/schemas/discriminated-union.js.map +1 -0
- package/dist/schemas/nullable.js +1 -6
- package/dist/schemas/nullable.js.map +1 -1
- package/dist/temporal.js +7 -7
- package/dist/temporal.js.map +1 -1
- package/dist/types/any.js +3 -43
- package/dist/types/any.js.map +1 -1
- package/dist/types/array.js +17 -63
- package/dist/types/array.js.map +1 -1
- package/dist/types/base.js +78 -41
- package/dist/types/base.js.map +1 -1
- package/dist/types/boolean.js +3 -43
- package/dist/types/boolean.js.map +1 -1
- package/dist/types/custom.js +8 -48
- package/dist/types/custom.js.map +1 -1
- package/dist/types/date.js +8 -0
- package/dist/types/date.js.map +1 -0
- package/dist/types/enum.js +10 -94
- package/dist/types/enum.js.map +1 -1
- package/dist/types/literal.js +3 -43
- package/dist/types/literal.js.map +1 -1
- package/dist/types/never.js +3 -26
- package/dist/types/never.js.map +1 -1
- package/dist/types/number.js +52 -186
- package/dist/types/number.js.map +1 -1
- package/dist/types/object.js +10 -131
- package/dist/types/object.js.map +1 -1
- package/dist/types/string.js +25 -65
- package/dist/types/string.js.map +1 -1
- package/dist/types/temporal.js +23 -328
- package/dist/types/temporal.js.map +1 -1
- package/dist/types/union.js +16 -90
- package/dist/types/union.js.map +1 -1
- package/dist/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/compiler.ts +124 -41
- package/src/formats.ts +1 -1
- package/src/index.ts +145 -63
- package/src/schemas/discriminated-union.ts +49 -0
- package/src/schemas/nullable.ts +7 -13
- package/src/temporal.ts +8 -7
- package/src/types/any.ts +6 -46
- package/src/types/array.ts +38 -86
- package/src/types/base.ts +205 -81
- package/src/types/boolean.ts +13 -47
- package/src/types/custom.ts +21 -79
- package/src/types/date.ts +10 -0
- package/src/types/enum.ts +18 -107
- package/src/types/literal.ts +7 -63
- package/src/types/never.ts +6 -36
- package/src/types/number.ts +52 -188
- package/src/types/object.ts +61 -202
- package/src/types/string.ts +25 -61
- package/src/types/temporal.ts +53 -410
- package/src/types/union.ts +98 -138
- package/src/utils.ts +8 -0
- package/dist/constants.js +0 -2
- package/dist/constants.js.map +0 -1
- package/dist/types/datetime.js +0 -53
- package/dist/types/datetime.js.map +0 -1
- package/src/constants.ts +0 -5
- package/src/types/datetime.ts +0 -65
package/src/compiler.ts
CHANGED
|
@@ -3,28 +3,52 @@ import {
|
|
|
3
3
|
TypeCompiler,
|
|
4
4
|
type ValueErrorIterator,
|
|
5
5
|
} from '@sinclair/typebox/compiler'
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import {
|
|
7
|
+
TransformDecode,
|
|
8
|
+
TransformEncode,
|
|
9
|
+
Value,
|
|
10
|
+
} from '@sinclair/typebox/value'
|
|
11
|
+
import type { t } from './index.ts'
|
|
12
|
+
import { IsDiscriminatedUnion } from './schemas/discriminated-union.ts'
|
|
13
|
+
import type { BaseType } from './types/base.ts'
|
|
14
|
+
|
|
15
|
+
type ValidationError = {
|
|
16
|
+
path: string
|
|
17
|
+
message: string
|
|
18
|
+
value: unknown
|
|
19
|
+
}
|
|
9
20
|
|
|
10
21
|
export type Compiled<T extends BaseType = BaseType> = {
|
|
11
22
|
check: (val: unknown) => boolean
|
|
12
|
-
errors: (val: unknown) =>
|
|
23
|
+
errors: (val: unknown) => ValidationError[]
|
|
13
24
|
parse: (val: unknown) => unknown
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Requires to `check` before calling
|
|
27
|
+
*/
|
|
28
|
+
decode: (val: unknown) => t.infer.decoded<T>
|
|
29
|
+
/**
|
|
30
|
+
* Requires to `check` before calling
|
|
31
|
+
*/
|
|
32
|
+
encode: (val: unknown) => t.infer.encoded<T>
|
|
33
|
+
/**
|
|
34
|
+
* Requires to `check` before calling
|
|
35
|
+
*/
|
|
16
36
|
decodeSafe: (
|
|
17
37
|
val: unknown,
|
|
18
38
|
) =>
|
|
19
|
-
| { success: true; value: T
|
|
39
|
+
| { success: true; value: t.infer.decoded<T> }
|
|
20
40
|
| { success: false; error: any }
|
|
41
|
+
/**
|
|
42
|
+
* Requires to `check` before calling
|
|
43
|
+
*/
|
|
21
44
|
encodeSafe: (
|
|
22
45
|
val: unknown,
|
|
23
46
|
) =>
|
|
24
|
-
| { success: true; value: T
|
|
47
|
+
| { success: true; value: t.infer.encoded<T> }
|
|
25
48
|
| { success: false; error: any }
|
|
26
49
|
}
|
|
27
50
|
|
|
51
|
+
// FIXME: this one is very slow
|
|
28
52
|
function _parse(schema: TSchema, value: any) {
|
|
29
53
|
// Clone -> Clean -> Default -> Convert
|
|
30
54
|
return Value.Convert(
|
|
@@ -33,70 +57,129 @@ function _parse(schema: TSchema, value: any) {
|
|
|
33
57
|
)
|
|
34
58
|
}
|
|
35
59
|
|
|
60
|
+
function _errors(errors: ValueErrorIterator) {
|
|
61
|
+
const result: ValidationError[] = []
|
|
62
|
+
|
|
63
|
+
for (const error of errors) {
|
|
64
|
+
if (IsDiscriminatedUnion(error.schema)) {
|
|
65
|
+
const discriminator = error.schema.discriminator
|
|
66
|
+
const discriminatorValue = error.value?.[discriminator]
|
|
67
|
+
if (discriminatorValue !== undefined) {
|
|
68
|
+
const variantSchema = error.schema.anyOf.find(
|
|
69
|
+
(schema) =>
|
|
70
|
+
schema.properties[discriminator].const === discriminatorValue,
|
|
71
|
+
)
|
|
72
|
+
if (variantSchema) {
|
|
73
|
+
const propertiesSchemas: TSchema[] = []
|
|
74
|
+
for (const element in variantSchema.properties) {
|
|
75
|
+
const propertySchema = variantSchema.properties[element]
|
|
76
|
+
if (propertySchema !== variantSchema.properties[discriminator]) {
|
|
77
|
+
propertiesSchemas.push(propertySchema)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (const iter of error.errors) {
|
|
82
|
+
for (const err of iter) {
|
|
83
|
+
if (!propertiesSchemas.includes(err.schema)) continue
|
|
84
|
+
result.push({
|
|
85
|
+
path: err.path,
|
|
86
|
+
message: err.message,
|
|
87
|
+
value: err.value,
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
continue
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
result.push({
|
|
98
|
+
path: error.path,
|
|
99
|
+
message: error.message,
|
|
100
|
+
value: error.value,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
for (const nestedError of error.errors) {
|
|
104
|
+
result.push(..._errors(nestedError))
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return result
|
|
109
|
+
}
|
|
110
|
+
|
|
36
111
|
function compileType(type: BaseType) {
|
|
37
|
-
const schema =
|
|
112
|
+
const { final: schema } = type
|
|
38
113
|
const compiled = TypeCompiler.Compile(schema)
|
|
114
|
+
const errors = (value) => {
|
|
115
|
+
return _errors(compiled.Errors(value))
|
|
116
|
+
}
|
|
117
|
+
|
|
39
118
|
return {
|
|
40
119
|
check: compiled.Check.bind(compiled),
|
|
41
|
-
errors: compiled.Errors.bind(compiled),
|
|
42
|
-
decode: compiled.Decode.bind(compiled),
|
|
43
|
-
encode: compiled.Encode.bind(compiled),
|
|
44
120
|
parse: _parse.bind(null, schema),
|
|
121
|
+
errors,
|
|
122
|
+
decode: TransformDecode.bind(null, schema, compiled.References()),
|
|
123
|
+
encode: TransformEncode.bind(null, schema, compiled.References()),
|
|
45
124
|
}
|
|
46
125
|
}
|
|
47
126
|
|
|
48
127
|
export function compile<T extends BaseType>(schema: T): Compiled<T> {
|
|
49
128
|
const compiled = compileType(schema)
|
|
50
129
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
success: true as const,
|
|
57
|
-
value: compiled.decode(val),
|
|
58
|
-
}
|
|
59
|
-
} catch (error) {
|
|
60
|
-
return { success: false as const, error }
|
|
130
|
+
function decodeSafe(val: unknown) {
|
|
131
|
+
try {
|
|
132
|
+
return {
|
|
133
|
+
success: true as const,
|
|
134
|
+
value: compiled.decode(val),
|
|
61
135
|
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
136
|
+
} catch (error) {
|
|
137
|
+
return { success: false as const, error }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function encodeSafe(val: unknown) {
|
|
142
|
+
try {
|
|
143
|
+
return {
|
|
144
|
+
success: true as const,
|
|
145
|
+
value: compiled.encode(val),
|
|
71
146
|
}
|
|
72
|
-
}
|
|
147
|
+
} catch (error) {
|
|
148
|
+
return { success: false as const, error }
|
|
149
|
+
}
|
|
73
150
|
}
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
...compiled,
|
|
154
|
+
decodeSafe,
|
|
155
|
+
encodeSafe,
|
|
156
|
+
} as any
|
|
74
157
|
}
|
|
75
158
|
|
|
76
159
|
export namespace runtime {
|
|
77
160
|
export function parse(type: BaseType, value: any) {
|
|
78
|
-
return _parse(
|
|
161
|
+
return _parse(type.schema, value)
|
|
79
162
|
}
|
|
80
163
|
|
|
81
|
-
export function errors(type: BaseType, value: any):
|
|
82
|
-
return Value.Errors(
|
|
164
|
+
export function errors(type: BaseType, value: any): ValidationError[] {
|
|
165
|
+
return _errors(Value.Errors(type.schema, value))
|
|
83
166
|
}
|
|
84
167
|
|
|
85
168
|
export function check(type: BaseType, value: any): boolean {
|
|
86
|
-
return Value.Check(
|
|
169
|
+
return Value.Check(type.schema, value)
|
|
87
170
|
}
|
|
88
171
|
|
|
89
172
|
export function decode<T extends BaseType>(
|
|
90
|
-
type:
|
|
173
|
+
type: T,
|
|
91
174
|
value: any,
|
|
92
|
-
): T
|
|
93
|
-
return
|
|
175
|
+
): t.infer.decoded<T> {
|
|
176
|
+
return TransformDecode(type.schema, [], value)
|
|
94
177
|
}
|
|
95
178
|
|
|
96
179
|
export function encode<T extends BaseType>(
|
|
97
180
|
type: T,
|
|
98
181
|
value: any,
|
|
99
|
-
): T
|
|
100
|
-
return
|
|
182
|
+
): t.infer.encoded<T> {
|
|
183
|
+
return TransformEncode(type.schema, [], value)
|
|
101
184
|
}
|
|
102
185
|
}
|
package/src/formats.ts
CHANGED
|
@@ -32,7 +32,7 @@ export const fullFormats: Record<
|
|
|
32
32
|
'iso-date-time': getDateTime(),
|
|
33
33
|
// duration: https://tools.ietf.org/html/rfc3339#appendix-A
|
|
34
34
|
duration:
|
|
35
|
-
/^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?((\d+|\d
|
|
35
|
+
/^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?((\d+|\d+\.\d+)S)?)?|(\d+W)?)$/,
|
|
36
36
|
uri,
|
|
37
37
|
'uri-reference':
|
|
38
38
|
/^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i,
|
package/src/index.ts
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
StaticDecode,
|
|
3
|
+
StaticEncode,
|
|
4
|
+
TLiteralValue,
|
|
5
|
+
} from '@sinclair/typebox/type'
|
|
6
|
+
import { AnyType } from './types/any.ts'
|
|
2
7
|
import { ArrayType } from './types/array.ts'
|
|
3
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
BaseType,
|
|
10
|
+
BaseTypeAny,
|
|
11
|
+
OptionalType,
|
|
12
|
+
Static,
|
|
13
|
+
} from './types/base.ts'
|
|
4
14
|
import { BooleanType } from './types/boolean.ts'
|
|
5
15
|
import { CustomType } from './types/custom.ts'
|
|
6
|
-
import { DateType } from './types/
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
EnumType,
|
|
11
|
-
ObjectEnumType,
|
|
12
|
-
} from './types/enum.ts'
|
|
13
|
-
import { type AnyLiteralType, LiteralType } from './types/literal.ts'
|
|
16
|
+
import { DateType } from './types/date.ts'
|
|
17
|
+
import { EnumType, ObjectEnumType } from './types/enum.ts'
|
|
18
|
+
import { LiteralType } from './types/literal.ts'
|
|
19
|
+
import { NeverType } from './types/never.ts'
|
|
14
20
|
import { BigIntType, IntegerType, NumberType } from './types/number.ts'
|
|
15
|
-
import { ObjectType, RecordType } from './types/object.ts'
|
|
16
|
-
import {
|
|
21
|
+
import { ObjectType, type ObjectTypeProps, RecordType } from './types/object.ts'
|
|
22
|
+
import { StringType } from './types/string.ts'
|
|
17
23
|
import {
|
|
18
|
-
|
|
24
|
+
DiscriminatedUnionType,
|
|
19
25
|
IntersactionType,
|
|
20
26
|
UnionType,
|
|
21
27
|
} from './types/union.ts'
|
|
22
|
-
|
|
23
|
-
import type { typeStatic } from './constants.ts'
|
|
24
|
-
import { AnyType } from './types/any.ts'
|
|
25
|
-
import { NeverType } from './types/never.ts'
|
|
28
|
+
import type { UnionToTupleString } from './utils.ts'
|
|
26
29
|
|
|
27
30
|
// register ajv formats
|
|
28
31
|
import { register } from './formats.ts'
|
|
29
32
|
register()
|
|
30
33
|
|
|
31
34
|
export * from './schemas/nullable.ts'
|
|
32
|
-
export {
|
|
33
|
-
BaseType,
|
|
34
|
-
getTypeSchema,
|
|
35
|
-
} from './types/base.ts'
|
|
35
|
+
export { BaseType, type BaseTypeAny } from './types/base.ts'
|
|
36
36
|
export { type TSchema } from '@sinclair/typebox'
|
|
37
37
|
export {
|
|
38
38
|
ArrayType,
|
|
@@ -53,48 +53,130 @@ export {
|
|
|
53
53
|
|
|
54
54
|
export namespace t {
|
|
55
55
|
export namespace infer {
|
|
56
|
-
export type
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
export type decoded<T extends BaseTypeAny> = StaticDecode<
|
|
57
|
+
T['_']['decoded']['output']
|
|
58
|
+
>
|
|
59
|
+
export type encoded<T extends BaseTypeAny> = StaticEncode<
|
|
60
|
+
T['_']['encoded']['output']
|
|
61
|
+
>
|
|
62
|
+
export namespace input {
|
|
63
|
+
export type decoded<T extends BaseTypeAny> = StaticDecode<
|
|
64
|
+
T['_']['decoded']['input']
|
|
65
|
+
>
|
|
66
|
+
export type encoded<T extends BaseTypeAny> = StaticEncode<
|
|
67
|
+
T['_']['encoded']['input']
|
|
68
|
+
>
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const never = NeverType.factory
|
|
73
|
+
export const boolean = BooleanType.factory
|
|
74
|
+
export const string = StringType.factory
|
|
75
|
+
export const number = NumberType.factory
|
|
76
|
+
export const integer = IntegerType.factory
|
|
77
|
+
export const bitint = BigIntType.factory
|
|
78
|
+
export const literal = LiteralType.factory
|
|
79
|
+
export const objectEnum = ObjectEnumType.factory
|
|
80
|
+
export const arrayEnum = EnumType.factory
|
|
81
|
+
export const date = DateType.factory
|
|
82
|
+
export const array = ArrayType.factory
|
|
83
|
+
export const object = ObjectType.factory
|
|
84
|
+
export const record = RecordType.factory
|
|
85
|
+
export const any = AnyType.factory
|
|
86
|
+
export const or = UnionType.factory
|
|
87
|
+
export const and = IntersactionType.factory
|
|
88
|
+
export const discriminatedUnion = DiscriminatedUnionType.factory
|
|
89
|
+
export const custom = CustomType.factory
|
|
90
|
+
|
|
91
|
+
export const keyof = <T extends ObjectType>(
|
|
92
|
+
type: T,
|
|
93
|
+
): EnumType<
|
|
94
|
+
UnionToTupleString<T extends ObjectType<infer Props> ? keyof Props : never>
|
|
95
|
+
> => {
|
|
96
|
+
return arrayEnum(Object.keys(type.props.properties) as any)
|
|
59
97
|
}
|
|
60
|
-
|
|
61
|
-
export const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
export const integer = () => new IntegerType()
|
|
65
|
-
export const bitint = () => new BigIntType()
|
|
66
|
-
export const literal = <T extends TLiteralValue>(value: T) =>
|
|
67
|
-
new LiteralType(value)
|
|
68
|
-
export const objectEnum = <T extends { [K in string]: K }>(enumLike: T) =>
|
|
69
|
-
new ObjectEnumType(enumLike)
|
|
70
|
-
export const arrayEnum = <T extends (string | number)[]>(enumLike: [...T]) =>
|
|
71
|
-
new EnumType(enumLike)
|
|
72
|
-
export const date = () => new DateType()
|
|
73
|
-
export const array = <T extends BaseType>(element: T) =>
|
|
74
|
-
new ArrayType(element)
|
|
75
|
-
export const object = <T extends Record<string, BaseType>>(properties: T) =>
|
|
76
|
-
new ObjectType(properties)
|
|
77
|
-
export const record = <
|
|
78
|
-
K extends
|
|
79
|
-
| AnyLiteralType
|
|
80
|
-
| AnyEnumType
|
|
81
|
-
| AnyObjectEnumType
|
|
82
|
-
| AnyStringType
|
|
83
|
-
| AnyUnionType,
|
|
84
|
-
E extends BaseType,
|
|
98
|
+
|
|
99
|
+
export const pick = <
|
|
100
|
+
T extends ObjectType,
|
|
101
|
+
P extends { [K in keyof T['props']['properties']]?: true },
|
|
85
102
|
>(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
source: T,
|
|
104
|
+
pick: P,
|
|
105
|
+
): ObjectType<{
|
|
106
|
+
[K in keyof T['props']['properties'] as K extends keyof P
|
|
107
|
+
? K
|
|
108
|
+
: never]: T['props']['properties'][K]
|
|
109
|
+
}> => {
|
|
110
|
+
const properties = Object.fromEntries(
|
|
111
|
+
Object.entries(source.props.properties).filter(([key]) => pick[key]),
|
|
112
|
+
)
|
|
113
|
+
return ObjectType.factory(properties) as any
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const omit = <
|
|
117
|
+
T extends ObjectType,
|
|
118
|
+
P extends { [K in keyof T]?: true },
|
|
119
|
+
>(
|
|
120
|
+
source: T,
|
|
121
|
+
omit: P,
|
|
122
|
+
): ObjectType<{
|
|
123
|
+
[K in keyof T['props']['properties'] as K extends keyof P
|
|
124
|
+
? never
|
|
125
|
+
: K]: T['props']['properties'][K]
|
|
126
|
+
}> => {
|
|
127
|
+
const properties = Object.fromEntries(
|
|
128
|
+
Object.entries(source.props.properties).filter(([key]) => !omit[key]),
|
|
129
|
+
)
|
|
130
|
+
return ObjectType.factory(properties) as any
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const extend = <T extends ObjectType, P extends ObjectTypeProps>(
|
|
134
|
+
object1: T,
|
|
135
|
+
properties: P,
|
|
136
|
+
): ObjectType<{
|
|
137
|
+
[K in keyof T['props']['properties'] | keyof P]: K extends keyof P
|
|
138
|
+
? P[K]
|
|
139
|
+
: K extends keyof T['props']['properties']
|
|
140
|
+
? T['props']['properties'][K]
|
|
141
|
+
: never
|
|
142
|
+
}> => {
|
|
143
|
+
return ObjectType.factory({
|
|
144
|
+
...object1.props.properties,
|
|
145
|
+
...properties,
|
|
146
|
+
}) as any
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const merge = <T1 extends ObjectType, T2 extends ObjectType>(
|
|
150
|
+
object1: T1,
|
|
151
|
+
object2: T2,
|
|
152
|
+
): ObjectType<{
|
|
153
|
+
[K in
|
|
154
|
+
| keyof T1['props']['properties']
|
|
155
|
+
| keyof T2['props']['properties']]: K extends keyof T2['props']['properties']
|
|
156
|
+
? T2['props']['properties'][K]
|
|
157
|
+
: K extends keyof T1['props']['properties']
|
|
158
|
+
? T1['props']['properties'][K]
|
|
159
|
+
: never
|
|
160
|
+
}> => {
|
|
161
|
+
return ObjectType.factory({
|
|
162
|
+
...object1.props.properties,
|
|
163
|
+
...object2.props.properties,
|
|
164
|
+
}) as any
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export const partial = <T extends ObjectType>(
|
|
168
|
+
object: T,
|
|
169
|
+
): ObjectType<{
|
|
170
|
+
[K in keyof T['props']['properties']]: OptionalType<
|
|
171
|
+
T['props']['properties'][K]
|
|
172
|
+
>
|
|
173
|
+
}> => {
|
|
174
|
+
const properties = {} as any
|
|
175
|
+
|
|
176
|
+
for (const [key, value] of Object.entries(object.props.properties)) {
|
|
177
|
+
properties[key] = value.optional()
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return ObjectType.factory(properties, {}) as any
|
|
181
|
+
}
|
|
100
182
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
KindGuard,
|
|
3
|
+
type TLiteral,
|
|
4
|
+
type TObject,
|
|
5
|
+
type TPropertyKey,
|
|
6
|
+
type TSchema,
|
|
7
|
+
type TUnion,
|
|
8
|
+
Type,
|
|
9
|
+
TypeGuard,
|
|
10
|
+
ValueGuard,
|
|
11
|
+
} from '@sinclair/typebox'
|
|
12
|
+
|
|
13
|
+
export function IsDiscriminatedUnion(
|
|
14
|
+
schema: TSchema,
|
|
15
|
+
): schema is TDiscriminatedUnion {
|
|
16
|
+
return (
|
|
17
|
+
TypeGuard.IsUnion(schema) &&
|
|
18
|
+
'discriminator' in schema &&
|
|
19
|
+
ValueGuard.IsString(schema.discriminator) &&
|
|
20
|
+
schema.anyOf.every(
|
|
21
|
+
(variant) =>
|
|
22
|
+
KindGuard.IsObject(variant) &&
|
|
23
|
+
KindGuard.IsLiteralString(variant.properties[schema.discriminator]),
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type DiscriminatedUnionProperties<K extends string = string> = {
|
|
29
|
+
[OK in K]: TLiteral<any>
|
|
30
|
+
} & {
|
|
31
|
+
[OK in TPropertyKey]: any
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface TDiscriminatedUnion<
|
|
35
|
+
K extends string = string,
|
|
36
|
+
T extends TObject<DiscriminatedUnionProperties<K>>[] = TObject<
|
|
37
|
+
DiscriminatedUnionProperties<K>
|
|
38
|
+
>[],
|
|
39
|
+
> extends TUnion<T> {
|
|
40
|
+
discriminator: K
|
|
41
|
+
anyOf: T
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function DiscriminatedUnion<
|
|
45
|
+
K extends string,
|
|
46
|
+
T extends TObject<DiscriminatedUnionProperties<K>>[],
|
|
47
|
+
>(key: K, types: T): TDiscriminatedUnion<K, T> {
|
|
48
|
+
return Type.Union(types, { discriminator: key }) as any
|
|
49
|
+
}
|
package/src/schemas/nullable.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type SchemaOptions,
|
|
3
3
|
type TNull,
|
|
4
|
+
type TOptional,
|
|
4
5
|
type TSchema,
|
|
6
|
+
type TUndefined,
|
|
5
7
|
type TUnion,
|
|
6
8
|
Type,
|
|
7
9
|
} from '@sinclair/typebox/type'
|
|
@@ -11,22 +13,14 @@ export const Nullable = <T extends TSchema>(
|
|
|
11
13
|
schema: T,
|
|
12
14
|
options: SchemaOptions = {},
|
|
13
15
|
) => {
|
|
14
|
-
const {
|
|
15
|
-
default: _default,
|
|
16
|
-
description,
|
|
17
|
-
examples,
|
|
18
|
-
readOnly,
|
|
19
|
-
title,
|
|
20
|
-
writeOnly,
|
|
21
|
-
} = schema
|
|
16
|
+
const { default: _default } = schema
|
|
22
17
|
|
|
23
18
|
return Type.Union([schema, Type.Null()], {
|
|
24
19
|
default: _default,
|
|
25
|
-
description,
|
|
26
|
-
examples,
|
|
27
|
-
readOnly,
|
|
28
|
-
title,
|
|
29
|
-
writeOnly,
|
|
30
20
|
...options,
|
|
31
21
|
})
|
|
32
22
|
}
|
|
23
|
+
|
|
24
|
+
export type TOptionalUndefined<T extends TSchema> = TOptional<
|
|
25
|
+
TUnion<[T, TUndefined]>
|
|
26
|
+
>
|
package/src/temporal.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Temporal } from 'temporal-polyfill'
|
|
1
2
|
import {
|
|
2
3
|
DurationType,
|
|
3
4
|
PlainDateTimeType,
|
|
@@ -8,13 +9,13 @@ import {
|
|
|
8
9
|
ZonedDateTimeType,
|
|
9
10
|
} from './types/temporal.ts'
|
|
10
11
|
|
|
11
|
-
export const plainDate =
|
|
12
|
-
export const plainDatetime =
|
|
13
|
-
export const plainTime =
|
|
14
|
-
export const zonedDatetime =
|
|
15
|
-
export const duration =
|
|
16
|
-
export const plainYearMonth =
|
|
17
|
-
export const plainMonthDay =
|
|
12
|
+
export const plainDate = PlainDateType.factory
|
|
13
|
+
export const plainDatetime = PlainDateTimeType.factory
|
|
14
|
+
export const plainTime = PlainTimeType.factory
|
|
15
|
+
export const zonedDatetime = ZonedDateTimeType.factory
|
|
16
|
+
export const duration = DurationType.factory
|
|
17
|
+
export const plainYearMonth = PlainYearMonthType.factory
|
|
18
|
+
export const plainMonthDay = PlainMonthDayType.factory
|
|
18
19
|
|
|
19
20
|
export {
|
|
20
21
|
DurationType,
|
package/src/types/any.ts
CHANGED
|
@@ -1,50 +1,10 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { BaseType } from './base.ts'
|
|
1
|
+
import { type TAny, Type } from '@sinclair/typebox'
|
|
2
|
+
import { BaseType, type ConstantType } from './base.ts'
|
|
3
3
|
|
|
4
|
-
export class AnyType<
|
|
5
|
-
|
|
6
|
-
O extends boolean = false,
|
|
7
|
-
D extends boolean = false,
|
|
8
|
-
> extends BaseType<TAny, N, O, D, SchemaOptions> {
|
|
9
|
-
constructor(
|
|
10
|
-
options: SchemaOptions = {},
|
|
11
|
-
isNullable: N = false as N,
|
|
12
|
-
isOptional: O = false as O,
|
|
13
|
-
hasDefault: D = false as D,
|
|
14
|
-
) {
|
|
15
|
-
super(options, isNullable, isOptional, hasDefault)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
protected _constructSchema(options: SchemaOptions): TAny {
|
|
19
|
-
return Type.Any(options)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
nullable() {
|
|
23
|
-
return new AnyType(...this._with({ isNullable: true }))
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
optional() {
|
|
27
|
-
return new AnyType(...this._with({ isOptional: true }))
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
nullish() {
|
|
31
|
-
return new AnyType(...this._with({ isNullable: true, isOptional: true }))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
default(value: any) {
|
|
35
|
-
return new AnyType(
|
|
36
|
-
...this._with({
|
|
37
|
-
options: { default: value },
|
|
38
|
-
hasDefault: true,
|
|
39
|
-
}),
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
description(description: string) {
|
|
44
|
-
return new AnyType(...this._with({ options: { description } }))
|
|
45
|
-
}
|
|
4
|
+
export class AnyType extends BaseType<TAny> {
|
|
5
|
+
_!: ConstantType<this['schema']>
|
|
46
6
|
|
|
47
|
-
|
|
48
|
-
return new AnyType(
|
|
7
|
+
static factory() {
|
|
8
|
+
return new AnyType(Type.Any())
|
|
49
9
|
}
|
|
50
10
|
}
|