@atproto/lex-schema 0.0.11 → 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 +19 -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 +60 -0
- 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 +9 -24
- package/dist/helpers.d.ts.map +1 -1
- 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 +90 -10
- 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 +3 -3
- 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 +9 -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 +125 -19
- 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
|
@@ -1,10 +1,53 @@
|
|
|
1
1
|
import { LexError } from '@atproto/lex-data';
|
|
2
2
|
import { ResultFailure } from './result.js';
|
|
3
3
|
import { Issue } from './validation-issue.js';
|
|
4
|
+
/**
|
|
5
|
+
* Error thrown when validation fails.
|
|
6
|
+
*
|
|
7
|
+
* Contains detailed information about all validation issues encountered,
|
|
8
|
+
* including the path to each invalid value and descriptions of what was
|
|
9
|
+
* expected vs what was received.
|
|
10
|
+
*
|
|
11
|
+
* Extends {@link LexError} with the error name "InvalidRequest" for
|
|
12
|
+
* consistency with the AT Protocol error handling conventions.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const error = new ValidationError([
|
|
17
|
+
* new IssueInvalidType(['user', 'age'], 'hello', ['number'])
|
|
18
|
+
* ])
|
|
19
|
+
* console.log(error.message)
|
|
20
|
+
* // "Expected number value type at $.user.age (got string)"
|
|
21
|
+
*
|
|
22
|
+
* console.log(error.issues.length) // 1
|
|
23
|
+
* console.log(error.toJSON())
|
|
24
|
+
* // { error: 'InvalidRequest', message: '...', issues: [...] }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
4
27
|
export declare class ValidationError extends LexError {
|
|
5
28
|
name: string;
|
|
29
|
+
/**
|
|
30
|
+
* The list of validation issues that caused this error.
|
|
31
|
+
*
|
|
32
|
+
* Issues are aggregated when possible (e.g., multiple invalid type issues
|
|
33
|
+
* at the same path are combined into a single issue listing all expected types).
|
|
34
|
+
*/
|
|
6
35
|
readonly issues: Issue[];
|
|
36
|
+
/**
|
|
37
|
+
* Creates a new validation error from a list of issues.
|
|
38
|
+
*
|
|
39
|
+
* Issues are automatically aggregated to combine related issues at the same
|
|
40
|
+
* path (e.g., multiple type expectations from a union schema).
|
|
41
|
+
*
|
|
42
|
+
* @param issues - The validation issues that caused this error
|
|
43
|
+
* @param options - Standard Error options (e.g., `cause`)
|
|
44
|
+
*/
|
|
7
45
|
constructor(issues: Issue[], options?: ErrorOptions);
|
|
46
|
+
/**
|
|
47
|
+
* Converts the error to a JSON-serializable object.
|
|
48
|
+
*
|
|
49
|
+
* @returns An object containing the error details and all issues in JSON format
|
|
50
|
+
*/
|
|
8
51
|
toJSON(): {
|
|
9
52
|
issues: {
|
|
10
53
|
code: string;
|
|
@@ -14,6 +57,23 @@ export declare class ValidationError extends LexError {
|
|
|
14
57
|
error: import("@atproto/lex-data").LexErrorCode;
|
|
15
58
|
message?: string;
|
|
16
59
|
};
|
|
60
|
+
/**
|
|
61
|
+
* Creates a validation error by combining multiple validation failures.
|
|
62
|
+
*
|
|
63
|
+
* This is useful when validating against multiple possible schemas (e.g., unions)
|
|
64
|
+
* and all branches fail. The resulting error contains issues from all failures.
|
|
65
|
+
*
|
|
66
|
+
* @param failures - The validation failures to combine
|
|
67
|
+
* @returns A single validation error containing all issues from the failures
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const failures = schemas.map(s => s.safeValidate(data)).filter(r => !r.success)
|
|
72
|
+
* if (failures.length === schemas.length) {
|
|
73
|
+
* throw ValidationError.fromFailures(failures)
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
17
77
|
static fromFailures(failures: ResultFailure<ValidationError>[]): ValidationError;
|
|
18
78
|
}
|
|
19
79
|
//# sourceMappingURL=validation-error.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-error.d.ts","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,EAAE,aAAa,EAAiB,MAAM,aAAa,CAAA;AAC1D,OAAO,EACL,KAAK,EAGN,MAAM,uBAAuB,CAAA;AAE9B,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C,IAAI,SAAoB;IAExB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"validation-error.d.ts","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,EAAE,aAAa,EAAiB,MAAM,aAAa,CAAA;AAC1D,OAAO,EACL,KAAK,EAGN,MAAM,uBAAuB,CAAA;AAE9B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C,IAAI,SAAoB;IAExB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAA;IAExB;;;;;;;;OAQG;gBACS,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY;IAMnD;;;;OAIG;IACH,MAAM;;;;;;;;;IAON;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,YAAY,CACjB,QAAQ,EAAE,aAAa,CAAC,eAAe,CAAC,EAAE,GACzC,eAAe;CAQnB"}
|
|
@@ -5,20 +5,80 @@ const lex_data_1 = require("@atproto/lex-data");
|
|
|
5
5
|
const array_agg_js_1 = require("../util/array-agg.js");
|
|
6
6
|
const result_js_1 = require("./result.js");
|
|
7
7
|
const validation_issue_js_1 = require("./validation-issue.js");
|
|
8
|
+
/**
|
|
9
|
+
* Error thrown when validation fails.
|
|
10
|
+
*
|
|
11
|
+
* Contains detailed information about all validation issues encountered,
|
|
12
|
+
* including the path to each invalid value and descriptions of what was
|
|
13
|
+
* expected vs what was received.
|
|
14
|
+
*
|
|
15
|
+
* Extends {@link LexError} with the error name "InvalidRequest" for
|
|
16
|
+
* consistency with the AT Protocol error handling conventions.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const error = new ValidationError([
|
|
21
|
+
* new IssueInvalidType(['user', 'age'], 'hello', ['number'])
|
|
22
|
+
* ])
|
|
23
|
+
* console.log(error.message)
|
|
24
|
+
* // "Expected number value type at $.user.age (got string)"
|
|
25
|
+
*
|
|
26
|
+
* console.log(error.issues.length) // 1
|
|
27
|
+
* console.log(error.toJSON())
|
|
28
|
+
* // { error: 'InvalidRequest', message: '...', issues: [...] }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
8
31
|
class ValidationError extends lex_data_1.LexError {
|
|
9
32
|
name = 'ValidationError';
|
|
33
|
+
/**
|
|
34
|
+
* The list of validation issues that caused this error.
|
|
35
|
+
*
|
|
36
|
+
* Issues are aggregated when possible (e.g., multiple invalid type issues
|
|
37
|
+
* at the same path are combined into a single issue listing all expected types).
|
|
38
|
+
*/
|
|
10
39
|
issues;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new validation error from a list of issues.
|
|
42
|
+
*
|
|
43
|
+
* Issues are automatically aggregated to combine related issues at the same
|
|
44
|
+
* path (e.g., multiple type expectations from a union schema).
|
|
45
|
+
*
|
|
46
|
+
* @param issues - The validation issues that caused this error
|
|
47
|
+
* @param options - Standard Error options (e.g., `cause`)
|
|
48
|
+
*/
|
|
11
49
|
constructor(issues, options) {
|
|
12
50
|
const issuesAgg = aggregateIssues(issues);
|
|
13
51
|
super('InvalidRequest', issuesAgg.join(', '), options);
|
|
14
52
|
this.issues = issuesAgg;
|
|
15
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Converts the error to a JSON-serializable object.
|
|
56
|
+
*
|
|
57
|
+
* @returns An object containing the error details and all issues in JSON format
|
|
58
|
+
*/
|
|
16
59
|
toJSON() {
|
|
17
60
|
return {
|
|
18
61
|
...super.toJSON(),
|
|
19
62
|
issues: this.issues.map((issue) => issue.toJSON()),
|
|
20
63
|
};
|
|
21
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Creates a validation error by combining multiple validation failures.
|
|
67
|
+
*
|
|
68
|
+
* This is useful when validating against multiple possible schemas (e.g., unions)
|
|
69
|
+
* and all branches fail. The resulting error contains issues from all failures.
|
|
70
|
+
*
|
|
71
|
+
* @param failures - The validation failures to combine
|
|
72
|
+
* @returns A single validation error containing all issues from the failures
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const failures = schemas.map(s => s.safeValidate(data)).filter(r => !r.success)
|
|
77
|
+
* if (failures.length === schemas.length) {
|
|
78
|
+
* throw ValidationError.fromFailures(failures)
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
22
82
|
static fromFailures(failures) {
|
|
23
83
|
if (failures.length === 1)
|
|
24
84
|
return (0, result_js_1.failureReason)(failures[0]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-error.js","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":";;;AAAA,gDAA4C;AAC5C,uDAA+C;AAC/C,2CAA0D;AAC1D,+DAI8B;AAE9B,MAAa,eAAgB,SAAQ,mBAAQ;IAC3C,IAAI,GAAG,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"validation-error.js","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":";;;AAAA,gDAA4C;AAC5C,uDAA+C;AAC/C,2CAA0D;AAC1D,+DAI8B;AAE9B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAa,eAAgB,SAAQ,mBAAQ;IAC3C,IAAI,GAAG,iBAAiB,CAAA;IAExB;;;;;OAKG;IACM,MAAM,CAAS;IAExB;;;;;;;;OAQG;IACH,YAAY,MAAe,EAAE,OAAsB;QACjD,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;QACzC,KAAK,CAAC,gBAAgB,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;QACtD,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;IACzB,CAAC;IAED;;;;OAIG;IACH,MAAM;QACJ,OAAO;YACL,GAAG,KAAK,CAAC,MAAM,EAAE;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;SACnD,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,YAAY,CACjB,QAA0C;QAE1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAA,yBAAa,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5D,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;QACrD,OAAO,IAAI,eAAe,CAAC,MAAM,EAAE;YACjC,8CAA8C;YAC9C,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,yBAAa,CAAC;SACnC,CAAC,CAAA;IACJ,CAAC;CACF;AAjED,0CAiEC;AAED,SAAS,oBAAoB,CAAC,MAAsC;IAClE,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAA;AAC7B,CAAC;AAED,SAAS,eAAe,CAAC,MAAe;IACtC,8BAA8B;IAC9B,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAA;IACrC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI;QAAE,OAAO,MAAM,CAAA;IAE3E,OAAO;QACL,8CAA8C;QAC9C,GAAG,IAAA,uBAAQ,EACT,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,YAAY,sCAAgB,CAAC,EAC3D,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAC9C,CAAC,MAAM,EAAE,EAAE,CACT,IAAI,sCAAgB,CAClB,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EACd,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,EACf,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC3D,CACJ;QACD,+CAA+C;QAC/C,GAAG,IAAA,uBAAQ,EACT,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,YAAY,uCAAiB,CAAC,EAC5D,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAC9C,CAAC,MAAM,EAAE,EAAE,CACT,IAAI,uCAAiB,CACnB,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EACd,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,EACf,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CACzD,CACJ;QACD,4BAA4B;QAC5B,GAAG,MAAM,CAAC,MAAM,CACd,CAAC,KAAK,EAAE,EAAE,CACR,CAAC,CAAC,KAAK,YAAY,sCAAgB,CAAC;YACpC,CAAC,CAAC,KAAK,YAAY,uCAAiB,CAAC,CACxC;KACF,CAAA;AACH,CAAC;AAED,wBAAwB;AACxB,SAAS,oBAAoB,CAC3B,CAAyB,EACzB,CAAyB;IAEzB,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAA;IACjC,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { LexError } from '@atproto/lex-data'\nimport { arrayAgg } from '../util/array-agg.js'\nimport { ResultFailure, failureReason } from './result.js'\nimport {\n Issue,\n IssueInvalidType,\n IssueInvalidValue,\n} from './validation-issue.js'\n\n/**\n * Error thrown when validation fails.\n *\n * Contains detailed information about all validation issues encountered,\n * including the path to each invalid value and descriptions of what was\n * expected vs what was received.\n *\n * Extends {@link LexError} with the error name \"InvalidRequest\" for\n * consistency with the AT Protocol error handling conventions.\n *\n * @example\n * ```typescript\n * const error = new ValidationError([\n * new IssueInvalidType(['user', 'age'], 'hello', ['number'])\n * ])\n * console.log(error.message)\n * // \"Expected number value type at $.user.age (got string)\"\n *\n * console.log(error.issues.length) // 1\n * console.log(error.toJSON())\n * // { error: 'InvalidRequest', message: '...', issues: [...] }\n * ```\n */\nexport class ValidationError extends LexError {\n name = 'ValidationError'\n\n /**\n * The list of validation issues that caused this error.\n *\n * Issues are aggregated when possible (e.g., multiple invalid type issues\n * at the same path are combined into a single issue listing all expected types).\n */\n readonly issues: Issue[]\n\n /**\n * Creates a new validation error from a list of issues.\n *\n * Issues are automatically aggregated to combine related issues at the same\n * path (e.g., multiple type expectations from a union schema).\n *\n * @param issues - The validation issues that caused this error\n * @param options - Standard Error options (e.g., `cause`)\n */\n constructor(issues: Issue[], options?: ErrorOptions) {\n const issuesAgg = aggregateIssues(issues)\n super('InvalidRequest', issuesAgg.join(', '), options)\n this.issues = issuesAgg\n }\n\n /**\n * Converts the error to a JSON-serializable object.\n *\n * @returns An object containing the error details and all issues in JSON format\n */\n toJSON() {\n return {\n ...super.toJSON(),\n issues: this.issues.map((issue) => issue.toJSON()),\n }\n }\n\n /**\n * Creates a validation error by combining multiple validation failures.\n *\n * This is useful when validating against multiple possible schemas (e.g., unions)\n * and all branches fail. The resulting error contains issues from all failures.\n *\n * @param failures - The validation failures to combine\n * @returns A single validation error containing all issues from the failures\n *\n * @example\n * ```typescript\n * const failures = schemas.map(s => s.safeValidate(data)).filter(r => !r.success)\n * if (failures.length === schemas.length) {\n * throw ValidationError.fromFailures(failures)\n * }\n * ```\n */\n static fromFailures(\n failures: ResultFailure<ValidationError>[],\n ): ValidationError {\n if (failures.length === 1) return failureReason(failures[0])\n const issues = failures.flatMap(extractFailureIssues)\n return new ValidationError(issues, {\n // Keep the original errors as the cause chain\n cause: failures.map(failureReason),\n })\n }\n}\n\nfunction extractFailureIssues(result: ResultFailure<ValidationError>) {\n return result.reason.issues\n}\n\nfunction aggregateIssues(issues: Issue[]): Issue[] {\n // Quick path for common cases\n if (issues.length <= 1) return issues\n if (issues.length === 2 && issues[0].code !== issues[1].code) return issues\n\n return [\n // Aggregate invalid_type with identical paths\n ...arrayAgg(\n issues.filter((issue) => issue instanceof IssueInvalidType),\n (a, b) => comparePropertyPaths(a.path, b.path),\n (issues) =>\n new IssueInvalidType(\n issues[0].path,\n issues[0].input,\n Array.from(new Set(issues.flatMap((iss) => iss.expected))),\n ),\n ),\n // Aggregate invalid_value with identical paths\n ...arrayAgg(\n issues.filter((issue) => issue instanceof IssueInvalidValue),\n (a, b) => comparePropertyPaths(a.path, b.path),\n (issues) =>\n new IssueInvalidValue(\n issues[0].path,\n issues[0].input,\n Array.from(new Set(issues.flatMap((iss) => iss.values))),\n ),\n ),\n // Pass through other issues\n ...issues.filter(\n (issue) =>\n !(issue instanceof IssueInvalidType) &&\n !(issue instanceof IssueInvalidValue),\n ),\n ]\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction comparePropertyPaths(\n a: readonly PropertyKey[],\n b: readonly PropertyKey[],\n) {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false\n }\n return true\n}\n"]}
|
|
@@ -1,16 +1,40 @@
|
|
|
1
1
|
import { PropertyKey } from './property-key.js';
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base class for all validation issues.
|
|
4
|
+
*
|
|
5
|
+
* An issue represents a single validation failure, containing:
|
|
6
|
+
* - A code identifying the type of issue
|
|
7
|
+
* - The path to the invalid value in the data structure
|
|
8
|
+
* - The actual input value that failed validation
|
|
9
|
+
*
|
|
10
|
+
* Subclasses add specific properties relevant to each issue type and
|
|
11
|
+
* implement the {@link toString} method for human-readable error messages.
|
|
12
|
+
*/
|
|
2
13
|
export declare abstract class Issue {
|
|
3
14
|
readonly code: string;
|
|
4
15
|
readonly path: readonly PropertyKey[];
|
|
5
16
|
readonly input: unknown;
|
|
6
17
|
constructor(code: string, path: readonly PropertyKey[], input: unknown);
|
|
18
|
+
/**
|
|
19
|
+
* Returns a human-readable description of the validation issue.
|
|
20
|
+
*/
|
|
7
21
|
abstract toString(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Converts the issue to a JSON-serializable object.
|
|
24
|
+
*
|
|
25
|
+
* @returns An object containing the issue code, path, and message
|
|
26
|
+
*/
|
|
8
27
|
toJSON(): {
|
|
9
28
|
code: string;
|
|
10
29
|
path: readonly PropertyKey[];
|
|
11
30
|
message: string;
|
|
12
31
|
};
|
|
13
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* A custom validation issue with a user-defined message.
|
|
35
|
+
*
|
|
36
|
+
* Use this for validation rules that don't fit into the standard issue categories.
|
|
37
|
+
*/
|
|
14
38
|
export declare class IssueCustom extends Issue {
|
|
15
39
|
readonly path: readonly PropertyKey[];
|
|
16
40
|
readonly input: unknown;
|
|
@@ -18,6 +42,11 @@ export declare class IssueCustom extends Issue {
|
|
|
18
42
|
constructor(path: readonly PropertyKey[], input: unknown, message: string);
|
|
19
43
|
toString(): string;
|
|
20
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Issue for string values that don't match an expected format.
|
|
47
|
+
*
|
|
48
|
+
* Used for AT Protocol specific formats like DID, handle, NSID, AT-URI, etc.
|
|
49
|
+
*/
|
|
21
50
|
export declare class IssueInvalidFormat extends Issue {
|
|
22
51
|
readonly format: string;
|
|
23
52
|
readonly message?: string | undefined;
|
|
@@ -29,8 +58,15 @@ export declare class IssueInvalidFormat extends Issue {
|
|
|
29
58
|
path: readonly PropertyKey[];
|
|
30
59
|
message: string;
|
|
31
60
|
};
|
|
61
|
+
/** Returns a human-readable description of the expected format. */
|
|
32
62
|
get formatDescription(): string;
|
|
33
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Issue for values that have an unexpected type.
|
|
66
|
+
*
|
|
67
|
+
* This is one of the most common validation issues, occurring when the
|
|
68
|
+
* runtime type of a value doesn't match the expected schema type.
|
|
69
|
+
*/
|
|
34
70
|
export declare class IssueInvalidType extends Issue {
|
|
35
71
|
readonly expected: readonly string[];
|
|
36
72
|
constructor(path: readonly PropertyKey[], input: unknown, expected: readonly string[]);
|
|
@@ -42,6 +78,12 @@ export declare class IssueInvalidType extends Issue {
|
|
|
42
78
|
message: string;
|
|
43
79
|
};
|
|
44
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Issue for values that don't match any of the expected literal values.
|
|
83
|
+
*
|
|
84
|
+
* Used when a value must be one of a specific set of allowed values
|
|
85
|
+
* (e.g., enum-like constraints).
|
|
86
|
+
*/
|
|
45
87
|
export declare class IssueInvalidValue extends Issue {
|
|
46
88
|
readonly values: readonly unknown[];
|
|
47
89
|
constructor(path: readonly PropertyKey[], input: unknown, values: readonly unknown[]);
|
|
@@ -53,6 +95,9 @@ export declare class IssueInvalidValue extends Issue {
|
|
|
53
95
|
message: string;
|
|
54
96
|
};
|
|
55
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Issue for missing required object properties.
|
|
100
|
+
*/
|
|
56
101
|
export declare class IssueRequiredKey extends Issue {
|
|
57
102
|
readonly key: PropertyKey;
|
|
58
103
|
constructor(path: readonly PropertyKey[], input: unknown, key: PropertyKey);
|
|
@@ -64,7 +109,20 @@ export declare class IssueRequiredKey extends Issue {
|
|
|
64
109
|
message: string;
|
|
65
110
|
};
|
|
66
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* The type of measurement for size constraint issues.
|
|
114
|
+
*
|
|
115
|
+
* - `'array'` - Array length
|
|
116
|
+
* - `'string'` - String length in characters
|
|
117
|
+
* - `'integer'` - Numeric value
|
|
118
|
+
* - `'grapheme'` - String length in grapheme clusters
|
|
119
|
+
* - `'bytes'` - Byte length
|
|
120
|
+
* - `'blob'` - Blob size
|
|
121
|
+
*/
|
|
67
122
|
export type MeasurableType = 'array' | 'string' | 'integer' | 'grapheme' | 'bytes' | 'blob';
|
|
123
|
+
/**
|
|
124
|
+
* Issue for values that exceed a maximum constraint.
|
|
125
|
+
*/
|
|
68
126
|
export declare class IssueTooBig extends Issue {
|
|
69
127
|
readonly maximum: number;
|
|
70
128
|
readonly type: MeasurableType;
|
|
@@ -79,6 +137,9 @@ export declare class IssueTooBig extends Issue {
|
|
|
79
137
|
message: string;
|
|
80
138
|
};
|
|
81
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Issue for values that are below a minimum constraint.
|
|
142
|
+
*/
|
|
82
143
|
export declare class IssueTooSmall extends Issue {
|
|
83
144
|
readonly minimum: number;
|
|
84
145
|
readonly type: MeasurableType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-issue.d.ts","sourceRoot":"","sources":["../../src/core/validation-issue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,8BAAsB,KAAK;IAEvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE;IACrC,QAAQ,CAAC,KAAK,EAAE,OAAO;gBAFd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,OAAO;IAGzB,QAAQ,CAAC,QAAQ,IAAI,MAAM;IAE3B,MAAM;;;;;CAOP;AAED,qBAAa,WAAY,SAAQ,KAAK;IAElC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE;IACrC,QAAQ,CAAC,KAAK,EAAE,OAAO;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAFf,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM;IAK1B,QAAQ;CAGT;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAIzC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM;gBAHzB,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,OAAO,EACL,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,YAAA;IAK3B,QAAQ;IAIR,MAAM;;;;;;IAON,IAAI,iBAAiB,IAAI,MAAM,CAiB9B;CACF;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IAIvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE;gBAFpC,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,OAAO,EACL,QAAQ,EAAE,SAAS,MAAM,EAAE;IAKtC,QAAQ;IAIR,MAAM;;;;;;CAMP;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAIxC,QAAQ,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE;gBAFnC,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,OAAO,EACL,MAAM,EAAE,SAAS,OAAO,EAAE;IAKrC,QAAQ;IAIR,MAAM;;;;;;CAMP;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IAIvC,QAAQ,CAAC,GAAG,EAAE,WAAW;gBAFzB,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,OAAO,EACL,GAAG,EAAE,WAAW;IAK3B,QAAQ;IAIR,MAAM;;;;;;CAMP;AAED,MAAM,MAAM,cAAc,GACtB,OAAO,GACP,QAAQ,GACR,SAAS,GACT,UAAU,GACV,OAAO,GACP,MAAM,CAAA;AAEV,qBAAa,WAAY,SAAQ,KAAK;IAIlC,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,QAAQ,CAAC,IAAI,EAAE,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAJvB,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,OAAO,EACL,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM;IAKzB,QAAQ;IAIR,MAAM;;;;;;;CAOP;AAED,qBAAa,aAAc,SAAQ,KAAK;IAIpC,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,QAAQ,CAAC,IAAI,EAAE,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAJvB,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,OAAO,EACL,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM;IAKzB,QAAQ;IAIR,MAAM;;;;;;;CAOP"}
|
|
1
|
+
{"version":3,"file":"validation-issue.d.ts","sourceRoot":"","sources":["../../src/core/validation-issue.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.IssueTooSmall = exports.IssueTooBig = exports.IssueRequiredKey = exports.IssueInvalidValue = exports.IssueInvalidType = exports.IssueInvalidFormat = exports.IssueCustom = exports.Issue = void 0;
|
|
4
4
|
const lex_data_1 = require("@atproto/lex-data");
|
|
5
|
+
/**
|
|
6
|
+
* Abstract base class for all validation issues.
|
|
7
|
+
*
|
|
8
|
+
* An issue represents a single validation failure, containing:
|
|
9
|
+
* - A code identifying the type of issue
|
|
10
|
+
* - The path to the invalid value in the data structure
|
|
11
|
+
* - The actual input value that failed validation
|
|
12
|
+
*
|
|
13
|
+
* Subclasses add specific properties relevant to each issue type and
|
|
14
|
+
* implement the {@link toString} method for human-readable error messages.
|
|
15
|
+
*/
|
|
5
16
|
class Issue {
|
|
6
17
|
code;
|
|
7
18
|
path;
|
|
@@ -11,6 +22,11 @@ class Issue {
|
|
|
11
22
|
this.path = path;
|
|
12
23
|
this.input = input;
|
|
13
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Converts the issue to a JSON-serializable object.
|
|
27
|
+
*
|
|
28
|
+
* @returns An object containing the issue code, path, and message
|
|
29
|
+
*/
|
|
14
30
|
toJSON() {
|
|
15
31
|
return {
|
|
16
32
|
code: this.code,
|
|
@@ -20,6 +36,11 @@ class Issue {
|
|
|
20
36
|
}
|
|
21
37
|
}
|
|
22
38
|
exports.Issue = Issue;
|
|
39
|
+
/**
|
|
40
|
+
* A custom validation issue with a user-defined message.
|
|
41
|
+
*
|
|
42
|
+
* Use this for validation rules that don't fit into the standard issue categories.
|
|
43
|
+
*/
|
|
23
44
|
class IssueCustom extends Issue {
|
|
24
45
|
path;
|
|
25
46
|
input;
|
|
@@ -35,6 +56,11 @@ class IssueCustom extends Issue {
|
|
|
35
56
|
}
|
|
36
57
|
}
|
|
37
58
|
exports.IssueCustom = IssueCustom;
|
|
59
|
+
/**
|
|
60
|
+
* Issue for string values that don't match an expected format.
|
|
61
|
+
*
|
|
62
|
+
* Used for AT Protocol specific formats like DID, handle, NSID, AT-URI, etc.
|
|
63
|
+
*/
|
|
38
64
|
class IssueInvalidFormat extends Issue {
|
|
39
65
|
format;
|
|
40
66
|
message;
|
|
@@ -52,6 +78,7 @@ class IssueInvalidFormat extends Issue {
|
|
|
52
78
|
format: this.format,
|
|
53
79
|
};
|
|
54
80
|
}
|
|
81
|
+
/** Returns a human-readable description of the expected format. */
|
|
55
82
|
get formatDescription() {
|
|
56
83
|
switch (this.format) {
|
|
57
84
|
case 'at-identifier':
|
|
@@ -72,6 +99,12 @@ class IssueInvalidFormat extends Issue {
|
|
|
72
99
|
}
|
|
73
100
|
}
|
|
74
101
|
exports.IssueInvalidFormat = IssueInvalidFormat;
|
|
102
|
+
/**
|
|
103
|
+
* Issue for values that have an unexpected type.
|
|
104
|
+
*
|
|
105
|
+
* This is one of the most common validation issues, occurring when the
|
|
106
|
+
* runtime type of a value doesn't match the expected schema type.
|
|
107
|
+
*/
|
|
75
108
|
class IssueInvalidType extends Issue {
|
|
76
109
|
expected;
|
|
77
110
|
constructor(path, input, expected) {
|
|
@@ -89,6 +122,12 @@ class IssueInvalidType extends Issue {
|
|
|
89
122
|
}
|
|
90
123
|
}
|
|
91
124
|
exports.IssueInvalidType = IssueInvalidType;
|
|
125
|
+
/**
|
|
126
|
+
* Issue for values that don't match any of the expected literal values.
|
|
127
|
+
*
|
|
128
|
+
* Used when a value must be one of a specific set of allowed values
|
|
129
|
+
* (e.g., enum-like constraints).
|
|
130
|
+
*/
|
|
92
131
|
class IssueInvalidValue extends Issue {
|
|
93
132
|
values;
|
|
94
133
|
constructor(path, input, values) {
|
|
@@ -106,6 +145,9 @@ class IssueInvalidValue extends Issue {
|
|
|
106
145
|
}
|
|
107
146
|
}
|
|
108
147
|
exports.IssueInvalidValue = IssueInvalidValue;
|
|
148
|
+
/**
|
|
149
|
+
* Issue for missing required object properties.
|
|
150
|
+
*/
|
|
109
151
|
class IssueRequiredKey extends Issue {
|
|
110
152
|
key;
|
|
111
153
|
constructor(path, input, key) {
|
|
@@ -123,6 +165,9 @@ class IssueRequiredKey extends Issue {
|
|
|
123
165
|
}
|
|
124
166
|
}
|
|
125
167
|
exports.IssueRequiredKey = IssueRequiredKey;
|
|
168
|
+
/**
|
|
169
|
+
* Issue for values that exceed a maximum constraint.
|
|
170
|
+
*/
|
|
126
171
|
class IssueTooBig extends Issue {
|
|
127
172
|
maximum;
|
|
128
173
|
type;
|
|
@@ -145,6 +190,9 @@ class IssueTooBig extends Issue {
|
|
|
145
190
|
}
|
|
146
191
|
}
|
|
147
192
|
exports.IssueTooBig = IssueTooBig;
|
|
193
|
+
/**
|
|
194
|
+
* Issue for values that are below a minimum constraint.
|
|
195
|
+
*/
|
|
148
196
|
class IssueTooSmall extends Issue {
|
|
149
197
|
minimum;
|
|
150
198
|
type;
|
|
@@ -167,6 +215,9 @@ class IssueTooSmall extends Issue {
|
|
|
167
215
|
}
|
|
168
216
|
}
|
|
169
217
|
exports.IssueTooSmall = IssueTooSmall;
|
|
218
|
+
// -----------------------------------------------------------------------------
|
|
219
|
+
// Helper functions for formatting error messages
|
|
220
|
+
// -----------------------------------------------------------------------------
|
|
170
221
|
function stringifyExpectedType(expected) {
|
|
171
222
|
if (expected === '$typed') {
|
|
172
223
|
return 'an object or record which includes a "$type" property';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-issue.js","sourceRoot":"","sources":["../../src/core/validation-issue.ts"],"names":[],"mappings":"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","sourcesContent":["import { ifCid, isPlainObject } from '@atproto/lex-data'\nimport { PropertyKey } from './property-key.js'\n\nexport abstract class Issue {\n constructor(\n readonly code: string,\n readonly path: readonly PropertyKey[],\n readonly input: unknown,\n ) {}\n\n abstract toString(): string\n\n toJSON() {\n return {\n code: this.code,\n path: this.path,\n message: this.toString(),\n }\n }\n}\n\nexport class IssueCustom extends Issue {\n constructor(\n readonly path: readonly PropertyKey[],\n readonly input: unknown,\n readonly message: string,\n ) {\n super('custom', path, input)\n }\n\n toString() {\n return `${this.message}${stringifyPath(this.path)}`\n }\n}\n\nexport class IssueInvalidFormat extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly format: string,\n readonly message?: string,\n ) {\n super('invalid_format', path, input)\n }\n\n toString() {\n return `Invalid ${this.formatDescription}${this.message ? ` (${this.message})` : ''}${stringifyPath(this.path)} (got ${stringifyValue(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n format: this.format,\n }\n }\n\n get formatDescription(): string {\n switch (this.format) {\n case 'at-identifier':\n return `AT identifier`\n case 'did':\n return `DID`\n case 'nsid':\n return `NSID`\n case 'cid':\n return `CID string`\n case 'tid':\n return `TID string`\n case 'record-key':\n return `record key`\n default:\n return this.format\n }\n }\n}\n\nexport class IssueInvalidType extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly expected: readonly string[],\n ) {\n super('invalid_type', path, input)\n }\n\n toString() {\n return `Expected ${oneOf(this.expected.map(stringifyExpectedType))} value type${stringifyPath(this.path)} (got ${stringifyType(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n expected: this.expected,\n }\n }\n}\n\nexport class IssueInvalidValue extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly values: readonly unknown[],\n ) {\n super('invalid_value', path, input)\n }\n\n toString() {\n return `Expected ${oneOf(this.values.map(stringifyValue))}${stringifyPath(this.path)} (got ${stringifyValue(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n values: this.values,\n }\n }\n}\n\nexport class IssueRequiredKey extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly key: PropertyKey,\n ) {\n super('required_key', path, input)\n }\n\n toString() {\n return `Missing required key \"${String(this.key)}\"${stringifyPath(this.path)}`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n key: this.key,\n }\n }\n}\n\nexport type MeasurableType =\n | 'array'\n | 'string'\n | 'integer'\n | 'grapheme'\n | 'bytes'\n | 'blob'\n\nexport class IssueTooBig extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly maximum: number,\n readonly type: MeasurableType,\n readonly actual: number,\n ) {\n super('too_big', path, input)\n }\n\n toString() {\n return `${this.type} too big (maximum ${this.maximum})${stringifyPath(this.path)} (got ${this.actual})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n type: this.type,\n maximum: this.maximum,\n }\n }\n}\n\nexport class IssueTooSmall extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly minimum: number,\n readonly type: MeasurableType,\n readonly actual: number,\n ) {\n super('too_small', path, input)\n }\n\n toString() {\n return `${this.type} too small (minimum ${this.minimum})${stringifyPath(this.path)} (got ${this.actual})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n type: this.type,\n minimum: this.minimum,\n }\n }\n}\n\nfunction stringifyExpectedType(expected: string): string {\n if (expected === '$typed') {\n return 'an object or record which includes a \"$type\" property'\n }\n return expected\n}\n\nfunction stringifyPath(path: readonly PropertyKey[]) {\n return ` at ${buildJsonPath(path)}`\n}\n\nfunction buildJsonPath(path: readonly PropertyKey[]): string {\n return `$${path.map(toJsonPathSegment).join('')}`\n}\n\nfunction toJsonPathSegment(segment: PropertyKey): string {\n if (typeof segment === 'number') {\n return `[${segment}]`\n } else if (/^[a-zA-Z_$][a-zA-Z0-9_]*$/.test(segment as string)) {\n return `.${segment}`\n } else {\n return `[${JSON.stringify(segment)}]`\n }\n}\n\nfunction oneOf(arr: readonly string[]): string {\n if (arr.length === 0) return ''\n if (arr.length === 1) return arr[0]\n return `one of ${arr.slice(0, -1).join(', ')} or ${arr.at(-1)}`\n}\n\nfunction stringifyType(value: unknown): string {\n switch (typeof value) {\n case 'object':\n if (value === null) return 'null'\n if (Array.isArray(value)) return 'array'\n if (ifCid(value)) return 'cid'\n if (value instanceof Date) return 'date'\n if (value instanceof RegExp) return 'regexp'\n if (value instanceof Map) return 'map'\n if (value instanceof Set) return 'set'\n return 'object'\n case 'number':\n if (Number.isInteger(value) && Number.isSafeInteger(value)) {\n return 'integer'\n }\n if (Number.isNaN(value)) {\n return 'NaN'\n }\n if (value === Infinity) {\n return 'Infinity'\n }\n if (value === -Infinity) {\n return '-Infinity'\n }\n return 'float'\n default:\n return typeof value\n }\n}\n\nfunction stringifyValue(value: unknown): string {\n switch (typeof value) {\n case 'bigint':\n return `${value}n`\n case 'number':\n case 'string':\n case 'boolean':\n return JSON.stringify(value)\n case 'object':\n if (Array.isArray(value)) {\n return `[${stringifyArray(value, stringifyValue)}]`\n }\n if (isPlainObject(value)) {\n return `{${stringifyArray(Object.entries(value), stringifyObjectEntry)}}`\n }\n // fallthrough\n default:\n return stringifyType(value)\n }\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringifyObjectEntry([key, _value]: [PropertyKey, unknown]): string {\n return `${JSON.stringify(key)}: ...`\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringifyArray<T>(\n arr: readonly T[],\n fn: (item: T) => string,\n n = 2,\n): string {\n return arr.slice(0, n).map(fn).join(', ') + (arr.length > n ? ', ...' : '')\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validation-issue.js","sourceRoot":"","sources":["../../src/core/validation-issue.ts"],"names":[],"mappings":";;;AAAA,gDAAwD;AAGxD;;;;;;;;;;GAUG;AACH,MAAsB,KAAK;IAEd;IACA;IACA;IAHX,YACW,IAAY,EACZ,IAA4B,EAC5B,KAAc;QAFd,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAwB;QAC5B,UAAK,GAAL,KAAK,CAAS;IACtB,CAAC;IAOJ;;;;OAIG;IACH,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE;SACzB,CAAA;IACH,CAAC;CACF;AAxBD,sBAwBC;AAED;;;;GAIG;AACH,MAAa,WAAY,SAAQ,KAAK;IAEzB;IACA;IACA;IAHX,YACW,IAA4B,EAC5B,KAAc,EACd,OAAe;QAExB,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAJnB,SAAI,GAAJ,IAAI,CAAwB;QAC5B,UAAK,GAAL,KAAK,CAAS;QACd,YAAO,GAAP,OAAO,CAAQ;IAG1B,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;IACrD,CAAC;CACF;AAZD,kCAYC;AAED;;;;GAIG;AACH,MAAa,kBAAmB,SAAQ,KAAK;IAIhC;IACA;IAJX,YACE,IAA4B,EAC5B,KAAc,EACL,MAAc,EACd,OAAgB;QAEzB,KAAK,CAAC,gBAAgB,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAH3B,WAAM,GAAN,MAAM,CAAQ;QACd,YAAO,GAAP,OAAO,CAAS;IAG3B,CAAC;IAED,QAAQ;QACN,OAAO,WAAW,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAA;IACtJ,CAAC;IAED,MAAM;QACJ,OAAO;YACL,GAAG,KAAK,CAAC,MAAM,EAAE;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAA;IACH,CAAC;IAED,mEAAmE;IACnE,IAAI,iBAAiB;QACnB,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,KAAK,eAAe;gBAClB,OAAO,eAAe,CAAA;YACxB,KAAK,KAAK;gBACR,OAAO,KAAK,CAAA;YACd,KAAK,MAAM;gBACT,OAAO,MAAM,CAAA;YACf,KAAK,KAAK;gBACR,OAAO,YAAY,CAAA;YACrB,KAAK,KAAK;gBACR,OAAO,YAAY,CAAA;YACrB,KAAK,YAAY;gBACf,OAAO,YAAY,CAAA;YACrB;gBACE,OAAO,IAAI,CAAC,MAAM,CAAA;QACtB,CAAC;IACH,CAAC;CACF;AAxCD,gDAwCC;AAED;;;;;GAKG;AACH,MAAa,gBAAiB,SAAQ,KAAK;IAI9B;IAHX,YACE,IAA4B,EAC5B,KAAc,EACL,QAA2B;QAEpC,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAFzB,aAAQ,GAAR,QAAQ,CAAmB;IAGtC,CAAC;IAED,QAAQ;QACN,OAAO,YAAY,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,cAAc,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAA;IAC/I,CAAC;IAED,MAAM;QACJ,OAAO;YACL,GAAG,KAAK,CAAC,MAAM,EAAE;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAA;IACH,CAAC;CACF;AAnBD,4CAmBC;AAED;;;;;GAKG;AACH,MAAa,iBAAkB,SAAQ,KAAK;IAI/B;IAHX,YACE,IAA4B,EAC5B,KAAc,EACL,MAA0B;QAEnC,KAAK,CAAC,eAAe,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAF1B,WAAM,GAAN,MAAM,CAAoB;IAGrC,CAAC;IAED,QAAQ;QACN,OAAO,YAAY,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAA;IAC5H,CAAC;IAED,MAAM;QACJ,OAAO;YACL,GAAG,KAAK,CAAC,MAAM,EAAE;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAA;IACH,CAAC;CACF;AAnBD,8CAmBC;AAED;;GAEG;AACH,MAAa,gBAAiB,SAAQ,KAAK;IAI9B;IAHX,YACE,IAA4B,EAC5B,KAAc,EACL,GAAgB;QAEzB,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAFzB,QAAG,GAAH,GAAG,CAAa;IAG3B,CAAC;IAED,QAAQ;QACN,OAAO,yBAAyB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;IAChF,CAAC;IAED,MAAM;QACJ,OAAO;YACL,GAAG,KAAK,CAAC,MAAM,EAAE;YACjB,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAA;IACH,CAAC;CACF;AAnBD,4CAmBC;AAoBD;;GAEG;AACH,MAAa,WAAY,SAAQ,KAAK;IAIzB;IACA;IACA;IALX,YACE,IAA4B,EAC5B,KAAc,EACL,OAAe,EACf,IAAoB,EACpB,MAAc;QAEvB,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAJpB,YAAO,GAAP,OAAO,CAAQ;QACf,SAAI,GAAJ,IAAI,CAAgB;QACpB,WAAM,GAAN,MAAM,CAAQ;IAGzB,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,IAAI,qBAAqB,IAAI,CAAC,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,GAAG,CAAA;IACzG,CAAC;IAED,MAAM;QACJ,OAAO;YACL,GAAG,KAAK,CAAC,MAAM,EAAE;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAA;IACH,CAAC;CACF;AAtBD,kCAsBC;AAED;;GAEG;AACH,MAAa,aAAc,SAAQ,KAAK;IAI3B;IACA;IACA;IALX,YACE,IAA4B,EAC5B,KAAc,EACL,OAAe,EACf,IAAoB,EACpB,MAAc;QAEvB,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAJtB,YAAO,GAAP,OAAO,CAAQ;QACf,SAAI,GAAJ,IAAI,CAAgB;QACpB,WAAM,GAAN,MAAM,CAAQ;IAGzB,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,IAAI,uBAAuB,IAAI,CAAC,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,GAAG,CAAA;IAC3G,CAAC;IAED,MAAM;QACJ,OAAO;YACL,GAAG,KAAK,CAAC,MAAM,EAAE;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAA;IACH,CAAC;CACF;AAtBD,sCAsBC;AAED,gFAAgF;AAChF,iDAAiD;AACjD,gFAAgF;AAEhF,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,uDAAuD,CAAA;IAChE,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,IAA4B;IACjD,OAAO,OAAO,aAAa,CAAC,IAAI,CAAC,EAAE,CAAA;AACrC,CAAC;AAED,SAAS,aAAa,CAAC,IAA4B;IACjD,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAA;AACnD,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAoB;IAC7C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,IAAI,OAAO,GAAG,CAAA;IACvB,CAAC;SAAM,IAAI,2BAA2B,CAAC,IAAI,CAAC,OAAiB,CAAC,EAAE,CAAC;QAC/D,OAAO,IAAI,OAAO,EAAE,CAAA;IACtB,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAA;IACvC,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,GAAsB;IACnC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAC/B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;IACnC,OAAO,UAAU,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AACjE,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,MAAM,CAAA;YACjC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO,OAAO,CAAA;YACxC,IAAI,IAAA,gBAAK,EAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;YAC9B,IAAI,KAAK,YAAY,IAAI;gBAAE,OAAO,MAAM,CAAA;YACxC,IAAI,KAAK,YAAY,MAAM;gBAAE,OAAO,QAAQ,CAAA;YAC5C,IAAI,KAAK,YAAY,GAAG;gBAAE,OAAO,KAAK,CAAA;YACtC,IAAI,KAAK,YAAY,GAAG;gBAAE,OAAO,KAAK,CAAA;YACtC,OAAO,QAAQ,CAAA;QACjB,KAAK,QAAQ;YACX,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3D,OAAO,SAAS,CAAA;YAClB,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,KAAK,CAAA;YACd,CAAC;YACD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACvB,OAAO,UAAU,CAAA;YACnB,CAAC;YACD,IAAI,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACxB,OAAO,WAAW,CAAA;YACpB,CAAC;YACD,OAAO,OAAO,CAAA;QAChB;YACE,OAAO,OAAO,KAAK,CAAA;IACvB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,GAAG,KAAK,GAAG,CAAA;QACpB,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS;YACZ,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;QAC9B,KAAK,QAAQ;YACX,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,IAAI,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAA;YACrD,CAAC;YACD,IAAI,IAAA,wBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC,GAAG,CAAA;YAC3E,CAAC;QACH,cAAc;QACd;YACE,OAAO,aAAa,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;AACH,CAAC;AAED,wBAAwB;AACxB,SAAS,oBAAoB,CAAC,CAAC,GAAG,EAAE,MAAM,CAAyB;IACjE,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAA;AACtC,CAAC;AAED,wBAAwB;AACxB,SAAS,cAAc,CACrB,GAAiB,EACjB,EAAuB,EACvB,CAAC,GAAG,CAAC;IAEL,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AAC7E,CAAC","sourcesContent":["import { ifCid, isPlainObject } from '@atproto/lex-data'\nimport { PropertyKey } from './property-key.js'\n\n/**\n * Abstract base class for all validation issues.\n *\n * An issue represents a single validation failure, containing:\n * - A code identifying the type of issue\n * - The path to the invalid value in the data structure\n * - The actual input value that failed validation\n *\n * Subclasses add specific properties relevant to each issue type and\n * implement the {@link toString} method for human-readable error messages.\n */\nexport abstract class Issue {\n constructor(\n readonly code: string,\n readonly path: readonly PropertyKey[],\n readonly input: unknown,\n ) {}\n\n /**\n * Returns a human-readable description of the validation issue.\n */\n abstract toString(): string\n\n /**\n * Converts the issue to a JSON-serializable object.\n *\n * @returns An object containing the issue code, path, and message\n */\n toJSON() {\n return {\n code: this.code,\n path: this.path,\n message: this.toString(),\n }\n }\n}\n\n/**\n * A custom validation issue with a user-defined message.\n *\n * Use this for validation rules that don't fit into the standard issue categories.\n */\nexport class IssueCustom extends Issue {\n constructor(\n readonly path: readonly PropertyKey[],\n readonly input: unknown,\n readonly message: string,\n ) {\n super('custom', path, input)\n }\n\n toString() {\n return `${this.message}${stringifyPath(this.path)}`\n }\n}\n\n/**\n * Issue for string values that don't match an expected format.\n *\n * Used for AT Protocol specific formats like DID, handle, NSID, AT-URI, etc.\n */\nexport class IssueInvalidFormat extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly format: string,\n readonly message?: string,\n ) {\n super('invalid_format', path, input)\n }\n\n toString() {\n return `Invalid ${this.formatDescription}${this.message ? ` (${this.message})` : ''}${stringifyPath(this.path)} (got ${stringifyValue(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n format: this.format,\n }\n }\n\n /** Returns a human-readable description of the expected format. */\n get formatDescription(): string {\n switch (this.format) {\n case 'at-identifier':\n return `AT identifier`\n case 'did':\n return `DID`\n case 'nsid':\n return `NSID`\n case 'cid':\n return `CID string`\n case 'tid':\n return `TID string`\n case 'record-key':\n return `record key`\n default:\n return this.format\n }\n }\n}\n\n/**\n * Issue for values that have an unexpected type.\n *\n * This is one of the most common validation issues, occurring when the\n * runtime type of a value doesn't match the expected schema type.\n */\nexport class IssueInvalidType extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly expected: readonly string[],\n ) {\n super('invalid_type', path, input)\n }\n\n toString() {\n return `Expected ${oneOf(this.expected.map(stringifyExpectedType))} value type${stringifyPath(this.path)} (got ${stringifyType(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n expected: this.expected,\n }\n }\n}\n\n/**\n * Issue for values that don't match any of the expected literal values.\n *\n * Used when a value must be one of a specific set of allowed values\n * (e.g., enum-like constraints).\n */\nexport class IssueInvalidValue extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly values: readonly unknown[],\n ) {\n super('invalid_value', path, input)\n }\n\n toString() {\n return `Expected ${oneOf(this.values.map(stringifyValue))}${stringifyPath(this.path)} (got ${stringifyValue(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n values: this.values,\n }\n }\n}\n\n/**\n * Issue for missing required object properties.\n */\nexport class IssueRequiredKey extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly key: PropertyKey,\n ) {\n super('required_key', path, input)\n }\n\n toString() {\n return `Missing required key \"${String(this.key)}\"${stringifyPath(this.path)}`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n key: this.key,\n }\n }\n}\n\n/**\n * The type of measurement for size constraint issues.\n *\n * - `'array'` - Array length\n * - `'string'` - String length in characters\n * - `'integer'` - Numeric value\n * - `'grapheme'` - String length in grapheme clusters\n * - `'bytes'` - Byte length\n * - `'blob'` - Blob size\n */\nexport type MeasurableType =\n | 'array'\n | 'string'\n | 'integer'\n | 'grapheme'\n | 'bytes'\n | 'blob'\n\n/**\n * Issue for values that exceed a maximum constraint.\n */\nexport class IssueTooBig extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly maximum: number,\n readonly type: MeasurableType,\n readonly actual: number,\n ) {\n super('too_big', path, input)\n }\n\n toString() {\n return `${this.type} too big (maximum ${this.maximum})${stringifyPath(this.path)} (got ${this.actual})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n type: this.type,\n maximum: this.maximum,\n }\n }\n}\n\n/**\n * Issue for values that are below a minimum constraint.\n */\nexport class IssueTooSmall extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly minimum: number,\n readonly type: MeasurableType,\n readonly actual: number,\n ) {\n super('too_small', path, input)\n }\n\n toString() {\n return `${this.type} too small (minimum ${this.minimum})${stringifyPath(this.path)} (got ${this.actual})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n type: this.type,\n minimum: this.minimum,\n }\n }\n}\n\n// -----------------------------------------------------------------------------\n// Helper functions for formatting error messages\n// -----------------------------------------------------------------------------\n\nfunction stringifyExpectedType(expected: string): string {\n if (expected === '$typed') {\n return 'an object or record which includes a \"$type\" property'\n }\n return expected\n}\n\nfunction stringifyPath(path: readonly PropertyKey[]) {\n return ` at ${buildJsonPath(path)}`\n}\n\nfunction buildJsonPath(path: readonly PropertyKey[]): string {\n return `$${path.map(toJsonPathSegment).join('')}`\n}\n\nfunction toJsonPathSegment(segment: PropertyKey): string {\n if (typeof segment === 'number') {\n return `[${segment}]`\n } else if (/^[a-zA-Z_$][a-zA-Z0-9_]*$/.test(segment as string)) {\n return `.${segment}`\n } else {\n return `[${JSON.stringify(segment)}]`\n }\n}\n\nfunction oneOf(arr: readonly string[]): string {\n if (arr.length === 0) return ''\n if (arr.length === 1) return arr[0]\n return `one of ${arr.slice(0, -1).join(', ')} or ${arr.at(-1)}`\n}\n\nfunction stringifyType(value: unknown): string {\n switch (typeof value) {\n case 'object':\n if (value === null) return 'null'\n if (Array.isArray(value)) return 'array'\n if (ifCid(value)) return 'cid'\n if (value instanceof Date) return 'date'\n if (value instanceof RegExp) return 'regexp'\n if (value instanceof Map) return 'map'\n if (value instanceof Set) return 'set'\n return 'object'\n case 'number':\n if (Number.isInteger(value) && Number.isSafeInteger(value)) {\n return 'integer'\n }\n if (Number.isNaN(value)) {\n return 'NaN'\n }\n if (value === Infinity) {\n return 'Infinity'\n }\n if (value === -Infinity) {\n return '-Infinity'\n }\n return 'float'\n default:\n return typeof value\n }\n}\n\nfunction stringifyValue(value: unknown): string {\n switch (typeof value) {\n case 'bigint':\n return `${value}n`\n case 'number':\n case 'string':\n case 'boolean':\n return JSON.stringify(value)\n case 'object':\n if (Array.isArray(value)) {\n return `[${stringifyArray(value, stringifyValue)}]`\n }\n if (isPlainObject(value)) {\n return `{${stringifyArray(Object.entries(value), stringifyObjectEntry)}}`\n }\n // fallthrough\n default:\n return stringifyType(value)\n }\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringifyObjectEntry([key, _value]: [PropertyKey, unknown]): string {\n return `${JSON.stringify(key)}: ...`\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringifyArray<T>(\n arr: readonly T[],\n fn: (item: T) => string,\n n = 2,\n): string {\n return arr.slice(0, n).map(fn).join(', ') + (arr.length > n ? ', ...' : '')\n}\n"]}
|