@atproto/lex-schema 0.1.4 → 0.1.6
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 +24 -0
- package/dist/core/$type.d.ts +2 -2
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.d.ts +1 -1
- package/dist/core/record-key.d.ts.map +1 -1
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/schema.d.ts +3 -2
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +1 -1
- package/dist/core/schema.js.map +1 -1
- package/dist/core/standard-schema.d.ts +2 -2
- package/dist/core/standard-schema.d.ts.map +1 -1
- package/dist/core/standard-schema.js.map +1 -1
- package/dist/core/string-format.d.ts +2 -2
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-error.d.ts +1 -1
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +1 -1
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validator.d.ts +1 -1
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +1 -1
- package/dist/core/validator.js.map +1 -1
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +2 -2
- package/dist/helpers.js.map +1 -1
- package/dist/schema/array.d.ts +1 -1
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +1 -1
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +1 -1
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +2 -2
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.js +1 -1
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.js +1 -1
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +1 -1
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +3 -3
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.js +1 -1
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +1 -1
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +1 -1
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +1 -1
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +2 -1
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.js +1 -1
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.js +1 -1
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +1 -1
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +3 -1
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/lex-map.d.ts +1 -1
- package/dist/schema/lex-map.d.ts.map +1 -1
- package/dist/schema/lex-map.js +1 -1
- package/dist/schema/lex-map.js.map +1 -1
- package/dist/schema/lex-value.d.ts +1 -1
- package/dist/schema/lex-value.d.ts.map +1 -1
- package/dist/schema/lex-value.js +1 -1
- package/dist/schema/lex-value.js.map +1 -1
- package/dist/schema/literal.js +1 -1
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.js +1 -1
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.js +1 -1
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +1 -1
- package/dist/schema/nullable.d.ts.map +1 -1
- package/dist/schema/nullable.js +1 -1
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.d.ts +2 -1
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +1 -1
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +2 -1
- package/dist/schema/optional.d.ts.map +1 -1
- package/dist/schema/optional.js +2 -1
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.d.ts +1 -1
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +1 -1
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +3 -2
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js +2 -1
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +1 -1
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +1 -0
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +1 -1
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +1 -1
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +2 -0
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +1 -1
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +2 -0
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +2 -2
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +1 -1
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +1 -1
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +1 -1
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +2 -2
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.js +1 -1
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.d.ts +2 -2
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +1 -1
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +3 -2
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js +2 -0
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +1 -1
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +1 -1
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +2 -2
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +1 -1
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +1 -1
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +1 -1
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +1 -1
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +3 -1
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +1 -1
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +1 -1
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown.js +1 -1
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.d.ts +1 -1
- package/dist/schema/with-default.d.ts.map +1 -1
- package/dist/schema/with-default.js +1 -1
- package/dist/schema/with-default.js.map +1 -1
- package/package.json +6 -10
- package/src/core/$type.test.ts +0 -24
- package/src/core/$type.ts +0 -199
- package/src/core/record-key.ts +0 -85
- package/src/core/result.ts +0 -15
- package/src/core/schema.ts +0 -412
- package/src/core/standard-schema.test.ts +0 -124
- package/src/core/standard-schema.ts +0 -31
- package/src/core/string-format.ts +0 -411
- package/src/core/types.ts +0 -120
- package/src/core/validation-error.ts +0 -134
- package/src/core/validation-issue.ts +0 -340
- package/src/core/validator.ts +0 -636
- package/src/core.ts +0 -9
- package/src/external.ts +0 -3
- package/src/helpers.test.ts +0 -694
- package/src/helpers.ts +0 -222
- package/src/index.ts +0 -3
- package/src/schema/array.test.ts +0 -251
- package/src/schema/array.ts +0 -126
- package/src/schema/blob.test.ts +0 -733
- package/src/schema/blob.ts +0 -150
- package/src/schema/boolean.test.ts +0 -118
- package/src/schema/boolean.ts +0 -46
- package/src/schema/bytes.test.ts +0 -227
- package/src/schema/bytes.ts +0 -81
- package/src/schema/cid.test.ts +0 -125
- package/src/schema/cid.ts +0 -69
- package/src/schema/custom.test.ts +0 -414
- package/src/schema/custom.ts +0 -106
- package/src/schema/dict.test.ts +0 -181
- package/src/schema/dict.ts +0 -122
- package/src/schema/discriminated-union.test.ts +0 -676
- package/src/schema/discriminated-union.ts +0 -196
- package/src/schema/enum.test.ts +0 -398
- package/src/schema/enum.ts +0 -77
- package/src/schema/integer.test.ts +0 -314
- package/src/schema/integer.ts +0 -86
- package/src/schema/intersection.test.ts +0 -33
- package/src/schema/intersection.ts +0 -113
- package/src/schema/lex-map.test.ts +0 -593
- package/src/schema/lex-map.ts +0 -63
- package/src/schema/lex-value.test.ts +0 -81
- package/src/schema/lex-value.ts +0 -86
- package/src/schema/literal.test.ts +0 -533
- package/src/schema/literal.ts +0 -70
- package/src/schema/never.test.ts +0 -175
- package/src/schema/never.ts +0 -56
- package/src/schema/null.test.ts +0 -80
- package/src/schema/null.ts +0 -49
- package/src/schema/nullable.test.ts +0 -470
- package/src/schema/nullable.ts +0 -74
- package/src/schema/object.test.ts +0 -69
- package/src/schema/object.ts +0 -136
- package/src/schema/optional.test.ts +0 -479
- package/src/schema/optional.ts +0 -92
- package/src/schema/params.test.ts +0 -1118
- package/src/schema/params.ts +0 -371
- package/src/schema/payload.test.ts +0 -340
- package/src/schema/payload.ts +0 -204
- package/src/schema/permission-set.test.ts +0 -613
- package/src/schema/permission-set.ts +0 -86
- package/src/schema/permission.test.ts +0 -537
- package/src/schema/permission.ts +0 -63
- package/src/schema/procedure.test.ts +0 -324
- package/src/schema/procedure.ts +0 -98
- package/src/schema/query.test.ts +0 -348
- package/src/schema/query.ts +0 -86
- package/src/schema/record.test.ts +0 -812
- package/src/schema/record.ts +0 -217
- package/src/schema/ref.test.ts +0 -349
- package/src/schema/ref.ts +0 -103
- package/src/schema/refine.test.ts +0 -579
- package/src/schema/refine.ts +0 -153
- package/src/schema/regexp.test.ts +0 -577
- package/src/schema/regexp.ts +0 -82
- package/src/schema/string.test.ts +0 -773
- package/src/schema/string.ts +0 -229
- package/src/schema/subscription.test.ts +0 -499
- package/src/schema/subscription.ts +0 -108
- package/src/schema/token.test.ts +0 -152
- package/src/schema/token.ts +0 -103
- package/src/schema/typed-object.test.ts +0 -745
- package/src/schema/typed-object.ts +0 -181
- package/src/schema/typed-ref.test.ts +0 -796
- package/src/schema/typed-ref.ts +0 -126
- package/src/schema/typed-union.test.ts +0 -355
- package/src/schema/typed-union.ts +0 -130
- package/src/schema/union.test.ts +0 -191
- package/src/schema/union.ts +0 -89
- package/src/schema/unknown.test.ts +0 -313
- package/src/schema/unknown.ts +0 -47
- package/src/schema/with-default.ts +0 -81
- package/src/schema.ts +0 -43
- package/src/util/array-agg.test.ts +0 -42
- package/src/util/array-agg.ts +0 -44
- package/src/util/assertion-util.ts +0 -1
- package/src/util/if-any.ts +0 -3
- package/src/util/lazy-property.ts +0 -14
- package/src/util/memoize.ts +0 -37
- package/tsconfig.build.json +0 -12
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
package/src/schema/blob.ts
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BlobRef,
|
|
3
|
-
LegacyBlobRef,
|
|
4
|
-
TypedBlobRef,
|
|
5
|
-
getBlobSize,
|
|
6
|
-
isBlobRef,
|
|
7
|
-
isLegacyBlobRef,
|
|
8
|
-
isTypedBlobRef,
|
|
9
|
-
} from '@atproto/lex-data'
|
|
10
|
-
import { Schema, ValidationContext } from '../core.js'
|
|
11
|
-
import { memoizedOptions } from '../util/memoize.js'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Configuration options for blob schema validation.
|
|
15
|
-
*/
|
|
16
|
-
export type BlobSchemaOptions = {
|
|
17
|
-
/**
|
|
18
|
-
* List of accepted MIME types (supports wildcards like 'image/*' or '*\/*')
|
|
19
|
-
*
|
|
20
|
-
* @default undefined // accepts all MIME types
|
|
21
|
-
*/
|
|
22
|
-
accept?: string[]
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Maximum blob size in bytes
|
|
26
|
-
*
|
|
27
|
-
* @default undefined // no size limit
|
|
28
|
-
*/
|
|
29
|
-
maxSize?: number
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export type { BlobRef, LegacyBlobRef, TypedBlobRef }
|
|
33
|
-
export { isBlobRef, isLegacyBlobRef, isTypedBlobRef }
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Schema for validating blob references in AT Protocol.
|
|
37
|
-
*
|
|
38
|
-
* Validates BlobRef objects which contain a CID reference to binary data,
|
|
39
|
-
* along with metadata like MIME type and size. Can optionally accept
|
|
40
|
-
* legacy blob reference format.
|
|
41
|
-
*
|
|
42
|
-
* @template TOptions - The configuration options type
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* ```ts
|
|
46
|
-
* const schema = new BlobSchema({ accept: ['image/*'], maxSize: 1000000 })
|
|
47
|
-
* const result = schema.validate(blobRef)
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export class BlobSchema<
|
|
51
|
-
const TOptions extends BlobSchemaOptions = NonNullable<unknown>,
|
|
52
|
-
> extends Schema<BlobRef> {
|
|
53
|
-
readonly type = 'blob' as const
|
|
54
|
-
|
|
55
|
-
constructor(readonly options?: TOptions) {
|
|
56
|
-
super()
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
60
|
-
const blob = parseValue.call(ctx, input)
|
|
61
|
-
if (!blob) {
|
|
62
|
-
return ctx.issueUnexpectedType(input, 'blob')
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// In non-strict mode, we allow blob refs to pass through without MIME
|
|
66
|
-
// type or size checks.
|
|
67
|
-
if (ctx.options.strict && this.options != null) {
|
|
68
|
-
const { accept } = this.options
|
|
69
|
-
if (accept && !matchesMime(blob.mimeType, accept)) {
|
|
70
|
-
return ctx.issueInvalidPropertyValue(blob, 'mimeType', accept)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const { maxSize } = this.options
|
|
74
|
-
if (maxSize != null) {
|
|
75
|
-
const size = getBlobSize(blob)
|
|
76
|
-
if (size === undefined) {
|
|
77
|
-
// Unable to enforce size constraint if size is not available (legacy
|
|
78
|
-
// blob ref), so we treat it as a validation failure in strict mode.
|
|
79
|
-
return ctx.issueInvalidPropertyType(blob, 'size' as any, 'integer')
|
|
80
|
-
} else if (size > maxSize) {
|
|
81
|
-
return ctx.issueTooBig(blob, 'blob', maxSize, size)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return ctx.success(blob)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
matchesMime(mime: string): boolean {
|
|
90
|
-
const accept = this.options?.accept
|
|
91
|
-
if (!accept) return true
|
|
92
|
-
return matchesMime(mime, accept)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function parseValue(this: ValidationContext, input: unknown): BlobRef | null {
|
|
97
|
-
// If there is a $type property, we treat if as a potential TypedBlobRef and
|
|
98
|
-
// validate accordingly.
|
|
99
|
-
if ((input as any)?.$type !== undefined) {
|
|
100
|
-
// Use the context's option for the "strict" check
|
|
101
|
-
return isTypedBlobRef(input, this.options) ? input : null
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// If there is no $type property, we may be dealing with a legacy blob ref. If
|
|
105
|
-
// legacy refs are allowed (non-strict mode), we check if the input matches
|
|
106
|
-
// the legacy format.
|
|
107
|
-
if (!this.options.strict) {
|
|
108
|
-
if (isLegacyBlobRef(input, this.options)) return input
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return null
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function matchesMime(mime: string, accepted: string[]): boolean {
|
|
115
|
-
if (accepted.includes('*/*')) return true
|
|
116
|
-
if (accepted.includes(mime)) return true
|
|
117
|
-
for (const value of accepted) {
|
|
118
|
-
if (value.endsWith('/*') && mime.startsWith(value.slice(0, -1))) {
|
|
119
|
-
return true
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return false
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Creates a blob schema for validating blob references with optional constraints.
|
|
127
|
-
*
|
|
128
|
-
* Blob references are used in AT Protocol to reference binary data stored
|
|
129
|
-
* separately from records. They contain a CID, MIME type, and size information.
|
|
130
|
-
*
|
|
131
|
-
* @param options - Optional configuration for MIME type filtering and size limits
|
|
132
|
-
* @returns A new {@link BlobSchema} instance
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* ```ts
|
|
136
|
-
* // Basic blob reference
|
|
137
|
-
* const fileSchema = l.blob()
|
|
138
|
-
*
|
|
139
|
-
* // Image files only
|
|
140
|
-
* const imageSchema = l.blob({ accept: ['image/png', 'image/jpeg', 'image/gif'] })
|
|
141
|
-
*
|
|
142
|
-
* // Any image type with size limit
|
|
143
|
-
* const avatarSchema = l.blob({ accept: ['image/*'], maxSize: 1000000 })
|
|
144
|
-
* ```
|
|
145
|
-
*/
|
|
146
|
-
export const blob = /*#__PURE__*/ memoizedOptions(function <
|
|
147
|
-
O extends BlobSchemaOptions = NonNullable<unknown>,
|
|
148
|
-
>(options?: O) {
|
|
149
|
-
return new BlobSchema(options)
|
|
150
|
-
})
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { boolean } from './boolean.js'
|
|
3
|
-
import { withDefault } from './with-default.js'
|
|
4
|
-
|
|
5
|
-
describe('BooleanSchema', () => {
|
|
6
|
-
describe('basic validation', () => {
|
|
7
|
-
const schema = boolean()
|
|
8
|
-
|
|
9
|
-
it('validates true', () => {
|
|
10
|
-
const result = schema.safeParse(true)
|
|
11
|
-
expect(result.success).toBe(true)
|
|
12
|
-
if (result.success) {
|
|
13
|
-
expect(result.value).toBe(true)
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('validates false', () => {
|
|
18
|
-
const result = schema.safeParse(false)
|
|
19
|
-
expect(result.success).toBe(true)
|
|
20
|
-
if (result.success) {
|
|
21
|
-
expect(result.value).toBe(false)
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('rejects strings', () => {
|
|
26
|
-
const result = schema.safeParse('true')
|
|
27
|
-
expect(result.success).toBe(false)
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('rejects numbers', () => {
|
|
31
|
-
const result = schema.safeParse(1)
|
|
32
|
-
expect(result.success).toBe(false)
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it('rejects null', () => {
|
|
36
|
-
const result = schema.safeParse(null)
|
|
37
|
-
expect(result.success).toBe(false)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('rejects undefined', () => {
|
|
41
|
-
const result = schema.safeParse(undefined)
|
|
42
|
-
expect(result.success).toBe(false)
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('rejects objects', () => {
|
|
46
|
-
const result = schema.safeParse({})
|
|
47
|
-
expect(result.success).toBe(false)
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('rejects arrays', () => {
|
|
51
|
-
const result = schema.safeParse([])
|
|
52
|
-
expect(result.success).toBe(false)
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
describe('with default value', () => {
|
|
57
|
-
it('uses default value of true when input is undefined', () => {
|
|
58
|
-
const schema = withDefault(boolean(), true)
|
|
59
|
-
const result = schema.safeParse(undefined)
|
|
60
|
-
expect(result.success).toBe(true)
|
|
61
|
-
if (result.success) {
|
|
62
|
-
expect(result.value).toBe(true)
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('uses default value of false when input is undefined', () => {
|
|
67
|
-
const schema = withDefault(boolean(), false)
|
|
68
|
-
const result = schema.safeParse(undefined)
|
|
69
|
-
expect(result.success).toBe(true)
|
|
70
|
-
if (result.success) {
|
|
71
|
-
expect(result.value).toBe(false)
|
|
72
|
-
}
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('overrides default value with explicit true', () => {
|
|
76
|
-
const schema = withDefault(boolean(), false)
|
|
77
|
-
const result = schema.safeParse(true)
|
|
78
|
-
expect(result.success).toBe(true)
|
|
79
|
-
if (result.success) {
|
|
80
|
-
expect(result.value).toBe(true)
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('overrides default value with explicit false', () => {
|
|
85
|
-
const schema = withDefault(boolean(), true)
|
|
86
|
-
const result = schema.safeParse(false)
|
|
87
|
-
expect(result.success).toBe(true)
|
|
88
|
-
if (result.success) {
|
|
89
|
-
expect(result.value).toBe(false)
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it('rejects invalid types even with default', () => {
|
|
94
|
-
const schema = withDefault(boolean(), true)
|
|
95
|
-
const result = schema.safeParse('not a boolean')
|
|
96
|
-
expect(result.success).toBe(false)
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
describe('edge cases', () => {
|
|
101
|
-
const schema = boolean()
|
|
102
|
-
|
|
103
|
-
it('rejects Boolean object', () => {
|
|
104
|
-
const result = schema.safeParse(new Boolean(true))
|
|
105
|
-
expect(result.success).toBe(false)
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
it('rejects truthy values', () => {
|
|
109
|
-
const result = schema.safeParse('truthy')
|
|
110
|
-
expect(result.success).toBe(false)
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
it('rejects falsy values', () => {
|
|
114
|
-
const result = schema.safeParse(0)
|
|
115
|
-
expect(result.success).toBe(false)
|
|
116
|
-
})
|
|
117
|
-
})
|
|
118
|
-
})
|
package/src/schema/boolean.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Schema, ValidationContext } from '../core.js'
|
|
2
|
-
import { memoizedOptions } from '../util/memoize.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Schema for validating boolean values.
|
|
6
|
-
*
|
|
7
|
-
* Only accepts JavaScript `true` or `false` values. Does not perform
|
|
8
|
-
* any coercion from strings or numbers.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* const schema = new BooleanSchema()
|
|
13
|
-
* schema.validate(true) // success
|
|
14
|
-
* schema.validate(false) // success
|
|
15
|
-
* schema.validate('true') // fails - no string coercion
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
export class BooleanSchema extends Schema<boolean> {
|
|
19
|
-
readonly type = 'boolean' as const
|
|
20
|
-
|
|
21
|
-
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
22
|
-
if (typeof input === 'boolean') {
|
|
23
|
-
return ctx.success(input)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return ctx.issueUnexpectedType(input, 'boolean')
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Creates a boolean schema that validates true/false values.
|
|
32
|
-
*
|
|
33
|
-
* @returns A new {@link BooleanSchema} instance
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```ts
|
|
37
|
-
* const enabledSchema = l.boolean()
|
|
38
|
-
*
|
|
39
|
-
* enabledSchema.parse(true) // true
|
|
40
|
-
* enabledSchema.parse(false) // false
|
|
41
|
-
* enabledSchema.parse('true') // throws - strings not accepted
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export const boolean = /*#__PURE__*/ memoizedOptions(function () {
|
|
45
|
-
return new BooleanSchema()
|
|
46
|
-
})
|
package/src/schema/bytes.test.ts
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { bytes } from './bytes.js'
|
|
3
|
-
|
|
4
|
-
describe('BytesSchema', () => {
|
|
5
|
-
describe('basic validation', () => {
|
|
6
|
-
const schema = bytes({})
|
|
7
|
-
|
|
8
|
-
it('validates Uint8Array', () => {
|
|
9
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2, 3]))
|
|
10
|
-
expect(result.success).toBe(true)
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('validates empty Uint8Array', () => {
|
|
14
|
-
const result = schema.safeParse(new Uint8Array([]))
|
|
15
|
-
expect(result.success).toBe(true)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('validates ArrayBuffer', () => {
|
|
19
|
-
const buffer = new ArrayBuffer(4)
|
|
20
|
-
const result = schema.safeParse(buffer)
|
|
21
|
-
expect(result.success).toBe(true)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('validates TypedArray views', () => {
|
|
25
|
-
const int8 = new Int8Array([1, 2, 3])
|
|
26
|
-
const result = schema.safeParse(int8)
|
|
27
|
-
expect(result.success).toBe(true)
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('validates Uint16Array', () => {
|
|
31
|
-
const uint16 = new Uint16Array([1, 2, 3])
|
|
32
|
-
const result = schema.safeParse(uint16)
|
|
33
|
-
expect(result.success).toBe(true)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('validates DataView', () => {
|
|
37
|
-
const buffer = new ArrayBuffer(4)
|
|
38
|
-
const dataView = new DataView(buffer)
|
|
39
|
-
const result = schema.safeParse(dataView)
|
|
40
|
-
expect(result.success).toBe(true)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
it('rejects strings', () => {
|
|
44
|
-
const result = schema.safeParse('not bytes')
|
|
45
|
-
expect(result.success).toBe(false)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('rejects numbers', () => {
|
|
49
|
-
const result = schema.safeParse(123)
|
|
50
|
-
expect(result.success).toBe(false)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('rejects objects', () => {
|
|
54
|
-
const result = schema.safeParse({ data: [1, 2, 3] })
|
|
55
|
-
expect(result.success).toBe(false)
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('rejects arrays', () => {
|
|
59
|
-
const result = schema.safeParse([1, 2, 3])
|
|
60
|
-
expect(result.success).toBe(false)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('rejects null', () => {
|
|
64
|
-
const result = schema.safeParse(null)
|
|
65
|
-
expect(result.success).toBe(false)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('rejects undefined', () => {
|
|
69
|
-
const result = schema.safeParse(undefined)
|
|
70
|
-
expect(result.success).toBe(false)
|
|
71
|
-
})
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
describe('minLength constraint', () => {
|
|
75
|
-
const schema = bytes({ minLength: 3 })
|
|
76
|
-
|
|
77
|
-
it('validates bytes at minimum length', () => {
|
|
78
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2]))
|
|
79
|
-
expect(result.success).toBe(true)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('validates bytes above minimum length', () => {
|
|
83
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2, 3, 4]))
|
|
84
|
-
expect(result.success).toBe(true)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('rejects bytes below minimum length', () => {
|
|
88
|
-
const result = schema.safeParse(new Uint8Array([0, 1]))
|
|
89
|
-
expect(result.success).toBe(false)
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('rejects empty bytes when minLength is set', () => {
|
|
93
|
-
const result = schema.safeParse(new Uint8Array([]))
|
|
94
|
-
expect(result.success).toBe(false)
|
|
95
|
-
})
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
describe('maxLength constraint', () => {
|
|
99
|
-
const schema = bytes({ maxLength: 5 })
|
|
100
|
-
|
|
101
|
-
it('validates bytes at maximum length', () => {
|
|
102
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2, 3, 4]))
|
|
103
|
-
expect(result.success).toBe(true)
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
it('validates bytes below maximum length', () => {
|
|
107
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2]))
|
|
108
|
-
expect(result.success).toBe(true)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
it('validates empty bytes when only maxLength is set', () => {
|
|
112
|
-
const result = schema.safeParse(new Uint8Array([]))
|
|
113
|
-
expect(result.success).toBe(true)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it('rejects bytes above maximum length', () => {
|
|
117
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2, 3, 4, 5]))
|
|
118
|
-
expect(result.success).toBe(false)
|
|
119
|
-
})
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
describe('minLength and maxLength constraints', () => {
|
|
123
|
-
const schema = bytes({ minLength: 2, maxLength: 5 })
|
|
124
|
-
|
|
125
|
-
it('validates bytes within range', () => {
|
|
126
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2]))
|
|
127
|
-
expect(result.success).toBe(true)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('validates bytes at minimum length', () => {
|
|
131
|
-
const result = schema.safeParse(new Uint8Array([0, 1]))
|
|
132
|
-
expect(result.success).toBe(true)
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
it('validates bytes at maximum length', () => {
|
|
136
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2, 3, 4]))
|
|
137
|
-
expect(result.success).toBe(true)
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('rejects bytes below minimum length', () => {
|
|
141
|
-
const result = schema.safeParse(new Uint8Array([0]))
|
|
142
|
-
expect(result.success).toBe(false)
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
it('rejects bytes above maximum length', () => {
|
|
146
|
-
const result = schema.safeParse(new Uint8Array([0, 1, 2, 3, 4, 5]))
|
|
147
|
-
expect(result.success).toBe(false)
|
|
148
|
-
})
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
describe('edge cases', () => {
|
|
152
|
-
it('validates with minLength of 0', () => {
|
|
153
|
-
const schema = bytes({ minLength: 0 })
|
|
154
|
-
const result = schema.safeParse(new Uint8Array([]))
|
|
155
|
-
expect(result.success).toBe(true)
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
it('validates with maxLength of 0', () => {
|
|
159
|
-
const schema = bytes({ maxLength: 0 })
|
|
160
|
-
const result = schema.safeParse(new Uint8Array([]))
|
|
161
|
-
expect(result.success).toBe(true)
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
it('rejects non-empty bytes with maxLength of 0', () => {
|
|
165
|
-
const schema = bytes({ maxLength: 0 })
|
|
166
|
-
const result = schema.safeParse(new Uint8Array([0]))
|
|
167
|
-
expect(result.success).toBe(false)
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
it('validates bytes with all zeros', () => {
|
|
171
|
-
const schema = bytes({})
|
|
172
|
-
const result = schema.safeParse(new Uint8Array([0, 0, 0, 0]))
|
|
173
|
-
expect(result.success).toBe(true)
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
it('validates bytes with all 255s', () => {
|
|
177
|
-
const schema = bytes({})
|
|
178
|
-
const result = schema.safeParse(new Uint8Array([255, 255, 255, 255]))
|
|
179
|
-
expect(result.success).toBe(true)
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
it('validates large byte arrays', () => {
|
|
183
|
-
const schema = bytes({})
|
|
184
|
-
const largeArray = new Uint8Array(10000)
|
|
185
|
-
const result = schema.safeParse(largeArray)
|
|
186
|
-
expect(result.success).toBe(true)
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
describe('TypedArray coercion', () => {
|
|
191
|
-
const schema = bytes({})
|
|
192
|
-
|
|
193
|
-
it('coerces Int8Array to Uint8Array', () => {
|
|
194
|
-
const int8 = new Int8Array([1, 2, 3])
|
|
195
|
-
const result = schema.safeParse(int8)
|
|
196
|
-
expect(result.success).toBe(true)
|
|
197
|
-
if (result.success) {
|
|
198
|
-
expect(result.value).toBeInstanceOf(Uint8Array)
|
|
199
|
-
}
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
it('coerces Uint16Array to Uint8Array', () => {
|
|
203
|
-
const uint16 = new Uint16Array([256, 512])
|
|
204
|
-
const result = schema.safeParse(uint16)
|
|
205
|
-
expect(result.success).toBe(true)
|
|
206
|
-
if (result.success) {
|
|
207
|
-
expect(result.value).toBeInstanceOf(Uint8Array)
|
|
208
|
-
}
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
it('coerces Float32Array to Uint8Array', () => {
|
|
212
|
-
const float32 = new Float32Array([1.5, 2.5])
|
|
213
|
-
const result = schema.safeParse(float32)
|
|
214
|
-
expect(result.success).toBe(true)
|
|
215
|
-
if (result.success) {
|
|
216
|
-
expect(result.value).toBeInstanceOf(Uint8Array)
|
|
217
|
-
}
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
it('validates coerced TypedArray with length constraints', () => {
|
|
221
|
-
const schema = bytes({ minLength: 2, maxLength: 10 })
|
|
222
|
-
const int16 = new Int16Array([1, 2, 3]) // 6 bytes
|
|
223
|
-
const result = schema.safeParse(int16)
|
|
224
|
-
expect(result.success).toBe(true)
|
|
225
|
-
})
|
|
226
|
-
})
|
|
227
|
-
})
|
package/src/schema/bytes.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { asUint8Array, ifUint8Array } from '@atproto/lex-data'
|
|
2
|
-
import { Schema, ValidationContext } from '../core.js'
|
|
3
|
-
import { memoizedOptions } from '../util/memoize.js'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Configuration options for bytes schema validation.
|
|
7
|
-
*
|
|
8
|
-
* @property minLength - Minimum length in bytes
|
|
9
|
-
* @property maxLength - Maximum length in bytes
|
|
10
|
-
*/
|
|
11
|
-
export type BytesSchemaOptions = {
|
|
12
|
-
minLength?: number
|
|
13
|
-
maxLength?: number
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Schema for validating binary data as Uint8Array with optional length constraints.
|
|
18
|
-
*
|
|
19
|
-
* In "parse" mode, coerces various binary formats (Buffer, ArrayBuffer, etc.)
|
|
20
|
-
* into Uint8Array. In "validate" mode, only accepts Uint8Array directly.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```ts
|
|
24
|
-
* const schema = new BytesSchema({ maxLength: 1024 })
|
|
25
|
-
* const result = schema.validate(new Uint8Array([1, 2, 3]))
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
export class BytesSchema extends Schema<Uint8Array> {
|
|
29
|
-
readonly type = 'bytes' as const
|
|
30
|
-
|
|
31
|
-
constructor(readonly options: BytesSchemaOptions = {}) {
|
|
32
|
-
super()
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
36
|
-
// In "parse" mode, coerce different binary formats into Uint8Array
|
|
37
|
-
const bytes =
|
|
38
|
-
ctx.options.mode === 'parse' ? asUint8Array(input) : ifUint8Array(input)
|
|
39
|
-
if (!bytes) {
|
|
40
|
-
return ctx.issueUnexpectedType(input, 'bytes')
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const { minLength } = this.options
|
|
44
|
-
if (minLength != null && bytes.length < minLength) {
|
|
45
|
-
return ctx.issueTooSmall(bytes, 'bytes', minLength, bytes.length)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const { maxLength } = this.options
|
|
49
|
-
if (maxLength != null && bytes.length > maxLength) {
|
|
50
|
-
return ctx.issueTooBig(bytes, 'bytes', maxLength, bytes.length)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return ctx.success(bytes)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Creates a bytes schema for validating binary data with optional length constraints.
|
|
59
|
-
*
|
|
60
|
-
* Validates Uint8Array values and can coerce other binary formats in parse mode.
|
|
61
|
-
*
|
|
62
|
-
* @param options - Optional configuration for minimum and maximum byte length
|
|
63
|
-
* @returns A new {@link BytesSchema} instance
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```ts
|
|
67
|
-
* // Basic bytes schema
|
|
68
|
-
* const dataSchema = l.bytes()
|
|
69
|
-
*
|
|
70
|
-
* // With size constraints
|
|
71
|
-
* const avatarSchema = l.bytes({ maxLength: 1000000 }) // 1MB max
|
|
72
|
-
*
|
|
73
|
-
* // With minimum size
|
|
74
|
-
* const hashSchema = l.bytes({ minLength: 32, maxLength: 32 }) // Exactly 32 bytes
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export const bytes = /*#__PURE__*/ memoizedOptions(function (
|
|
78
|
-
options?: BytesSchemaOptions,
|
|
79
|
-
) {
|
|
80
|
-
return new BytesSchema(options)
|
|
81
|
-
})
|