@atproto/lex-schema 0.0.13 → 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.
Files changed (81) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/core/schema.d.ts +27 -35
  3. package/dist/core/schema.d.ts.map +1 -1
  4. package/dist/core/schema.js +73 -54
  5. package/dist/core/schema.js.map +1 -1
  6. package/dist/core/standard-schema.d.ts +14 -0
  7. package/dist/core/standard-schema.d.ts.map +1 -0
  8. package/dist/core/standard-schema.js +27 -0
  9. package/dist/core/standard-schema.js.map +1 -0
  10. package/dist/core/string-format.d.ts +4 -28
  11. package/dist/core/string-format.d.ts.map +1 -1
  12. package/dist/core/string-format.js +23 -17
  13. package/dist/core/string-format.js.map +1 -1
  14. package/dist/core/validation-error.d.ts +14 -6
  15. package/dist/core/validation-error.d.ts.map +1 -1
  16. package/dist/core/validation-error.js +18 -8
  17. package/dist/core/validation-error.js.map +1 -1
  18. package/dist/core/validation-issue.d.ts +15 -15
  19. package/dist/core/validation-issue.d.ts.map +1 -1
  20. package/dist/core/validation-issue.js +33 -29
  21. package/dist/core/validation-issue.js.map +1 -1
  22. package/dist/core/validator.d.ts +21 -18
  23. package/dist/core/validator.d.ts.map +1 -1
  24. package/dist/core/validator.js +5 -4
  25. package/dist/core/validator.js.map +1 -1
  26. package/dist/core.d.ts +0 -1
  27. package/dist/core.d.ts.map +1 -1
  28. package/dist/core.js +0 -1
  29. package/dist/core.js.map +1 -1
  30. package/dist/schema/custom.d.ts +1 -1
  31. package/dist/schema/custom.d.ts.map +1 -1
  32. package/dist/schema/custom.js.map +1 -1
  33. package/dist/schema/never.d.ts +1 -1
  34. package/dist/schema/nullable.d.ts +1 -1
  35. package/dist/schema/params.d.ts.map +1 -1
  36. package/dist/schema/params.js +4 -1
  37. package/dist/schema/params.js.map +1 -1
  38. package/dist/schema/record.d.ts +12 -6
  39. package/dist/schema/record.d.ts.map +1 -1
  40. package/dist/schema/record.js +21 -12
  41. package/dist/schema/record.js.map +1 -1
  42. package/dist/schema/ref.d.ts +1 -1
  43. package/dist/schema/ref.d.ts.map +1 -1
  44. package/dist/schema/ref.js.map +1 -1
  45. package/dist/schema/refine.d.ts +1 -1
  46. package/dist/schema/refine.d.ts.map +1 -1
  47. package/dist/schema/refine.js.map +1 -1
  48. package/dist/schema/typed-object.d.ts +12 -4
  49. package/dist/schema/typed-object.d.ts.map +1 -1
  50. package/dist/schema/typed-object.js +21 -12
  51. package/dist/schema/typed-object.js.map +1 -1
  52. package/dist/schema/typed-ref.d.ts +1 -1
  53. package/dist/schema/typed-union.d.ts +1 -1
  54. package/dist/schema/union.d.ts +2 -2
  55. package/dist/schema/union.d.ts.map +1 -1
  56. package/dist/schema/union.js +1 -1
  57. package/dist/schema/union.js.map +1 -1
  58. package/package.json +4 -3
  59. package/src/core/schema.ts +78 -69
  60. package/src/core/standard-schema.test.ts +124 -0
  61. package/src/core/standard-schema.ts +31 -0
  62. package/src/core/string-format.ts +26 -33
  63. package/src/core/validation-error.ts +25 -10
  64. package/src/core/validation-issue.ts +32 -32
  65. package/src/core/validator.ts +16 -12
  66. package/src/core.ts +0 -1
  67. package/src/schema/array.test.ts +2 -2
  68. package/src/schema/custom.ts +1 -7
  69. package/src/schema/params.test.ts +18 -2
  70. package/src/schema/params.ts +5 -2
  71. package/src/schema/record.ts +27 -22
  72. package/src/schema/ref.ts +1 -5
  73. package/src/schema/refine.ts +0 -1
  74. package/src/schema/typed-object.test.ts +38 -0
  75. package/src/schema/typed-object.ts +29 -24
  76. package/src/schema/union.ts +2 -2
  77. package/dist/core/property-key.d.ts +0 -2
  78. package/dist/core/property-key.d.ts.map +0 -1
  79. package/dist/core/property-key.js +0 -3
  80. package/dist/core/property-key.js.map +0 -1
  81. 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
- * implement the {@link toString} method for human-readable error messages.
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
- abstract toString(): string
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.toString(),
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 message?: string,
70
+ readonly detail?: string,
71
71
  ) {
72
72
  super('invalid_format', path, input)
73
73
  }
74
74
 
75
- toString() {
76
- return `Invalid ${this.formatDescription}${this.message ? ` (${this.message})` : ''}${stringifyPath(this.path)} (got ${stringifyValue(this.input)})`
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
- toString() {
123
- return `Expected ${oneOf(this.expected.map(stringifyExpectedType))} value type${stringifyPath(this.path)} (got ${stringifyType(this.input)})`
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
- toString() {
150
- return `Expected ${oneOf(this.values.map(stringifyValue))}${stringifyPath(this.path)} (got ${stringifyValue(this.input)})`
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
- toString() {
174
- return `Missing required key "${String(this.key)}"${stringifyPath(this.path)}`
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
- toString() {
218
- return `${this.type} too big (maximum ${this.maximum})${stringifyPath(this.path)} (got ${this.actual})`
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
- toString() {
245
- return `${this.type} too small (minimum ${this.minimum})${stringifyPath(this.path)} (got ${this.actual})`
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 as string)) {
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)}]`
@@ -1,6 +1,6 @@
1
- import { PropertyKey } from './property-key.js'
2
- import { ResultFailure, ResultSuccess, failure, success } from './result.js'
3
- import { ValidationError } from './validation-error.js'
1
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2
+ import { ResultFailure, ResultSuccess, success } from './result.js'
3
+ import { LexValidationError } from './validation-error.js'
4
4
  import {
5
5
  Issue,
6
6
  IssueInvalidFormat,
@@ -20,16 +20,20 @@ import {
20
20
  export type ValidationSuccess<Value = unknown> = ResultSuccess<Value>
21
21
 
22
22
  /**
23
- * Represents a failed validation result containing a {@link ValidationError}.
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 = ResultFailure<ValidationError>
29
+ export type ValidationFailure = LexValidationError
26
30
 
27
31
  /**
28
32
  * Discriminated union representing the outcome of a validation operation.
29
33
  *
30
34
  * Check the `success` property to determine if validation passed or failed:
31
35
  * - If `success` is `true`, the `value` property contains the validated data
32
- * - If `success` is `false`, the `reason` property contains the {@link ValidationError}
36
+ * - If `success` is `false`, the `reason` property contains the {@link LexValidationError}
33
37
  *
34
38
  * @typeParam Value - The type of the validated value on success
35
39
  *
@@ -39,7 +43,7 @@ export type ValidationFailure = ResultFailure<ValidationError>
39
43
  * if (result.success) {
40
44
  * // result.value is string
41
45
  * } else {
42
- * // result.reason is ValidationError
46
+ * // result.reason is LexValidationError
43
47
  * }
44
48
  * ```
45
49
  */
@@ -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 failure(new ValidationError(Array.from(this.issues)))
333
+ return new LexValidationError(Array.from(this.issues))
330
334
  }
331
335
 
332
336
  if (this.options.mode !== 'parse' && !Object.is(result.value, input)) {
@@ -341,7 +345,7 @@ export class ValidationContext {
341
345
  // another.
342
346
 
343
347
  // This if block comes before the next one because 'this.issues' will
344
- // end-up being appended to the returned ValidationError (see the
348
+ // end-up being appended to the returned LexValidationError (see the
345
349
  // "failure" method below), resulting in a more complete error report.
346
350
  return this.issueInvalidValue(input, [result.value])
347
351
  }
@@ -425,8 +429,8 @@ export class ValidationContext {
425
429
  * @param reason - The validation error
426
430
  * @returns A failed validation result
427
431
  */
428
- failure(reason: ValidationError): ValidationFailure {
429
- return failure(reason)
432
+ failure(reason: LexValidationError): ValidationFailure {
433
+ return reason
430
434
  }
431
435
 
432
436
  /**
@@ -438,7 +442,7 @@ export class ValidationContext {
438
442
  * @returns A failed validation result
439
443
  */
440
444
  issue(issue: Issue) {
441
- return this.failure(new ValidationError([...this.issues, issue]))
445
+ return this.failure(new LexValidationError([...this.issues, issue]))
442
446
  }
443
447
 
444
448
  /**
package/src/core.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from './core/$type.js'
2
- export * from './core/property-key.js'
3
2
  export * from './core/record-key.js'
4
3
  export * from './core/result.js'
5
4
  export * from './core/schema.js'
@@ -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).toEqual({
80
+ expect(result).toMatchObject({
81
81
  success: false,
82
82
  reason: expect.objectContaining({
83
83
  message: expect.stringContaining(
84
- 'Expected array value type at $ (got integer)',
84
+ 'Expected array value type (got integer) at $',
85
85
  ),
86
86
  }),
87
87
  })
@@ -1,10 +1,4 @@
1
- import {
2
- Issue,
3
- IssueCustom,
4
- PropertyKey,
5
- Schema,
6
- ValidationContext,
7
- } from '../core.js'
1
+ import { Issue, IssueCustom, Schema, ValidationContext } from '../core.js'
8
2
 
9
3
  /**
10
4
  * Context object provided to custom assertion functions.
@@ -419,7 +419,7 @@ describe('ParamsSchema', () => {
419
419
  ['name', 'Alice'],
420
420
  ['bools', 'notabool'],
421
421
  ]),
422
- ).toThrow('Expected boolean value type at $.bools (got string)')
422
+ ).toThrow('Expected boolean value type (got string) at $.bools')
423
423
 
424
424
  expect(() =>
425
425
  schema.fromURLSearchParams(
@@ -431,7 +431,23 @@ describe('ParamsSchema', () => {
431
431
  path: ['foo', 'bar'],
432
432
  },
433
433
  ),
434
- ).toThrow('Expected boolean value type at $.foo.bar.bools (got string)')
434
+ ).toThrow('Expected boolean value type (got string) at $.foo.bar.bools')
435
+ })
436
+
437
+ it('ignores empty string values', () => {
438
+ const result = schema.fromURLSearchParams([
439
+ ['name', 'Alice'],
440
+ ['extra', ''],
441
+ ])
442
+ expect(result).toEqual({ name: 'Alice' })
443
+ })
444
+
445
+ it('ignores empty string values for known parameters', () => {
446
+ const result = schema.fromURLSearchParams([
447
+ ['name', 'Alice'],
448
+ ['age', ''],
449
+ ])
450
+ expect(result).toEqual({ name: 'Alice' })
435
451
  })
436
452
  })
437
453
 
@@ -6,10 +6,10 @@ import {
6
6
  Issue,
7
7
  IssueInvalidType,
8
8
  IssueInvalidValue,
9
+ LexValidationError,
9
10
  ParseOptions,
10
11
  Schema,
11
12
  ValidationContext,
12
- ValidationError,
13
13
  Validator,
14
14
  WithOptionalProperties,
15
15
  } from '../core.js'
@@ -209,6 +209,9 @@ export class ParamsSchema<
209
209
  iterable instanceof URLSearchParams ? iterable.entries() : iterable
210
210
 
211
211
  for (const [name, value] of entries) {
212
+ // Ignore empty strings
213
+ if (!value) continue
214
+
212
215
  const validator = this.shapeValidators.get(name)
213
216
  const innerValidator = validator ? unwrapSchema(validator) : undefined
214
217
  const expectsArray = innerValidator instanceof ArraySchema
@@ -302,7 +305,7 @@ function coerceParam(
302
305
  // the index of the param in case of array params (e.g. "tags[1]"), which
303
306
  // could be helpful for debugging. The cost overhead is not worth it though
304
307
  // (IMO).
305
- throw new ValidationError([issue])
308
+ throw new LexValidationError([issue])
306
309
  }
307
310
 
308
311
  function paramPath(key: string, options?: ParseOptions) {
@@ -11,6 +11,7 @@ import {
11
11
  ValidationContext,
12
12
  Validator,
13
13
  } from '../core.js'
14
+ import { lazyProperty } from '../util/lazy-property.js'
14
15
  import { literal } from './literal.js'
15
16
  import { string } from './string.js'
16
17
 
@@ -70,10 +71,18 @@ export class RecordSchema<
70
71
  this.keySchema = recordKey(key)
71
72
  }
72
73
 
73
- isTypeOf<TValue extends { $type?: unknown }>(
74
- value: TValue,
75
- ): value is TypedRecord<TType, TValue> {
76
- return value.$type === this.$type
74
+ validateInContext(input: unknown, ctx: ValidationContext) {
75
+ const result = ctx.validate(input, this.schema)
76
+
77
+ if (!result.success) {
78
+ return result
79
+ }
80
+
81
+ if (result.value.$type !== this.$type) {
82
+ return ctx.issueInvalidPropertyValue(result.value, '$type', [this.$type])
83
+ }
84
+
85
+ return result
77
86
  }
78
87
 
79
88
  build(
@@ -82,30 +91,26 @@ export class RecordSchema<
82
91
  return this.parse($typed(input, this.$type))
83
92
  }
84
93
 
85
- $isTypeOf<TValue extends { $type?: unknown }>(
94
+ isTypeOf<TValue extends { $type?: unknown }>(
86
95
  value: TValue,
87
96
  ): value is TypedRecord<TType, TValue> {
88
- return this.isTypeOf<TValue>(value)
97
+ return value.$type === this.$type
89
98
  }
90
99
 
91
- $build(
92
- input: Omit<InferInput<this>, '$type'>,
93
- ): $Typed<InferOutput<this>, TType> {
94
- return this.build(input)
100
+ /**
101
+ * Bound alias for {@link build} for compatibility with generated utilities.
102
+ * @see {@link build}
103
+ */
104
+ get $build(): typeof this.build {
105
+ return lazyProperty(this, '$build', this.build.bind(this))
95
106
  }
96
107
 
97
- validateInContext(input: unknown, ctx: ValidationContext) {
98
- const result = ctx.validate(input, this.schema)
99
-
100
- if (!result.success) {
101
- return result
102
- }
103
-
104
- if (result.value.$type !== this.$type) {
105
- return ctx.issueInvalidPropertyValue(result.value, '$type', [this.$type])
106
- }
107
-
108
- return result
108
+ /**
109
+ * Bound alias for {@link isTypeOf} for compatibility with generated utilities.
110
+ * @see {@link isTypeOf}
111
+ */
112
+ get $isTypeOf(): typeof this.isTypeOf {
113
+ return lazyProperty(this, '$isTypeOf', this.isTypeOf.bind(this))
109
114
  }
110
115
  }
111
116
 
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
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  InferInput,
3
3
  IssueCustom,
4
- PropertyKey,
5
4
  ValidationContext,
6
5
  ValidationResult,
7
6
  Validator,
@@ -332,6 +332,44 @@ describe('TypedObjectSchema', () => {
332
332
  })
333
333
  })
334
334
 
335
+ describe('bound $ methods', () => {
336
+ it('$build can be used as a detached function', () => {
337
+ const { $build } = schema
338
+ const result = $build({ text: 'Hello' })
339
+ expect(result).toEqual({
340
+ text: 'Hello',
341
+ $type: 'app.bsky.feed.post',
342
+ })
343
+ })
344
+
345
+ it('$isTypeOf can be used as a detached function', () => {
346
+ const { $isTypeOf } = schema
347
+ expect($isTypeOf({ text: 'Hello' })).toBe(true)
348
+ expect($isTypeOf({ $type: 'app.bsky.feed.post', text: 'Hello' })).toBe(
349
+ true,
350
+ )
351
+ expect($isTypeOf({ $type: 'other.type', text: 'Hello' })).toBe(false)
352
+ })
353
+
354
+ it('$parse can be used as a detached function', () => {
355
+ const { $parse } = schema
356
+ const result = $parse({ text: 'Hello' })
357
+ expect(result).toEqual({ text: 'Hello' })
358
+ })
359
+
360
+ it('$matches can be used as a detached function', () => {
361
+ const { $matches } = schema
362
+ expect($matches({ text: 'Hello' })).toBe(true)
363
+ expect($matches(42)).toBe(false)
364
+ })
365
+
366
+ it('lazy property returns the same function on repeated access', () => {
367
+ const fn1 = schema.$build
368
+ const fn2 = schema.$build
369
+ expect(fn1).toBe(fn2)
370
+ })
371
+ })
372
+
335
373
  describe('with complex nested schemas', () => {
336
374
  const complexSchema = typedObject(
337
375
  'app.bsky.actor.profile',
@@ -14,6 +14,7 @@ import {
14
14
  ValidationContext,
15
15
  Validator,
16
16
  } from '../core.js'
17
+ import { lazyProperty } from '../util/lazy-property.js'
17
18
 
18
19
  export type MaybeTypedObject<
19
20
  TType extends $Type,
@@ -56,10 +57,20 @@ export class TypedObjectSchema<
56
57
  super()
57
58
  }
58
59
 
59
- isTypeOf<TValue extends Record<string, unknown>>(
60
- value: TValue,
61
- ): value is MaybeTypedObject<TType, TValue> {
62
- return value.$type === undefined || value.$type === this.$type
60
+ validateInContext(input: unknown, ctx: ValidationContext) {
61
+ if (!isPlainObject(input)) {
62
+ return ctx.issueUnexpectedType(input, 'object')
63
+ }
64
+
65
+ if (
66
+ '$type' in input &&
67
+ input.$type !== undefined &&
68
+ input.$type !== this.$type
69
+ ) {
70
+ return ctx.issueInvalidPropertyValue(input, '$type', [this.$type])
71
+ }
72
+
73
+ return ctx.validate(input, this.schema)
63
74
  }
64
75
 
65
76
  build(
@@ -71,32 +82,26 @@ export class TypedObjectSchema<
71
82
  >
72
83
  }
73
84
 
74
- $isTypeOf<TValue extends Record<string, unknown>>(
85
+ isTypeOf<TValue extends Record<string, unknown>>(
75
86
  value: TValue,
76
87
  ): value is MaybeTypedObject<TType, TValue> {
77
- return this.isTypeOf(value)
88
+ return value.$type === undefined || value.$type === this.$type
78
89
  }
79
90
 
80
- $build(
81
- input: Omit<InferInput<this>, '$type'>,
82
- ): $Typed<InferOutput<this>, TType> {
83
- return this.build(input)
91
+ /**
92
+ * Bound alias for {@link build} for compatibility with generated utilities.
93
+ * @see {@link build}
94
+ */
95
+ get $build(): typeof this.build {
96
+ return lazyProperty(this, '$build', this.build.bind(this))
84
97
  }
85
98
 
86
- validateInContext(input: unknown, ctx: ValidationContext) {
87
- if (!isPlainObject(input)) {
88
- return ctx.issueUnexpectedType(input, 'object')
89
- }
90
-
91
- if (
92
- '$type' in input &&
93
- input.$type !== undefined &&
94
- input.$type !== this.$type
95
- ) {
96
- return ctx.issueInvalidPropertyValue(input, '$type', [this.$type])
97
- }
98
-
99
- return ctx.validate(input, this.schema)
99
+ /**
100
+ * Bound alias for {@link isTypeOf} for compatibility with generated utilities.
101
+ * @see {@link isTypeOf}
102
+ */
103
+ get $isTypeOf(): typeof this.isTypeOf {
104
+ return lazyProperty(this, '$isTypeOf', this.isTypeOf.bind(this))
100
105
  }
101
106
  }
102
107
 
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  InferInput,
3
3
  InferOutput,
4
+ LexValidationError,
4
5
  Schema,
5
6
  ValidationContext,
6
- ValidationError,
7
7
  ValidationFailure,
8
8
  Validator,
9
9
  } from '../core.js'
@@ -53,7 +53,7 @@ export class UnionSchema<
53
53
  failures.push(result)
54
54
  }
55
55
 
56
- return ctx.failure(ValidationError.fromFailures(failures))
56
+ return ctx.failure(LexValidationError.fromFailures(failures))
57
57
  }
58
58
  }
59
59
 
@@ -1,2 +0,0 @@
1
- export type PropertyKey = string | number;
2
- //# sourceMappingURL=property-key.d.ts.map
@@ -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,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=property-key.js.map
@@ -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"]}
@@ -1 +0,0 @@
1
- export type PropertyKey = string | number