@atproto/lex-schema 0.0.10 → 0.0.12
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 +26 -0
- package/dist/core/$type.d.ts +149 -0
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js +44 -0
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.d.ts +44 -0
- package/dist/core/record-key.d.ts.map +1 -1
- package/dist/core/record-key.js +30 -0
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/result.d.ts +85 -4
- package/dist/core/result.d.ts.map +1 -1
- package/dist/core/result.js +60 -4
- package/dist/core/result.js.map +1 -1
- package/dist/core/schema.d.ts +229 -2
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +197 -4
- package/dist/core/schema.js.map +1 -1
- package/dist/core/string-format.d.ts +244 -11
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +150 -0
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/types.d.ts +90 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/validation-error.d.ts +61 -1
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +60 -0
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validation-issue.d.ts +61 -0
- package/dist/core/validation-issue.d.ts.map +1 -1
- package/dist/core/validation-issue.js +51 -0
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.d.ts +347 -10
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +184 -3
- package/dist/core/validator.js.map +1 -1
- package/dist/helpers.d.ts +13 -25
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +2 -2
- package/dist/helpers.js.map +1 -1
- package/dist/schema/array.d.ts +45 -0
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +14 -0
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +46 -0
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +39 -0
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.d.ts +28 -0
- package/dist/schema/boolean.d.ts.map +1 -1
- package/dist/schema/boolean.js +28 -0
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.d.ts +38 -0
- package/dist/schema/bytes.d.ts.map +1 -1
- package/dist/schema/bytes.js +32 -0
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +38 -0
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +33 -0
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.d.ts +66 -1
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js +54 -0
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +44 -0
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +44 -0
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +58 -0
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +45 -0
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.d.ts +48 -0
- package/dist/schema/enum.d.ts.map +1 -1
- package/dist/schema/enum.js +48 -0
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.d.ts +42 -0
- package/dist/schema/integer.d.ts.map +1 -1
- package/dist/schema/integer.js +36 -0
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +54 -0
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +49 -0
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/literal.d.ts +44 -0
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +44 -0
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.d.ts +42 -0
- package/dist/schema/never.d.ts.map +1 -1
- package/dist/schema/never.js +42 -0
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.d.ts +29 -0
- package/dist/schema/null.d.ts.map +1 -1
- package/dist/schema/null.js +29 -0
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +41 -0
- package/dist/schema/nullable.d.ts.map +1 -1
- package/dist/schema/nullable.js +41 -0
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.d.ts +56 -0
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +51 -0
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +42 -0
- package/dist/schema/optional.d.ts.map +1 -1
- package/dist/schema/optional.js +42 -0
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.d.ts +89 -7
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +84 -10
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +111 -15
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js +70 -0
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +58 -0
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +50 -0
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +42 -0
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js +39 -0
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +64 -0
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +64 -0
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +55 -0
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +55 -0
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +63 -8
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +20 -0
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +50 -0
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +17 -0
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +58 -9
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.d.ts +44 -0
- package/dist/schema/regexp.d.ts.map +1 -1
- package/dist/schema/regexp.js +44 -0
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.d.ts +50 -0
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +41 -0
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +72 -2
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js +59 -0
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +47 -0
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +47 -0
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +62 -8
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +18 -0
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +53 -0
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +15 -0
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +50 -1
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +50 -1
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +45 -0
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +40 -0
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown-object.d.ts +34 -0
- package/dist/schema/unknown-object.d.ts.map +1 -1
- package/dist/schema/unknown-object.js +31 -0
- package/dist/schema/unknown-object.js.map +1 -1
- package/dist/schema/unknown.d.ts +33 -0
- package/dist/schema/unknown.d.ts.map +1 -1
- package/dist/schema/unknown.js +33 -0
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.d.ts +44 -0
- package/dist/schema/with-default.d.ts.map +1 -1
- package/dist/schema/with-default.js +44 -0
- package/dist/schema/with-default.js.map +1 -1
- package/package.json +4 -4
- package/src/core/$type.ts +150 -18
- package/src/core/record-key.ts +44 -0
- package/src/core/result.ts +86 -4
- package/src/core/schema.ts +236 -7
- package/src/core/string-format.ts +259 -13
- package/src/core/types.ts +91 -3
- package/src/core/validation-error.ts +60 -0
- package/src/core/validation-issue.ts +65 -0
- package/src/core/validator.ts +351 -10
- package/src/helpers.test.ts +110 -29
- package/src/helpers.ts +14 -14
- package/src/schema/array.test.ts +94 -79
- package/src/schema/array.ts +45 -0
- package/src/schema/blob.ts +46 -0
- package/src/schema/boolean.ts +28 -0
- package/src/schema/bytes.ts +38 -0
- package/src/schema/cid.ts +38 -0
- package/src/schema/custom.ts +66 -1
- package/src/schema/dict.ts +44 -0
- package/src/schema/discriminated-union.ts +58 -0
- package/src/schema/enum.ts +48 -0
- package/src/schema/integer.ts +42 -0
- package/src/schema/intersection.ts +54 -0
- package/src/schema/literal.ts +44 -0
- package/src/schema/never.ts +42 -0
- package/src/schema/null.ts +29 -0
- package/src/schema/nullable.ts +41 -0
- package/src/schema/object.ts +56 -0
- package/src/schema/optional.ts +42 -0
- package/src/schema/params.test.ts +58 -2
- package/src/schema/params.ts +124 -16
- package/src/schema/payload.test.ts +3 -3
- package/src/schema/payload.ts +142 -38
- package/src/schema/permission-set.ts +58 -0
- package/src/schema/permission.ts +42 -0
- package/src/schema/procedure.ts +64 -0
- package/src/schema/query.ts +55 -0
- package/src/schema/record.ts +63 -8
- package/src/schema/ref.ts +50 -0
- package/src/schema/refine.ts +58 -9
- package/src/schema/regexp.ts +44 -0
- package/src/schema/string.ts +50 -0
- package/src/schema/subscription.ts +72 -2
- package/src/schema/token.ts +47 -0
- package/src/schema/typed-object.ts +62 -8
- package/src/schema/typed-ref.ts +53 -0
- package/src/schema/typed-union.ts +55 -2
- package/src/schema/union.ts +45 -0
- package/src/schema/unknown-object.ts +34 -0
- package/src/schema/unknown.ts +33 -0
- package/src/schema/with-default.ts +44 -0
package/src/core/result.ts
CHANGED
|
@@ -1,23 +1,105 @@
|
|
|
1
1
|
export type ResultSuccess<V = any> = { success: true; value: V }
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a failed result containing an error reason.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam E - The type of the error reason
|
|
7
|
+
*/
|
|
2
8
|
export type ResultFailure<E = Error> = { success: false; reason: E }
|
|
3
9
|
|
|
10
|
+
/**
|
|
11
|
+
* A discriminated union type representing either a success or failure outcome.
|
|
12
|
+
*
|
|
13
|
+
* Check the `success` property to determine the outcome and access the
|
|
14
|
+
* appropriate property (`value` for success, `reason` for failure).
|
|
15
|
+
*
|
|
16
|
+
* @typeParam V - The type of the success value
|
|
17
|
+
* @typeParam E - The type of the error reason
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* function parseJson(text: string): Result<unknown, SyntaxError> {
|
|
22
|
+
* try {
|
|
23
|
+
* return success(JSON.parse(text))
|
|
24
|
+
* } catch (e) {
|
|
25
|
+
* return failure(e as SyntaxError)
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
4
30
|
export type Result<V = any, E = Error> = ResultSuccess<V> | ResultFailure<E>
|
|
5
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Creates a successful result wrapping the given value.
|
|
34
|
+
*
|
|
35
|
+
* @typeParam V - The type of the value
|
|
36
|
+
* @param value - The success value to wrap
|
|
37
|
+
* @returns {ResultSuccess} A success result containing the value
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const result = success(42)
|
|
42
|
+
* console.log(result.success) // true
|
|
43
|
+
* console.log(result.value) // 42
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
6
46
|
/*@__NO_SIDE_EFFECTS__*/
|
|
7
47
|
export function success<V>(value: V): ResultSuccess<V> {
|
|
8
48
|
return { success: true, value }
|
|
9
49
|
}
|
|
10
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Creates a failed result wrapping the given error reason.
|
|
53
|
+
*
|
|
54
|
+
* @typeParam E - The type of the error reason
|
|
55
|
+
* @param reason - The error reason to wrap
|
|
56
|
+
* @returns {ResultFailure} A failure result containing the error
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const result = failure(new Error('Something went wrong'))
|
|
61
|
+
* console.log(result.success) // false
|
|
62
|
+
* console.log(result.reason.message) // "Something went wrong"
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
11
65
|
/*@__NO_SIDE_EFFECTS__*/
|
|
12
66
|
export function failure<E>(reason: E): ResultFailure<E> {
|
|
13
67
|
return { success: false, reason }
|
|
14
68
|
}
|
|
15
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Extracts the error reason from a failure result.
|
|
72
|
+
*
|
|
73
|
+
* @typeParam T - The type of the error reason
|
|
74
|
+
* @param result - A failure result
|
|
75
|
+
* @returns {T} The error reason
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const result = failure(new Error('oops'))
|
|
80
|
+
* const error = failureReason(result)
|
|
81
|
+
* console.log(error.message) // "oops"
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
16
84
|
/*@__NO_SIDE_EFFECTS__*/
|
|
17
85
|
export function failureReason<T>(result: ResultFailure<T>): T {
|
|
18
86
|
return result.reason
|
|
19
87
|
}
|
|
20
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Extracts the value from a success result.
|
|
91
|
+
*
|
|
92
|
+
* @typeParam T - The type of the success value
|
|
93
|
+
* @param result - A success result
|
|
94
|
+
* @returns {T} The success value
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const result = success(42)
|
|
99
|
+
* const value = successValue(result)
|
|
100
|
+
* console.log(value) // 42
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
21
103
|
/*@__NO_SIDE_EFFECTS__*/
|
|
22
104
|
export function successValue<T>(result: ResultSuccess<T>): T {
|
|
23
105
|
return result.value
|
|
@@ -27,7 +109,7 @@ export function successValue<T>(result: ResultSuccess<T>): T {
|
|
|
27
109
|
* Catches any error and wraps it in a {@link ResultFailure<Error>}.
|
|
28
110
|
*
|
|
29
111
|
* @param err - The error to catch.
|
|
30
|
-
* @returns
|
|
112
|
+
* @returns {ResultFailure} A failure result containing the error.
|
|
31
113
|
* @example
|
|
32
114
|
*
|
|
33
115
|
* ```ts
|
|
@@ -37,8 +119,8 @@ export function successValue<T>(result: ResultSuccess<T>): T {
|
|
|
37
119
|
* if (result.success) {
|
|
38
120
|
* console.log(result.value) // string
|
|
39
121
|
* } else {
|
|
40
|
-
* console.error(result.
|
|
41
|
-
* console.error(result.
|
|
122
|
+
* console.error(result.reason instanceof Error) // true
|
|
123
|
+
* console.error(result.reason.message) // string
|
|
42
124
|
* }
|
|
43
125
|
* ```
|
|
44
126
|
*/
|
|
@@ -68,7 +150,7 @@ export function catchall(err: unknown): ResultFailure<Error> {
|
|
|
68
150
|
* if (result.success) {
|
|
69
151
|
* console.log(result.value) // string
|
|
70
152
|
* } else {
|
|
71
|
-
* console.error(result.
|
|
153
|
+
* console.error(result.reason) // FooError | BarError
|
|
72
154
|
* }
|
|
73
155
|
*/
|
|
74
156
|
/*@__NO_SIDE_EFFECTS__*/
|
package/src/core/schema.ts
CHANGED
|
@@ -7,17 +7,70 @@ import {
|
|
|
7
7
|
Validator,
|
|
8
8
|
} from './validator.js'
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Options for parsing operations.
|
|
12
|
+
* Excludes the `mode` option as it is implicitly set to `"parse"`.
|
|
13
|
+
*/
|
|
10
14
|
type ParseOptions = Omit<ValidationOptions, 'mode'>
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Options for validation operations.
|
|
18
|
+
* Excludes the `mode` option as it is implicitly set to `"validate"`.
|
|
19
|
+
*/
|
|
11
20
|
type ValidateOptions = Omit<ValidationOptions, 'mode'>
|
|
12
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Internal type structure for schema type inference.
|
|
24
|
+
*
|
|
25
|
+
* This interface defines the phantom types used for compile-time type inference
|
|
26
|
+
* without affecting runtime behavior. The `input` and `output` properties
|
|
27
|
+
* represent the expected input type during validation and the resulting output
|
|
28
|
+
* type after parsing, respectively.
|
|
29
|
+
*
|
|
30
|
+
* @typeParam TInput - The type accepted as input during validation
|
|
31
|
+
* @typeParam TOutput - The type returned after parsing (may differ from input due to coercion)
|
|
32
|
+
*/
|
|
13
33
|
export interface SchemaInternals<out TInput = unknown, out TOutput = TInput> {
|
|
14
|
-
/** @internal The inferred validation type */
|
|
15
34
|
input: TInput
|
|
16
|
-
|
|
17
|
-
/** @internal The inferred parse type */
|
|
18
35
|
output: TOutput
|
|
19
36
|
}
|
|
20
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Abstract base class for all schema validators in the lexicon system.
|
|
40
|
+
*
|
|
41
|
+
* This class provides the standard validation interface that all schema types
|
|
42
|
+
* implement. It offers multiple methods for validating and parsing data:
|
|
43
|
+
*
|
|
44
|
+
* - **Assertion methods**: `assert()`, `check()` - throw on invalid input
|
|
45
|
+
* - **Type guard methods**: `matches()`, `ifMatches()` - return boolean or optional value
|
|
46
|
+
* - **Parse methods**: `parse()`, `safeParse()` - allow value transformation/coercion
|
|
47
|
+
* - **Validate methods**: `validate()`, `safeValidate()` - strict validation without coercion
|
|
48
|
+
*
|
|
49
|
+
* All methods are also available with a `$` prefix (e.g., `$parse()`, `$validate()`)
|
|
50
|
+
* for consistent access in generated lexicon namespaces.
|
|
51
|
+
*
|
|
52
|
+
* @typeParam TInput - The type accepted as valid input during validation
|
|
53
|
+
* @typeParam TOutput - The type returned after parsing (may include transformations)
|
|
54
|
+
* @typeParam TInternals - Internal type structure for type inference
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* class MySchema extends Schema<string> {
|
|
59
|
+
* validateInContext(input: unknown, ctx: ValidationContext): ValidationResult {
|
|
60
|
+
* if (typeof input !== 'string') {
|
|
61
|
+
* return ctx.issueInvalidType(input, 'string')
|
|
62
|
+
* }
|
|
63
|
+
* return ctx.success(input)
|
|
64
|
+
* }
|
|
65
|
+
* }
|
|
66
|
+
*
|
|
67
|
+
* const schema = new MySchema()
|
|
68
|
+
* schema.assert('hello') // OK
|
|
69
|
+
* schema.assert(123) // Throws ValidationError
|
|
70
|
+
* schema.matches('hello') // true
|
|
71
|
+
* schema.matches(123) // false
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
21
74
|
export abstract class Schema<
|
|
22
75
|
out TInput = unknown,
|
|
23
76
|
out TOutput = TInput,
|
|
@@ -27,8 +80,27 @@ export abstract class Schema<
|
|
|
27
80
|
>,
|
|
28
81
|
> implements Validator<TInternals['input'], TInternals['output']>
|
|
29
82
|
{
|
|
83
|
+
/**
|
|
84
|
+
* Internal phantom property for type inference.
|
|
85
|
+
* This property does not exist at runtime.
|
|
86
|
+
*
|
|
87
|
+
* @internal
|
|
88
|
+
*/
|
|
30
89
|
declare readonly ['__lex']: TInternals
|
|
31
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Performs validation of the input value within a validation context.
|
|
93
|
+
*
|
|
94
|
+
* This method must be implemented by subclasses to define the actual
|
|
95
|
+
* validation logic. It should not be called directly; use
|
|
96
|
+
* {@link ValidationContext.validate} instead to ensure proper mode enforcement.
|
|
97
|
+
*
|
|
98
|
+
* @param input - The value to validate
|
|
99
|
+
* @param ctx - The validation context providing path tracking and issue reporting
|
|
100
|
+
* @returns A validation result indicating success with the validated value or failure with issues
|
|
101
|
+
*
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
32
104
|
abstract validateInContext(
|
|
33
105
|
input: unknown,
|
|
34
106
|
ctx: ValidationContext,
|
|
@@ -66,21 +138,91 @@ export abstract class Schema<
|
|
|
66
138
|
throw result.reason
|
|
67
139
|
}
|
|
68
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Type guard that checks if the input matches this schema.
|
|
143
|
+
*
|
|
144
|
+
* @param input - The value to check
|
|
145
|
+
* @returns `true` if the input is valid according to this schema
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* if (schema.matches(data)) {
|
|
150
|
+
* // data is narrowed to the schema's input type
|
|
151
|
+
* console.log(data)
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
69
155
|
matches<I>(input: I): input is I & InferInput<this> {
|
|
70
156
|
const result = ValidationContext.validate(input, this)
|
|
71
157
|
return result.success
|
|
72
158
|
}
|
|
73
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Returns the input if it matches this schema, otherwise returns `undefined`.
|
|
162
|
+
*
|
|
163
|
+
* This is useful for optional filtering operations where you want to
|
|
164
|
+
* conditionally extract values that match a schema.
|
|
165
|
+
*
|
|
166
|
+
* @param input - The value to check
|
|
167
|
+
* @returns The input value with narrowed type if valid, otherwise `undefined`
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const validData = schema.ifMatches(data)
|
|
172
|
+
* if (validData !== undefined) {
|
|
173
|
+
* // validData is the schema's input type
|
|
174
|
+
* console.log(validData)
|
|
175
|
+
* }
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
74
178
|
ifMatches<I>(input: I): (I & InferInput<this>) | undefined {
|
|
75
179
|
return this.matches(input) ? input : undefined
|
|
76
180
|
}
|
|
77
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Parses the input, allowing value transformations and coercion.
|
|
184
|
+
*
|
|
185
|
+
* Unlike {@link validate}, this method allows the schema to transform
|
|
186
|
+
* the input value (e.g., applying default values, type coercion).
|
|
187
|
+
* Throws a {@link ValidationError} if the input is invalid.
|
|
188
|
+
*
|
|
189
|
+
* @param input - The value to parse
|
|
190
|
+
* @param options - Optional parsing configuration
|
|
191
|
+
* @returns The parsed and potentially transformed value
|
|
192
|
+
* @throws {ValidationError} If the input fails validation
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* const result = schema.parse(rawData)
|
|
197
|
+
* // result has defaults applied and is fully typed
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
78
200
|
parse(input: unknown, options?: ParseOptions): InferOutput<this> {
|
|
79
201
|
const result = this.safeParse(input, options)
|
|
80
202
|
if (result.success) return result.value
|
|
81
203
|
throw result.reason
|
|
82
204
|
}
|
|
83
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Safely parses the input without throwing, returning a result object.
|
|
208
|
+
*
|
|
209
|
+
* This method allows value transformations like {@link parse}, but
|
|
210
|
+
* returns a discriminated union result instead of throwing on error.
|
|
211
|
+
*
|
|
212
|
+
* @param input - The value to parse
|
|
213
|
+
* @param options - Optional parsing configuration
|
|
214
|
+
* @returns A {@link ValidationResult} with either the parsed value or validation errors
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const result = schema.safeParse(data)
|
|
219
|
+
* if (result.success) {
|
|
220
|
+
* console.log(result.value)
|
|
221
|
+
* } else {
|
|
222
|
+
* console.error(result.reason.issues)
|
|
223
|
+
* }
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
84
226
|
safeParse(
|
|
85
227
|
input: unknown,
|
|
86
228
|
options?: ParseOptions,
|
|
@@ -91,12 +233,52 @@ export abstract class Schema<
|
|
|
91
233
|
})
|
|
92
234
|
}
|
|
93
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Validates the input strictly without allowing transformations.
|
|
238
|
+
*
|
|
239
|
+
* Unlike {@link parse}, this method requires the input to exactly match
|
|
240
|
+
* the schema without any transformations (no defaults applied, no coercion).
|
|
241
|
+
* Throws a {@link ValidationError} if the input is invalid or would require transformation.
|
|
242
|
+
*
|
|
243
|
+
* @typeParam I - The input type (preserved in the return type)
|
|
244
|
+
* @param input - The value to validate
|
|
245
|
+
* @param options - Optional validation configuration
|
|
246
|
+
* @returns The validated input with narrowed type
|
|
247
|
+
* @throws {ValidationError} If the input fails validation or requires transformation
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* const validated = schema.validate(data)
|
|
252
|
+
* // validated is typed as the intersection of input type and schema type
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
94
255
|
validate<I>(input: I, options?: ValidateOptions): I & InferInput<this> {
|
|
95
256
|
const result = this.safeValidate(input, options)
|
|
96
257
|
if (result.success) return result.value
|
|
97
258
|
throw result.reason
|
|
98
259
|
}
|
|
99
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Safely validates the input without throwing, returning a result object.
|
|
263
|
+
*
|
|
264
|
+
* This method performs strict validation like {@link validate}, but
|
|
265
|
+
* returns a discriminated union result instead of throwing on error.
|
|
266
|
+
*
|
|
267
|
+
* @typeParam I - The input type (preserved in the result value type)
|
|
268
|
+
* @param input - The value to validate
|
|
269
|
+
* @param options - Optional validation configuration
|
|
270
|
+
* @returns A {@link ValidationResult} with either the validated value or validation errors
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```typescript
|
|
274
|
+
* const result = schema.safeValidate(data)
|
|
275
|
+
* if (result.success) {
|
|
276
|
+
* console.log(result.value)
|
|
277
|
+
* } else {
|
|
278
|
+
* console.error(result.reason.issues)
|
|
279
|
+
* }
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
100
282
|
safeValidate<I>(
|
|
101
283
|
input: I,
|
|
102
284
|
options?: ValidateOptions,
|
|
@@ -107,10 +289,12 @@ export abstract class Schema<
|
|
|
107
289
|
})
|
|
108
290
|
}
|
|
109
291
|
|
|
110
|
-
// @NOTE
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
292
|
+
// @NOTE Dollar-prefixed aliases
|
|
293
|
+
//
|
|
294
|
+
// The built lexicons namespaces export utility functions that allow accessing
|
|
295
|
+
// the schema's methods without the need to specify ".main." as part of the
|
|
296
|
+
// namespace. This way, a utility for a particular record type can be called
|
|
297
|
+
// like "app.bsky.feed.post.<utility>()" instead of
|
|
114
298
|
// "app.bsky.feed.post.main.<utility>()". Because those utilities could
|
|
115
299
|
// conflict with other schemas (e.g. if there is a lexicon definition at
|
|
116
300
|
// "#<utility>"), those exported utilities will be prefixed with "$". In order
|
|
@@ -121,30 +305,65 @@ export abstract class Schema<
|
|
|
121
305
|
// - "app.bsky.feed.post.$parse(...)" // calls a utility function created by "lex build"
|
|
122
306
|
// - "app.bsky.feed.defs.postView.$parse(...)" // uses the alias defined below on the schema instance
|
|
123
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Alias for {@link assert} with `$` prefix for namespace compatibility.
|
|
310
|
+
*
|
|
311
|
+
* @see {@link assert}
|
|
312
|
+
*/
|
|
124
313
|
$assert(input: unknown): asserts input is InferInput<this> {
|
|
125
314
|
return this.assert(input)
|
|
126
315
|
}
|
|
127
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Alias for {@link check} with `$` prefix for namespace compatibility.
|
|
319
|
+
*
|
|
320
|
+
* @see {@link check}
|
|
321
|
+
*/
|
|
128
322
|
$check(input: unknown): void {
|
|
129
323
|
return this.check(input)
|
|
130
324
|
}
|
|
131
325
|
|
|
326
|
+
/**
|
|
327
|
+
* Alias for {@link cast} with `$` prefix for namespace compatibility.
|
|
328
|
+
*
|
|
329
|
+
* @see {@link cast}
|
|
330
|
+
*/
|
|
132
331
|
$cast<I>(input: I): I & InferInput<this> {
|
|
133
332
|
return this.cast(input)
|
|
134
333
|
}
|
|
135
334
|
|
|
335
|
+
/**
|
|
336
|
+
* Alias for {@link matches} with `$` prefix for namespace compatibility.
|
|
337
|
+
*
|
|
338
|
+
* @see {@link matches}
|
|
339
|
+
*/
|
|
136
340
|
$matches(input: unknown): input is InferInput<this> {
|
|
137
341
|
return this.matches(input)
|
|
138
342
|
}
|
|
139
343
|
|
|
344
|
+
/**
|
|
345
|
+
* Alias for {@link ifMatches} with `$` prefix for namespace compatibility.
|
|
346
|
+
*
|
|
347
|
+
* @see {@link ifMatches}
|
|
348
|
+
*/
|
|
140
349
|
$ifMatches<I>(input: I): (I & InferInput<this>) | undefined {
|
|
141
350
|
return this.ifMatches(input)
|
|
142
351
|
}
|
|
143
352
|
|
|
353
|
+
/**
|
|
354
|
+
* Alias for {@link parse} with `$` prefix for namespace compatibility.
|
|
355
|
+
*
|
|
356
|
+
* @see {@link parse}
|
|
357
|
+
*/
|
|
144
358
|
$parse(input: unknown, options?: ValidateOptions): InferOutput<this> {
|
|
145
359
|
return this.parse(input, options)
|
|
146
360
|
}
|
|
147
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Alias for {@link safeParse} with `$` prefix for namespace compatibility.
|
|
364
|
+
*
|
|
365
|
+
* @see {@link safeParse}
|
|
366
|
+
*/
|
|
148
367
|
$safeParse(
|
|
149
368
|
input: unknown,
|
|
150
369
|
options?: ValidateOptions,
|
|
@@ -152,10 +371,20 @@ export abstract class Schema<
|
|
|
152
371
|
return this.safeParse(input, options)
|
|
153
372
|
}
|
|
154
373
|
|
|
374
|
+
/**
|
|
375
|
+
* Alias for {@link validate} with `$` prefix for namespace compatibility.
|
|
376
|
+
*
|
|
377
|
+
* @see {@link validate}
|
|
378
|
+
*/
|
|
155
379
|
$validate<I>(input: I, options?: ValidateOptions): I & InferInput<this> {
|
|
156
380
|
return this.validate(input, options)
|
|
157
381
|
}
|
|
158
382
|
|
|
383
|
+
/**
|
|
384
|
+
* Alias for {@link safeValidate} with `$` prefix for namespace compatibility.
|
|
385
|
+
*
|
|
386
|
+
* @see {@link safeValidate}
|
|
387
|
+
*/
|
|
159
388
|
$safeValidate<I>(
|
|
160
389
|
input: I,
|
|
161
390
|
options?: ValidateOptions,
|