@atproto/lex-schema 0.0.1 → 0.0.3
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/CHANGELOG.md +68 -0
- package/dist/core/$type.d.ts +6 -3
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js +1 -0
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.d.ts +3 -3
- package/dist/core/record-key.d.ts.map +1 -1
- package/dist/core/record-key.js +12 -6
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/result.d.ts.map +1 -1
- package/dist/core/result.js +6 -0
- package/dist/core/result.js.map +1 -1
- package/dist/core/string-format.d.ts +30 -27
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +56 -42
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/types.d.ts +9 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/external.d.ts +31 -28
- package/dist/external.d.ts.map +1 -1
- package/dist/external.js +33 -17
- package/dist/external.js.map +1 -1
- package/dist/schema/_parameters.d.ts +2 -2
- package/dist/schema/_parameters.d.ts.map +1 -1
- package/dist/schema/array.d.ts +5 -6
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +5 -6
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +2 -3
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +1 -2
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.d.ts +4 -5
- package/dist/schema/boolean.d.ts.map +1 -1
- package/dist/schema/boolean.js +2 -3
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.d.ts +3 -4
- package/dist/schema/bytes.d.ts.map +1 -1
- package/dist/schema/bytes.js +2 -3
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +13 -6
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +2 -4
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.d.ts +3 -4
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js +4 -3
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +3 -3
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +1 -1
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +15 -24
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +40 -64
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.d.ts +8 -4
- package/dist/schema/enum.d.ts.map +1 -1
- package/dist/schema/enum.js +5 -3
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.d.ts +3 -4
- package/dist/schema/integer.d.ts.map +1 -1
- package/dist/schema/integer.js +3 -4
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +22 -14
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +12 -22
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/literal.d.ts +8 -4
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +5 -3
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.d.ts +2 -2
- package/dist/schema/never.d.ts.map +1 -1
- package/dist/schema/never.js +1 -1
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.d.ts +2 -3
- package/dist/schema/null.d.ts.map +1 -1
- package/dist/schema/null.js +1 -2
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +7 -0
- package/dist/schema/nullable.d.ts.map +1 -0
- package/dist/schema/nullable.js +19 -0
- package/dist/schema/nullable.js.map +1 -0
- package/dist/schema/object.d.ts +10 -44
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +13 -56
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +7 -0
- package/dist/schema/optional.d.ts.map +1 -0
- package/dist/schema/optional.js +25 -0
- package/dist/schema/optional.js.map +1 -0
- package/dist/schema/params.d.ts +14 -19
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +10 -24
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +4 -4
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +6 -6
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +1 -2
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +0 -1
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js +0 -1
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +8 -9
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +0 -1
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +7 -8
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +0 -1
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +34 -28
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +1 -2
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +2 -3
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +1 -2
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +18 -0
- package/dist/schema/refine.d.ts.map +1 -0
- package/dist/schema/refine.js +33 -0
- package/dist/schema/refine.js.map +1 -0
- package/dist/schema/regexp.d.ts +7 -0
- package/dist/schema/regexp.d.ts.map +1 -0
- package/dist/schema/regexp.js +22 -0
- package/dist/schema/regexp.js.map +1 -0
- package/dist/schema/string.d.ts +4 -8
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +6 -3
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +7 -6
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +2 -3
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +1 -2
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +29 -27
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +1 -2
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +2 -2
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +1 -1
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +3 -4
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +3 -10
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +2 -2
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +1 -1
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown-object.d.ts +2 -3
- package/dist/schema/unknown-object.d.ts.map +1 -1
- package/dist/schema/unknown-object.js +1 -2
- package/dist/schema/unknown-object.js.map +1 -1
- package/dist/schema/unknown.d.ts +2 -2
- package/dist/schema/unknown.d.ts.map +1 -1
- package/dist/schema/unknown.js +1 -1
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema.d.ts +4 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +6 -1
- package/dist/schema.js.map +1 -1
- package/dist/util/array-agg.d.ts.map +1 -1
- package/dist/util/array-agg.js +1 -0
- package/dist/util/array-agg.js.map +1 -1
- package/dist/util/lazy-property.d.ts +2 -0
- package/dist/util/lazy-property.d.ts.map +1 -0
- package/dist/util/lazy-property.js +14 -0
- package/dist/util/lazy-property.js.map +1 -0
- package/dist/validation/schema.d.ts +24 -0
- package/dist/validation/schema.d.ts.map +1 -0
- package/dist/validation/schema.js +57 -0
- package/dist/validation/schema.js.map +1 -0
- package/dist/validation/validation-error.d.ts +3 -3
- package/dist/validation/validation-error.d.ts.map +1 -1
- package/dist/validation/validation-error.js +32 -4
- package/dist/validation/validation-error.js.map +1 -1
- package/dist/validation/validation-issue.d.ts +32 -24
- package/dist/validation/validation-issue.d.ts.map +1 -1
- package/dist/validation/validation-issue.js +136 -92
- package/dist/validation/validation-issue.js.map +1 -1
- package/dist/validation/validator.d.ts +20 -50
- package/dist/validation/validator.d.ts.map +1 -1
- package/dist/validation/validator.js +40 -134
- package/dist/validation/validator.js.map +1 -1
- package/dist/validation.d.ts +1 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +1 -0
- package/dist/validation.js.map +1 -1
- package/package.json +8 -4
- package/src/core/$type.ts +7 -4
- package/src/core/record-key.ts +12 -5
- package/src/core/result.ts +6 -0
- package/src/core/string-format.ts +97 -61
- package/src/core/types.ts +12 -6
- package/src/external.ts +92 -70
- package/src/schema/_parameters.test.ts +416 -0
- package/src/schema/array.test.ts +237 -0
- package/src/schema/array.ts +17 -11
- package/src/schema/blob.test.ts +506 -0
- package/src/schema/blob.ts +3 -5
- package/src/schema/boolean.test.ts +116 -0
- package/src/schema/boolean.ts +5 -7
- package/src/schema/bytes.test.ts +226 -0
- package/src/schema/bytes.ts +4 -6
- package/src/schema/cid.test.ts +155 -0
- package/src/schema/cid.ts +14 -8
- package/src/schema/custom.test.ts +413 -0
- package/src/schema/custom.ts +10 -8
- package/src/schema/dict.test.ts +198 -0
- package/src/schema/dict.ts +6 -8
- package/src/schema/discriminated-union.test.ts +675 -0
- package/src/schema/discriminated-union.ts +68 -95
- package/src/schema/enum.test.ts +396 -0
- package/src/schema/enum.ts +12 -5
- package/src/schema/integer.test.ts +312 -0
- package/src/schema/integer.ts +5 -7
- package/src/schema/intersection.test.ts +32 -0
- package/src/schema/intersection.ts +37 -40
- package/src/schema/literal.test.ts +531 -0
- package/src/schema/literal.ts +12 -5
- package/src/schema/never.test.ts +174 -0
- package/src/schema/never.ts +3 -10
- package/src/schema/null.test.ts +79 -0
- package/src/schema/null.ts +3 -5
- package/src/schema/nullable.test.ts +480 -0
- package/src/schema/nullable.ts +23 -0
- package/src/schema/object.test.ts +47 -115
- package/src/schema/object.ts +23 -134
- package/src/schema/optional.test.ts +485 -0
- package/src/schema/optional.ts +31 -0
- package/src/schema/params.test.ts +582 -0
- package/src/schema/params.ts +37 -55
- package/src/schema/payload.test.ts +345 -0
- package/src/schema/payload.ts +5 -5
- package/src/schema/permission-set.test.ts +679 -0
- package/src/schema/permission-set.ts +6 -8
- package/src/schema/permission.test.ts +536 -0
- package/src/schema/permission.ts +0 -2
- package/src/schema/procedure.test.ts +443 -0
- package/src/schema/procedure.ts +11 -13
- package/src/schema/query.test.ts +408 -0
- package/src/schema/query.ts +9 -11
- package/src/schema/record.test.ts +694 -0
- package/src/schema/record.ts +38 -36
- package/src/schema/ref.test.ts +365 -0
- package/src/schema/ref.ts +8 -5
- package/src/schema/refine.test.ts +578 -0
- package/src/schema/refine.ts +85 -0
- package/src/schema/regexp.test.ts +580 -0
- package/src/schema/regexp.ts +22 -0
- package/src/schema/string.test.ts +612 -0
- package/src/schema/string.ts +11 -17
- package/src/schema/subscription.test.ts +689 -0
- package/src/schema/subscription.ts +13 -8
- package/src/schema/token.test.ts +428 -0
- package/src/schema/token.ts +3 -5
- package/src/schema/typed-object.test.ts +612 -0
- package/src/schema/typed-object.ts +23 -20
- package/src/schema/typed-ref.test.ts +823 -0
- package/src/schema/typed-ref.ts +10 -5
- package/src/schema/typed-union.test.ts +378 -0
- package/src/schema/typed-union.ts +6 -15
- package/src/schema/union.test.ts +200 -0
- package/src/schema/union.ts +5 -4
- package/src/schema/unknown-object.test.ts +592 -0
- package/src/schema/unknown-object.ts +3 -5
- package/src/schema/unknown.test.ts +312 -0
- package/src/schema/unknown.ts +3 -3
- package/src/schema.ts +7 -1
- package/src/util/array-agg.ts +1 -0
- package/src/util/lazy-property.ts +14 -0
- package/src/validation/schema.ts +92 -0
- package/src/validation/validation-error.ts +60 -9
- package/src/validation/validation-issue.ts +141 -144
- package/src/validation/validator.ts +67 -206
- package/src/validation.ts +1 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +7 -0
- package/tsconfig.tests.json +9 -0
|
@@ -2,9 +2,14 @@ import { ResultFailure, ResultSuccess, failure, success } from '../core.js'
|
|
|
2
2
|
import { PropertyKey } from './property-key.js'
|
|
3
3
|
import { ValidationError } from './validation-error.js'
|
|
4
4
|
import {
|
|
5
|
+
Issue,
|
|
6
|
+
IssueInvalidFormat,
|
|
7
|
+
IssueInvalidType,
|
|
8
|
+
IssueInvalidValue,
|
|
9
|
+
IssueRequiredKey,
|
|
5
10
|
IssueTooBig,
|
|
6
11
|
IssueTooSmall,
|
|
7
|
-
|
|
12
|
+
MeasurableType,
|
|
8
13
|
} from './validation-issue.js'
|
|
9
14
|
|
|
10
15
|
export type ValidationSuccess<Value = any> = ResultSuccess<Value>
|
|
@@ -13,7 +18,7 @@ export type ValidationResult<Value = any> =
|
|
|
13
18
|
| ValidationSuccess<Value>
|
|
14
19
|
| ValidationFailure
|
|
15
20
|
|
|
16
|
-
type ValidationOptions = {
|
|
21
|
+
export type ValidationOptions = {
|
|
17
22
|
path?: PropertyKey[]
|
|
18
23
|
|
|
19
24
|
/** @default true */
|
|
@@ -22,31 +27,25 @@ type ValidationOptions = {
|
|
|
22
27
|
|
|
23
28
|
export type Infer<T extends Validator> = T['_lex']['output']
|
|
24
29
|
|
|
25
|
-
export
|
|
30
|
+
export interface Validator<Output = any> {
|
|
26
31
|
/**
|
|
27
32
|
* This property is used for type inference purposes and does not actually
|
|
28
33
|
* exist at runtime.
|
|
29
34
|
*
|
|
30
|
-
* @deprecated
|
|
35
|
+
* @deprecated **INTERNAL API, DO NOT USE**.
|
|
31
36
|
*/
|
|
32
|
-
_lex
|
|
33
|
-
|
|
34
|
-
readonly lexiconType?: string
|
|
37
|
+
readonly ['_lex']: { output: Output }
|
|
35
38
|
|
|
36
39
|
/**
|
|
37
|
-
* @internal **INTERNAL API
|
|
38
|
-
*
|
|
39
|
-
* Use {@link Validator.assert assert}, {@link Validator.check check},
|
|
40
|
-
* {@link Validator.parse parse} or {@link Validator.validate validate}
|
|
41
|
-
* instead.
|
|
40
|
+
* @internal **INTERNAL API**: use {@link ValidatorContext.validate} instead
|
|
42
41
|
*
|
|
43
42
|
* This method is implemented by subclasses to perform transformation and
|
|
44
43
|
* validation of the input value. Do not call this method directly; as the
|
|
45
44
|
* {@link ValidatorContext.options.allowTransform} option will **not** be
|
|
46
45
|
* enforced. See {@link ValidatorContext.validate} for details. When
|
|
47
46
|
* delegating validation from one validator sub-class implementation to
|
|
48
|
-
* another schema, {@link ValidatorContext.validate}
|
|
49
|
-
*
|
|
47
|
+
* another schema, {@link ValidatorContext.validate} must be used instead of
|
|
48
|
+
* calling {@link Validator.validateInContext}. This will allow to stop the
|
|
50
49
|
* validation process if the value was transformed (by the other schema) but
|
|
51
50
|
* transformations are not allowed.
|
|
52
51
|
*
|
|
@@ -63,104 +62,12 @@ export abstract class Validator<Output = any> {
|
|
|
63
62
|
*
|
|
64
63
|
* @see {@link ValidatorContext.validate}
|
|
65
64
|
*/
|
|
66
|
-
|
|
65
|
+
validateInContext(
|
|
67
66
|
input: unknown,
|
|
68
67
|
ctx: ValidatorContext,
|
|
69
68
|
): ValidationResult<Output>
|
|
70
|
-
|
|
71
|
-
assert(input: unknown): asserts input is Output {
|
|
72
|
-
const result = this.validate(input, { allowTransform: false })
|
|
73
|
-
if (!result.success) throw result.error
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
check(input: unknown): input is Output {
|
|
77
|
-
const result = this.validate(input, { allowTransform: false })
|
|
78
|
-
return result.success
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
maybe<I>(input: I): (I & Output) | undefined {
|
|
82
|
-
return this.check(input) ? input : undefined
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
parse<I>(
|
|
86
|
-
input: I,
|
|
87
|
-
options: ValidationOptions & { allowTransform: false },
|
|
88
|
-
): I & Output
|
|
89
|
-
parse(input: unknown, options?: ValidationOptions): Output
|
|
90
|
-
parse(input: unknown, options?: ValidationOptions): Output {
|
|
91
|
-
const result = ValidatorContext.validate(input, this, options)
|
|
92
|
-
if (!result.success) throw result.error
|
|
93
|
-
return result.value
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
validate<I>(
|
|
97
|
-
input: I,
|
|
98
|
-
options: ValidationOptions & { allowTransform: false },
|
|
99
|
-
): ValidationResult<I & Output>
|
|
100
|
-
validate(
|
|
101
|
-
input: unknown,
|
|
102
|
-
options?: ValidationOptions,
|
|
103
|
-
): ValidationResult<Output>
|
|
104
|
-
validate(
|
|
105
|
-
input: unknown,
|
|
106
|
-
options?: ValidationOptions,
|
|
107
|
-
): ValidationResult<Output> {
|
|
108
|
-
return ValidatorContext.validate(input, this, options)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// @NOTE The built lexicons namespaces will export utility functions that
|
|
112
|
-
// allow accessing the schema's methods without the need to specify ".main."
|
|
113
|
-
// as part of the namespace. This way, a utility for a particular record type
|
|
114
|
-
// can be called like "app.bsky.feed.post.<utility>()" instead of
|
|
115
|
-
// "app.bsky.feed.post.main.<utility>()". Because those utilities could
|
|
116
|
-
// conflict with other schemas (e.g. if there is a lexicon definition at
|
|
117
|
-
// "#<utility>"), those exported utilities will be prefixed with "$". In order
|
|
118
|
-
// to be able to consistently call the utilities, when using the "main" and
|
|
119
|
-
// non "main" definitions, we also expose the same methods with a "$" prefix.
|
|
120
|
-
// Thanks to this, both of the following call will be possible:
|
|
121
|
-
//
|
|
122
|
-
// - "app.bsky.feed.post.$parse(...)" // calls a utility function created by "lex build"
|
|
123
|
-
// - "app.bsky.feed.defs.postView.$parse(...)" // uses the alias defined below on the schema instance
|
|
124
|
-
|
|
125
|
-
$assert(input: unknown): asserts input is Output {
|
|
126
|
-
return this.assert(input)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
$check(input: unknown): input is Output {
|
|
130
|
-
return this.check(input)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
$maybe<I>(input: I): (I & Output) | undefined {
|
|
134
|
-
return this.maybe(input)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
$parse(input: unknown, options?: ValidationOptions): Output {
|
|
138
|
-
return this.parse(input, options)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
$validate(
|
|
142
|
-
input: unknown,
|
|
143
|
-
options?: ValidationOptions,
|
|
144
|
-
): ValidationResult<Output> {
|
|
145
|
-
return this.validate(input, options)
|
|
146
|
-
}
|
|
147
69
|
}
|
|
148
70
|
|
|
149
|
-
export type ContextualIssue = {
|
|
150
|
-
[Code in ValidationIssue['code']]: Omit<
|
|
151
|
-
Extract<ValidationIssue, { code: Code }>,
|
|
152
|
-
'path'
|
|
153
|
-
> & { path?: PropertyKey | readonly PropertyKey[] }
|
|
154
|
-
}[ValidationIssue['code']]
|
|
155
|
-
|
|
156
|
-
const asIssue = (
|
|
157
|
-
{ path, ...issue }: ContextualIssue,
|
|
158
|
-
currentPath: readonly PropertyKey[],
|
|
159
|
-
): ValidationIssue & { path: PropertyKey[] } => ({
|
|
160
|
-
...issue,
|
|
161
|
-
path: path != null ? currentPath.concat(path) : [...currentPath],
|
|
162
|
-
})
|
|
163
|
-
|
|
164
71
|
export class ValidatorContext {
|
|
165
72
|
/**
|
|
166
73
|
* Creates a new validation context and validates the input using the
|
|
@@ -176,20 +83,20 @@ export class ValidatorContext {
|
|
|
176
83
|
}
|
|
177
84
|
|
|
178
85
|
private readonly currentPath: PropertyKey[]
|
|
179
|
-
private readonly issues:
|
|
86
|
+
private readonly issues: Issue[] = []
|
|
180
87
|
|
|
181
88
|
protected constructor(readonly options: ValidationOptions) {
|
|
182
89
|
// Create a copy because we will be mutating the array during validation.
|
|
183
|
-
this.currentPath = options?.path != null ?
|
|
90
|
+
this.currentPath = options?.path != null ? Array.from(options.path) : []
|
|
184
91
|
}
|
|
185
92
|
|
|
186
93
|
get path() {
|
|
187
|
-
return
|
|
94
|
+
return Array.from(this.currentPath)
|
|
188
95
|
}
|
|
189
96
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
return this.
|
|
97
|
+
concatPath(path?: PropertyKey | readonly PropertyKey[]) {
|
|
98
|
+
if (path == null) return this.path
|
|
99
|
+
return this.currentPath.concat(path)
|
|
193
100
|
}
|
|
194
101
|
|
|
195
102
|
/**
|
|
@@ -198,10 +105,15 @@ export class ValidatorContext {
|
|
|
198
105
|
* this method enforces the {@link ValidationOptions.allowTransform} option.
|
|
199
106
|
*/
|
|
200
107
|
validate<V>(input: unknown, validator: Validator<V>): ValidationResult<V> {
|
|
108
|
+
// This is the only place where validateInContext should be called.
|
|
201
109
|
const result = validator.validateInContext(input, this)
|
|
202
110
|
|
|
203
111
|
if (result.success) {
|
|
204
|
-
if (
|
|
112
|
+
if (
|
|
113
|
+
// Defaults to true
|
|
114
|
+
this.options?.allowTransform === false &&
|
|
115
|
+
!Object.is(result.value, input)
|
|
116
|
+
) {
|
|
205
117
|
// If the value changed, it means that a default (or some other
|
|
206
118
|
// transformation) was applied, meaning that the original value did
|
|
207
119
|
// *not* match the (output) schema. When "allowTransform" is false, we
|
|
@@ -221,18 +133,18 @@ export class ValidatorContext {
|
|
|
221
133
|
if (this.issues.length > 0) {
|
|
222
134
|
// Validator returned a success but issues were added via the context.
|
|
223
135
|
// This means the overall validation failed.
|
|
224
|
-
return
|
|
136
|
+
return failure(new ValidationError(Array.from(this.issues)))
|
|
225
137
|
}
|
|
226
138
|
}
|
|
227
139
|
|
|
228
|
-
return result
|
|
140
|
+
return result as ValidationResult<V>
|
|
229
141
|
}
|
|
230
142
|
|
|
231
|
-
validateChild<
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
): ValidationResult<V
|
|
143
|
+
validateChild<
|
|
144
|
+
I extends object,
|
|
145
|
+
K extends PropertyKey & keyof I,
|
|
146
|
+
V extends Validator,
|
|
147
|
+
>(input: I, key: K, validator: V): ValidationResult<Infer<V>> {
|
|
236
148
|
// Instead of creating a new context, we just push/pop the path segment.
|
|
237
149
|
this.currentPath.push(key)
|
|
238
150
|
try {
|
|
@@ -242,120 +154,69 @@ export class ValidatorContext {
|
|
|
242
154
|
}
|
|
243
155
|
}
|
|
244
156
|
|
|
245
|
-
addIssue(issue:
|
|
246
|
-
this.issues.push(
|
|
157
|
+
addIssue(issue: Issue): void {
|
|
158
|
+
this.issues.push(issue)
|
|
247
159
|
}
|
|
248
160
|
|
|
249
161
|
success<V>(value: V): ValidationResult<V> {
|
|
250
162
|
return success(value)
|
|
251
163
|
}
|
|
252
164
|
|
|
253
|
-
failure(issue:
|
|
254
|
-
return failure(
|
|
255
|
-
new ValidationError([...this.issues, asIssue(issue, this.currentPath)]),
|
|
256
|
-
)
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
issueInvalidValue(
|
|
260
|
-
input: unknown,
|
|
261
|
-
values: readonly unknown[],
|
|
262
|
-
path?: PropertyKey | readonly PropertyKey[],
|
|
263
|
-
) {
|
|
264
|
-
return this.failure({
|
|
265
|
-
code: 'invalid_value',
|
|
266
|
-
input,
|
|
267
|
-
values,
|
|
268
|
-
path,
|
|
269
|
-
})
|
|
165
|
+
failure(issue: Issue): ValidationFailure {
|
|
166
|
+
return failure(new ValidationError([...this.issues, issue]))
|
|
270
167
|
}
|
|
271
168
|
|
|
272
|
-
|
|
273
|
-
input
|
|
274
|
-
expected: string | readonly string[],
|
|
275
|
-
path?: PropertyKey | readonly PropertyKey[],
|
|
276
|
-
) {
|
|
277
|
-
return this.failure({
|
|
278
|
-
code: 'invalid_type',
|
|
279
|
-
input,
|
|
280
|
-
expected: Array.isArray(expected) ? expected : [expected],
|
|
281
|
-
path,
|
|
282
|
-
})
|
|
169
|
+
issueInvalidValue(input: unknown, values: readonly unknown[]) {
|
|
170
|
+
return this.failure(new IssueInvalidValue(this.path, input, values))
|
|
283
171
|
}
|
|
284
172
|
|
|
285
|
-
|
|
286
|
-
input
|
|
287
|
-
property: keyof I & PropertyKey,
|
|
288
|
-
values: readonly unknown[],
|
|
289
|
-
) {
|
|
290
|
-
return this.issueInvalidValue(input[property], values, property)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
issueInvalidPropertyType<I>(
|
|
294
|
-
input: I,
|
|
295
|
-
property: keyof I & PropertyKey,
|
|
296
|
-
expected: string | readonly string[],
|
|
297
|
-
) {
|
|
298
|
-
return this.issueInvalidType(input[property], expected, property)
|
|
173
|
+
issueInvalidType(input: unknown, expected: string) {
|
|
174
|
+
return this.failure(new IssueInvalidType(this.path, input, [expected]))
|
|
299
175
|
}
|
|
300
176
|
|
|
301
177
|
issueRequiredKey(input: object, key: PropertyKey) {
|
|
302
|
-
return this.failure(
|
|
303
|
-
code: 'required_key',
|
|
304
|
-
key,
|
|
305
|
-
input,
|
|
306
|
-
path: key,
|
|
307
|
-
})
|
|
178
|
+
return this.failure(new IssueRequiredKey(this.path, input, key))
|
|
308
179
|
}
|
|
309
180
|
|
|
310
|
-
issueInvalidFormat(input: unknown, format: string,
|
|
311
|
-
return this.failure(
|
|
312
|
-
code: 'invalid_format',
|
|
313
|
-
message,
|
|
314
|
-
format,
|
|
315
|
-
input,
|
|
316
|
-
})
|
|
181
|
+
issueInvalidFormat(input: unknown, format: string, msg?: string) {
|
|
182
|
+
return this.failure(new IssueInvalidFormat(this.path, input, format, msg))
|
|
317
183
|
}
|
|
318
184
|
|
|
319
185
|
issueTooBig(
|
|
320
186
|
input: unknown,
|
|
321
|
-
type:
|
|
322
|
-
|
|
187
|
+
type: MeasurableType,
|
|
188
|
+
max: number,
|
|
323
189
|
actual: number,
|
|
324
190
|
) {
|
|
325
|
-
return this.failure(
|
|
326
|
-
code: 'too_big',
|
|
327
|
-
type,
|
|
328
|
-
maximum,
|
|
329
|
-
actual,
|
|
330
|
-
input,
|
|
331
|
-
})
|
|
191
|
+
return this.failure(new IssueTooBig(this.path, input, max, type, actual))
|
|
332
192
|
}
|
|
333
193
|
|
|
334
194
|
issueTooSmall(
|
|
335
195
|
input: unknown,
|
|
336
|
-
type:
|
|
337
|
-
|
|
196
|
+
type: MeasurableType,
|
|
197
|
+
min: number,
|
|
338
198
|
actual: number,
|
|
339
199
|
) {
|
|
340
|
-
return this.failure(
|
|
341
|
-
code: 'too_small',
|
|
342
|
-
type,
|
|
343
|
-
minimum,
|
|
344
|
-
actual,
|
|
345
|
-
input,
|
|
346
|
-
})
|
|
200
|
+
return this.failure(new IssueTooSmall(this.path, input, min, type, actual))
|
|
347
201
|
}
|
|
348
202
|
|
|
349
|
-
|
|
350
|
-
input:
|
|
351
|
-
|
|
352
|
-
|
|
203
|
+
issueInvalidPropertyValue<I>(
|
|
204
|
+
input: I,
|
|
205
|
+
property: keyof I & PropertyKey,
|
|
206
|
+
values: readonly unknown[],
|
|
207
|
+
) {
|
|
208
|
+
const value = input[property]
|
|
209
|
+
const path = this.concatPath(property)
|
|
210
|
+
return this.failure(new IssueInvalidValue(path, value, values))
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
issueInvalidPropertyType<I>(
|
|
214
|
+
input: I,
|
|
215
|
+
property: keyof I & PropertyKey,
|
|
216
|
+
expected: string,
|
|
353
217
|
) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
message,
|
|
358
|
-
path,
|
|
359
|
-
})
|
|
218
|
+
const value = input[property]
|
|
219
|
+
const path = this.concatPath(property)
|
|
220
|
+
return this.failure(new IssueInvalidType(path, value, [expected]))
|
|
360
221
|
}
|
|
361
222
|
}
|
package/src/validation.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": ["../../../tsconfig/isomorphic.json"],
|
|
3
|
+
"include": ["./src"],
|
|
4
|
+
"exclude": ["**/*.test.ts"],
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"noImplicitAny": true,
|
|
7
|
+
"importHelpers": true,
|
|
8
|
+
"target": "ES2023",
|
|
9
|
+
"rootDir": "./src",
|
|
10
|
+
"outDir": "./dist"
|
|
11
|
+
}
|
|
12
|
+
}
|
package/tsconfig.json
ADDED