@atproto/lex-schema 0.1.5 → 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.
Files changed (263) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/core/$type.d.ts +2 -2
  3. package/dist/core/$type.d.ts.map +1 -1
  4. package/dist/core/$type.js.map +1 -1
  5. package/dist/core/record-key.d.ts +1 -1
  6. package/dist/core/record-key.d.ts.map +1 -1
  7. package/dist/core/record-key.js.map +1 -1
  8. package/dist/core/schema.d.ts +3 -2
  9. package/dist/core/schema.d.ts.map +1 -1
  10. package/dist/core/schema.js +1 -1
  11. package/dist/core/schema.js.map +1 -1
  12. package/dist/core/standard-schema.d.ts +2 -2
  13. package/dist/core/standard-schema.d.ts.map +1 -1
  14. package/dist/core/standard-schema.js.map +1 -1
  15. package/dist/core/string-format.d.ts +2 -2
  16. package/dist/core/string-format.d.ts.map +1 -1
  17. package/dist/core/string-format.js.map +1 -1
  18. package/dist/core/validation-error.d.ts +1 -1
  19. package/dist/core/validation-error.d.ts.map +1 -1
  20. package/dist/core/validation-error.js +1 -1
  21. package/dist/core/validation-error.js.map +1 -1
  22. package/dist/core/validator.d.ts +1 -1
  23. package/dist/core/validator.d.ts.map +1 -1
  24. package/dist/core/validator.js +1 -1
  25. package/dist/core/validator.js.map +1 -1
  26. package/dist/helpers.d.ts +2 -2
  27. package/dist/helpers.d.ts.map +1 -1
  28. package/dist/helpers.js +2 -2
  29. package/dist/helpers.js.map +1 -1
  30. package/dist/schema/array.d.ts +1 -1
  31. package/dist/schema/array.d.ts.map +1 -1
  32. package/dist/schema/array.js +1 -1
  33. package/dist/schema/array.js.map +1 -1
  34. package/dist/schema/blob.d.ts +1 -1
  35. package/dist/schema/blob.d.ts.map +1 -1
  36. package/dist/schema/blob.js +2 -2
  37. package/dist/schema/blob.js.map +1 -1
  38. package/dist/schema/boolean.js +1 -1
  39. package/dist/schema/boolean.js.map +1 -1
  40. package/dist/schema/bytes.js +1 -1
  41. package/dist/schema/bytes.js.map +1 -1
  42. package/dist/schema/cid.d.ts +1 -1
  43. package/dist/schema/cid.d.ts.map +1 -1
  44. package/dist/schema/cid.js +3 -3
  45. package/dist/schema/cid.js.map +1 -1
  46. package/dist/schema/custom.js +1 -1
  47. package/dist/schema/custom.js.map +1 -1
  48. package/dist/schema/dict.d.ts +1 -1
  49. package/dist/schema/dict.d.ts.map +1 -1
  50. package/dist/schema/dict.js +1 -1
  51. package/dist/schema/dict.js.map +1 -1
  52. package/dist/schema/discriminated-union.d.ts +1 -1
  53. package/dist/schema/discriminated-union.d.ts.map +1 -1
  54. package/dist/schema/discriminated-union.js +2 -1
  55. package/dist/schema/discriminated-union.js.map +1 -1
  56. package/dist/schema/enum.js +1 -1
  57. package/dist/schema/enum.js.map +1 -1
  58. package/dist/schema/integer.js +1 -1
  59. package/dist/schema/integer.js.map +1 -1
  60. package/dist/schema/intersection.d.ts +1 -1
  61. package/dist/schema/intersection.d.ts.map +1 -1
  62. package/dist/schema/intersection.js +3 -1
  63. package/dist/schema/intersection.js.map +1 -1
  64. package/dist/schema/lex-map.d.ts +1 -1
  65. package/dist/schema/lex-map.d.ts.map +1 -1
  66. package/dist/schema/lex-map.js +1 -1
  67. package/dist/schema/lex-map.js.map +1 -1
  68. package/dist/schema/lex-value.d.ts +1 -1
  69. package/dist/schema/lex-value.d.ts.map +1 -1
  70. package/dist/schema/lex-value.js +1 -1
  71. package/dist/schema/lex-value.js.map +1 -1
  72. package/dist/schema/literal.js +1 -1
  73. package/dist/schema/literal.js.map +1 -1
  74. package/dist/schema/never.js +1 -1
  75. package/dist/schema/never.js.map +1 -1
  76. package/dist/schema/null.js +1 -1
  77. package/dist/schema/null.js.map +1 -1
  78. package/dist/schema/nullable.d.ts +1 -1
  79. package/dist/schema/nullable.d.ts.map +1 -1
  80. package/dist/schema/nullable.js +1 -1
  81. package/dist/schema/nullable.js.map +1 -1
  82. package/dist/schema/object.d.ts +2 -1
  83. package/dist/schema/object.d.ts.map +1 -1
  84. package/dist/schema/object.js +1 -1
  85. package/dist/schema/object.js.map +1 -1
  86. package/dist/schema/optional.d.ts +2 -1
  87. package/dist/schema/optional.d.ts.map +1 -1
  88. package/dist/schema/optional.js +2 -1
  89. package/dist/schema/optional.js.map +1 -1
  90. package/dist/schema/params.d.ts +1 -1
  91. package/dist/schema/params.d.ts.map +1 -1
  92. package/dist/schema/params.js +1 -1
  93. package/dist/schema/params.js.map +1 -1
  94. package/dist/schema/payload.d.ts +3 -2
  95. package/dist/schema/payload.d.ts.map +1 -1
  96. package/dist/schema/payload.js +2 -1
  97. package/dist/schema/payload.js.map +1 -1
  98. package/dist/schema/permission-set.d.ts +1 -1
  99. package/dist/schema/permission-set.d.ts.map +1 -1
  100. package/dist/schema/permission-set.js +1 -0
  101. package/dist/schema/permission-set.js.map +1 -1
  102. package/dist/schema/permission.d.ts +1 -1
  103. package/dist/schema/permission.d.ts.map +1 -1
  104. package/dist/schema/permission.js.map +1 -1
  105. package/dist/schema/procedure.d.ts +1 -1
  106. package/dist/schema/procedure.d.ts.map +1 -1
  107. package/dist/schema/procedure.js +2 -0
  108. package/dist/schema/procedure.js.map +1 -1
  109. package/dist/schema/query.d.ts +1 -1
  110. package/dist/schema/query.d.ts.map +1 -1
  111. package/dist/schema/query.js +2 -0
  112. package/dist/schema/query.js.map +1 -1
  113. package/dist/schema/record.d.ts +2 -2
  114. package/dist/schema/record.d.ts.map +1 -1
  115. package/dist/schema/record.js +1 -1
  116. package/dist/schema/record.js.map +1 -1
  117. package/dist/schema/ref.d.ts +1 -1
  118. package/dist/schema/ref.d.ts.map +1 -1
  119. package/dist/schema/ref.js +1 -1
  120. package/dist/schema/ref.js.map +1 -1
  121. package/dist/schema/refine.d.ts +2 -2
  122. package/dist/schema/refine.d.ts.map +1 -1
  123. package/dist/schema/refine.js +1 -1
  124. package/dist/schema/refine.js.map +1 -1
  125. package/dist/schema/regexp.js +1 -1
  126. package/dist/schema/regexp.js.map +1 -1
  127. package/dist/schema/string.d.ts +2 -2
  128. package/dist/schema/string.d.ts.map +1 -1
  129. package/dist/schema/string.js +1 -1
  130. package/dist/schema/string.js.map +1 -1
  131. package/dist/schema/subscription.d.ts +3 -2
  132. package/dist/schema/subscription.d.ts.map +1 -1
  133. package/dist/schema/subscription.js +2 -0
  134. package/dist/schema/subscription.js.map +1 -1
  135. package/dist/schema/token.d.ts +1 -1
  136. package/dist/schema/token.d.ts.map +1 -1
  137. package/dist/schema/token.js +1 -1
  138. package/dist/schema/token.js.map +1 -1
  139. package/dist/schema/typed-object.d.ts +2 -2
  140. package/dist/schema/typed-object.d.ts.map +1 -1
  141. package/dist/schema/typed-object.js +1 -1
  142. package/dist/schema/typed-object.js.map +1 -1
  143. package/dist/schema/typed-ref.d.ts +1 -1
  144. package/dist/schema/typed-ref.d.ts.map +1 -1
  145. package/dist/schema/typed-ref.js +1 -1
  146. package/dist/schema/typed-ref.js.map +1 -1
  147. package/dist/schema/typed-union.d.ts +1 -1
  148. package/dist/schema/typed-union.d.ts.map +1 -1
  149. package/dist/schema/typed-union.js +3 -1
  150. package/dist/schema/typed-union.js.map +1 -1
  151. package/dist/schema/union.d.ts +1 -1
  152. package/dist/schema/union.d.ts.map +1 -1
  153. package/dist/schema/union.js +1 -1
  154. package/dist/schema/union.js.map +1 -1
  155. package/dist/schema/unknown.js +1 -1
  156. package/dist/schema/unknown.js.map +1 -1
  157. package/dist/schema/with-default.d.ts +1 -1
  158. package/dist/schema/with-default.d.ts.map +1 -1
  159. package/dist/schema/with-default.js +1 -1
  160. package/dist/schema/with-default.js.map +1 -1
  161. package/package.json +6 -10
  162. package/src/core/$type.test.ts +0 -24
  163. package/src/core/$type.ts +0 -199
  164. package/src/core/record-key.ts +0 -85
  165. package/src/core/result.ts +0 -15
  166. package/src/core/schema.ts +0 -412
  167. package/src/core/standard-schema.test.ts +0 -124
  168. package/src/core/standard-schema.ts +0 -31
  169. package/src/core/string-format.ts +0 -411
  170. package/src/core/types.ts +0 -120
  171. package/src/core/validation-error.ts +0 -134
  172. package/src/core/validation-issue.ts +0 -340
  173. package/src/core/validator.ts +0 -636
  174. package/src/core.ts +0 -9
  175. package/src/external.ts +0 -3
  176. package/src/helpers.test.ts +0 -694
  177. package/src/helpers.ts +0 -222
  178. package/src/index.ts +0 -3
  179. package/src/schema/array.test.ts +0 -251
  180. package/src/schema/array.ts +0 -126
  181. package/src/schema/blob.test.ts +0 -733
  182. package/src/schema/blob.ts +0 -150
  183. package/src/schema/boolean.test.ts +0 -118
  184. package/src/schema/boolean.ts +0 -46
  185. package/src/schema/bytes.test.ts +0 -227
  186. package/src/schema/bytes.ts +0 -81
  187. package/src/schema/cid.test.ts +0 -125
  188. package/src/schema/cid.ts +0 -69
  189. package/src/schema/custom.test.ts +0 -414
  190. package/src/schema/custom.ts +0 -106
  191. package/src/schema/dict.test.ts +0 -181
  192. package/src/schema/dict.ts +0 -122
  193. package/src/schema/discriminated-union.test.ts +0 -676
  194. package/src/schema/discriminated-union.ts +0 -196
  195. package/src/schema/enum.test.ts +0 -398
  196. package/src/schema/enum.ts +0 -77
  197. package/src/schema/integer.test.ts +0 -314
  198. package/src/schema/integer.ts +0 -86
  199. package/src/schema/intersection.test.ts +0 -33
  200. package/src/schema/intersection.ts +0 -113
  201. package/src/schema/lex-map.test.ts +0 -593
  202. package/src/schema/lex-map.ts +0 -63
  203. package/src/schema/lex-value.test.ts +0 -81
  204. package/src/schema/lex-value.ts +0 -86
  205. package/src/schema/literal.test.ts +0 -533
  206. package/src/schema/literal.ts +0 -70
  207. package/src/schema/never.test.ts +0 -175
  208. package/src/schema/never.ts +0 -56
  209. package/src/schema/null.test.ts +0 -80
  210. package/src/schema/null.ts +0 -49
  211. package/src/schema/nullable.test.ts +0 -470
  212. package/src/schema/nullable.ts +0 -74
  213. package/src/schema/object.test.ts +0 -69
  214. package/src/schema/object.ts +0 -136
  215. package/src/schema/optional.test.ts +0 -479
  216. package/src/schema/optional.ts +0 -92
  217. package/src/schema/params.test.ts +0 -1118
  218. package/src/schema/params.ts +0 -371
  219. package/src/schema/payload.test.ts +0 -340
  220. package/src/schema/payload.ts +0 -204
  221. package/src/schema/permission-set.test.ts +0 -613
  222. package/src/schema/permission-set.ts +0 -86
  223. package/src/schema/permission.test.ts +0 -537
  224. package/src/schema/permission.ts +0 -63
  225. package/src/schema/procedure.test.ts +0 -324
  226. package/src/schema/procedure.ts +0 -98
  227. package/src/schema/query.test.ts +0 -348
  228. package/src/schema/query.ts +0 -86
  229. package/src/schema/record.test.ts +0 -812
  230. package/src/schema/record.ts +0 -217
  231. package/src/schema/ref.test.ts +0 -349
  232. package/src/schema/ref.ts +0 -103
  233. package/src/schema/refine.test.ts +0 -579
  234. package/src/schema/refine.ts +0 -153
  235. package/src/schema/regexp.test.ts +0 -577
  236. package/src/schema/regexp.ts +0 -82
  237. package/src/schema/string.test.ts +0 -773
  238. package/src/schema/string.ts +0 -229
  239. package/src/schema/subscription.test.ts +0 -499
  240. package/src/schema/subscription.ts +0 -108
  241. package/src/schema/token.test.ts +0 -152
  242. package/src/schema/token.ts +0 -103
  243. package/src/schema/typed-object.test.ts +0 -745
  244. package/src/schema/typed-object.ts +0 -181
  245. package/src/schema/typed-ref.test.ts +0 -796
  246. package/src/schema/typed-ref.ts +0 -126
  247. package/src/schema/typed-union.test.ts +0 -355
  248. package/src/schema/typed-union.ts +0 -130
  249. package/src/schema/union.test.ts +0 -191
  250. package/src/schema/union.ts +0 -89
  251. package/src/schema/unknown.test.ts +0 -313
  252. package/src/schema/unknown.ts +0 -47
  253. package/src/schema/with-default.ts +0 -81
  254. package/src/schema.ts +0 -43
  255. package/src/util/array-agg.test.ts +0 -42
  256. package/src/util/array-agg.ts +0 -44
  257. package/src/util/assertion-util.ts +0 -1
  258. package/src/util/if-any.ts +0 -3
  259. package/src/util/lazy-property.ts +0 -14
  260. package/src/util/memoize.ts +0 -37
  261. package/tsconfig.build.json +0 -12
  262. package/tsconfig.json +0 -7
  263. package/tsconfig.tests.json +0 -8
@@ -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
- })
@@ -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
- })
@@ -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
- })
@@ -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
- })