justus 0.4.2 → 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/README.md +78 -0
- package/dist/dts-generator.cjs +36 -22
- package/dist/dts-generator.cjs.map +1 -1
- package/dist/dts-generator.d.ts +1 -1
- package/dist/dts-generator.mjs +15 -22
- package/dist/dts-generator.mjs.map +1 -1
- package/dist/extra/arn.cjs +98 -0
- package/dist/extra/arn.cjs.map +6 -0
- package/dist/extra/arn.d.ts +71 -0
- package/dist/extra/arn.mjs +68 -0
- package/dist/extra/arn.mjs.map +6 -0
- package/dist/extra/ean13.cjs +52 -0
- package/dist/extra/ean13.cjs.map +6 -0
- package/dist/extra/ean13.d.ts +9 -0
- package/dist/extra/ean13.mjs +26 -0
- package/dist/extra/ean13.mjs.map +6 -0
- package/dist/{validators → extra}/url.cjs +4 -6
- package/dist/{validators → extra}/url.cjs.map +3 -3
- package/dist/{validators → extra}/url.d.ts +2 -2
- package/dist/{validators → extra}/url.mjs +4 -6
- package/dist/{validators → extra}/url.mjs.map +3 -3
- package/dist/extra/uuid.cjs +45 -0
- package/dist/extra/uuid.cjs.map +6 -0
- package/dist/extra/uuid.d.ts +10 -0
- package/dist/extra/uuid.mjs +18 -0
- package/dist/extra/uuid.mjs.map +6 -0
- package/dist/index.cjs +0 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.mjs +0 -3
- package/dist/index.mjs.map +1 -1
- package/dist/registry.cjs +44 -0
- package/dist/registry.cjs.map +6 -0
- package/dist/registry.d.ts +16 -0
- package/dist/registry.mjs +19 -0
- package/dist/registry.mjs.map +6 -0
- package/dist/schema.cjs +3 -5
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.ts +6 -5
- package/dist/schema.mjs +3 -4
- package/dist/schema.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +38 -12
- package/dist/types.mjs.map +1 -1
- package/dist/utilities.cjs +5 -7
- package/dist/utilities.cjs.map +1 -1
- package/dist/utilities.mjs +5 -7
- package/dist/utilities.mjs.map +1 -1
- package/dist/validators/array.cjs.map +1 -1
- package/dist/validators/array.d.ts +1 -1
- package/dist/validators/array.mjs.map +1 -1
- package/dist/validators/constant.cjs +4 -5
- package/dist/validators/constant.cjs.map +1 -1
- package/dist/validators/constant.d.ts +0 -2
- package/dist/validators/constant.mjs +3 -3
- package/dist/validators/constant.mjs.map +1 -1
- package/dist/validators/date.cjs +2 -6
- package/dist/validators/date.cjs.map +1 -1
- package/dist/validators/date.d.ts +1 -1
- package/dist/validators/date.mjs +2 -6
- package/dist/validators/date.mjs.map +1 -1
- package/dist/validators/number.cjs.map +1 -1
- package/dist/validators/number.d.ts +1 -1
- package/dist/validators/number.mjs.map +1 -1
- package/dist/validators/object.cjs +3 -2
- package/dist/validators/object.cjs.map +1 -1
- package/dist/validators/object.d.ts +4 -4
- package/dist/validators/object.mjs +4 -7
- package/dist/validators/object.mjs.map +1 -1
- package/dist/validators/optional.cjs.map +1 -1
- package/dist/validators/optional.d.ts +5 -4
- package/dist/validators/optional.mjs.map +1 -1
- package/dist/validators/string.cjs.map +1 -1
- package/dist/validators/string.d.ts +1 -1
- package/dist/validators/string.mjs.map +1 -1
- package/dist/validators/tuple.cjs +3 -2
- package/dist/validators/tuple.cjs.map +1 -1
- package/dist/validators/tuple.d.ts +3 -3
- package/dist/validators/tuple.mjs +3 -2
- package/dist/validators/tuple.mjs.map +1 -1
- package/dist/validators/union.cjs.map +1 -1
- package/dist/validators/union.d.ts +9 -7
- package/dist/validators/union.mjs.map +1 -1
- package/package.json +43 -3
- package/src/dts-generator.ts +17 -27
- package/src/extra/arn.ts +151 -0
- package/src/extra/ean13.ts +31 -0
- package/src/{validators → extra}/url.ts +4 -6
- package/src/extra/uuid.ts +18 -0
- package/src/index.ts +0 -2
- package/src/registry.ts +28 -0
- package/src/schema.ts +10 -11
- package/src/types.ts +80 -11
- package/src/utilities.ts +5 -9
- package/src/validators/array.ts +1 -1
- package/src/validators/constant.ts +3 -2
- package/src/validators/date.ts +7 -7
- package/src/validators/number.ts +1 -1
- package/src/validators/object.ts +13 -12
- package/src/validators/optional.ts +9 -7
- package/src/validators/string.ts +1 -1
- package/src/validators/tuple.ts +20 -6
- package/src/validators/union.ts +35 -10
package/src/types.ts
CHANGED
|
@@ -49,7 +49,7 @@ export const defaultValidationOptions: Readonly<Required<ValidationOptions>> = {
|
|
|
49
49
|
* A `Validator` is an object capable of validating a given _value_ and
|
|
50
50
|
* (possibly) converting it the required type `T`.
|
|
51
51
|
*/
|
|
52
|
-
export interface Validator<T = any> extends Iterable<TupleRestParameter<T>> {
|
|
52
|
+
export interface Validator<T = any, I = T> extends Iterable<TupleRestParameter<T, I>> {
|
|
53
53
|
[Symbol.justusValidator]: this
|
|
54
54
|
|
|
55
55
|
optional?: boolean
|
|
@@ -58,7 +58,7 @@ export interface Validator<T = any> extends Iterable<TupleRestParameter<T>> {
|
|
|
58
58
|
validate(value: unknown, options?: ValidationOptions | undefined): T
|
|
59
59
|
|
|
60
60
|
/** Allow any `Validator` to be used as a rest parameter in `Tuple`s */
|
|
61
|
-
[Symbol.iterator](): Generator<TupleRestParameter<T>>;
|
|
61
|
+
[Symbol.iterator](): Generator<TupleRestParameter<T, I>>;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/**
|
|
@@ -83,8 +83,8 @@ export function makeValidatorFactory<
|
|
|
83
83
|
* A `Validator` is an object capable of validating a given _value_ and
|
|
84
84
|
* (possibly) converting it the required type `T`.
|
|
85
85
|
*/
|
|
86
|
-
export abstract class AbstractValidator<T =
|
|
87
|
-
implements Validator<T>, Iterable<TupleRestParameter<T>> {
|
|
86
|
+
export abstract class AbstractValidator<T, I = T>
|
|
87
|
+
implements Validator<T, I>, Iterable<TupleRestParameter<T, I>> {
|
|
88
88
|
[Symbol.justusValidator] = this
|
|
89
89
|
|
|
90
90
|
optional?: boolean = undefined
|
|
@@ -93,7 +93,7 @@ implements Validator<T>, Iterable<TupleRestParameter<T>> {
|
|
|
93
93
|
abstract validate(value: unknown, options?: ValidationOptions | undefined): T
|
|
94
94
|
|
|
95
95
|
/** Allow any `Validator` to be used as a rest parameter in `Tuple`s */
|
|
96
|
-
* [Symbol.iterator](): Generator<TupleRestParameter<T>> {
|
|
96
|
+
* [Symbol.iterator](): Generator<TupleRestParameter<T, I>> {
|
|
97
97
|
yield { [Symbol.justusRestValidator]: this }
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -118,7 +118,7 @@ export type Validation =
|
|
|
118
118
|
*/
|
|
119
119
|
export type InferValidation<V> =
|
|
120
120
|
// Validators return their validation type
|
|
121
|
-
V extends Validator<infer T> ? T :
|
|
121
|
+
V extends Validator<infer T, any> ? T :
|
|
122
122
|
|
|
123
123
|
// Primitives are returned as constants
|
|
124
124
|
V extends undefined ? V :
|
|
@@ -133,6 +133,25 @@ export type InferValidation<V> =
|
|
|
133
133
|
// Anyhing else can only be a schema
|
|
134
134
|
InferSchema<V>
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Infer the type compatible with a `Validation`'s input.
|
|
138
|
+
*/
|
|
139
|
+
export type InferInput<V> =
|
|
140
|
+
// Validators return their validation type
|
|
141
|
+
V extends Validator<any, infer T> ? T :
|
|
142
|
+
|
|
143
|
+
// Primitives are returned as constants
|
|
144
|
+
V extends undefined ? V :
|
|
145
|
+
V extends boolean ? V :
|
|
146
|
+
V extends number ? V :
|
|
147
|
+
V extends string ? V :
|
|
148
|
+
V extends null ? V :
|
|
149
|
+
|
|
150
|
+
// // Tuples are inferred using their own types
|
|
151
|
+
V extends Tuple ? InferInputTuple<V> :
|
|
152
|
+
|
|
153
|
+
// // Anyhing else can only be a schema
|
|
154
|
+
InferInputSchema<V>
|
|
136
155
|
|
|
137
156
|
/* ========================================================================== *
|
|
138
157
|
* TUPLES *
|
|
@@ -140,16 +159,22 @@ export type InferValidation<V> =
|
|
|
140
159
|
|
|
141
160
|
/** Infer the type validated by a `Validation` or `TupleRestParameter` */
|
|
142
161
|
export type InferValidationOrTupleRest<T> =
|
|
143
|
-
T extends TupleRestParameter<infer X> ? X :
|
|
162
|
+
T extends TupleRestParameter<infer X, any> ? X :
|
|
144
163
|
T extends Validation ? InferValidation<T> :
|
|
145
164
|
never
|
|
146
165
|
|
|
166
|
+
/** Infer the input type for a `Validation` or `TupleRestParameter` */
|
|
167
|
+
export type InferInputValidationOrTupleRest<T> =
|
|
168
|
+
T extends TupleRestParameter<any, infer X> ? X :
|
|
169
|
+
T extends Validation ? InferInput<T> :
|
|
170
|
+
never
|
|
171
|
+
|
|
147
172
|
/* -------------------------------------------------------------------------- */
|
|
148
173
|
|
|
149
174
|
/**
|
|
150
175
|
* A `Tuple` is defined to be an array of `Validation` or `TupleRest`
|
|
151
176
|
*/
|
|
152
|
-
export type Tuple = readonly (Validation | TupleRestParameter)[]
|
|
177
|
+
export type Tuple = readonly (Validation | TupleRestParameter<any, any>)[]
|
|
153
178
|
|
|
154
179
|
/**
|
|
155
180
|
* The `TupleRestParameter` defines a tuple member that can occur several
|
|
@@ -164,8 +189,8 @@ export type Tuple = readonly (Validation | TupleRestParameter)[]
|
|
|
164
189
|
* const myTuple = tuple([ number, ...nonEmptyString ])
|
|
165
190
|
* ```
|
|
166
191
|
*/
|
|
167
|
-
export type TupleRestParameter<T
|
|
168
|
-
[Symbol.justusRestValidator] : Validator<T>
|
|
192
|
+
export type TupleRestParameter<T, I> = {
|
|
193
|
+
[Symbol.justusRestValidator] : Validator<T, I>
|
|
169
194
|
}
|
|
170
195
|
|
|
171
196
|
/**
|
|
@@ -187,6 +212,24 @@ export type InferTuple<T> =
|
|
|
187
212
|
never :
|
|
188
213
|
never
|
|
189
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Infer a time compatible with a `TupleValidator`'s input.
|
|
217
|
+
*/
|
|
218
|
+
export type InferInputTuple<T> =
|
|
219
|
+
T extends Tuple ?
|
|
220
|
+
T extends readonly [] ? [] :
|
|
221
|
+
T extends readonly [ Validation, ...any[] ] ?
|
|
222
|
+
T extends readonly [ infer V, ...infer Rest ] ?
|
|
223
|
+
[ InferInput<V>, ...InferInputTuple<Rest> ] :
|
|
224
|
+
never :
|
|
225
|
+
T extends readonly [ ...any[], Validation ] ?
|
|
226
|
+
T extends readonly [ ...infer Rest, infer V ] ?
|
|
227
|
+
[ ...InferInputTuple<Rest>, InferInput<V> ] :
|
|
228
|
+
never :
|
|
229
|
+
T extends readonly (infer V)[] ?
|
|
230
|
+
[ ...InferInputValidationOrTupleRest<V>[] ] :
|
|
231
|
+
never :
|
|
232
|
+
never
|
|
190
233
|
|
|
191
234
|
/* ========================================================================== *
|
|
192
235
|
* OBJECT SCHEMAS *
|
|
@@ -237,11 +280,37 @@ export type InferSchema2<S> = {
|
|
|
237
280
|
InferValidation<S[key]>
|
|
238
281
|
}
|
|
239
282
|
|
|
283
|
+
/** Infer the input type compatible with a `Schema` */
|
|
284
|
+
export type InferInputSchema<S> =
|
|
285
|
+
S extends AdditionalProperties<Validator<any, infer X>> ?
|
|
286
|
+
{ [ key in string ] : X } & InferInputSchema2<S> :
|
|
287
|
+
InferInputSchema2<S>
|
|
288
|
+
|
|
289
|
+
/** Infer the input type of the properties described by a `Schema` */
|
|
290
|
+
export type InferInputSchema2<S> = {
|
|
291
|
+
// this first part of the type infers all keys from the schema into their
|
|
292
|
+
// type, but makes *each* key optional... we'll restrict in the next part...
|
|
293
|
+
[ key in keyof S as key extends string ? key : never ] ? : InferInput<S[key]>
|
|
294
|
+
} & {
|
|
295
|
+
// this second part infers *only* keys that _do not_ contain a "undefined"
|
|
296
|
+
// in their unions, and associates them with the inferred value, basically
|
|
297
|
+
// making the key *non optional*
|
|
298
|
+
[ key in keyof S as
|
|
299
|
+
key extends string ?
|
|
300
|
+
InferInput<S[key]> extends never ?
|
|
301
|
+
never :
|
|
302
|
+
undefined extends InferInput<S[key]> ?
|
|
303
|
+
never :
|
|
304
|
+
key :
|
|
305
|
+
never ] -? :
|
|
306
|
+
InferInput<S[key]>
|
|
307
|
+
}
|
|
308
|
+
|
|
240
309
|
/* ========================================================================== *
|
|
241
310
|
* TYPE BRANDING *
|
|
242
311
|
* ========================================================================== */
|
|
243
312
|
|
|
244
313
|
/** Utility type to infer primitive branding according to a string */
|
|
245
314
|
export type Branding<S extends string> = {
|
|
246
|
-
[
|
|
315
|
+
[ brand in `__brand_${S}` ] : never
|
|
247
316
|
}
|
package/src/utilities.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
// eslint-disable-next-line import/no-cycle
|
|
3
|
-
import { ObjectValidator } from './validators/object'
|
|
4
|
-
// eslint-disable-next-line import/no-cycle
|
|
5
|
-
import { TupleValidator } from './validators/tuple'
|
|
1
|
+
import { registry } from './registry'
|
|
6
2
|
|
|
7
3
|
import type { Schema, Validation, Validator } from './types'
|
|
8
4
|
|
|
@@ -17,7 +13,7 @@ import type { Schema, Validation, Validator } from './types'
|
|
|
17
13
|
*/
|
|
18
14
|
export function getValidator(validation: Validation): Validator {
|
|
19
15
|
// Null is a constant
|
|
20
|
-
if (validation === null) return
|
|
16
|
+
if (validation === null) return new (registry.get('constant'))(null)
|
|
21
17
|
|
|
22
18
|
// Anything with a validor associated with
|
|
23
19
|
if ((<any> validation)[Symbol.justusValidator]) {
|
|
@@ -30,14 +26,14 @@ export function getValidator(validation: Validation): Validator {
|
|
|
30
26
|
case 'boolean':
|
|
31
27
|
case 'string':
|
|
32
28
|
case 'number':
|
|
33
|
-
return new
|
|
29
|
+
return new (registry.get('constant'))(validation)
|
|
34
30
|
|
|
35
31
|
// other objects...
|
|
36
32
|
case 'object':
|
|
37
33
|
// arrays are tuples
|
|
38
|
-
if (Array.isArray(validation)) return new
|
|
34
|
+
if (Array.isArray(validation)) return new (registry.get('tuple'))(validation)
|
|
39
35
|
// any other object is a schema
|
|
40
|
-
return new
|
|
36
|
+
return new (registry.get('object'))(validation as Schema)
|
|
41
37
|
|
|
42
38
|
// definitely not one of our types
|
|
43
39
|
default:
|
package/src/validators/array.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface ArrayConstraints<V extends Validation> {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/** Basic validator for `Array` instances. */
|
|
25
|
-
export class AnyArrayValidator<T = any> extends AbstractValidator<T[]> {
|
|
25
|
+
export class AnyArrayValidator<T = any> extends AbstractValidator<T[], T[]> {
|
|
26
26
|
validate(value: unknown): T[] {
|
|
27
27
|
assertValidation(Array.isArray(value), 'Value is not an "array"')
|
|
28
28
|
return [ ...value ]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assertValidation } from '../errors'
|
|
2
|
+
import { registry } from '../registry'
|
|
2
3
|
import { AbstractValidator } from '../types'
|
|
3
4
|
|
|
4
5
|
import type { Validator } from '../types'
|
|
@@ -23,5 +24,5 @@ export function constant<T extends string | number | boolean | null>(constant: T
|
|
|
23
24
|
return new ConstantValidator(constant)
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
// Register our "constant" validator
|
|
28
|
+
registry.set('constant', ConstantValidator)
|
package/src/validators/date.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface DateConstraints {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/** A `Validator` validating dates and converting them to `Date` instances. */
|
|
18
|
-
export class DateValidator extends AbstractValidator<Date> {
|
|
18
|
+
export class DateValidator extends AbstractValidator<Date, Date | string | number> {
|
|
19
19
|
readonly format?: 'iso' | 'timestamp'
|
|
20
20
|
readonly from?: Date
|
|
21
21
|
readonly until?: Date
|
|
@@ -36,12 +36,12 @@ export class DateValidator extends AbstractValidator<Date> {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
validate(value: unknown): Date {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
const date =
|
|
40
|
+
value instanceof Date ? new Date(value.getTime()) :
|
|
41
|
+
typeof value === 'string' ? new Date(value) :
|
|
42
|
+
typeof value === 'number' ? new Date(value) :
|
|
43
|
+
undefined
|
|
44
|
+
assertValidation(!! date, 'Value could not be converted to a "Date"')
|
|
45
45
|
|
|
46
46
|
if (isNaN(date.getTime())) throw new ValidationError('Invalid date')
|
|
47
47
|
|
package/src/validators/number.ts
CHANGED
|
@@ -53,7 +53,7 @@ export class AnyNumberValidator extends AbstractValidator<number> {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/** A `Validator` validating `number`s with constaints. */
|
|
56
|
-
export class NumberValidator<N extends number = number> extends AbstractValidator<N> {
|
|
56
|
+
export class NumberValidator<N extends number = number> extends AbstractValidator<N, number> {
|
|
57
57
|
#isMultipleOf?: ((value: number) => boolean)
|
|
58
58
|
|
|
59
59
|
readonly allowNaN: boolean
|
package/src/validators/object.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { assertValidation, ValidationErrorBuilder } from '../errors'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
AbstractValidator,
|
|
6
|
-
defaultValidationOptions,
|
|
7
|
-
makeValidatorFactory,
|
|
8
|
-
} from '../types'
|
|
2
|
+
import { registry } from '../registry'
|
|
3
|
+
import { AbstractValidator, defaultValidationOptions, makeValidatorFactory } from '../types'
|
|
9
4
|
import { getValidator } from '../utilities'
|
|
10
5
|
|
|
11
6
|
import type {
|
|
12
|
-
|
|
7
|
+
InferInputSchema,
|
|
8
|
+
InferSchema, InferValidation, Schema, TupleRestParameter, Validation,
|
|
9
|
+
ValidationOptions,
|
|
13
10
|
Validator,
|
|
14
11
|
} from '../types'
|
|
15
12
|
|
|
@@ -27,7 +24,7 @@ export class AnyObjectValidator extends AbstractValidator<Record<string, any>> {
|
|
|
27
24
|
}
|
|
28
25
|
|
|
29
26
|
/** A `Validator` validating `object`s according to a `Schema`. */
|
|
30
|
-
export class ObjectValidator<S extends Schema> extends AbstractValidator<InferSchema<S>> {
|
|
27
|
+
export class ObjectValidator<S extends Schema> extends AbstractValidator<InferSchema<S>, InferInputSchema<S>> {
|
|
31
28
|
readonly schema: Readonly<S>
|
|
32
29
|
|
|
33
30
|
validators = new Map<string, Validator>()
|
|
@@ -118,10 +115,11 @@ export class ObjectValidator<S extends Schema> extends AbstractValidator<InferSc
|
|
|
118
115
|
}
|
|
119
116
|
|
|
120
117
|
export function objectFactory<S extends Schema>(schema: S): S & {
|
|
121
|
-
[Symbol.iterator](): Generator<TupleRestParameter<InferSchema<S>>>
|
|
118
|
+
[Symbol.iterator](): Generator<TupleRestParameter<InferSchema<S>, InferInputSchema<S>>>
|
|
122
119
|
} {
|
|
123
120
|
const validator = new ObjectValidator(schema)
|
|
124
|
-
|
|
121
|
+
|
|
122
|
+
function* iterator(): Generator<TupleRestParameter<any, any>> {
|
|
125
123
|
yield { [Symbol.justusRestValidator]: validator }
|
|
126
124
|
}
|
|
127
125
|
|
|
@@ -136,5 +134,8 @@ export const object = makeValidatorFactory(new AnyObjectValidator(), objectFacto
|
|
|
136
134
|
|
|
137
135
|
/** Validate `Object`s containing only the specified elements. */
|
|
138
136
|
export function objectOf<V extends Validation>(validation: V): Validator<Record<string, InferValidation<V>>> {
|
|
139
|
-
return new ObjectValidator({
|
|
137
|
+
return new ObjectValidator({ [Symbol.justusAdditionalValidator]: getValidator(validation) })
|
|
140
138
|
}
|
|
139
|
+
|
|
140
|
+
// Register our "object" validator
|
|
141
|
+
registry.set('object', ObjectValidator)
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { AbstractValidator, defaultValidationOptions } from '../types'
|
|
2
2
|
import { getValidator } from '../utilities'
|
|
3
3
|
|
|
4
|
-
import type { InferValidation, Validation, ValidationOptions, Validator } from '../types'
|
|
4
|
+
import type { InferInput, InferValidation, Validation, ValidationOptions, Validator } from '../types'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* A `Validator` for _optional_ properties (that is `type | undefined`).
|
|
8
8
|
*/
|
|
9
9
|
export class OptionalValidator<
|
|
10
10
|
T = any, // the type of the "validation", that is the optional type to validate
|
|
11
|
+
I = T, // the _input_ type of the "validation", that is anything acceptable
|
|
11
12
|
D = undefined, // the default value (or undefined)
|
|
12
|
-
> extends AbstractValidator<D extends undefined ? T | undefined : T> {
|
|
13
|
+
> extends AbstractValidator<D extends undefined ? T | undefined : T, I | undefined> {
|
|
13
14
|
validator: Validator<T>
|
|
14
15
|
defaultValue: T | undefined
|
|
15
16
|
|
|
@@ -32,8 +33,9 @@ export class OptionalValidator<
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
validate(value: unknown, options?: ValidationOptions): D extends undefined ? T | undefined : T
|
|
36
|
-
|
|
36
|
+
validate(value: unknown, options?: ValidationOptions): D extends undefined ? T | undefined : T
|
|
37
|
+
validate(value: unknown, options?: ValidationOptions): T | undefined {
|
|
38
|
+
if (value === undefined) return this.defaultValue // do not validate defaults!
|
|
37
39
|
return this.validator.validate(value, options)
|
|
38
40
|
}
|
|
39
41
|
}
|
|
@@ -45,15 +47,15 @@ export class OptionalValidator<
|
|
|
45
47
|
*/
|
|
46
48
|
export function optional<
|
|
47
49
|
V extends Validation
|
|
48
|
-
>(validation: V): OptionalValidator<InferValidation<V>, undefined>
|
|
50
|
+
>(validation: V): OptionalValidator<InferValidation<V>, InferInput<V>, undefined>
|
|
49
51
|
|
|
50
52
|
export function optional<
|
|
51
53
|
V extends Validation, D,
|
|
52
|
-
>(validation: V, defaultValue: D): OptionalValidator<InferValidation<V>, D>
|
|
54
|
+
>(validation: V, defaultValue: D): OptionalValidator<InferValidation<V>, InferInput<V>, D>
|
|
53
55
|
|
|
54
56
|
export function optional<
|
|
55
57
|
V extends Validation, D,
|
|
56
|
-
>(validation: V, defaultValue?: D): OptionalValidator<InferValidation<V
|
|
58
|
+
>(validation: V, defaultValue?: D): OptionalValidator<InferValidation<V>, InferInput<V>, D> {
|
|
57
59
|
const validator = getValidator(validation)
|
|
58
60
|
return new OptionalValidator(validator, defaultValue)
|
|
59
61
|
}
|
package/src/validators/string.ts
CHANGED
|
@@ -28,7 +28,7 @@ export class AnyStringValidator extends AbstractValidator<string> {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/** A `Validator` validating `string`s with constraints. */
|
|
31
|
-
export class StringValidator<S extends string = string> extends AbstractValidator<S> {
|
|
31
|
+
export class StringValidator<S extends string = string, I = string> extends AbstractValidator<S, I> {
|
|
32
32
|
readonly maxLength: number
|
|
33
33
|
readonly minLength: number
|
|
34
34
|
readonly pattern?: RegExp
|
package/src/validators/tuple.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { assertValidation, ValidationError } from '../errors'
|
|
2
|
+
import { registry } from '../registry'
|
|
2
3
|
import { AbstractValidator } from '../types'
|
|
3
|
-
// eslint-disable-next-line import/no-cycle
|
|
4
4
|
import { getValidator } from '../utilities'
|
|
5
|
-
import { nullValidator } from './constant'
|
|
6
5
|
|
|
7
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
InferInputTuple,
|
|
8
|
+
InferTuple,
|
|
9
|
+
Tuple,
|
|
10
|
+
TupleRestParameter,
|
|
11
|
+
Validation,
|
|
12
|
+
ValidationOptions,
|
|
13
|
+
Validator,
|
|
14
|
+
} from '../types'
|
|
8
15
|
|
|
9
16
|
export interface TupleMember { single: boolean, validator: Validator }
|
|
10
17
|
|
|
11
18
|
/** A `Validator` for _tuples_. */
|
|
12
|
-
export class TupleValidator<T extends Tuple> extends AbstractValidator<InferTuple<T>> {
|
|
19
|
+
export class TupleValidator<T extends Tuple> extends AbstractValidator<InferTuple<T>, InferInputTuple<T>> {
|
|
13
20
|
readonly members: readonly TupleMember[]
|
|
14
21
|
readonly tuple: T
|
|
15
22
|
|
|
@@ -19,7 +26,7 @@ export class TupleValidator<T extends Tuple> extends AbstractValidator<InferTupl
|
|
|
19
26
|
const members: TupleMember[] = []
|
|
20
27
|
for (const item of tuple) {
|
|
21
28
|
if (item === null) { // god knows why typeof null === "object"
|
|
22
|
-
members.push({ single: true, validator:
|
|
29
|
+
members.push({ single: true, validator: getValidator(null) })
|
|
23
30
|
} else if ((typeof item === 'object') && (Symbol.justusRestValidator in item)) {
|
|
24
31
|
members.push({ single: false, validator: (<any>item)[Symbol.justusRestValidator] })
|
|
25
32
|
} else {
|
|
@@ -77,6 +84,13 @@ export class TupleValidator<T extends Tuple> extends AbstractValidator<InferTupl
|
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
/** Validate _tuples_. */
|
|
80
|
-
export function tuple<T extends
|
|
87
|
+
export function tuple<T extends
|
|
88
|
+
| readonly [ Validation | TupleRestParameter<any, any>, ...Tuple ]
|
|
89
|
+
| readonly [ ...Tuple, Validation | TupleRestParameter<any, any> ]
|
|
90
|
+
| readonly [ ...Tuple ] // ... this is bascially an array...
|
|
91
|
+
>(tuple: T): Validator<InferTuple<T>, InferInputTuple<T>> {
|
|
81
92
|
return new TupleValidator(tuple)
|
|
82
93
|
}
|
|
94
|
+
|
|
95
|
+
// Register our "tuple" validator
|
|
96
|
+
registry.set('tuple', TupleValidator)
|
package/src/validators/union.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { AbstractValidator } from '../types'
|
|
|
3
3
|
import { getValidator } from '../utilities'
|
|
4
4
|
|
|
5
5
|
import type {
|
|
6
|
+
InferInput,
|
|
6
7
|
InferValidation,
|
|
7
8
|
Validation,
|
|
8
9
|
ValidationOptions,
|
|
@@ -13,11 +14,11 @@ import type {
|
|
|
13
14
|
|
|
14
15
|
export type OneOfArguments = readonly Validation[]
|
|
15
16
|
|
|
16
|
-
export type
|
|
17
|
+
export type InferOneOfValidation<A extends OneOfArguments> =
|
|
17
18
|
A extends readonly [ infer First, ...infer Rest ] ?
|
|
18
19
|
First extends Validation ?
|
|
19
20
|
Rest extends OneOfArguments ?
|
|
20
|
-
InferValidation<First> |
|
|
21
|
+
InferValidation<First> | InferOneOfValidation<Rest> :
|
|
21
22
|
InferValidation<First> :
|
|
22
23
|
never :
|
|
23
24
|
A extends readonly (infer Type)[] ?
|
|
@@ -26,8 +27,22 @@ export type InferOneOfValidationType<A extends OneOfArguments> =
|
|
|
26
27
|
never :
|
|
27
28
|
never
|
|
28
29
|
|
|
30
|
+
export type InferOneOfInput<A extends OneOfArguments> =
|
|
31
|
+
A extends readonly [ infer First, ...infer Rest ] ?
|
|
32
|
+
First extends Validation ?
|
|
33
|
+
Rest extends OneOfArguments ?
|
|
34
|
+
InferInput<First> | InferOneOfValidation<Rest> :
|
|
35
|
+
InferInput<First> :
|
|
36
|
+
never :
|
|
37
|
+
A extends readonly (infer Type)[] ?
|
|
38
|
+
Type extends Validation ?
|
|
39
|
+
InferInput<Type> :
|
|
40
|
+
never :
|
|
41
|
+
never
|
|
42
|
+
|
|
29
43
|
/** A `Validator` validating a value as _one of_ the specified arguments. */
|
|
30
|
-
export class OneOfValidator<A extends OneOfArguments>
|
|
44
|
+
export class OneOfValidator<A extends OneOfArguments>
|
|
45
|
+
extends AbstractValidator<InferOneOfValidation<A>, InferOneOfInput<A>> {
|
|
31
46
|
readonly validators: readonly Validator[]
|
|
32
47
|
|
|
33
48
|
constructor(args: A) {
|
|
@@ -36,7 +51,7 @@ export class OneOfValidator<A extends OneOfArguments> extends AbstractValidator<
|
|
|
36
51
|
assertSchema(this.validators.length > 0, 'At least one validation required in "oneOf"')
|
|
37
52
|
}
|
|
38
53
|
|
|
39
|
-
validate(value: unknown, options?: ValidationOptions):
|
|
54
|
+
validate(value: unknown, options?: ValidationOptions): InferOneOfValidation<A> {
|
|
40
55
|
const builder = new ValidationErrorBuilder()
|
|
41
56
|
for (const validator of this.validators) {
|
|
42
57
|
try {
|
|
@@ -45,7 +60,7 @@ export class OneOfValidator<A extends OneOfArguments> extends AbstractValidator<
|
|
|
45
60
|
builder.record(error)
|
|
46
61
|
}
|
|
47
62
|
}
|
|
48
|
-
return builder.assert(value as
|
|
63
|
+
return builder.assert(value as InferOneOfValidation<A>)
|
|
49
64
|
}
|
|
50
65
|
}
|
|
51
66
|
|
|
@@ -58,17 +73,27 @@ export function oneOf<A extends OneOfArguments>(...args: A): OneOfValidator<A> {
|
|
|
58
73
|
|
|
59
74
|
export type AllOfArguments = readonly [ Validation, ...Validation[] ]
|
|
60
75
|
|
|
61
|
-
export type
|
|
76
|
+
export type InferAllOfValidation<A extends AllOfArguments> =
|
|
62
77
|
A extends readonly [ infer First, ...infer Rest ] ?
|
|
63
78
|
First extends Validation ?
|
|
64
79
|
Rest extends AllOfArguments ?
|
|
65
|
-
InferValidation<First> &
|
|
80
|
+
InferValidation<First> & InferAllOfValidation<Rest> :
|
|
66
81
|
InferValidation<First> :
|
|
67
82
|
never :
|
|
68
83
|
never
|
|
69
84
|
|
|
85
|
+
export type InferAllOfInput<A extends AllOfArguments> =
|
|
86
|
+
A extends readonly [ infer First, ...infer Rest ] ?
|
|
87
|
+
First extends Validation ?
|
|
88
|
+
Rest extends AllOfArguments ?
|
|
89
|
+
InferInput<First> & InferAllOfValidation<Rest> :
|
|
90
|
+
InferInput<First> :
|
|
91
|
+
never :
|
|
92
|
+
never
|
|
93
|
+
|
|
70
94
|
/** A `Validator` validating a value as _all of_ the specified arguments. */
|
|
71
|
-
export class AllOfValidator<A extends AllOfArguments>
|
|
95
|
+
export class AllOfValidator<A extends AllOfArguments>
|
|
96
|
+
extends AbstractValidator<InferAllOfValidation<A>, InferAllOfInput<A>> {
|
|
72
97
|
readonly validators: readonly Validator[]
|
|
73
98
|
|
|
74
99
|
constructor(args: A) {
|
|
@@ -77,11 +102,11 @@ export class AllOfValidator<A extends AllOfArguments> extends AbstractValidator<
|
|
|
77
102
|
assertSchema(this.validators.length > 0, 'At least one validation required in "allOf"')
|
|
78
103
|
}
|
|
79
104
|
|
|
80
|
-
validate(value: unknown, options?: ValidationOptions):
|
|
105
|
+
validate(value: unknown, options?: ValidationOptions): InferAllOfValidation<A> {
|
|
81
106
|
for (const validator of this.validators) {
|
|
82
107
|
value = validator.validate(value, options)
|
|
83
108
|
}
|
|
84
|
-
return value as
|
|
109
|
+
return value as InferAllOfValidation<A>
|
|
85
110
|
}
|
|
86
111
|
}
|
|
87
112
|
|