@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.
Files changed (289) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/dist/core/$type.d.ts +6 -3
  3. package/dist/core/$type.d.ts.map +1 -1
  4. package/dist/core/$type.js +1 -0
  5. package/dist/core/$type.js.map +1 -1
  6. package/dist/core/record-key.d.ts +3 -3
  7. package/dist/core/record-key.d.ts.map +1 -1
  8. package/dist/core/record-key.js +12 -6
  9. package/dist/core/record-key.js.map +1 -1
  10. package/dist/core/result.d.ts.map +1 -1
  11. package/dist/core/result.js +6 -0
  12. package/dist/core/result.js.map +1 -1
  13. package/dist/core/string-format.d.ts +30 -27
  14. package/dist/core/string-format.d.ts.map +1 -1
  15. package/dist/core/string-format.js +56 -42
  16. package/dist/core/string-format.js.map +1 -1
  17. package/dist/core/types.d.ts +9 -1
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/core/types.js.map +1 -1
  20. package/dist/external.d.ts +31 -28
  21. package/dist/external.d.ts.map +1 -1
  22. package/dist/external.js +33 -17
  23. package/dist/external.js.map +1 -1
  24. package/dist/schema/_parameters.d.ts +2 -2
  25. package/dist/schema/_parameters.d.ts.map +1 -1
  26. package/dist/schema/array.d.ts +5 -6
  27. package/dist/schema/array.d.ts.map +1 -1
  28. package/dist/schema/array.js +5 -6
  29. package/dist/schema/array.js.map +1 -1
  30. package/dist/schema/blob.d.ts +2 -3
  31. package/dist/schema/blob.d.ts.map +1 -1
  32. package/dist/schema/blob.js +1 -2
  33. package/dist/schema/blob.js.map +1 -1
  34. package/dist/schema/boolean.d.ts +4 -5
  35. package/dist/schema/boolean.d.ts.map +1 -1
  36. package/dist/schema/boolean.js +2 -3
  37. package/dist/schema/boolean.js.map +1 -1
  38. package/dist/schema/bytes.d.ts +3 -4
  39. package/dist/schema/bytes.d.ts.map +1 -1
  40. package/dist/schema/bytes.js +2 -3
  41. package/dist/schema/bytes.js.map +1 -1
  42. package/dist/schema/cid.d.ts +13 -6
  43. package/dist/schema/cid.d.ts.map +1 -1
  44. package/dist/schema/cid.js +2 -4
  45. package/dist/schema/cid.js.map +1 -1
  46. package/dist/schema/custom.d.ts +3 -4
  47. package/dist/schema/custom.d.ts.map +1 -1
  48. package/dist/schema/custom.js +4 -3
  49. package/dist/schema/custom.js.map +1 -1
  50. package/dist/schema/dict.d.ts +3 -3
  51. package/dist/schema/dict.d.ts.map +1 -1
  52. package/dist/schema/dict.js +1 -1
  53. package/dist/schema/dict.js.map +1 -1
  54. package/dist/schema/discriminated-union.d.ts +15 -24
  55. package/dist/schema/discriminated-union.d.ts.map +1 -1
  56. package/dist/schema/discriminated-union.js +40 -64
  57. package/dist/schema/discriminated-union.js.map +1 -1
  58. package/dist/schema/enum.d.ts +8 -4
  59. package/dist/schema/enum.d.ts.map +1 -1
  60. package/dist/schema/enum.js +5 -3
  61. package/dist/schema/enum.js.map +1 -1
  62. package/dist/schema/integer.d.ts +3 -4
  63. package/dist/schema/integer.d.ts.map +1 -1
  64. package/dist/schema/integer.js +3 -4
  65. package/dist/schema/integer.js.map +1 -1
  66. package/dist/schema/intersection.d.ts +22 -14
  67. package/dist/schema/intersection.d.ts.map +1 -1
  68. package/dist/schema/intersection.js +12 -22
  69. package/dist/schema/intersection.js.map +1 -1
  70. package/dist/schema/literal.d.ts +8 -4
  71. package/dist/schema/literal.d.ts.map +1 -1
  72. package/dist/schema/literal.js +5 -3
  73. package/dist/schema/literal.js.map +1 -1
  74. package/dist/schema/never.d.ts +2 -2
  75. package/dist/schema/never.d.ts.map +1 -1
  76. package/dist/schema/never.js +1 -1
  77. package/dist/schema/never.js.map +1 -1
  78. package/dist/schema/null.d.ts +2 -3
  79. package/dist/schema/null.d.ts.map +1 -1
  80. package/dist/schema/null.js +1 -2
  81. package/dist/schema/null.js.map +1 -1
  82. package/dist/schema/nullable.d.ts +7 -0
  83. package/dist/schema/nullable.d.ts.map +1 -0
  84. package/dist/schema/nullable.js +19 -0
  85. package/dist/schema/nullable.js.map +1 -0
  86. package/dist/schema/object.d.ts +10 -44
  87. package/dist/schema/object.d.ts.map +1 -1
  88. package/dist/schema/object.js +13 -56
  89. package/dist/schema/object.js.map +1 -1
  90. package/dist/schema/optional.d.ts +7 -0
  91. package/dist/schema/optional.d.ts.map +1 -0
  92. package/dist/schema/optional.js +25 -0
  93. package/dist/schema/optional.js.map +1 -0
  94. package/dist/schema/params.d.ts +14 -19
  95. package/dist/schema/params.d.ts.map +1 -1
  96. package/dist/schema/params.js +10 -24
  97. package/dist/schema/params.js.map +1 -1
  98. package/dist/schema/payload.d.ts +4 -4
  99. package/dist/schema/payload.d.ts.map +1 -1
  100. package/dist/schema/payload.js.map +1 -1
  101. package/dist/schema/permission-set.d.ts +6 -6
  102. package/dist/schema/permission-set.d.ts.map +1 -1
  103. package/dist/schema/permission-set.js +1 -2
  104. package/dist/schema/permission-set.js.map +1 -1
  105. package/dist/schema/permission.d.ts +0 -1
  106. package/dist/schema/permission.d.ts.map +1 -1
  107. package/dist/schema/permission.js +0 -1
  108. package/dist/schema/permission.js.map +1 -1
  109. package/dist/schema/procedure.d.ts +8 -9
  110. package/dist/schema/procedure.d.ts.map +1 -1
  111. package/dist/schema/procedure.js +0 -1
  112. package/dist/schema/procedure.js.map +1 -1
  113. package/dist/schema/query.d.ts +7 -8
  114. package/dist/schema/query.d.ts.map +1 -1
  115. package/dist/schema/query.js +0 -1
  116. package/dist/schema/query.js.map +1 -1
  117. package/dist/schema/record.d.ts +34 -28
  118. package/dist/schema/record.d.ts.map +1 -1
  119. package/dist/schema/record.js +1 -2
  120. package/dist/schema/record.js.map +1 -1
  121. package/dist/schema/ref.d.ts +2 -3
  122. package/dist/schema/ref.d.ts.map +1 -1
  123. package/dist/schema/ref.js +1 -2
  124. package/dist/schema/ref.js.map +1 -1
  125. package/dist/schema/refine.d.ts +18 -0
  126. package/dist/schema/refine.d.ts.map +1 -0
  127. package/dist/schema/refine.js +33 -0
  128. package/dist/schema/refine.js.map +1 -0
  129. package/dist/schema/regexp.d.ts +7 -0
  130. package/dist/schema/regexp.d.ts.map +1 -0
  131. package/dist/schema/regexp.js +22 -0
  132. package/dist/schema/regexp.js.map +1 -0
  133. package/dist/schema/string.d.ts +4 -8
  134. package/dist/schema/string.d.ts.map +1 -1
  135. package/dist/schema/string.js +6 -3
  136. package/dist/schema/string.js.map +1 -1
  137. package/dist/schema/subscription.d.ts +7 -6
  138. package/dist/schema/subscription.d.ts.map +1 -1
  139. package/dist/schema/subscription.js.map +1 -1
  140. package/dist/schema/token.d.ts +2 -3
  141. package/dist/schema/token.d.ts.map +1 -1
  142. package/dist/schema/token.js +1 -2
  143. package/dist/schema/token.js.map +1 -1
  144. package/dist/schema/typed-object.d.ts +29 -27
  145. package/dist/schema/typed-object.d.ts.map +1 -1
  146. package/dist/schema/typed-object.js +1 -2
  147. package/dist/schema/typed-object.js.map +1 -1
  148. package/dist/schema/typed-ref.d.ts +2 -2
  149. package/dist/schema/typed-ref.d.ts.map +1 -1
  150. package/dist/schema/typed-ref.js +1 -1
  151. package/dist/schema/typed-ref.js.map +1 -1
  152. package/dist/schema/typed-union.d.ts +3 -4
  153. package/dist/schema/typed-union.d.ts.map +1 -1
  154. package/dist/schema/typed-union.js +3 -10
  155. package/dist/schema/typed-union.js.map +1 -1
  156. package/dist/schema/union.d.ts +2 -2
  157. package/dist/schema/union.d.ts.map +1 -1
  158. package/dist/schema/union.js +1 -1
  159. package/dist/schema/union.js.map +1 -1
  160. package/dist/schema/unknown-object.d.ts +2 -3
  161. package/dist/schema/unknown-object.d.ts.map +1 -1
  162. package/dist/schema/unknown-object.js +1 -2
  163. package/dist/schema/unknown-object.js.map +1 -1
  164. package/dist/schema/unknown.d.ts +2 -2
  165. package/dist/schema/unknown.d.ts.map +1 -1
  166. package/dist/schema/unknown.js +1 -1
  167. package/dist/schema/unknown.js.map +1 -1
  168. package/dist/schema.d.ts +4 -0
  169. package/dist/schema.d.ts.map +1 -1
  170. package/dist/schema.js +6 -1
  171. package/dist/schema.js.map +1 -1
  172. package/dist/util/array-agg.d.ts.map +1 -1
  173. package/dist/util/array-agg.js +1 -0
  174. package/dist/util/array-agg.js.map +1 -1
  175. package/dist/util/lazy-property.d.ts +2 -0
  176. package/dist/util/lazy-property.d.ts.map +1 -0
  177. package/dist/util/lazy-property.js +14 -0
  178. package/dist/util/lazy-property.js.map +1 -0
  179. package/dist/validation/schema.d.ts +24 -0
  180. package/dist/validation/schema.d.ts.map +1 -0
  181. package/dist/validation/schema.js +57 -0
  182. package/dist/validation/schema.js.map +1 -0
  183. package/dist/validation/validation-error.d.ts +3 -3
  184. package/dist/validation/validation-error.d.ts.map +1 -1
  185. package/dist/validation/validation-error.js +32 -4
  186. package/dist/validation/validation-error.js.map +1 -1
  187. package/dist/validation/validation-issue.d.ts +32 -24
  188. package/dist/validation/validation-issue.d.ts.map +1 -1
  189. package/dist/validation/validation-issue.js +136 -92
  190. package/dist/validation/validation-issue.js.map +1 -1
  191. package/dist/validation/validator.d.ts +20 -50
  192. package/dist/validation/validator.d.ts.map +1 -1
  193. package/dist/validation/validator.js +40 -134
  194. package/dist/validation/validator.js.map +1 -1
  195. package/dist/validation.d.ts +1 -0
  196. package/dist/validation.d.ts.map +1 -1
  197. package/dist/validation.js +1 -0
  198. package/dist/validation.js.map +1 -1
  199. package/package.json +8 -4
  200. package/src/core/$type.ts +7 -4
  201. package/src/core/record-key.ts +12 -5
  202. package/src/core/result.ts +6 -0
  203. package/src/core/string-format.ts +97 -61
  204. package/src/core/types.ts +12 -6
  205. package/src/external.ts +92 -70
  206. package/src/schema/_parameters.test.ts +416 -0
  207. package/src/schema/array.test.ts +237 -0
  208. package/src/schema/array.ts +17 -11
  209. package/src/schema/blob.test.ts +506 -0
  210. package/src/schema/blob.ts +3 -5
  211. package/src/schema/boolean.test.ts +116 -0
  212. package/src/schema/boolean.ts +5 -7
  213. package/src/schema/bytes.test.ts +226 -0
  214. package/src/schema/bytes.ts +4 -6
  215. package/src/schema/cid.test.ts +155 -0
  216. package/src/schema/cid.ts +14 -8
  217. package/src/schema/custom.test.ts +413 -0
  218. package/src/schema/custom.ts +10 -8
  219. package/src/schema/dict.test.ts +198 -0
  220. package/src/schema/dict.ts +6 -8
  221. package/src/schema/discriminated-union.test.ts +675 -0
  222. package/src/schema/discriminated-union.ts +68 -95
  223. package/src/schema/enum.test.ts +396 -0
  224. package/src/schema/enum.ts +12 -5
  225. package/src/schema/integer.test.ts +312 -0
  226. package/src/schema/integer.ts +5 -7
  227. package/src/schema/intersection.test.ts +32 -0
  228. package/src/schema/intersection.ts +37 -40
  229. package/src/schema/literal.test.ts +531 -0
  230. package/src/schema/literal.ts +12 -5
  231. package/src/schema/never.test.ts +174 -0
  232. package/src/schema/never.ts +3 -10
  233. package/src/schema/null.test.ts +79 -0
  234. package/src/schema/null.ts +3 -5
  235. package/src/schema/nullable.test.ts +480 -0
  236. package/src/schema/nullable.ts +23 -0
  237. package/src/schema/object.test.ts +47 -115
  238. package/src/schema/object.ts +23 -134
  239. package/src/schema/optional.test.ts +485 -0
  240. package/src/schema/optional.ts +31 -0
  241. package/src/schema/params.test.ts +582 -0
  242. package/src/schema/params.ts +37 -55
  243. package/src/schema/payload.test.ts +345 -0
  244. package/src/schema/payload.ts +5 -5
  245. package/src/schema/permission-set.test.ts +679 -0
  246. package/src/schema/permission-set.ts +6 -8
  247. package/src/schema/permission.test.ts +536 -0
  248. package/src/schema/permission.ts +0 -2
  249. package/src/schema/procedure.test.ts +443 -0
  250. package/src/schema/procedure.ts +11 -13
  251. package/src/schema/query.test.ts +408 -0
  252. package/src/schema/query.ts +9 -11
  253. package/src/schema/record.test.ts +694 -0
  254. package/src/schema/record.ts +38 -36
  255. package/src/schema/ref.test.ts +365 -0
  256. package/src/schema/ref.ts +8 -5
  257. package/src/schema/refine.test.ts +578 -0
  258. package/src/schema/refine.ts +85 -0
  259. package/src/schema/regexp.test.ts +580 -0
  260. package/src/schema/regexp.ts +22 -0
  261. package/src/schema/string.test.ts +612 -0
  262. package/src/schema/string.ts +11 -17
  263. package/src/schema/subscription.test.ts +689 -0
  264. package/src/schema/subscription.ts +13 -8
  265. package/src/schema/token.test.ts +428 -0
  266. package/src/schema/token.ts +3 -5
  267. package/src/schema/typed-object.test.ts +612 -0
  268. package/src/schema/typed-object.ts +23 -20
  269. package/src/schema/typed-ref.test.ts +823 -0
  270. package/src/schema/typed-ref.ts +10 -5
  271. package/src/schema/typed-union.test.ts +378 -0
  272. package/src/schema/typed-union.ts +6 -15
  273. package/src/schema/union.test.ts +200 -0
  274. package/src/schema/union.ts +5 -4
  275. package/src/schema/unknown-object.test.ts +592 -0
  276. package/src/schema/unknown-object.ts +3 -5
  277. package/src/schema/unknown.test.ts +312 -0
  278. package/src/schema/unknown.ts +3 -3
  279. package/src/schema.ts +7 -1
  280. package/src/util/array-agg.ts +1 -0
  281. package/src/util/lazy-property.ts +14 -0
  282. package/src/validation/schema.ts +92 -0
  283. package/src/validation/validation-error.ts +60 -9
  284. package/src/validation/validation-issue.ts +141 -144
  285. package/src/validation/validator.ts +67 -206
  286. package/src/validation.ts +1 -0
  287. package/tsconfig.build.json +12 -0
  288. package/tsconfig.json +7 -0
  289. 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
- ValidationIssue,
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 abstract class Validator<Output = any> {
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 For internal use only (not actually deprecated)
35
+ * @deprecated **INTERNAL API, DO NOT USE**.
31
36
  */
32
- _lex!: { output: Output }
33
-
34
- readonly lexiconType?: string
37
+ readonly ['_lex']: { output: Output }
35
38
 
36
39
  /**
37
- * @internal **INTERNAL API, DO NOT USE**.
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} should be used instead
49
- * of calling {@link Validator.validateInContext}. This will allow to stop the
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
- abstract validateInContext(
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: ValidationIssue[] = []
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 ? [...options.path] : []
90
+ this.currentPath = options?.path != null ? Array.from(options.path) : []
184
91
  }
185
92
 
186
93
  get path() {
187
- return [...this.currentPath]
94
+ return Array.from(this.currentPath)
188
95
  }
189
96
 
190
- get allowTransform() {
191
- // Default to true
192
- return this.options?.allowTransform !== false
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 (!this.allowTransform && !Object.is(result.value, input)) {
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 { success: false, error: new ValidationError(this.issues) }
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<I extends object, K extends PropertyKey & keyof I, V>(
232
- input: I,
233
- key: K,
234
- validator: Validator<V>,
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: ContextualIssue): void {
246
- this.issues.push(asIssue(issue, this.currentPath))
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: ContextualIssue): ValidationFailure {
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
- issueInvalidType(
273
- input: unknown,
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
- issueInvalidPropertyValue<I>(
286
- input: I,
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, message?: 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: IssueTooBig['type'],
322
- maximum: number,
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: IssueTooSmall['type'],
337
- minimum: number,
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
- custom(
350
- input: unknown,
351
- message: string,
352
- path?: PropertyKey | readonly PropertyKey[],
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
- return this.failure({
355
- code: 'custom',
356
- input,
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
@@ -1,4 +1,5 @@
1
1
  export * from './validation/property-key.js'
2
+ export * from './validation/schema.js'
2
3
  export * from './validation/validation-error.js'
3
4
  export * from './validation/validation-issue.js'
4
5
  export * from './validation/validator.js'
@@ -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
@@ -0,0 +1,7 @@
1
+ {
2
+ "include": [],
3
+ "references": [
4
+ { "path": "./tsconfig.build.json" },
5
+ { "path": "./tsconfig.tests.json" }
6
+ ]
7
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../../tsconfig/tests.json",
3
+ "include": ["./tests", "./src/**.test.ts"],
4
+ "compilerOptions": {
5
+ "noImplicitAny": true,
6
+ "rootDir": "./",
7
+ "baseUrl": "./"
8
+ }
9
+ }