@atproto/lex-schema 0.0.11 → 0.0.13

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 (261) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/core/$type.d.ts +149 -0
  3. package/dist/core/$type.d.ts.map +1 -1
  4. package/dist/core/$type.js +44 -0
  5. package/dist/core/$type.js.map +1 -1
  6. package/dist/core/record-key.d.ts +44 -0
  7. package/dist/core/record-key.d.ts.map +1 -1
  8. package/dist/core/record-key.js +30 -0
  9. package/dist/core/record-key.js.map +1 -1
  10. package/dist/core/result.d.ts +85 -4
  11. package/dist/core/result.d.ts.map +1 -1
  12. package/dist/core/result.js +60 -4
  13. package/dist/core/result.js.map +1 -1
  14. package/dist/core/schema.d.ts +232 -5
  15. package/dist/core/schema.d.ts.map +1 -1
  16. package/dist/core/schema.js +197 -4
  17. package/dist/core/schema.js.map +1 -1
  18. package/dist/core/string-format.d.ts +244 -11
  19. package/dist/core/string-format.d.ts.map +1 -1
  20. package/dist/core/string-format.js +150 -0
  21. package/dist/core/string-format.js.map +1 -1
  22. package/dist/core/types.d.ts +90 -3
  23. package/dist/core/types.d.ts.map +1 -1
  24. package/dist/core/types.js.map +1 -1
  25. package/dist/core/validation-error.d.ts +60 -0
  26. package/dist/core/validation-error.d.ts.map +1 -1
  27. package/dist/core/validation-error.js +60 -0
  28. package/dist/core/validation-error.js.map +1 -1
  29. package/dist/core/validation-issue.d.ts +61 -0
  30. package/dist/core/validation-issue.d.ts.map +1 -1
  31. package/dist/core/validation-issue.js +54 -1
  32. package/dist/core/validation-issue.js.map +1 -1
  33. package/dist/core/validator.d.ts +356 -11
  34. package/dist/core/validator.d.ts.map +1 -1
  35. package/dist/core/validator.js +203 -4
  36. package/dist/core/validator.js.map +1 -1
  37. package/dist/helpers.d.ts +12 -28
  38. package/dist/helpers.d.ts.map +1 -1
  39. package/dist/helpers.js.map +1 -1
  40. package/dist/schema/array.d.ts +46 -0
  41. package/dist/schema/array.d.ts.map +1 -1
  42. package/dist/schema/array.js +16 -1
  43. package/dist/schema/array.js.map +1 -1
  44. package/dist/schema/blob.d.ts +50 -2
  45. package/dist/schema/blob.d.ts.map +1 -1
  46. package/dist/schema/blob.js +44 -2
  47. package/dist/schema/blob.js.map +1 -1
  48. package/dist/schema/boolean.d.ts +29 -0
  49. package/dist/schema/boolean.d.ts.map +1 -1
  50. package/dist/schema/boolean.js +30 -1
  51. package/dist/schema/boolean.js.map +1 -1
  52. package/dist/schema/bytes.d.ts +39 -0
  53. package/dist/schema/bytes.d.ts.map +1 -1
  54. package/dist/schema/bytes.js +34 -1
  55. package/dist/schema/bytes.js.map +1 -1
  56. package/dist/schema/cid.d.ts +39 -0
  57. package/dist/schema/cid.d.ts.map +1 -1
  58. package/dist/schema/cid.js +35 -1
  59. package/dist/schema/cid.js.map +1 -1
  60. package/dist/schema/custom.d.ts +67 -1
  61. package/dist/schema/custom.d.ts.map +1 -1
  62. package/dist/schema/custom.js +55 -0
  63. package/dist/schema/custom.js.map +1 -1
  64. package/dist/schema/dict.d.ts +45 -0
  65. package/dist/schema/dict.d.ts.map +1 -1
  66. package/dist/schema/dict.js +46 -1
  67. package/dist/schema/dict.js.map +1 -1
  68. package/dist/schema/discriminated-union.d.ts +59 -0
  69. package/dist/schema/discriminated-union.d.ts.map +1 -1
  70. package/dist/schema/discriminated-union.js +47 -1
  71. package/dist/schema/discriminated-union.js.map +1 -1
  72. package/dist/schema/enum.d.ts +49 -0
  73. package/dist/schema/enum.d.ts.map +1 -1
  74. package/dist/schema/enum.js +49 -0
  75. package/dist/schema/enum.js.map +1 -1
  76. package/dist/schema/integer.d.ts +43 -0
  77. package/dist/schema/integer.d.ts.map +1 -1
  78. package/dist/schema/integer.js +38 -1
  79. package/dist/schema/integer.js.map +1 -1
  80. package/dist/schema/intersection.d.ts +55 -0
  81. package/dist/schema/intersection.d.ts.map +1 -1
  82. package/dist/schema/intersection.js +50 -0
  83. package/dist/schema/intersection.js.map +1 -1
  84. package/dist/schema/lex-map.d.ts +37 -0
  85. package/dist/schema/lex-map.d.ts.map +1 -0
  86. package/dist/schema/lex-map.js +60 -0
  87. package/dist/schema/lex-map.js.map +1 -0
  88. package/dist/schema/lex-value.d.ts +35 -0
  89. package/dist/schema/lex-value.d.ts.map +1 -0
  90. package/dist/schema/lex-value.js +87 -0
  91. package/dist/schema/lex-value.js.map +1 -0
  92. package/dist/schema/literal.d.ts +45 -0
  93. package/dist/schema/literal.d.ts.map +1 -1
  94. package/dist/schema/literal.js +45 -0
  95. package/dist/schema/literal.js.map +1 -1
  96. package/dist/schema/never.d.ts +43 -0
  97. package/dist/schema/never.d.ts.map +1 -1
  98. package/dist/schema/never.js +44 -1
  99. package/dist/schema/never.js.map +1 -1
  100. package/dist/schema/null.d.ts +30 -0
  101. package/dist/schema/null.d.ts.map +1 -1
  102. package/dist/schema/null.js +31 -1
  103. package/dist/schema/null.js.map +1 -1
  104. package/dist/schema/nullable.d.ts +42 -0
  105. package/dist/schema/nullable.d.ts.map +1 -1
  106. package/dist/schema/nullable.js +42 -0
  107. package/dist/schema/nullable.js.map +1 -1
  108. package/dist/schema/object.d.ts +57 -0
  109. package/dist/schema/object.d.ts.map +1 -1
  110. package/dist/schema/object.js +53 -1
  111. package/dist/schema/object.js.map +1 -1
  112. package/dist/schema/optional.d.ts +43 -0
  113. package/dist/schema/optional.d.ts.map +1 -1
  114. package/dist/schema/optional.js +43 -0
  115. package/dist/schema/optional.js.map +1 -1
  116. package/dist/schema/params.d.ts +96 -12
  117. package/dist/schema/params.d.ts.map +1 -1
  118. package/dist/schema/params.js +155 -21
  119. package/dist/schema/params.js.map +1 -1
  120. package/dist/schema/payload.d.ts +111 -15
  121. package/dist/schema/payload.d.ts.map +1 -1
  122. package/dist/schema/payload.js +73 -3
  123. package/dist/schema/payload.js.map +1 -1
  124. package/dist/schema/permission-set.d.ts +58 -0
  125. package/dist/schema/permission-set.d.ts.map +1 -1
  126. package/dist/schema/permission-set.js +50 -0
  127. package/dist/schema/permission-set.js.map +1 -1
  128. package/dist/schema/permission.d.ts +42 -0
  129. package/dist/schema/permission.d.ts.map +1 -1
  130. package/dist/schema/permission.js +39 -0
  131. package/dist/schema/permission.js.map +1 -1
  132. package/dist/schema/procedure.d.ts +64 -0
  133. package/dist/schema/procedure.d.ts.map +1 -1
  134. package/dist/schema/procedure.js +64 -0
  135. package/dist/schema/procedure.js.map +1 -1
  136. package/dist/schema/query.d.ts +55 -0
  137. package/dist/schema/query.d.ts.map +1 -1
  138. package/dist/schema/query.js +55 -0
  139. package/dist/schema/query.js.map +1 -1
  140. package/dist/schema/record.d.ts +76 -25
  141. package/dist/schema/record.d.ts.map +1 -1
  142. package/dist/schema/record.js +21 -0
  143. package/dist/schema/record.js.map +1 -1
  144. package/dist/schema/ref.d.ts +51 -0
  145. package/dist/schema/ref.d.ts.map +1 -1
  146. package/dist/schema/ref.js +18 -0
  147. package/dist/schema/ref.js.map +1 -1
  148. package/dist/schema/refine.d.ts +58 -9
  149. package/dist/schema/refine.d.ts.map +1 -1
  150. package/dist/schema/refine.js.map +1 -1
  151. package/dist/schema/regexp.d.ts +45 -0
  152. package/dist/schema/regexp.d.ts.map +1 -1
  153. package/dist/schema/regexp.js +46 -1
  154. package/dist/schema/regexp.js.map +1 -1
  155. package/dist/schema/string.d.ts +72 -6
  156. package/dist/schema/string.d.ts.map +1 -1
  157. package/dist/schema/string.js +56 -8
  158. package/dist/schema/string.js.map +1 -1
  159. package/dist/schema/subscription.d.ts +72 -2
  160. package/dist/schema/subscription.d.ts.map +1 -1
  161. package/dist/schema/subscription.js +59 -0
  162. package/dist/schema/subscription.js.map +1 -1
  163. package/dist/schema/token.d.ts +48 -0
  164. package/dist/schema/token.d.ts.map +1 -1
  165. package/dist/schema/token.js +49 -1
  166. package/dist/schema/token.js.map +1 -1
  167. package/dist/schema/typed-object.d.ts +73 -23
  168. package/dist/schema/typed-object.d.ts.map +1 -1
  169. package/dist/schema/typed-object.js +20 -1
  170. package/dist/schema/typed-object.js.map +1 -1
  171. package/dist/schema/typed-ref.d.ts +54 -0
  172. package/dist/schema/typed-ref.d.ts.map +1 -1
  173. package/dist/schema/typed-ref.js +16 -0
  174. package/dist/schema/typed-ref.js.map +1 -1
  175. package/dist/schema/typed-union.d.ts +51 -1
  176. package/dist/schema/typed-union.d.ts.map +1 -1
  177. package/dist/schema/typed-union.js +52 -2
  178. package/dist/schema/typed-union.js.map +1 -1
  179. package/dist/schema/union.d.ts +46 -0
  180. package/dist/schema/union.d.ts.map +1 -1
  181. package/dist/schema/union.js +41 -0
  182. package/dist/schema/union.js.map +1 -1
  183. package/dist/schema/unknown.d.ts +34 -0
  184. package/dist/schema/unknown.d.ts.map +1 -1
  185. package/dist/schema/unknown.js +34 -0
  186. package/dist/schema/unknown.js.map +1 -1
  187. package/dist/schema/with-default.d.ts +45 -0
  188. package/dist/schema/with-default.d.ts.map +1 -1
  189. package/dist/schema/with-default.js +45 -0
  190. package/dist/schema/with-default.js.map +1 -1
  191. package/dist/schema.d.ts +2 -1
  192. package/dist/schema.d.ts.map +1 -1
  193. package/dist/schema.js +2 -1
  194. package/dist/schema.js.map +1 -1
  195. package/dist/util/if-any.d.ts +2 -0
  196. package/dist/util/if-any.d.ts.map +1 -0
  197. package/dist/util/if-any.js +3 -0
  198. package/dist/util/if-any.js.map +1 -0
  199. package/package.json +3 -3
  200. package/src/core/$type.ts +150 -18
  201. package/src/core/record-key.ts +44 -0
  202. package/src/core/result.ts +86 -4
  203. package/src/core/schema.ts +244 -9
  204. package/src/core/string-format.ts +259 -13
  205. package/src/core/types.ts +91 -3
  206. package/src/core/validation-error.ts +60 -0
  207. package/src/core/validation-issue.ts +68 -2
  208. package/src/core/validator.ts +373 -12
  209. package/src/helpers.test.ts +110 -29
  210. package/src/helpers.ts +54 -25
  211. package/src/schema/array.test.ts +94 -79
  212. package/src/schema/array.ts +48 -1
  213. package/src/schema/blob.ts +50 -1
  214. package/src/schema/boolean.ts +31 -1
  215. package/src/schema/bytes.ts +41 -1
  216. package/src/schema/cid.ts +41 -1
  217. package/src/schema/custom.ts +68 -1
  218. package/src/schema/dict.ts +47 -1
  219. package/src/schema/discriminated-union.ts +61 -1
  220. package/src/schema/enum.ts +50 -0
  221. package/src/schema/integer.ts +45 -1
  222. package/src/schema/intersection.ts +56 -0
  223. package/src/schema/{unknown-object.test.ts → lex-map.test.ts} +9 -9
  224. package/src/schema/lex-map.ts +63 -0
  225. package/src/schema/lex-value.test.ts +81 -0
  226. package/src/schema/lex-value.ts +86 -0
  227. package/src/schema/literal.ts +46 -0
  228. package/src/schema/never.ts +45 -1
  229. package/src/schema/null.ts +32 -1
  230. package/src/schema/nullable.ts +43 -0
  231. package/src/schema/object.ts +59 -1
  232. package/src/schema/optional.ts +44 -0
  233. package/src/schema/params.test.ts +133 -38
  234. package/src/schema/params.ts +237 -37
  235. package/src/schema/payload.test.ts +3 -3
  236. package/src/schema/payload.ts +145 -42
  237. package/src/schema/permission-set.ts +58 -0
  238. package/src/schema/permission.ts +42 -0
  239. package/src/schema/procedure.ts +64 -0
  240. package/src/schema/query.ts +55 -0
  241. package/src/schema/record.ts +82 -16
  242. package/src/schema/ref.ts +52 -0
  243. package/src/schema/refine.ts +58 -9
  244. package/src/schema/regexp.ts +47 -1
  245. package/src/schema/string.test.ts +99 -2
  246. package/src/schema/string.ts +108 -15
  247. package/src/schema/subscription.ts +72 -2
  248. package/src/schema/token.ts +50 -1
  249. package/src/schema/typed-object.ts +81 -16
  250. package/src/schema/typed-ref.ts +55 -0
  251. package/src/schema/typed-union.ts +58 -3
  252. package/src/schema/union.ts +47 -0
  253. package/src/schema/unknown.ts +35 -0
  254. package/src/schema/with-default.ts +46 -0
  255. package/src/schema.ts +2 -1
  256. package/src/util/if-any.ts +3 -0
  257. package/dist/schema/unknown-object.d.ts +0 -8
  258. package/dist/schema/unknown-object.d.ts.map +0 -1
  259. package/dist/schema/unknown-object.js +0 -19
  260. package/dist/schema/unknown-object.js.map +0 -1
  261. package/src/schema/unknown-object.ts +0 -19
@@ -5,103 +5,118 @@ import { object } from './object.js'
5
5
  import { string } from './string.js'
6
6
 
7
7
  describe('ArraySchema', () => {
8
- it('validates arrays with string items', () => {
9
- const schema = array(string())
10
- const result = schema.safeParse(['hello', 'world'])
11
- expect(result.success).toBe(true)
12
- })
13
-
14
- it('validates arrays with integer items', () => {
15
- const schema = array(integer())
16
- const result = schema.safeParse([1, 2, 3])
17
- expect(result.success).toBe(true)
18
- })
8
+ describe('validation', () => {
9
+ it('validates arrays with string items', () => {
10
+ const schema = array(string())
11
+ const result = schema.safeValidate(['hello', 'world'])
12
+ expect(result).toMatchObject({ success: true })
13
+ })
14
+
15
+ it('validates arrays with integer items', () => {
16
+ const schema = array(integer())
17
+ const result = schema.safeValidate([1, 2, 3])
18
+ expect(result).toMatchObject({ success: true })
19
+ })
20
+
21
+ it('validates arrays with object items', () => {
22
+ const schema = array(
23
+ object({
24
+ name: string(),
25
+ age: integer(),
26
+ }),
27
+ )
28
+ const result = schema.safeValidate([
29
+ { name: 'Alice', age: 30 },
30
+ { name: 'Bob', age: 25 },
31
+ ])
32
+ expect(result).toMatchObject({ success: true })
33
+ })
19
34
 
20
- it('validates arrays with object items', () => {
21
- const schema = array(
22
- object({
23
- name: string(),
24
- age: integer(),
25
- }),
26
- )
27
- const result = schema.safeParse([
28
- { name: 'Alice', age: 30 },
29
- { name: 'Bob', age: 25 },
30
- ])
31
- expect(result.success).toBe(true)
32
- })
35
+ it('validates empty arrays', () => {
36
+ const schema = array(string())
37
+ const result = schema.safeValidate([])
38
+ expect(result).toMatchObject({ success: true })
39
+ })
33
40
 
34
- it('validates empty arrays', () => {
35
- const schema = array(string())
36
- const result = schema.safeParse([])
37
- expect(result.success).toBe(true)
38
- })
41
+ it('rejects non-array values', () => {
42
+ const schema = array(string())
43
+ const result = schema.safeValidate('not an array')
44
+ expect(result).toMatchObject({ success: false })
45
+ })
39
46
 
40
- it('rejects non-array values', () => {
41
- const schema = array(string())
42
- const result = schema.safeParse('not an array')
43
- expect(result.success).toBe(false)
44
- })
47
+ it('rejects null values', () => {
48
+ const schema = array(string())
49
+ const result = schema.safeValidate(null)
50
+ expect(result).toMatchObject({ success: false })
51
+ })
45
52
 
46
- it('rejects null values', () => {
47
- const schema = array(string())
48
- const result = schema.safeParse(null)
49
- expect(result.success).toBe(false)
50
- })
53
+ it('rejects undefined values', () => {
54
+ const schema = array(string())
55
+ const result = schema.safeValidate(undefined)
56
+ expect(result).toMatchObject({ success: false })
57
+ })
51
58
 
52
- it('rejects undefined values', () => {
53
- const schema = array(string())
54
- const result = schema.safeParse(undefined)
55
- expect(result.success).toBe(false)
56
- })
59
+ it('rejects objects that look like arrays', () => {
60
+ const schema = array(string())
61
+ const result = schema.safeValidate({ 0: 'a', 1: 'b', length: 2 })
62
+ expect(result).toMatchObject({ success: false })
63
+ })
57
64
 
58
- it('rejects objects that look like arrays', () => {
59
- const schema = array(string())
60
- const result = schema.safeParse({ 0: 'a', 1: 'b', length: 2 })
61
- expect(result.success).toBe(false)
62
- })
65
+ it('rejects arrays with invalid items', () => {
66
+ const schema = array(integer())
67
+ const result = schema.safeValidate([1, 2, 'three'])
68
+ expect(result).toMatchObject({ success: false })
69
+ })
63
70
 
64
- it('rejects arrays with invalid items', () => {
65
- const schema = array(integer())
66
- const result = schema.safeParse([1, 2, 'three'])
67
- expect(result.success).toBe(false)
68
- })
71
+ it('rejects arrays with some invalid items', () => {
72
+ const schema = array(string())
73
+ const result = schema.safeValidate(['valid', null, 'also valid'])
74
+ expect(result).toMatchObject({ success: false })
75
+ })
69
76
 
70
- it('rejects arrays with some invalid items', () => {
71
- const schema = array(string())
72
- const result = schema.safeParse(['valid', null, 'also valid'])
73
- expect(result.success).toBe(false)
77
+ it('rejects single values', () => {
78
+ const schema = array(string())
79
+ const result = schema.safeValidate(3)
80
+ expect(result).toEqual({
81
+ success: false,
82
+ reason: expect.objectContaining({
83
+ message: expect.stringContaining(
84
+ 'Expected array value type at $ (got integer)',
85
+ ),
86
+ }),
87
+ })
88
+ })
74
89
  })
75
90
 
76
91
  describe('minLength constraint', () => {
77
92
  it('validates arrays meeting minLength', () => {
78
93
  const schema = array(string(), { minLength: 2 })
79
94
  const result = schema.safeParse(['a', 'b'])
80
- expect(result.success).toBe(true)
95
+ expect(result).toMatchObject({ success: true })
81
96
  })
82
97
 
83
98
  it('validates arrays exceeding minLength', () => {
84
99
  const schema = array(string(), { minLength: 2 })
85
100
  const result = schema.safeParse(['a', 'b', 'c'])
86
- expect(result.success).toBe(true)
101
+ expect(result).toMatchObject({ success: true })
87
102
  })
88
103
 
89
104
  it('rejects arrays below minLength', () => {
90
105
  const schema = array(string(), { minLength: 3 })
91
106
  const result = schema.safeParse(['a', 'b'])
92
- expect(result.success).toBe(false)
107
+ expect(result).toMatchObject({ success: false })
93
108
  })
94
109
 
95
110
  it('rejects empty arrays when minLength is set', () => {
96
111
  const schema = array(string(), { minLength: 1 })
97
112
  const result = schema.safeParse([])
98
- expect(result.success).toBe(false)
113
+ expect(result).toMatchObject({ success: false })
99
114
  })
100
115
 
101
116
  it('validates empty arrays when minLength is 0', () => {
102
117
  const schema = array(string(), { minLength: 0 })
103
118
  const result = schema.safeParse([])
104
- expect(result.success).toBe(true)
119
+ expect(result).toMatchObject({ success: true })
105
120
  })
106
121
  })
107
122
 
@@ -109,37 +124,37 @@ describe('ArraySchema', () => {
109
124
  it('validates arrays meeting maxLength', () => {
110
125
  const schema = array(string(), { maxLength: 3 })
111
126
  const result = schema.safeParse(['a', 'b', 'c'])
112
- expect(result.success).toBe(true)
127
+ expect(result).toMatchObject({ success: true })
113
128
  })
114
129
 
115
130
  it('validates arrays below maxLength', () => {
116
131
  const schema = array(string(), { maxLength: 3 })
117
132
  const result = schema.safeParse(['a', 'b'])
118
- expect(result.success).toBe(true)
133
+ expect(result).toMatchObject({ success: true })
119
134
  })
120
135
 
121
136
  it('rejects arrays exceeding maxLength', () => {
122
137
  const schema = array(string(), { maxLength: 2 })
123
138
  const result = schema.safeParse(['a', 'b', 'c'])
124
- expect(result.success).toBe(false)
139
+ expect(result).toMatchObject({ success: false })
125
140
  })
126
141
 
127
142
  it('validates empty arrays with maxLength', () => {
128
143
  const schema = array(string(), { maxLength: 5 })
129
144
  const result = schema.safeParse([])
130
- expect(result.success).toBe(true)
145
+ expect(result).toMatchObject({ success: true })
131
146
  })
132
147
 
133
148
  it('rejects empty arrays when maxLength is 0', () => {
134
149
  const schema = array(string(), { maxLength: 0 })
135
150
  const result = schema.safeParse(['a'])
136
- expect(result.success).toBe(false)
151
+ expect(result).toMatchObject({ success: false })
137
152
  })
138
153
 
139
154
  it('validates empty arrays when maxLength is 0', () => {
140
155
  const schema = array(string(), { maxLength: 0 })
141
156
  const result = schema.safeParse([])
142
- expect(result.success).toBe(true)
157
+ expect(result).toMatchObject({ success: true })
143
158
  })
144
159
  })
145
160
 
@@ -150,7 +165,7 @@ describe('ArraySchema', () => {
150
165
  maxLength: 4,
151
166
  })
152
167
  const result = schema.safeParse(['a', 'b', 'c'])
153
- expect(result.success).toBe(true)
168
+ expect(result).toMatchObject({ success: true })
154
169
  })
155
170
 
156
171
  it('validates arrays at min boundary', () => {
@@ -159,7 +174,7 @@ describe('ArraySchema', () => {
159
174
  maxLength: 4,
160
175
  })
161
176
  const result = schema.safeParse(['a', 'b'])
162
- expect(result.success).toBe(true)
177
+ expect(result).toMatchObject({ success: true })
163
178
  })
164
179
 
165
180
  it('validates arrays at max boundary', () => {
@@ -168,7 +183,7 @@ describe('ArraySchema', () => {
168
183
  maxLength: 4,
169
184
  })
170
185
  const result = schema.safeParse(['a', 'b', 'c', 'd'])
171
- expect(result.success).toBe(true)
186
+ expect(result).toMatchObject({ success: true })
172
187
  })
173
188
 
174
189
  it('rejects arrays below minLength', () => {
@@ -177,7 +192,7 @@ describe('ArraySchema', () => {
177
192
  maxLength: 4,
178
193
  })
179
194
  const result = schema.safeParse(['a'])
180
- expect(result.success).toBe(false)
195
+ expect(result).toMatchObject({ success: false })
181
196
  })
182
197
 
183
198
  it('rejects arrays above maxLength', () => {
@@ -186,7 +201,7 @@ describe('ArraySchema', () => {
186
201
  maxLength: 4,
187
202
  })
188
203
  const result = schema.safeParse(['a', 'b', 'c', 'd', 'e'])
189
- expect(result.success).toBe(false)
204
+ expect(result).toMatchObject({ success: false })
190
205
  })
191
206
 
192
207
  it('validates single-length range', () => {
@@ -195,7 +210,7 @@ describe('ArraySchema', () => {
195
210
  maxLength: 3,
196
211
  })
197
212
  const result = schema.safeParse(['a', 'b', 'c'])
198
- expect(result.success).toBe(true)
213
+ expect(result).toMatchObject({ success: true })
199
214
  })
200
215
 
201
216
  it('rejects arrays not matching exact length', () => {
@@ -204,7 +219,7 @@ describe('ArraySchema', () => {
204
219
  maxLength: 3,
205
220
  })
206
221
  const result = schema.safeParse(['a', 'b'])
207
- expect(result.success).toBe(false)
222
+ expect(result).toMatchObject({ success: false })
208
223
  })
209
224
  })
210
225
 
@@ -215,7 +230,7 @@ describe('ArraySchema', () => {
215
230
  ['a', 'b'],
216
231
  ['c', 'd'],
217
232
  ])
218
- expect(result.success).toBe(true)
233
+ expect(result).toMatchObject({ success: true })
219
234
  })
220
235
 
221
236
  it('rejects invalid nested arrays', () => {
@@ -224,13 +239,13 @@ describe('ArraySchema', () => {
224
239
  [1, 2],
225
240
  [3, 'four'],
226
241
  ])
227
- expect(result.success).toBe(false)
242
+ expect(result).toMatchObject({ success: false })
228
243
  })
229
244
 
230
245
  it('validates deeply nested arrays', () => {
231
246
  const schema = array(array(array(integer())))
232
247
  const result = schema.safeParse([[[1, 2], [3]], [[4, 5, 6]]])
233
- expect(result.success).toBe(true)
248
+ expect(result).toMatchObject({ success: true })
234
249
  })
235
250
  })
236
251
  })
@@ -7,15 +7,37 @@ import {
7
7
  } from '../core.js'
8
8
  import { memoizedTransformer } from '../util/memoize.js'
9
9
 
10
+ /**
11
+ * Configuration options for array schema validation.
12
+ *
13
+ * @property minLength - Minimum number of items in the array
14
+ * @property maxLength - Maximum number of items in the array
15
+ */
10
16
  export type ArraySchemaOptions = {
11
17
  minLength?: number
12
18
  maxLength?: number
13
19
  }
14
20
 
21
+ /**
22
+ * Schema for validating arrays where all items match a given schema.
23
+ *
24
+ * Validates that the input is an array, checks length constraints, and
25
+ * validates each item against the provided item schema.
26
+ *
27
+ * @template TItem - The validator type for array items
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const schema = new ArraySchema(l.string(), { maxLength: 10 })
32
+ * const result = schema.validate(['a', 'b', 'c'])
33
+ * ```
34
+ */
15
35
  export class ArraySchema<const TItem extends Validator> extends Schema<
16
36
  Array<InferInput<TItem>>,
17
37
  Array<InferOutput<TItem>>
18
38
  > {
39
+ readonly type = 'array' as const
40
+
19
41
  constructor(
20
42
  readonly validator: TItem,
21
43
  readonly options: ArraySchemaOptions = {},
@@ -25,7 +47,7 @@ export class ArraySchema<const TItem extends Validator> extends Schema<
25
47
 
26
48
  validateInContext(input: unknown, ctx: ValidationContext) {
27
49
  if (!Array.isArray(input)) {
28
- return ctx.issueInvalidType(input, 'array')
50
+ return ctx.issueUnexpectedType(input, 'array')
29
51
  }
30
52
 
31
53
  const { minLength, maxLength } = this.options
@@ -60,6 +82,31 @@ export class ArraySchema<const TItem extends Validator> extends Schema<
60
82
  }
61
83
  }
62
84
 
85
+ /**
86
+ * Creates an array schema that validates each item against the provided schema.
87
+ *
88
+ * @param items - Schema to validate each array item against
89
+ * @param options - Optional length constraints
90
+ * @returns A new {@link ArraySchema} instance
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * // Array of strings
95
+ * const tagsSchema = l.array(l.string())
96
+ *
97
+ * // Array with length constraints
98
+ * const limitedSchema = l.array(l.integer(), { maxLength: 100 })
99
+ *
100
+ * // Array of objects
101
+ * const usersSchema = l.array(l.object({
102
+ * name: l.string(),
103
+ * age: l.integer(),
104
+ * }))
105
+ *
106
+ * // Non-empty array
107
+ * const nonEmptySchema = l.array(l.string(), { minLength: 1 })
108
+ * ```
109
+ */
63
110
  /*@__NO_SIDE_EFFECTS__*/
64
111
  function arraySchema<const TValidator extends Validator>(
65
112
  items: TValidator,
@@ -8,6 +8,13 @@ import {
8
8
  import { Schema, ValidationContext } from '../core.js'
9
9
  import { memoizedOptions } from '../util/memoize.js'
10
10
 
11
+ /**
12
+ * Configuration options for blob schema validation.
13
+ *
14
+ * @property allowLegacy - Whether to allow legacy blob references format
15
+ * @property accept - List of accepted MIME types (supports wildcards like 'image/*' or '*\/*')
16
+ * @property maxSize - Maximum blob size in bytes
17
+ */
11
18
  export type BlobSchemaOptions = BlobRefCheckOptions & {
12
19
  /**
13
20
  * Whether to allow legacy blob references format
@@ -25,12 +32,30 @@ export type BlobSchemaOptions = BlobRefCheckOptions & {
25
32
  }
26
33
 
27
34
  export type { BlobRef, LegacyBlobRef }
35
+ export { isBlobRef, isLegacyBlobRef }
28
36
 
37
+ /**
38
+ * Schema for validating blob references in AT Protocol.
39
+ *
40
+ * Validates BlobRef objects which contain a CID reference to binary data,
41
+ * along with metadata like MIME type and size. Can optionally accept
42
+ * legacy blob reference format.
43
+ *
44
+ * @template TOptions - The configuration options type
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const schema = new BlobSchema({ accept: ['image/*'], maxSize: 1000000 })
49
+ * const result = schema.validate(blobRef)
50
+ * ```
51
+ */
29
52
  export class BlobSchema<
30
53
  const TOptions extends BlobSchemaOptions = NonNullable<unknown>,
31
54
  > extends Schema<
32
55
  TOptions extends { allowLegacy: true } ? BlobRef | LegacyBlobRef : BlobRef
33
56
  > {
57
+ readonly type = 'blob' as const
58
+
34
59
  constructor(readonly options?: TOptions) {
35
60
  super()
36
61
  }
@@ -46,7 +71,7 @@ export class BlobSchema<
46
71
  : null
47
72
 
48
73
  if (!blob) {
49
- return ctx.issueInvalidType(input, 'blob')
74
+ return ctx.issueUnexpectedType(input, 'blob')
50
75
  }
51
76
 
52
77
  const accept = this.options?.accept
@@ -80,6 +105,30 @@ function matchesMime(mime: string, accepted: string[]): boolean {
80
105
  return false
81
106
  }
82
107
 
108
+ /**
109
+ * Creates a blob schema for validating blob references with optional constraints.
110
+ *
111
+ * Blob references are used in AT Protocol to reference binary data stored
112
+ * separately from records. They contain a CID, MIME type, and size information.
113
+ *
114
+ * @param options - Optional configuration for MIME type filtering and size limits
115
+ * @returns A new {@link BlobSchema} instance
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * // Basic blob reference
120
+ * const fileSchema = l.blob()
121
+ *
122
+ * // Image files only
123
+ * const imageSchema = l.blob({ accept: ['image/png', 'image/jpeg', 'image/gif'] })
124
+ *
125
+ * // Any image type with size limit
126
+ * const avatarSchema = l.blob({ accept: ['image/*'], maxSize: 1000000 })
127
+ *
128
+ * // Allow legacy format
129
+ * const legacySchema = l.blob({ allowLegacy: true })
130
+ * ```
131
+ */
83
132
  export const blob = /*#__PURE__*/ memoizedOptions(function <
84
133
  O extends BlobSchemaOptions = { allowLegacy?: false },
85
134
  >(options?: O) {
@@ -1,16 +1,46 @@
1
1
  import { Schema, ValidationContext } from '../core.js'
2
2
  import { memoizedOptions } from '../util/memoize.js'
3
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
+ */
4
18
  export class BooleanSchema extends Schema<boolean> {
19
+ readonly type = 'boolean' as const
20
+
5
21
  validateInContext(input: unknown, ctx: ValidationContext) {
6
22
  if (typeof input === 'boolean') {
7
23
  return ctx.success(input)
8
24
  }
9
25
 
10
- return ctx.issueInvalidType(input, 'boolean')
26
+ return ctx.issueUnexpectedType(input, 'boolean')
11
27
  }
12
28
  }
13
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
+ */
14
44
  export const boolean = /*#__PURE__*/ memoizedOptions(function () {
15
45
  return new BooleanSchema()
16
46
  })
@@ -2,12 +2,32 @@ import { asUint8Array, ifUint8Array } from '@atproto/lex-data'
2
2
  import { Schema, ValidationContext } from '../core.js'
3
3
  import { memoizedOptions } from '../util/memoize.js'
4
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
+ */
5
11
  export type BytesSchemaOptions = {
6
12
  minLength?: number
7
13
  maxLength?: number
8
14
  }
9
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
+ */
10
28
  export class BytesSchema extends Schema<Uint8Array> {
29
+ readonly type = 'bytes' as const
30
+
11
31
  constructor(readonly options: BytesSchemaOptions = {}) {
12
32
  super()
13
33
  }
@@ -17,7 +37,7 @@ export class BytesSchema extends Schema<Uint8Array> {
17
37
  const bytes =
18
38
  ctx.options.mode === 'parse' ? asUint8Array(input) : ifUint8Array(input)
19
39
  if (!bytes) {
20
- return ctx.issueInvalidType(input, 'bytes')
40
+ return ctx.issueUnexpectedType(input, 'bytes')
21
41
  }
22
42
 
23
43
  const { minLength } = this.options
@@ -34,6 +54,26 @@ export class BytesSchema extends Schema<Uint8Array> {
34
54
  }
35
55
  }
36
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
+ */
37
77
  export const bytes = /*#__PURE__*/ memoizedOptions(function (
38
78
  options?: BytesSchemaOptions,
39
79
  ) {
package/src/schema/cid.ts CHANGED
@@ -4,24 +4,64 @@ import { memoizedOptions } from '../util/memoize.js'
4
4
 
5
5
  export type { Cid }
6
6
 
7
+ /**
8
+ * Configuration options for CID schema validation.
9
+ *
10
+ * @see CheckCidOptions from @atproto/lex-data for available options
11
+ */
7
12
  export type CidSchemaOptions = CheckCidOptions
8
13
 
14
+ /**
15
+ * Schema for validating Content Identifiers (CIDs).
16
+ *
17
+ * CIDs are self-describing content-addressed identifiers used in AT Protocol
18
+ * to reference data by its cryptographic hash. This schema validates that
19
+ * the input is a valid CID object.
20
+ *
21
+ * @template TOptions - The configuration options type
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const schema = new CidSchema()
26
+ * const result = schema.validate(someCid)
27
+ * ```
28
+ */
9
29
  export class CidSchema<
10
30
  const TOptions extends CidSchemaOptions = { flavor: undefined },
11
31
  > extends Schema<InferCheckedCid<TOptions>> {
32
+ readonly type = 'cid' as const
33
+
12
34
  constructor(readonly options?: TOptions) {
13
35
  super()
14
36
  }
15
37
 
16
38
  validateInContext(input: unknown, ctx: ValidationContext) {
17
39
  if (!isCid(input, this.options)) {
18
- return ctx.issueInvalidType(input, 'cid')
40
+ return ctx.issueUnexpectedType(input, 'cid')
19
41
  }
20
42
 
21
43
  return ctx.success(input)
22
44
  }
23
45
  }
24
46
 
47
+ /**
48
+ * Creates a CID schema for validating Content Identifiers.
49
+ *
50
+ * CIDs are used throughout AT Protocol to reference content by its hash.
51
+ * This is commonly used for referencing blobs, commits, and other data.
52
+ *
53
+ * @param options - Optional configuration for CID validation
54
+ * @returns A new {@link CidSchema} instance
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * // Basic CID validation
59
+ * const cidSchema = l.cid()
60
+ *
61
+ * // Validate a CID from a blob reference
62
+ * const result = cidSchema.validate(blobRef.ref)
63
+ * ```
64
+ */
25
65
  export const cid = /*#__PURE__*/ memoizedOptions(function <
26
66
  O extends CidSchemaOptions = NonNullable<unknown>,
27
67
  >(options?: O) {