@atproto/lex-schema 0.0.14 → 0.0.15
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 +21 -0
- package/dist/core/schema.d.ts +4 -3
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +6 -1
- package/dist/core/schema.js.map +1 -1
- package/dist/core/standard-schema.d.ts +14 -0
- package/dist/core/standard-schema.d.ts.map +1 -0
- package/dist/core/standard-schema.js +27 -0
- package/dist/core/standard-schema.js.map +1 -0
- package/dist/core/string-format.d.ts +4 -15
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +17 -14
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-error.d.ts +10 -2
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +10 -0
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validation-issue.d.ts +15 -15
- package/dist/core/validation-issue.d.ts.map +1 -1
- package/dist/core/validation-issue.js +33 -29
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.d.ts +16 -13
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +3 -2
- package/dist/core/validator.js.map +1 -1
- package/dist/core.d.ts +0 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +0 -1
- package/dist/core.js.map +1 -1
- package/dist/schema/custom.d.ts +1 -1
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/never.d.ts +1 -1
- package/dist/schema/nullable.d.ts +1 -1
- package/dist/schema/record.d.ts +1 -1
- package/dist/schema/ref.d.ts +1 -1
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +1 -1
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +1 -1
- package/dist/schema/typed-union.d.ts +1 -1
- package/dist/schema/union.d.ts +2 -2
- package/dist/schema/union.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/core/schema.ts +11 -10
- package/src/core/standard-schema.test.ts +124 -0
- package/src/core/standard-schema.ts +31 -0
- package/src/core/string-format.ts +14 -18
- package/src/core/validation-error.ts +16 -1
- package/src/core/validation-issue.ts +32 -32
- package/src/core/validator.ts +9 -5
- package/src/core.ts +0 -1
- package/src/schema/array.test.ts +2 -2
- package/src/schema/custom.ts +1 -7
- package/src/schema/params.test.ts +2 -2
- package/src/schema/ref.ts +1 -5
- package/src/schema/refine.ts +0 -1
- package/dist/core/property-key.d.ts +0 -2
- package/dist/core/property-key.d.ts.map +0 -1
- package/dist/core/property-key.js +0 -3
- package/dist/core/property-key.js.map +0 -1
- package/src/core/property-key.ts +0 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ifCid, isLegacyBlobRef, isPlainObject } from '@atproto/lex-data'
|
|
2
|
-
import { PropertyKey } from './property-key.js'
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Abstract base class for all validation issues.
|
|
@@ -9,10 +8,13 @@ import { PropertyKey } from './property-key.js'
|
|
|
9
8
|
* - The path to the invalid value in the data structure
|
|
10
9
|
* - The actual input value that failed validation
|
|
11
10
|
*
|
|
12
|
-
* Subclasses add specific properties relevant to each issue type and
|
|
13
|
-
*
|
|
11
|
+
* Subclasses add specific properties relevant to each issue type and implement
|
|
12
|
+
* the {@link message} property for human-readable error messages (that don't
|
|
13
|
+
* contain the error path)
|
|
14
14
|
*/
|
|
15
15
|
export abstract class Issue {
|
|
16
|
+
abstract readonly message: string
|
|
17
|
+
|
|
16
18
|
constructor(
|
|
17
19
|
readonly code: string,
|
|
18
20
|
readonly path: readonly PropertyKey[],
|
|
@@ -22,7 +24,9 @@ export abstract class Issue {
|
|
|
22
24
|
/**
|
|
23
25
|
* Returns a human-readable description of the validation issue.
|
|
24
26
|
*/
|
|
25
|
-
|
|
27
|
+
toString() {
|
|
28
|
+
return `${this.message}${stringifyPath(this.path)}`
|
|
29
|
+
}
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
32
|
* Converts the issue to a JSON-serializable object.
|
|
@@ -33,7 +37,7 @@ export abstract class Issue {
|
|
|
33
37
|
return {
|
|
34
38
|
code: this.code,
|
|
35
39
|
path: this.path,
|
|
36
|
-
message: this.
|
|
40
|
+
message: this.message,
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
}
|
|
@@ -51,10 +55,6 @@ export class IssueCustom extends Issue {
|
|
|
51
55
|
) {
|
|
52
56
|
super('custom', path, input)
|
|
53
57
|
}
|
|
54
|
-
|
|
55
|
-
toString() {
|
|
56
|
-
return `${this.message}${stringifyPath(this.path)}`
|
|
57
|
-
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/**
|
|
@@ -67,20 +67,13 @@ export class IssueInvalidFormat extends Issue {
|
|
|
67
67
|
path: readonly PropertyKey[],
|
|
68
68
|
input: unknown,
|
|
69
69
|
readonly format: string,
|
|
70
|
-
readonly
|
|
70
|
+
readonly detail?: string,
|
|
71
71
|
) {
|
|
72
72
|
super('invalid_format', path, input)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
return `Invalid ${this.formatDescription}${this.
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
toJSON() {
|
|
80
|
-
return {
|
|
81
|
-
...super.toJSON(),
|
|
82
|
-
format: this.format,
|
|
83
|
-
}
|
|
75
|
+
override get message(): string {
|
|
76
|
+
return `Invalid ${this.formatDescription}${this.detail ? ` (${this.detail}, ` : ' ('}got ${stringifyValue(this.input)})`
|
|
84
77
|
}
|
|
85
78
|
|
|
86
79
|
/** Returns a human-readable description of the expected format. */
|
|
@@ -102,6 +95,13 @@ export class IssueInvalidFormat extends Issue {
|
|
|
102
95
|
return this.format
|
|
103
96
|
}
|
|
104
97
|
}
|
|
98
|
+
|
|
99
|
+
toJSON() {
|
|
100
|
+
return {
|
|
101
|
+
...super.toJSON(),
|
|
102
|
+
format: this.format,
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/**
|
|
@@ -119,8 +119,8 @@ export class IssueInvalidType extends Issue {
|
|
|
119
119
|
super('invalid_type', path, input)
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
return `Expected ${oneOf(this.expected.map(stringifyExpectedType))} value type
|
|
122
|
+
override get message(): string {
|
|
123
|
+
return `Expected ${oneOf(this.expected.map(stringifyExpectedType))} value type (got ${stringifyType(this.input)})`
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
toJSON() {
|
|
@@ -146,8 +146,8 @@ export class IssueInvalidValue extends Issue {
|
|
|
146
146
|
super('invalid_value', path, input)
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
return `Expected ${oneOf(this.values.map(stringifyValue))}
|
|
149
|
+
override get message(): string {
|
|
150
|
+
return `Expected ${oneOf(this.values.map(stringifyValue))} (got ${stringifyValue(this.input)})`
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
toJSON() {
|
|
@@ -170,8 +170,8 @@ export class IssueRequiredKey extends Issue {
|
|
|
170
170
|
super('required_key', path, input)
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
return `Missing required key "${String(this.key)}"
|
|
173
|
+
override get message(): string {
|
|
174
|
+
return `Missing required key "${String(this.key)}"`
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
toJSON() {
|
|
@@ -214,8 +214,8 @@ export class IssueTooBig extends Issue {
|
|
|
214
214
|
super('too_big', path, input)
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
|
|
218
|
-
return `${this.type} too big (maximum ${this.maximum}
|
|
217
|
+
override get message(): string {
|
|
218
|
+
return `${this.type} too big (maximum ${this.maximum}, got ${this.actual})`
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
toJSON() {
|
|
@@ -241,8 +241,8 @@ export class IssueTooSmall extends Issue {
|
|
|
241
241
|
super('too_small', path, input)
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
return `${this.type} too small (minimum ${this.minimum}
|
|
244
|
+
override get message(): string {
|
|
245
|
+
return `${this.type} too small (minimum ${this.minimum}, got ${this.actual})`
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
toJSON() {
|
|
@@ -274,9 +274,9 @@ function buildJsonPath(path: readonly PropertyKey[]): string {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
function toJsonPathSegment(segment: PropertyKey): string {
|
|
277
|
-
if (typeof segment === 'number') {
|
|
278
|
-
return `[${segment}]`
|
|
279
|
-
} else if (/^[a-zA-Z_$][a-zA-Z0-9_]*$/.test(segment
|
|
277
|
+
if (typeof segment === 'number' || typeof segment === 'symbol') {
|
|
278
|
+
return `[${String(segment)}]`
|
|
279
|
+
} else if (/^[a-zA-Z_$][a-zA-Z0-9_]*$/.test(segment)) {
|
|
280
280
|
return `.${segment}`
|
|
281
281
|
} else {
|
|
282
282
|
return `[${JSON.stringify(segment)}]`
|
package/src/core/validator.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import { ResultFailure, ResultSuccess,
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
|
+
import { ResultFailure, ResultSuccess, success } from './result.js'
|
|
3
3
|
import { LexValidationError } from './validation-error.js'
|
|
4
4
|
import {
|
|
5
5
|
Issue,
|
|
@@ -21,8 +21,12 @@ export type ValidationSuccess<Value = unknown> = ResultSuccess<Value>
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Represents a failed validation result containing a {@link LexValidationError}.
|
|
24
|
+
*
|
|
25
|
+
* @extends ResultFailure<LexValidationError>
|
|
26
|
+
* @see {@link ResultFailure}
|
|
27
|
+
* @see {@link LexValidationError}
|
|
24
28
|
*/
|
|
25
|
-
export type ValidationFailure =
|
|
29
|
+
export type ValidationFailure = LexValidationError
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
32
|
* Discriminated union representing the outcome of a validation operation.
|
|
@@ -326,7 +330,7 @@ export class ValidationContext {
|
|
|
326
330
|
if (this.issues.length > 0) {
|
|
327
331
|
// Validator returned a success but issues were added via the context.
|
|
328
332
|
// This means the overall validation failed.
|
|
329
|
-
return
|
|
333
|
+
return new LexValidationError(Array.from(this.issues))
|
|
330
334
|
}
|
|
331
335
|
|
|
332
336
|
if (this.options.mode !== 'parse' && !Object.is(result.value, input)) {
|
|
@@ -426,7 +430,7 @@ export class ValidationContext {
|
|
|
426
430
|
* @returns A failed validation result
|
|
427
431
|
*/
|
|
428
432
|
failure(reason: LexValidationError): ValidationFailure {
|
|
429
|
-
return
|
|
433
|
+
return reason
|
|
430
434
|
}
|
|
431
435
|
|
|
432
436
|
/**
|
package/src/core.ts
CHANGED
package/src/schema/array.test.ts
CHANGED
|
@@ -77,11 +77,11 @@ describe('ArraySchema', () => {
|
|
|
77
77
|
it('rejects single values', () => {
|
|
78
78
|
const schema = array(string())
|
|
79
79
|
const result = schema.safeValidate(3)
|
|
80
|
-
expect(result).
|
|
80
|
+
expect(result).toMatchObject({
|
|
81
81
|
success: false,
|
|
82
82
|
reason: expect.objectContaining({
|
|
83
83
|
message: expect.stringContaining(
|
|
84
|
-
'Expected array value type
|
|
84
|
+
'Expected array value type (got integer) at $',
|
|
85
85
|
),
|
|
86
86
|
}),
|
|
87
87
|
})
|
package/src/schema/custom.ts
CHANGED
|
@@ -419,7 +419,7 @@ describe('ParamsSchema', () => {
|
|
|
419
419
|
['name', 'Alice'],
|
|
420
420
|
['bools', 'notabool'],
|
|
421
421
|
]),
|
|
422
|
-
).toThrow('Expected boolean value type
|
|
422
|
+
).toThrow('Expected boolean value type (got string) at $.bools')
|
|
423
423
|
|
|
424
424
|
expect(() =>
|
|
425
425
|
schema.fromURLSearchParams(
|
|
@@ -431,7 +431,7 @@ describe('ParamsSchema', () => {
|
|
|
431
431
|
path: ['foo', 'bar'],
|
|
432
432
|
},
|
|
433
433
|
),
|
|
434
|
-
).toThrow('Expected boolean value type at $.foo.bar.bools
|
|
434
|
+
).toThrow('Expected boolean value type (got string) at $.foo.bar.bools')
|
|
435
435
|
})
|
|
436
436
|
|
|
437
437
|
it('ignores empty string values', () => {
|
package/src/schema/ref.ts
CHANGED
|
@@ -32,11 +32,7 @@ export type RefSchemaGetter<out TValidator extends Validator> = () => TValidator
|
|
|
32
32
|
* ```
|
|
33
33
|
*/
|
|
34
34
|
export class RefSchema<const TValidator extends Validator>
|
|
35
|
-
extends Schema<
|
|
36
|
-
InferInput<TValidator>,
|
|
37
|
-
InferOutput<TValidator>,
|
|
38
|
-
TValidator['__lex']
|
|
39
|
-
>
|
|
35
|
+
extends Schema<InferInput<TValidator>, InferOutput<TValidator>>
|
|
40
36
|
implements WrappedValidator<TValidator>
|
|
41
37
|
{
|
|
42
38
|
readonly type = 'ref' as const
|
package/src/schema/refine.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"property-key.d.ts","sourceRoot":"","sources":["../../src/core/property-key.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"property-key.js","sourceRoot":"","sources":["../../src/core/property-key.ts"],"names":[],"mappings":"","sourcesContent":["export type PropertyKey = string | number\n"]}
|
package/src/core/property-key.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type PropertyKey = string | number
|