@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.
Files changed (263) hide show
  1. package/CHANGELOG.md +24 -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,499 +0,0 @@
1
- import { describe, expect, expectTypeOf, it } from 'vitest'
2
- import { integer } from './integer.js'
3
- import { ObjectSchema, object } from './object.js'
4
- import { optional } from './optional.js'
5
- import { ParamsSchema, params } from './params.js'
6
- import { RefSchema, ref } from './ref.js'
7
- import { string } from './string.js'
8
- import {
9
- InferSubscriptionMessage,
10
- InferSubscriptionParameters,
11
- Subscription,
12
- subscription,
13
- } from './subscription.js'
14
-
15
- describe('Subscription', () => {
16
- describe('constructor', () => {
17
- it('creates a Subscription instance with all parameters', () => {
18
- const nsid = 'com.atproto.sync.subscribeRepos'
19
- const parameters = params({
20
- cursor: optional(integer()),
21
- })
22
- const message = object({
23
- seq: integer(),
24
- data: string(),
25
- })
26
- const errors = ['ConsumerTooSlow', 'FutureCursor'] as const
27
-
28
- const mySub = subscription(nsid, parameters, message, errors)
29
-
30
- expect(mySub).toBeInstanceOf(Subscription)
31
- expect(mySub.nsid).toBe(nsid)
32
- expect(mySub.parameters).toBe(parameters)
33
- expect(mySub.message).toBe(message)
34
- expect(mySub.errors).toBe(errors)
35
- })
36
-
37
- it('creates a Subscription instance without errors', () => {
38
- const nsid = 'com.atproto.sync.subscribeRepos'
39
- const parameters = params({
40
- cursor: optional(integer()),
41
- })
42
- const message = object({
43
- seq: integer(),
44
- })
45
-
46
- const mySub = subscription(nsid, parameters, message, undefined)
47
-
48
- expect(mySub).toBeInstanceOf(Subscription)
49
- expect(mySub.nsid).toBe(nsid)
50
- expect(mySub.parameters).toBe(parameters)
51
- expect(mySub.message).toBe(message)
52
- expect(mySub.errors).toBeUndefined()
53
- })
54
-
55
- it('creates a Subscription instance with empty parameters', () => {
56
- const nsid = 'app.bsky.notification.subscribe'
57
- const parameters = params()
58
- const message = object({
59
- type: string(),
60
- })
61
-
62
- const mySub = subscription(nsid, parameters, message, undefined)
63
-
64
- expect(mySub).toBeInstanceOf(Subscription)
65
- expect(mySub.parameters).toBe(parameters)
66
- })
67
- })
68
-
69
- describe('type property', () => {
70
- it('has type set to "subscription"', () => {
71
- const nsid = 'com.atproto.sync.subscribeRepos'
72
- const parameters = params()
73
- const message = object({
74
- seq: integer(),
75
- })
76
-
77
- const mySub = subscription(nsid, parameters, message, undefined)
78
-
79
- expect(mySub.type).toBe('subscription')
80
- })
81
-
82
- it('type is a constant value', () => {
83
- const nsid = 'com.atproto.sync.subscribeRepos'
84
- const parameters = params()
85
- const message = object({
86
- seq: integer(),
87
- })
88
-
89
- const mySub = subscription(nsid, parameters, message, undefined)
90
-
91
- expect(mySub.type).toBe('subscription')
92
- // TypeScript enforces readonly at compile time
93
- expect(typeof mySub.type).toBe('string')
94
- })
95
- })
96
-
97
- describe('properties', () => {
98
- it('has nsid property', () => {
99
- const nsid = 'com.atproto.sync.subscribeRepos'
100
- const parameters = params()
101
- const message = object({
102
- seq: integer(),
103
- })
104
-
105
- const mySub = subscription(nsid, parameters, message, undefined)
106
-
107
- expect(mySub.nsid).toBe(nsid)
108
- expect(typeof mySub.nsid).toBe('string')
109
- })
110
-
111
- it('has parameters property', () => {
112
- const nsid = 'com.atproto.sync.subscribeRepos'
113
- const parameters = params()
114
- const message = object({
115
- seq: integer(),
116
- })
117
-
118
- const mySub = subscription(nsid, parameters, message, undefined)
119
-
120
- expect(mySub.parameters).toBe(parameters)
121
- expect(mySub.parameters).toBeInstanceOf(ParamsSchema)
122
- })
123
-
124
- it('has message property', () => {
125
- const nsid = 'com.atproto.sync.subscribeRepos'
126
- const parameters = params()
127
- const message = object({
128
- seq: integer(),
129
- })
130
-
131
- const mySub = subscription(nsid, parameters, message, undefined)
132
-
133
- expect(mySub.message).toBe(message)
134
- expect(mySub.message).toBeInstanceOf(ObjectSchema)
135
- })
136
-
137
- it('has errors property', () => {
138
- const nsid = 'com.atproto.sync.subscribeRepos'
139
- const parameters = params()
140
- const message = object({
141
- seq: integer(),
142
- })
143
- const errors = ['ConsumerTooSlow'] as const
144
-
145
- const mySub = subscription(nsid, parameters, message, errors)
146
-
147
- expect(mySub.errors).toBe(errors)
148
- expect(Array.isArray(mySub.errors)).toBe(true)
149
- })
150
- })
151
-
152
- describe('with complex parameters', () => {
153
- it('creates a Subscription with multiple parameter types', () => {
154
- const nsid = 'com.atproto.sync.subscribeRepos'
155
- const parameters = params({
156
- cursor: optional(integer({ minimum: 0 })),
157
- includeDeletes: optional(integer({ minimum: 0, maximum: 1 })),
158
- })
159
- const message = object({
160
- seq: integer(),
161
- data: string(),
162
- })
163
- const errors = ['ConsumerTooSlow', 'FutureCursor'] as const
164
-
165
- const mySub = subscription(nsid, parameters, message, errors)
166
-
167
- expect(mySub).toBeInstanceOf(Subscription)
168
- expect(mySub.parameters).toBe(parameters)
169
- expect(mySub.errors).toEqual(['ConsumerTooSlow', 'FutureCursor'])
170
- })
171
- })
172
-
173
- describe('with various message types', () => {
174
- it('creates a Subscription with ObjectSchema message', () => {
175
- const mySub = subscription(
176
- 'com.atproto.sync.subscribeRepos',
177
- params(),
178
- object({
179
- seq: integer(),
180
- data: string(),
181
- }),
182
- undefined,
183
- )
184
-
185
- expect(mySub).toBeInstanceOf(Subscription)
186
- expect(mySub.message).toBeInstanceOf(ObjectSchema)
187
- })
188
-
189
- it('creates a Subscription with RefSchema message', () => {
190
- const message = string()
191
- const mySub = subscription(
192
- 'app.bsky.feed.subscribe',
193
- params(),
194
- ref(() => message),
195
- undefined,
196
- )
197
-
198
- expect(mySub).toBeInstanceOf(Subscription)
199
- expect(mySub.message).toBeInstanceOf(RefSchema)
200
- })
201
- })
202
-
203
- describe('with different error configurations', () => {
204
- it('creates a Subscription with a single error', () => {
205
- const mySub = subscription(
206
- 'com.atproto.sync.subscribeRepos',
207
- params(),
208
- object({}),
209
- ['ConsumerTooSlow'],
210
- )
211
-
212
- expect(mySub.errors).toEqual(['ConsumerTooSlow'])
213
- })
214
-
215
- it('creates a Subscription with multiple errors', () => {
216
- const mySub = subscription(
217
- 'com.atproto.sync.subscribeRepos',
218
- params(),
219
- object({}),
220
- ['ConsumerTooSlow', 'FutureCursor', 'InvalidCursor'],
221
- )
222
-
223
- expectTypeOf<
224
- readonly ['ConsumerTooSlow', 'FutureCursor', 'InvalidCursor']
225
- >(mySub.errors)
226
-
227
- expect(mySub.errors).toEqual([
228
- 'ConsumerTooSlow',
229
- 'FutureCursor',
230
- 'InvalidCursor',
231
- ])
232
- })
233
-
234
- it('creates a Subscription with empty errors array', () => {
235
- const mySub = subscription(
236
- 'com.atproto.sync.subscribeRepos',
237
- params(),
238
- object({}),
239
- [],
240
- )
241
-
242
- expect(mySub.errors).toEqual([])
243
- })
244
- })
245
-
246
- describe('type inference', () => {
247
- it('InferSubscriptionParameters correctly infers parameter types', () => {
248
- const _mySub = subscription(
249
- 'com.atproto.sync.subscribeRepos',
250
- params({
251
- cursor: optional(integer()),
252
- }),
253
- object({
254
- seq: integer(),
255
- }),
256
- )
257
-
258
- type Params = InferSubscriptionParameters<typeof _mySub>
259
-
260
- expectTypeOf<Params>({
261
- cursor: 12345,
262
- })
263
- })
264
-
265
- it('InferSubscriptionMessage correctly infers message type', () => {
266
- const nsid = 'com.atproto.sync.subscribeRepos'
267
- const parameters = params()
268
- const message = object({
269
- seq: integer(),
270
- data: string(),
271
- })
272
-
273
- const _mySub = subscription(nsid, parameters, message, undefined)
274
-
275
- type Message = InferSubscriptionMessage<typeof _mySub>
276
-
277
- expectTypeOf<Message>({
278
- seq: 12345,
279
- data: 'test data',
280
- })
281
- })
282
- })
283
-
284
- describe('edge cases', () => {
285
- it('handles very long NSID', () => {
286
- const nsid =
287
- 'com.example.very.long.namespace.identifier.subscription.name'
288
- const parameters = params()
289
- const message = object({})
290
-
291
- const mySub = subscription(nsid, parameters, message, undefined)
292
-
293
- expect(mySub.nsid).toBe(nsid)
294
- })
295
-
296
- it('handles subscription with all optional parameters', () => {
297
- const nsid = 'app.bsky.feed.subscribe'
298
- const parameters = params({
299
- cursor: optional(integer()),
300
- includeDeletes: optional(integer()),
301
- includeEdits: optional(integer()),
302
- })
303
- const message = object({})
304
-
305
- const mySub = subscription(nsid, parameters, message, undefined)
306
-
307
- expect(mySub.parameters).toBe(parameters)
308
- })
309
-
310
- it('handles subscription with complex nested message schema', () => {
311
- const nsid = 'com.atproto.sync.subscribeRepos'
312
- const parameters = params()
313
- const message = object({
314
- seq: integer(),
315
- blocks: object({
316
- cid: string({ format: 'cid' }),
317
- data: object({
318
- uri: string({ format: 'at-uri' }),
319
- content: string(),
320
- }),
321
- }),
322
- })
323
-
324
- const mySub = subscription(nsid, parameters, message, undefined)
325
-
326
- expect(mySub.message).toBeInstanceOf(ObjectSchema)
327
- })
328
- })
329
-
330
- describe('real-world subscription examples', () => {
331
- it('creates a subscribeLabels subscription', () => {
332
- const nsid = 'com.atproto.label.subscribeLabels'
333
- const parameters = params({
334
- cursor: optional(integer({ minimum: 0 })),
335
- })
336
- const message = object({
337
- seq: integer(),
338
- labels: object({
339
- uri: string({ format: 'uri' }),
340
- val: string(),
341
- }),
342
- })
343
-
344
- const mySub = subscription(nsid, parameters, message, undefined)
345
-
346
- expect(mySub.type).toBe('subscription')
347
- expect(mySub.nsid).toBe('com.atproto.label.subscribeLabels')
348
- expect(mySub.parameters.matches({ cursor: 10 })).toBe(true)
349
- expect(mySub.parameters.matches({ cursor: -10 })).toBe(false)
350
- expect(
351
- mySub.message.matches({
352
- seq: 1,
353
- labels: { uri: 'http://foo.com', val: 'test' },
354
- }),
355
- ).toBe(true)
356
- expect(
357
- mySub.message.matches({
358
- seq: 1,
359
- labels: { uri: 'http://foo.com', val: 3 },
360
- }),
361
- ).toBe(false)
362
- })
363
-
364
- it('creates a notification subscription', () => {
365
- const nsid = 'app.bsky.notification.subscribe'
366
- const parameters = params({
367
- cursor: optional(string()),
368
- })
369
- const message = object({
370
- type: string(),
371
- uri: string({ format: 'at-uri' }),
372
- cid: string({ format: 'cid' }),
373
- })
374
-
375
- const mySub = subscription(nsid, parameters, message, undefined)
376
-
377
- expect(mySub.type).toBe('subscription')
378
- expect(mySub.nsid).toBe('app.bsky.notification.subscribe')
379
- })
380
- })
381
-
382
- describe('with mixed parameter and message types', () => {
383
- it('handles required and optional parameters with complex message', () => {
384
- const nsid = 'com.atproto.sync.subscribeRepos'
385
- const parameters = params({
386
- cursor: optional(integer({ minimum: 0 })),
387
- includeDeletes: optional(integer({ minimum: 0, maximum: 1 })),
388
- })
389
- const message = object({
390
- seq: integer(),
391
- rebase: optional(integer({ minimum: 0, maximum: 1 })),
392
- tooBig: optional(integer({ minimum: 0, maximum: 1 })),
393
- repo: string({ format: 'did' }),
394
- commit: string({ format: 'cid' }),
395
- blocks: string(),
396
- ops: object({}),
397
- })
398
-
399
- const mySub = subscription(nsid, parameters, message, undefined)
400
-
401
- expect(mySub.type).toBe('subscription')
402
- expect(mySub.parameters).toBe(parameters)
403
- expect(mySub.message).toBe(message)
404
- })
405
- })
406
-
407
- describe('validation through nested schemas', () => {
408
- it('parameters can validate input through ParamsSchema', () => {
409
- const nsid = 'com.atproto.sync.subscribeRepos'
410
- const parameters = params({
411
- cursor: integer({ minimum: 0 }),
412
- })
413
- const message = object({})
414
-
415
- const mySub = subscription(nsid, parameters, message, undefined)
416
-
417
- // Test that the parameters schema can validate
418
- const validResult = mySub.parameters.safeParse({ cursor: 100 })
419
- expect(validResult.success).toBe(true)
420
-
421
- const invalidResult = mySub.parameters.safeParse({ cursor: -1 })
422
- expect(invalidResult.success).toBe(false)
423
- })
424
-
425
- it('message can validate input through ObjectSchema', () => {
426
- const nsid = 'com.atproto.sync.subscribeRepos'
427
- const parameters = params()
428
- const message = object({
429
- seq: integer({ minimum: 0 }),
430
- data: string({ minLength: 1 }),
431
- })
432
-
433
- const mySub = subscription(nsid, parameters, message, undefined)
434
-
435
- // Test that the message schema can validate
436
- const validResult = mySub.message.safeParse({
437
- seq: 100,
438
- data: 'test',
439
- })
440
- expect(validResult.success).toBe(true)
441
-
442
- const invalidResult = mySub.message.safeParse({
443
- seq: -1,
444
- data: '',
445
- })
446
- expect(invalidResult.success).toBe(false)
447
- })
448
- })
449
-
450
- describe('property access', () => {
451
- it('can access nsid after construction', () => {
452
- const nsid = 'com.atproto.sync.subscribeRepos'
453
- const parameters = params()
454
- const message = object({})
455
-
456
- const mySub = subscription(nsid, parameters, message, undefined)
457
-
458
- expect(mySub.nsid).toBe(nsid)
459
- expect(mySub.nsid).toBe('com.atproto.sync.subscribeRepos')
460
- })
461
-
462
- it('can access type after construction', () => {
463
- const nsid = 'com.atproto.sync.subscribeRepos'
464
- const parameters = params()
465
- const message = object({})
466
-
467
- const mySub = subscription(nsid, parameters, message, undefined)
468
-
469
- expect(mySub.type).toBe('subscription')
470
- expect(typeof mySub.type).toBe('string')
471
- })
472
- })
473
-
474
- describe('different message schema types', () => {
475
- it('constructs with ObjectSchema message', () => {
476
- const nsid = 'app.bsky.test'
477
- const parameters = params()
478
- const message = object({
479
- field: string(),
480
- })
481
-
482
- const mySub = subscription(nsid, parameters, message, undefined)
483
-
484
- expect(mySub.message).toBeInstanceOf(ObjectSchema)
485
- expect(mySub.message).toBe(message)
486
- })
487
-
488
- it('constructs with RefSchema message', () => {
489
- const nsid = 'app.bsky.test'
490
- const parameters = params()
491
- const message = ref(() => object({}))
492
-
493
- const mySub = subscription(nsid, parameters, message, undefined)
494
-
495
- expect(mySub.message).toBeInstanceOf(RefSchema)
496
- expect(mySub.message).toBe(message)
497
- })
498
- })
499
- })
@@ -1,108 +0,0 @@
1
- import { LexValue } from '@atproto/lex-data'
2
- import { Infer, NsidString, Schema } from '../core.js'
3
- import { ParamsSchema } from './params.js'
4
-
5
- /**
6
- * Infers the parameters type from a Subscription definition.
7
- *
8
- * @template S - The Subscription type
9
- */
10
- export type InferSubscriptionParameters<S extends Subscription> = Infer<
11
- S['parameters']
12
- >
13
-
14
- /**
15
- * Infers the message type from a Subscription definition.
16
- *
17
- * @template S - The Subscription type
18
- */
19
- export type InferSubscriptionMessage<S extends Subscription> = Infer<
20
- S['message']
21
- >
22
-
23
- /**
24
- * Represents a Lexicon subscription (WebSocket) endpoint definition.
25
- *
26
- * Subscriptions are real-time event streams delivered over WebSocket.
27
- * They have parameters for initializing the connection and a message
28
- * schema for validating incoming events.
29
- *
30
- * @template TNsid - The NSID identifying this subscription
31
- * @template TParameters - The connection parameters schema type
32
- * @template TMessage - The message schema type
33
- * @template TErrors - Array of error type strings, or undefined
34
- *
35
- * @example
36
- * ```ts
37
- * const firehose = new Subscription(
38
- * 'com.atproto.sync.subscribeRepos',
39
- * l.params({ cursor: l.optional(l.integer()) }),
40
- * repoEventSchema,
41
- * ['FutureCursor']
42
- * )
43
- * ```
44
- */
45
- export class Subscription<
46
- const TNsid extends NsidString = NsidString,
47
- const TParameters extends ParamsSchema = ParamsSchema,
48
- const TMessage extends Schema<LexValue> = Schema<LexValue>,
49
- const TErrors extends undefined | readonly string[] =
50
- | undefined
51
- | readonly string[],
52
- > {
53
- readonly type = 'subscription' as const
54
-
55
- constructor(
56
- readonly nsid: TNsid,
57
- readonly parameters: TParameters,
58
- readonly message: TMessage,
59
- readonly errors: TErrors,
60
- ) {}
61
- }
62
-
63
- /**
64
- * Creates a subscription definition for a Lexicon WebSocket endpoint.
65
- *
66
- * Subscriptions enable real-time event streaming. The connection is
67
- * initialized with parameters, and the server sends messages matching
68
- * the message schema.
69
- *
70
- * @param nsid - The NSID identifying this subscription endpoint
71
- * @param parameters - Schema for connection parameters
72
- * @param message - Schema for validating incoming messages
73
- * @param errors - Optional array of error type strings
74
- * @returns A new {@link Subscription} instance
75
- *
76
- * @example
77
- * ```ts
78
- * // Repository event stream
79
- * const subscribeRepos = l.subscription(
80
- * 'com.atproto.sync.subscribeRepos',
81
- * l.params({
82
- * cursor: l.optional(l.integer()),
83
- * }),
84
- * l.typedUnion([
85
- * l.typedRef(() => commitEventSchema),
86
- * l.typedRef(() => handleEventSchema),
87
- * l.typedRef(() => identityEventSchema),
88
- * ], false),
89
- * ['FutureCursor', 'ConsumerTooSlow'],
90
- * )
91
- *
92
- * // Label stream
93
- * const subscribeLabels = l.subscription(
94
- * 'com.atproto.label.subscribeLabels',
95
- * l.params({ cursor: l.optional(l.integer()) }),
96
- * labelEventSchema,
97
- * )
98
- * ```
99
- */
100
- /*@__NO_SIDE_EFFECTS__*/
101
- export function subscription<
102
- const N extends NsidString,
103
- const P extends ParamsSchema,
104
- const M extends Schema<LexValue>,
105
- const E extends undefined | readonly string[] = undefined,
106
- >(nsid: N, parameters: P, message: M, errors: E = undefined as E) {
107
- return new Subscription<N, P, M, E>(nsid, parameters, message, errors)
108
- }