@nmtjs/type 0.5.2 → 0.6.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 +16 -79
- package/dist/compiler.js.map +1 -1
- package/dist/index.js +30 -54
- package/dist/index.js.map +1 -1
- package/dist/inference.js +1 -0
- package/dist/inference.js.map +1 -0
- package/dist/parse.js +145 -0
- package/dist/parse.js.map +1 -0
- package/dist/runtime.js +73 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schemas/default.js +6 -0
- package/dist/schemas/default.js.map +1 -0
- package/dist/schemas/discriminated-union.js.map +1 -1
- package/dist/schemas/nullable.js.map +1 -1
- package/dist/temporal.js.map +1 -1
- package/dist/types/any.js +0 -1
- package/dist/types/any.js.map +1 -1
- package/dist/types/array.js +0 -1
- package/dist/types/array.js.map +1 -1
- package/dist/types/base.js +4 -13
- package/dist/types/base.js.map +1 -1
- package/dist/types/boolean.js +0 -1
- package/dist/types/boolean.js.map +1 -1
- package/dist/types/custom.js +0 -1
- package/dist/types/custom.js.map +1 -1
- package/dist/types/date.js +9 -1
- package/dist/types/date.js.map +1 -1
- package/dist/types/enum.js +6 -4
- package/dist/types/enum.js.map +1 -1
- package/dist/types/literal.js +3 -2
- package/dist/types/literal.js.map +1 -1
- package/dist/types/never.js +0 -1
- package/dist/types/never.js.map +1 -1
- package/dist/types/number.js +2 -3
- package/dist/types/number.js.map +1 -1
- package/dist/types/object.js +31 -1
- package/dist/types/object.js.map +1 -1
- package/dist/types/string.js +0 -1
- package/dist/types/string.js.map +1 -1
- package/dist/types/union.js +8 -7
- package/dist/types/union.js.map +1 -1
- package/package.json +8 -8
- package/src/compiler.ts +36 -121
- package/src/index.ts +36 -119
- package/src/inference.ts +128 -0
- package/src/parse.ts +217 -0
- package/src/runtime.ts +137 -0
- package/src/schemas/default.ts +12 -0
- package/src/schemas/discriminated-union.ts +1 -1
- package/src/schemas/nullable.ts +0 -6
- package/src/temporal.ts +0 -1
- package/src/types/any.ts +2 -4
- package/src/types/array.ts +0 -11
- package/src/types/base.ts +45 -139
- package/src/types/boolean.ts +3 -10
- package/src/types/custom.ts +14 -13
- package/src/types/date.ts +13 -1
- package/src/types/enum.ts +12 -15
- package/src/types/literal.ts +3 -5
- package/src/types/never.ts +2 -4
- package/src/types/number.ts +18 -18
- package/src/types/object.ts +107 -42
- package/src/types/string.ts +8 -5
- package/src/types/union.ts +42 -77
package/src/parse.ts
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// --------------------------------------------------------------------------
|
|
2
|
+
// Iterators
|
|
3
|
+
// --------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
/** Returns true if this value is an async iterator */
|
|
6
|
+
export function IsAsyncIterator(value) {
|
|
7
|
+
return IsObject(value) && Symbol.asyncIterator in value
|
|
8
|
+
}
|
|
9
|
+
/** Returns true if this value is an iterator */
|
|
10
|
+
export function IsIterator(value) {
|
|
11
|
+
return IsObject(value) && Symbol.iterator in value
|
|
12
|
+
}
|
|
13
|
+
// --------------------------------------------------------------------------
|
|
14
|
+
// Object Instances
|
|
15
|
+
// --------------------------------------------------------------------------
|
|
16
|
+
/** Returns true if this value is not an instance of a class */
|
|
17
|
+
export function IsStandardObject(value) {
|
|
18
|
+
return (
|
|
19
|
+
IsObject(value) &&
|
|
20
|
+
(Object.getPrototypeOf(value) === Object.prototype ||
|
|
21
|
+
Object.getPrototypeOf(value) === null)
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
/** Returns true if this value is an instance of a class */
|
|
25
|
+
export function IsInstanceObject(value) {
|
|
26
|
+
return (
|
|
27
|
+
IsObject(value) &&
|
|
28
|
+
!IsArray(value) &&
|
|
29
|
+
IsFunction(value.constructor) &&
|
|
30
|
+
value.constructor.name !== 'Object'
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
// --------------------------------------------------------------------------
|
|
34
|
+
// JavaScript
|
|
35
|
+
// --------------------------------------------------------------------------
|
|
36
|
+
/** Returns true if this value is a Promise */
|
|
37
|
+
export function IsPromise(value) {
|
|
38
|
+
return value instanceof Promise
|
|
39
|
+
}
|
|
40
|
+
/** Returns true if this value is a Date */
|
|
41
|
+
export function IsDate(value) {
|
|
42
|
+
return value instanceof Date && Number.isFinite(value.getTime())
|
|
43
|
+
}
|
|
44
|
+
/** Returns true if this value is an instance of Map<K, T> */
|
|
45
|
+
export function IsMap(value) {
|
|
46
|
+
return value instanceof globalThis.Map
|
|
47
|
+
}
|
|
48
|
+
/** Returns true if this value is an instance of Set<T> */
|
|
49
|
+
export function IsSet(value) {
|
|
50
|
+
return value instanceof globalThis.Set
|
|
51
|
+
}
|
|
52
|
+
/** Returns true if this value is RegExp */
|
|
53
|
+
export function IsRegExp(value) {
|
|
54
|
+
return value instanceof globalThis.RegExp
|
|
55
|
+
}
|
|
56
|
+
/** Returns true if this value is a typed array */
|
|
57
|
+
export function IsTypedArray(value) {
|
|
58
|
+
return ArrayBuffer.isView(value)
|
|
59
|
+
}
|
|
60
|
+
/** Returns true if the value is a Int8Array */
|
|
61
|
+
export function IsInt8Array(value) {
|
|
62
|
+
return value instanceof globalThis.Int8Array
|
|
63
|
+
}
|
|
64
|
+
/** Returns true if the value is a Uint8Array */
|
|
65
|
+
export function IsUint8Array(value) {
|
|
66
|
+
return value instanceof globalThis.Uint8Array
|
|
67
|
+
}
|
|
68
|
+
/** Returns true if the value is a Uint8ClampedArray */
|
|
69
|
+
export function IsUint8ClampedArray(value) {
|
|
70
|
+
return value instanceof globalThis.Uint8ClampedArray
|
|
71
|
+
}
|
|
72
|
+
/** Returns true if the value is a Int16Array */
|
|
73
|
+
export function IsInt16Array(value) {
|
|
74
|
+
return value instanceof globalThis.Int16Array
|
|
75
|
+
}
|
|
76
|
+
/** Returns true if the value is a Uint16Array */
|
|
77
|
+
export function IsUint16Array(value) {
|
|
78
|
+
return value instanceof globalThis.Uint16Array
|
|
79
|
+
}
|
|
80
|
+
/** Returns true if the value is a Int32Array */
|
|
81
|
+
export function IsInt32Array(value) {
|
|
82
|
+
return value instanceof globalThis.Int32Array
|
|
83
|
+
}
|
|
84
|
+
/** Returns true if the value is a Uint32Array */
|
|
85
|
+
export function IsUint32Array(value) {
|
|
86
|
+
return value instanceof globalThis.Uint32Array
|
|
87
|
+
}
|
|
88
|
+
/** Returns true if the value is a Float32Array */
|
|
89
|
+
export function IsFloat32Array(value) {
|
|
90
|
+
return value instanceof globalThis.Float32Array
|
|
91
|
+
}
|
|
92
|
+
/** Returns true if the value is a Float64Array */
|
|
93
|
+
export function IsFloat64Array(value) {
|
|
94
|
+
return value instanceof globalThis.Float64Array
|
|
95
|
+
}
|
|
96
|
+
/** Returns true if the value is a BigInt64Array */
|
|
97
|
+
export function IsBigInt64Array(value) {
|
|
98
|
+
return value instanceof globalThis.BigInt64Array
|
|
99
|
+
}
|
|
100
|
+
/** Returns true if the value is a BigUint64Array */
|
|
101
|
+
export function IsBigUint64Array(value) {
|
|
102
|
+
return value instanceof globalThis.BigUint64Array
|
|
103
|
+
}
|
|
104
|
+
// --------------------------------------------------------------------------
|
|
105
|
+
// PropertyKey
|
|
106
|
+
// --------------------------------------------------------------------------
|
|
107
|
+
/** Returns true if this value has this property key */
|
|
108
|
+
export function HasPropertyKey(value, key) {
|
|
109
|
+
return key in value
|
|
110
|
+
}
|
|
111
|
+
// --------------------------------------------------------------------------
|
|
112
|
+
// Standard
|
|
113
|
+
// --------------------------------------------------------------------------
|
|
114
|
+
/** Returns true of this value is an object type */
|
|
115
|
+
export function IsObject(value) {
|
|
116
|
+
return value !== null && typeof value === 'object'
|
|
117
|
+
}
|
|
118
|
+
/** Returns true if this value is an array, but not a typed array */
|
|
119
|
+
export function IsArray(value) {
|
|
120
|
+
return Array.isArray(value) && !ArrayBuffer.isView(value)
|
|
121
|
+
}
|
|
122
|
+
/** Returns true if this value is an undefined */
|
|
123
|
+
export function IsUndefined(value) {
|
|
124
|
+
return value === undefined
|
|
125
|
+
}
|
|
126
|
+
/** Returns true if this value is an null */
|
|
127
|
+
export function IsNull(value) {
|
|
128
|
+
return value === null
|
|
129
|
+
}
|
|
130
|
+
/** Returns true if this value is an boolean */
|
|
131
|
+
export function IsBoolean(value) {
|
|
132
|
+
return typeof value === 'boolean'
|
|
133
|
+
}
|
|
134
|
+
/** Returns true if this value is an number */
|
|
135
|
+
export function IsNumber(value) {
|
|
136
|
+
return typeof value === 'number'
|
|
137
|
+
}
|
|
138
|
+
/** Returns true if this value is an integer */
|
|
139
|
+
export function IsInteger(value) {
|
|
140
|
+
return Number.isInteger(value)
|
|
141
|
+
}
|
|
142
|
+
/** Returns true if this value is bigint */
|
|
143
|
+
export function IsBigInt(value) {
|
|
144
|
+
return typeof value === 'bigint'
|
|
145
|
+
}
|
|
146
|
+
/** Returns true if this value is string */
|
|
147
|
+
export function IsString(value) {
|
|
148
|
+
return typeof value === 'string'
|
|
149
|
+
}
|
|
150
|
+
/** Returns true if this value is a function */
|
|
151
|
+
export function IsFunction(value) {
|
|
152
|
+
return typeof value === 'function'
|
|
153
|
+
}
|
|
154
|
+
/** Returns true if this value is a symbol */
|
|
155
|
+
export function IsSymbol(value) {
|
|
156
|
+
return typeof value === 'symbol'
|
|
157
|
+
}
|
|
158
|
+
/** Returns true if this value is a value type such as number, string, boolean */
|
|
159
|
+
export function IsValueType(value) {
|
|
160
|
+
// prettier-ignore
|
|
161
|
+
return (
|
|
162
|
+
IsBigInt(value) ||
|
|
163
|
+
IsBoolean(value) ||
|
|
164
|
+
IsNull(value) ||
|
|
165
|
+
IsNumber(value) ||
|
|
166
|
+
IsString(value) ||
|
|
167
|
+
IsSymbol(value) ||
|
|
168
|
+
IsUndefined(value)
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ------------------------------------------------------------------
|
|
173
|
+
// Clonable
|
|
174
|
+
// ------------------------------------------------------------------
|
|
175
|
+
function FromObject(value, exclude) {
|
|
176
|
+
const Acc = {}
|
|
177
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
178
|
+
Acc[key] = Clone(value[key], exclude)
|
|
179
|
+
}
|
|
180
|
+
for (const key of Object.getOwnPropertySymbols(value)) {
|
|
181
|
+
Acc[key] = Clone(value[key], exclude)
|
|
182
|
+
}
|
|
183
|
+
return Acc
|
|
184
|
+
}
|
|
185
|
+
function FromArray(value, exclude) {
|
|
186
|
+
return value.map((element) => Clone(element, exclude))
|
|
187
|
+
}
|
|
188
|
+
function FromTypedArray(value) {
|
|
189
|
+
return value.slice()
|
|
190
|
+
}
|
|
191
|
+
function FromMap(value, exclude) {
|
|
192
|
+
return new Map(Clone([...value.entries()], exclude))
|
|
193
|
+
}
|
|
194
|
+
function FromSet(value, exclude) {
|
|
195
|
+
return new Set(Clone([...value.entries()], exclude))
|
|
196
|
+
}
|
|
197
|
+
function FromDate(value) {
|
|
198
|
+
return new Date(value.toISOString())
|
|
199
|
+
}
|
|
200
|
+
function FromValue(value) {
|
|
201
|
+
return value
|
|
202
|
+
}
|
|
203
|
+
// ------------------------------------------------------------------
|
|
204
|
+
// Clone
|
|
205
|
+
// ------------------------------------------------------------------
|
|
206
|
+
/** Returns a clone of the given value */
|
|
207
|
+
export function Clone(value, exclude?: Set<any>) {
|
|
208
|
+
if (IsArray(value)) return FromArray(value, exclude)
|
|
209
|
+
if (IsDate(value)) return FromDate(value)
|
|
210
|
+
if (IsTypedArray(value)) return FromTypedArray(value)
|
|
211
|
+
if (IsMap(value)) return FromMap(value, exclude)
|
|
212
|
+
if (IsSet(value)) return FromSet(value, exclude)
|
|
213
|
+
if (IsObject(value)) return FromObject(value, exclude)
|
|
214
|
+
if (IsValueType(value)) return FromValue(value)
|
|
215
|
+
if (exclude?.has(value.constructor)) return value
|
|
216
|
+
throw new Error('Cannot clone value')
|
|
217
|
+
}
|
package/src/runtime.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { ClassConstructor } from '@nmtjs/common'
|
|
2
|
+
import type { TSchema } from '@sinclair/typebox'
|
|
3
|
+
import type { ValueErrorIterator } from '@sinclair/typebox/compiler'
|
|
4
|
+
import {
|
|
5
|
+
TransformDecode,
|
|
6
|
+
TransformEncode,
|
|
7
|
+
Value,
|
|
8
|
+
} from '@sinclair/typebox/value'
|
|
9
|
+
import { register } from './formats.ts'
|
|
10
|
+
import type {
|
|
11
|
+
StaticInputEncode,
|
|
12
|
+
StaticOutputDecode,
|
|
13
|
+
StaticOutputEncode,
|
|
14
|
+
} from './inference.ts'
|
|
15
|
+
import { Clone } from './parse.ts'
|
|
16
|
+
import { IsDiscriminatedUnion } from './schemas/discriminated-union.ts'
|
|
17
|
+
import type { BaseType } from './types/base.ts'
|
|
18
|
+
|
|
19
|
+
// register ajv formats
|
|
20
|
+
register()
|
|
21
|
+
|
|
22
|
+
export type CloneOptions = {
|
|
23
|
+
clone?: boolean
|
|
24
|
+
exclude?: Set<any>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type ValidationError = {
|
|
28
|
+
path: string
|
|
29
|
+
message: string
|
|
30
|
+
value: unknown
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// TODO: this one is very slow
|
|
34
|
+
export function _applyDefaults(schema: TSchema, value: any) {
|
|
35
|
+
return Value.Default(schema, value)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// TODO: this one is very slow
|
|
39
|
+
// Clone -> Clean -> Convert
|
|
40
|
+
export function _parse(
|
|
41
|
+
schema: TSchema,
|
|
42
|
+
value: any,
|
|
43
|
+
cloneOptions?: CloneOptions,
|
|
44
|
+
) {
|
|
45
|
+
if (cloneOptions?.clone !== false) {
|
|
46
|
+
value = Clone(value, cloneOptions?.exclude)
|
|
47
|
+
}
|
|
48
|
+
return Value.Clean(schema, Value.Convert(schema, value))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function _traversErrors(errors: ValueErrorIterator) {
|
|
52
|
+
const result: ValidationError[] = []
|
|
53
|
+
|
|
54
|
+
for (const error of errors) {
|
|
55
|
+
if (IsDiscriminatedUnion(error.schema)) {
|
|
56
|
+
const discriminator = error.schema.discriminator
|
|
57
|
+
const discriminatorValue = error.value?.[discriminator]
|
|
58
|
+
if (discriminatorValue !== undefined) {
|
|
59
|
+
const variantSchema = error.schema.anyOf.find(
|
|
60
|
+
(schema) =>
|
|
61
|
+
schema.properties[discriminator].const === discriminatorValue,
|
|
62
|
+
)
|
|
63
|
+
if (variantSchema) {
|
|
64
|
+
const propertiesSchemas: TSchema[] = []
|
|
65
|
+
for (const element in variantSchema.properties) {
|
|
66
|
+
const propertySchema = variantSchema.properties[element]
|
|
67
|
+
if (propertySchema !== variantSchema.properties[discriminator]) {
|
|
68
|
+
propertiesSchemas.push(propertySchema)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (const iter of error.errors) {
|
|
73
|
+
for (const err of iter) {
|
|
74
|
+
if (!propertiesSchemas.includes(err.schema)) continue
|
|
75
|
+
result.push({
|
|
76
|
+
path: err.path,
|
|
77
|
+
message: err.message,
|
|
78
|
+
value: err.value,
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
result.push({
|
|
89
|
+
path: error.path,
|
|
90
|
+
message: error.message,
|
|
91
|
+
value: error.value,
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
for (const nestedError of error.errors) {
|
|
95
|
+
result.push(..._traversErrors(nestedError))
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return result
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function applyDefaults(type: BaseType, value: unknown) {
|
|
103
|
+
return _applyDefaults(type.schema, value)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function parse(
|
|
107
|
+
type: BaseType,
|
|
108
|
+
value: unknown,
|
|
109
|
+
cloneOptions?: CloneOptions,
|
|
110
|
+
) {
|
|
111
|
+
return _parse(type.schema, value, cloneOptions)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function errors(type: BaseType, value: unknown): ValidationError[] {
|
|
115
|
+
return _traversErrors(Value.Errors(type.schema, value))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function check<T extends BaseType>(
|
|
119
|
+
type: T,
|
|
120
|
+
value: unknown,
|
|
121
|
+
): value is StaticInputEncode<T['schema']> {
|
|
122
|
+
return Value.Check(type.schema, value)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function decode<T extends BaseType>(
|
|
126
|
+
type: T,
|
|
127
|
+
value: unknown,
|
|
128
|
+
): StaticOutputDecode<T['schema']> {
|
|
129
|
+
return TransformDecode(type.schema, [], value)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function encode<T extends BaseType>(
|
|
133
|
+
type: T,
|
|
134
|
+
value: unknown,
|
|
135
|
+
): StaticOutputEncode<T['schema']> {
|
|
136
|
+
return TransformEncode(type.schema, [], value)
|
|
137
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TSchema } from '@sinclair/typebox'
|
|
2
|
+
|
|
3
|
+
export type TDefault<Type extends TSchema, Default = unknown> = Type & {
|
|
4
|
+
default: Default
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function Default<Type extends TSchema, const Default>(
|
|
8
|
+
type: Type,
|
|
9
|
+
default_: Default,
|
|
10
|
+
): TDefault<Type, Default> {
|
|
11
|
+
return { ...type, default: default_ } as never
|
|
12
|
+
}
|
package/src/schemas/nullable.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type SchemaOptions,
|
|
3
3
|
type TNull,
|
|
4
|
-
type TOptional,
|
|
5
4
|
type TSchema,
|
|
6
|
-
type TUndefined,
|
|
7
5
|
type TUnion,
|
|
8
6
|
Type,
|
|
9
7
|
} from '@sinclair/typebox/type'
|
|
@@ -20,7 +18,3 @@ export const Nullable = <T extends TSchema>(
|
|
|
20
18
|
...options,
|
|
21
19
|
})
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
export type TOptionalUndefined<T extends TSchema> = TOptional<
|
|
25
|
-
TUnion<[T, TUndefined]>
|
|
26
|
-
>
|
package/src/temporal.ts
CHANGED
package/src/types/any.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { type TAny, Type } from '@sinclair/typebox'
|
|
2
|
-
import { BaseType
|
|
3
|
-
|
|
4
|
-
export class AnyType extends BaseType<TAny> {
|
|
5
|
-
_!: ConstantType<this['schema']>
|
|
2
|
+
import { BaseType } from './base.ts'
|
|
6
3
|
|
|
4
|
+
export class AnyType extends BaseType<TAny, {}, any> {
|
|
7
5
|
static factory() {
|
|
8
6
|
return new AnyType(Type.Any())
|
|
9
7
|
}
|
package/src/types/array.ts
CHANGED
|
@@ -10,17 +10,6 @@ export class ArrayType<T extends BaseType = BaseType> extends BaseType<
|
|
|
10
10
|
TArray<T['schema']>,
|
|
11
11
|
{ element: T; options: ArrayOptions }
|
|
12
12
|
> {
|
|
13
|
-
_!: {
|
|
14
|
-
encoded: {
|
|
15
|
-
input: TArray<T['_']['encoded']['input']>
|
|
16
|
-
output: TArray<T['_']['encoded']['output']>
|
|
17
|
-
}
|
|
18
|
-
decoded: {
|
|
19
|
-
input: TArray<T['_']['decoded']['input']>
|
|
20
|
-
output: TArray<T['_']['decoded']['output']>
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
13
|
static factory<T extends BaseType>(element: T, options: ArrayOptions = {}) {
|
|
25
14
|
return new ArrayType<T>(Type.Array(element.schema, options))
|
|
26
15
|
}
|
package/src/types/base.ts
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type StaticDecode,
|
|
5
|
-
type StaticEncode,
|
|
6
|
-
type TSchema,
|
|
7
|
-
} from '@sinclair/typebox'
|
|
8
|
-
import {
|
|
9
|
-
Nullable,
|
|
10
|
-
type TNullable,
|
|
11
|
-
type TOptionalUndefined,
|
|
12
|
-
} from '../schemas/nullable.ts'
|
|
13
|
-
import type { Merge } from '../utils.ts'
|
|
1
|
+
import { Optional, type TOptional, type TSchema } from '@sinclair/typebox'
|
|
2
|
+
import { Default, type TDefault } from '../schemas/default.ts'
|
|
3
|
+
import { Nullable, type TNullable } from '../schemas/nullable.ts'
|
|
14
4
|
|
|
15
5
|
export type TypeProps = Record<string, any>
|
|
16
6
|
|
|
@@ -28,80 +18,42 @@ export type DefaultTypeParams = {
|
|
|
28
18
|
encode?: TypeParams['encode']
|
|
29
19
|
}
|
|
30
20
|
|
|
31
|
-
export type BaseTypeAny<T extends TSchema = TSchema> = BaseType<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
> = P['nullable'] extends true
|
|
37
|
-
? T extends TNullable<infer S>
|
|
38
|
-
? TNullable<S>
|
|
39
|
-
: TNullable<T>
|
|
40
|
-
: T
|
|
41
|
-
|
|
42
|
-
type ResolveOptional<
|
|
43
|
-
T extends TSchema,
|
|
44
|
-
P extends TypeParams,
|
|
45
|
-
> = P['optional'] extends true
|
|
46
|
-
? T extends TOptionalUndefined<infer S>
|
|
47
|
-
? TOptionalUndefined<S>
|
|
48
|
-
: TOptionalUndefined<T>
|
|
49
|
-
: T
|
|
50
|
-
|
|
51
|
-
type ResolveDefault<
|
|
52
|
-
T extends TSchema,
|
|
53
|
-
P extends TypeParams,
|
|
54
|
-
> = P['hasDefault'] extends true
|
|
55
|
-
? T extends TOptionalUndefined<infer U>
|
|
56
|
-
? U
|
|
57
|
-
: T
|
|
58
|
-
: T
|
|
21
|
+
export type BaseTypeAny<T extends TSchema = TSchema> = BaseType<
|
|
22
|
+
T,
|
|
23
|
+
TypeProps,
|
|
24
|
+
any
|
|
25
|
+
>
|
|
59
26
|
|
|
60
27
|
export abstract class BaseType<
|
|
61
28
|
Schema extends TSchema = TSchema,
|
|
62
29
|
Props extends TypeProps = TypeProps,
|
|
63
|
-
|
|
30
|
+
ValueType = unknown,
|
|
64
31
|
> {
|
|
65
|
-
abstract _: {
|
|
66
|
-
encoded: {
|
|
67
|
-
input: TSchema
|
|
68
|
-
output: TSchema
|
|
69
|
-
}
|
|
70
|
-
decoded: {
|
|
71
|
-
input: TSchema
|
|
72
|
-
output: TSchema
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
32
|
readonly schema: Schema
|
|
77
|
-
readonly final: TSchema
|
|
78
33
|
readonly props: Props
|
|
79
|
-
readonly params:
|
|
34
|
+
readonly params: TypeParams
|
|
80
35
|
|
|
81
36
|
constructor(
|
|
82
37
|
schema: Schema,
|
|
83
38
|
props: Props = {} as Props,
|
|
84
|
-
params:
|
|
39
|
+
params: TypeParams = {} as TypeParams,
|
|
85
40
|
) {
|
|
86
41
|
const { hasDefault = false, nullable = false, optional = false } = params
|
|
87
42
|
this.schema = schema
|
|
88
|
-
this.final = schema
|
|
89
|
-
if (nullable) this.final = Nullable(this.final) as any
|
|
90
|
-
if (optional || hasDefault) this.final = Optional(this.final) as any
|
|
91
43
|
|
|
92
44
|
this.props = props
|
|
93
45
|
this.params = {
|
|
94
46
|
hasDefault,
|
|
95
47
|
nullable,
|
|
96
48
|
optional,
|
|
97
|
-
} as
|
|
49
|
+
} as TypeParams
|
|
98
50
|
}
|
|
99
51
|
|
|
100
|
-
optional(): OptionalType<
|
|
52
|
+
optional(): OptionalType<BaseType<Schema, Props>, ValueType> {
|
|
101
53
|
return OptionalType.factory(this) as any
|
|
102
54
|
}
|
|
103
55
|
|
|
104
|
-
nullable(): NullableType<
|
|
56
|
+
nullable(): NullableType<BaseType<Schema, Props>, ValueType> {
|
|
105
57
|
return NullableType.factory(this) as any
|
|
106
58
|
}
|
|
107
59
|
|
|
@@ -109,16 +61,14 @@ export abstract class BaseType<
|
|
|
109
61
|
return this.nullable().optional()
|
|
110
62
|
}
|
|
111
63
|
|
|
112
|
-
default(
|
|
113
|
-
value: StaticDecode<this['_']['decoded']['output']>,
|
|
114
|
-
): DefaultType<this> {
|
|
64
|
+
default(value: ValueType): DefaultType<BaseType<Schema, Props>, ValueType> {
|
|
115
65
|
return DefaultType.factory(
|
|
116
66
|
this,
|
|
117
67
|
this.params.encode?.(value) ?? value,
|
|
118
68
|
) as any
|
|
119
69
|
}
|
|
120
70
|
|
|
121
|
-
description(description: string):
|
|
71
|
+
description(description: string): BaseType<Schema, Props, ValueType> {
|
|
122
72
|
const ThisConstructor = this.constructor as any
|
|
123
73
|
return new ThisConstructor(
|
|
124
74
|
{
|
|
@@ -130,7 +80,7 @@ export abstract class BaseType<
|
|
|
130
80
|
) as any
|
|
131
81
|
}
|
|
132
82
|
|
|
133
|
-
examples(...examples:
|
|
83
|
+
examples(...examples: ValueType[]): BaseType<Schema, Props, ValueType> {
|
|
134
84
|
const ThisConstructor = this.constructor as any
|
|
135
85
|
return new ThisConstructor(
|
|
136
86
|
{
|
|
@@ -143,89 +93,45 @@ export abstract class BaseType<
|
|
|
143
93
|
}
|
|
144
94
|
}
|
|
145
95
|
|
|
146
|
-
export type ConstantType<T extends TSchema> = {
|
|
147
|
-
encoded: {
|
|
148
|
-
input: T
|
|
149
|
-
output: T
|
|
150
|
-
}
|
|
151
|
-
decoded: {
|
|
152
|
-
input: T
|
|
153
|
-
output: T
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export type Static<
|
|
158
|
-
T extends BaseTypeAny,
|
|
159
|
-
P extends TypeProps,
|
|
160
|
-
Params extends Merge<T['params'], P> = Merge<T['params'], P>,
|
|
161
|
-
> = {
|
|
162
|
-
encoded: {
|
|
163
|
-
input: ResolveOptional<
|
|
164
|
-
ResolveNullable<T['_']['encoded']['input'], Params>,
|
|
165
|
-
Params
|
|
166
|
-
>
|
|
167
|
-
output: ResolveDefault<
|
|
168
|
-
ResolveOptional<
|
|
169
|
-
ResolveNullable<T['_']['encoded']['output'], Params>,
|
|
170
|
-
Params
|
|
171
|
-
>,
|
|
172
|
-
Params
|
|
173
|
-
>
|
|
174
|
-
}
|
|
175
|
-
decoded: {
|
|
176
|
-
input: ResolveOptional<
|
|
177
|
-
ResolveNullable<T['_']['decoded']['input'], Params>,
|
|
178
|
-
Params
|
|
179
|
-
>
|
|
180
|
-
output: ResolveDefault<
|
|
181
|
-
ResolveOptional<
|
|
182
|
-
ResolveNullable<T['_']['decoded']['output'], Params>,
|
|
183
|
-
Params
|
|
184
|
-
>,
|
|
185
|
-
Params
|
|
186
|
-
>
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
96
|
export class OptionalType<
|
|
191
|
-
Type extends BaseTypeAny
|
|
192
|
-
|
|
193
|
-
> extends BaseType<Type['schema']
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
{ inner: type },
|
|
200
|
-
{ ...type.params, optional: true } as any,
|
|
201
|
-
)
|
|
97
|
+
Type extends BaseTypeAny = BaseTypeAny,
|
|
98
|
+
ValueType = unknown,
|
|
99
|
+
> extends BaseType<TOptional<Type['schema']>, { inner: Type }, ValueType> {
|
|
100
|
+
static factory<T extends BaseTypeAny>(type: T) {
|
|
101
|
+
return new OptionalType<T>(Optional(type.schema) as any, { inner: type }, {
|
|
102
|
+
...type.params,
|
|
103
|
+
optional: true,
|
|
104
|
+
} as any)
|
|
202
105
|
}
|
|
203
106
|
}
|
|
204
107
|
|
|
205
108
|
export class NullableType<
|
|
206
|
-
Type extends BaseTypeAny<any>,
|
|
207
|
-
|
|
208
|
-
> extends BaseType<
|
|
209
|
-
|
|
210
|
-
|
|
109
|
+
Type extends BaseTypeAny<any> = BaseTypeAny<any>,
|
|
110
|
+
ValueType = unknown,
|
|
111
|
+
> extends BaseType<
|
|
112
|
+
TNullable<Type['schema']>,
|
|
113
|
+
{ inner: Type },
|
|
114
|
+
ValueType | null
|
|
115
|
+
> {
|
|
211
116
|
static factory<T extends BaseTypeAny<any>>(type: T) {
|
|
212
|
-
return new NullableType<T,
|
|
213
|
-
type.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
)
|
|
117
|
+
return new NullableType<T>(Nullable(type.schema), { inner: type }, {
|
|
118
|
+
...type.params,
|
|
119
|
+
nullable: true,
|
|
120
|
+
} as any)
|
|
217
121
|
}
|
|
218
122
|
}
|
|
219
123
|
|
|
220
124
|
export class DefaultType<
|
|
221
|
-
Type extends BaseTypeAny
|
|
222
|
-
|
|
223
|
-
> extends BaseType<
|
|
224
|
-
|
|
225
|
-
|
|
125
|
+
Type extends BaseTypeAny = BaseTypeAny,
|
|
126
|
+
ValueType = unknown,
|
|
127
|
+
> extends BaseType<
|
|
128
|
+
TDefault<TOptional<Type['schema']>>,
|
|
129
|
+
{ inner: Type },
|
|
130
|
+
ValueType
|
|
131
|
+
> {
|
|
226
132
|
static factory<T extends BaseTypeAny<any>>(type: T, defaultValue: any) {
|
|
227
|
-
return new DefaultType<T
|
|
228
|
-
|
|
133
|
+
return new DefaultType<T>(
|
|
134
|
+
Default(Optional(type.schema), defaultValue) as any,
|
|
229
135
|
{ inner: type },
|
|
230
136
|
{ ...type.params, hasDefault: true } as any,
|
|
231
137
|
)
|