@atproto/lex-schema 0.0.2 → 0.0.3

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 (289) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/dist/core/$type.d.ts +6 -3
  3. package/dist/core/$type.d.ts.map +1 -1
  4. package/dist/core/$type.js +1 -0
  5. package/dist/core/$type.js.map +1 -1
  6. package/dist/core/record-key.d.ts +3 -3
  7. package/dist/core/record-key.d.ts.map +1 -1
  8. package/dist/core/record-key.js +12 -6
  9. package/dist/core/record-key.js.map +1 -1
  10. package/dist/core/result.d.ts.map +1 -1
  11. package/dist/core/result.js +6 -0
  12. package/dist/core/result.js.map +1 -1
  13. package/dist/core/string-format.d.ts +30 -27
  14. package/dist/core/string-format.d.ts.map +1 -1
  15. package/dist/core/string-format.js +56 -42
  16. package/dist/core/string-format.js.map +1 -1
  17. package/dist/core/types.d.ts +9 -1
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/core/types.js.map +1 -1
  20. package/dist/external.d.ts +31 -28
  21. package/dist/external.d.ts.map +1 -1
  22. package/dist/external.js +33 -17
  23. package/dist/external.js.map +1 -1
  24. package/dist/schema/_parameters.d.ts +2 -2
  25. package/dist/schema/_parameters.d.ts.map +1 -1
  26. package/dist/schema/array.d.ts +5 -6
  27. package/dist/schema/array.d.ts.map +1 -1
  28. package/dist/schema/array.js +5 -6
  29. package/dist/schema/array.js.map +1 -1
  30. package/dist/schema/blob.d.ts +2 -3
  31. package/dist/schema/blob.d.ts.map +1 -1
  32. package/dist/schema/blob.js +1 -2
  33. package/dist/schema/blob.js.map +1 -1
  34. package/dist/schema/boolean.d.ts +4 -5
  35. package/dist/schema/boolean.d.ts.map +1 -1
  36. package/dist/schema/boolean.js +2 -3
  37. package/dist/schema/boolean.js.map +1 -1
  38. package/dist/schema/bytes.d.ts +3 -4
  39. package/dist/schema/bytes.d.ts.map +1 -1
  40. package/dist/schema/bytes.js +2 -3
  41. package/dist/schema/bytes.js.map +1 -1
  42. package/dist/schema/cid.d.ts +13 -6
  43. package/dist/schema/cid.d.ts.map +1 -1
  44. package/dist/schema/cid.js +2 -4
  45. package/dist/schema/cid.js.map +1 -1
  46. package/dist/schema/custom.d.ts +3 -4
  47. package/dist/schema/custom.d.ts.map +1 -1
  48. package/dist/schema/custom.js +4 -3
  49. package/dist/schema/custom.js.map +1 -1
  50. package/dist/schema/dict.d.ts +3 -3
  51. package/dist/schema/dict.d.ts.map +1 -1
  52. package/dist/schema/dict.js +1 -1
  53. package/dist/schema/dict.js.map +1 -1
  54. package/dist/schema/discriminated-union.d.ts +15 -24
  55. package/dist/schema/discriminated-union.d.ts.map +1 -1
  56. package/dist/schema/discriminated-union.js +40 -64
  57. package/dist/schema/discriminated-union.js.map +1 -1
  58. package/dist/schema/enum.d.ts +8 -4
  59. package/dist/schema/enum.d.ts.map +1 -1
  60. package/dist/schema/enum.js +5 -3
  61. package/dist/schema/enum.js.map +1 -1
  62. package/dist/schema/integer.d.ts +3 -4
  63. package/dist/schema/integer.d.ts.map +1 -1
  64. package/dist/schema/integer.js +3 -4
  65. package/dist/schema/integer.js.map +1 -1
  66. package/dist/schema/intersection.d.ts +22 -14
  67. package/dist/schema/intersection.d.ts.map +1 -1
  68. package/dist/schema/intersection.js +12 -22
  69. package/dist/schema/intersection.js.map +1 -1
  70. package/dist/schema/literal.d.ts +7 -3
  71. package/dist/schema/literal.d.ts.map +1 -1
  72. package/dist/schema/literal.js +5 -3
  73. package/dist/schema/literal.js.map +1 -1
  74. package/dist/schema/never.d.ts +2 -2
  75. package/dist/schema/never.d.ts.map +1 -1
  76. package/dist/schema/never.js +1 -1
  77. package/dist/schema/never.js.map +1 -1
  78. package/dist/schema/null.d.ts +2 -3
  79. package/dist/schema/null.d.ts.map +1 -1
  80. package/dist/schema/null.js +1 -2
  81. package/dist/schema/null.js.map +1 -1
  82. package/dist/schema/nullable.d.ts +7 -0
  83. package/dist/schema/nullable.d.ts.map +1 -0
  84. package/dist/schema/nullable.js +19 -0
  85. package/dist/schema/nullable.js.map +1 -0
  86. package/dist/schema/object.d.ts +10 -44
  87. package/dist/schema/object.d.ts.map +1 -1
  88. package/dist/schema/object.js +10 -46
  89. package/dist/schema/object.js.map +1 -1
  90. package/dist/schema/optional.d.ts +7 -0
  91. package/dist/schema/optional.d.ts.map +1 -0
  92. package/dist/schema/optional.js +25 -0
  93. package/dist/schema/optional.js.map +1 -0
  94. package/dist/schema/params.d.ts +14 -19
  95. package/dist/schema/params.d.ts.map +1 -1
  96. package/dist/schema/params.js +10 -24
  97. package/dist/schema/params.js.map +1 -1
  98. package/dist/schema/payload.d.ts +4 -4
  99. package/dist/schema/payload.d.ts.map +1 -1
  100. package/dist/schema/payload.js.map +1 -1
  101. package/dist/schema/permission-set.d.ts +6 -6
  102. package/dist/schema/permission-set.d.ts.map +1 -1
  103. package/dist/schema/permission-set.js +1 -2
  104. package/dist/schema/permission-set.js.map +1 -1
  105. package/dist/schema/permission.d.ts +0 -1
  106. package/dist/schema/permission.d.ts.map +1 -1
  107. package/dist/schema/permission.js +0 -1
  108. package/dist/schema/permission.js.map +1 -1
  109. package/dist/schema/procedure.d.ts +8 -9
  110. package/dist/schema/procedure.d.ts.map +1 -1
  111. package/dist/schema/procedure.js +0 -1
  112. package/dist/schema/procedure.js.map +1 -1
  113. package/dist/schema/query.d.ts +7 -8
  114. package/dist/schema/query.d.ts.map +1 -1
  115. package/dist/schema/query.js +0 -1
  116. package/dist/schema/query.js.map +1 -1
  117. package/dist/schema/record.d.ts +34 -28
  118. package/dist/schema/record.d.ts.map +1 -1
  119. package/dist/schema/record.js +1 -2
  120. package/dist/schema/record.js.map +1 -1
  121. package/dist/schema/ref.d.ts +2 -3
  122. package/dist/schema/ref.d.ts.map +1 -1
  123. package/dist/schema/ref.js +1 -2
  124. package/dist/schema/ref.js.map +1 -1
  125. package/dist/schema/refine.d.ts +18 -0
  126. package/dist/schema/refine.d.ts.map +1 -0
  127. package/dist/schema/refine.js +33 -0
  128. package/dist/schema/refine.js.map +1 -0
  129. package/dist/schema/regexp.d.ts +7 -0
  130. package/dist/schema/regexp.d.ts.map +1 -0
  131. package/dist/schema/regexp.js +22 -0
  132. package/dist/schema/regexp.js.map +1 -0
  133. package/dist/schema/string.d.ts +4 -8
  134. package/dist/schema/string.d.ts.map +1 -1
  135. package/dist/schema/string.js +6 -3
  136. package/dist/schema/string.js.map +1 -1
  137. package/dist/schema/subscription.d.ts +7 -6
  138. package/dist/schema/subscription.d.ts.map +1 -1
  139. package/dist/schema/subscription.js.map +1 -1
  140. package/dist/schema/token.d.ts +2 -3
  141. package/dist/schema/token.d.ts.map +1 -1
  142. package/dist/schema/token.js +1 -2
  143. package/dist/schema/token.js.map +1 -1
  144. package/dist/schema/typed-object.d.ts +29 -27
  145. package/dist/schema/typed-object.d.ts.map +1 -1
  146. package/dist/schema/typed-object.js +1 -2
  147. package/dist/schema/typed-object.js.map +1 -1
  148. package/dist/schema/typed-ref.d.ts +2 -2
  149. package/dist/schema/typed-ref.d.ts.map +1 -1
  150. package/dist/schema/typed-ref.js +1 -1
  151. package/dist/schema/typed-ref.js.map +1 -1
  152. package/dist/schema/typed-union.d.ts +3 -4
  153. package/dist/schema/typed-union.d.ts.map +1 -1
  154. package/dist/schema/typed-union.js +3 -10
  155. package/dist/schema/typed-union.js.map +1 -1
  156. package/dist/schema/union.d.ts +2 -2
  157. package/dist/schema/union.d.ts.map +1 -1
  158. package/dist/schema/union.js +1 -1
  159. package/dist/schema/union.js.map +1 -1
  160. package/dist/schema/unknown-object.d.ts +2 -3
  161. package/dist/schema/unknown-object.d.ts.map +1 -1
  162. package/dist/schema/unknown-object.js +1 -2
  163. package/dist/schema/unknown-object.js.map +1 -1
  164. package/dist/schema/unknown.d.ts +2 -2
  165. package/dist/schema/unknown.d.ts.map +1 -1
  166. package/dist/schema/unknown.js +1 -1
  167. package/dist/schema/unknown.js.map +1 -1
  168. package/dist/schema.d.ts +4 -0
  169. package/dist/schema.d.ts.map +1 -1
  170. package/dist/schema.js +6 -1
  171. package/dist/schema.js.map +1 -1
  172. package/dist/util/array-agg.d.ts.map +1 -1
  173. package/dist/util/array-agg.js +1 -0
  174. package/dist/util/array-agg.js.map +1 -1
  175. package/dist/util/lazy-property.d.ts +2 -0
  176. package/dist/util/lazy-property.d.ts.map +1 -0
  177. package/dist/util/lazy-property.js +14 -0
  178. package/dist/util/lazy-property.js.map +1 -0
  179. package/dist/validation/schema.d.ts +24 -0
  180. package/dist/validation/schema.d.ts.map +1 -0
  181. package/dist/validation/schema.js +57 -0
  182. package/dist/validation/schema.js.map +1 -0
  183. package/dist/validation/validation-error.d.ts +3 -3
  184. package/dist/validation/validation-error.d.ts.map +1 -1
  185. package/dist/validation/validation-error.js +32 -4
  186. package/dist/validation/validation-error.js.map +1 -1
  187. package/dist/validation/validation-issue.d.ts +32 -24
  188. package/dist/validation/validation-issue.d.ts.map +1 -1
  189. package/dist/validation/validation-issue.js +136 -92
  190. package/dist/validation/validation-issue.js.map +1 -1
  191. package/dist/validation/validator.d.ts +20 -50
  192. package/dist/validation/validator.d.ts.map +1 -1
  193. package/dist/validation/validator.js +40 -134
  194. package/dist/validation/validator.js.map +1 -1
  195. package/dist/validation.d.ts +1 -0
  196. package/dist/validation.d.ts.map +1 -1
  197. package/dist/validation.js +1 -0
  198. package/dist/validation.js.map +1 -1
  199. package/package.json +8 -4
  200. package/src/core/$type.ts +7 -4
  201. package/src/core/record-key.ts +12 -5
  202. package/src/core/result.ts +6 -0
  203. package/src/core/string-format.ts +97 -61
  204. package/src/core/types.ts +12 -6
  205. package/src/external.ts +92 -70
  206. package/src/schema/_parameters.test.ts +416 -0
  207. package/src/schema/array.test.ts +237 -0
  208. package/src/schema/array.ts +17 -11
  209. package/src/schema/blob.test.ts +506 -0
  210. package/src/schema/blob.ts +3 -5
  211. package/src/schema/boolean.test.ts +116 -0
  212. package/src/schema/boolean.ts +5 -7
  213. package/src/schema/bytes.test.ts +226 -0
  214. package/src/schema/bytes.ts +4 -6
  215. package/src/schema/cid.test.ts +155 -0
  216. package/src/schema/cid.ts +14 -8
  217. package/src/schema/custom.test.ts +413 -0
  218. package/src/schema/custom.ts +10 -8
  219. package/src/schema/dict.test.ts +198 -0
  220. package/src/schema/dict.ts +6 -8
  221. package/src/schema/discriminated-union.test.ts +675 -0
  222. package/src/schema/discriminated-union.ts +68 -95
  223. package/src/schema/enum.test.ts +396 -0
  224. package/src/schema/enum.ts +12 -5
  225. package/src/schema/integer.test.ts +312 -0
  226. package/src/schema/integer.ts +5 -7
  227. package/src/schema/intersection.test.ts +32 -0
  228. package/src/schema/intersection.ts +37 -40
  229. package/src/schema/literal.test.ts +531 -0
  230. package/src/schema/literal.ts +12 -5
  231. package/src/schema/never.test.ts +174 -0
  232. package/src/schema/never.ts +3 -10
  233. package/src/schema/null.test.ts +79 -0
  234. package/src/schema/null.ts +3 -5
  235. package/src/schema/nullable.test.ts +480 -0
  236. package/src/schema/nullable.ts +23 -0
  237. package/src/schema/object.test.ts +47 -115
  238. package/src/schema/object.ts +19 -123
  239. package/src/schema/optional.test.ts +485 -0
  240. package/src/schema/optional.ts +31 -0
  241. package/src/schema/params.test.ts +582 -0
  242. package/src/schema/params.ts +37 -55
  243. package/src/schema/payload.test.ts +345 -0
  244. package/src/schema/payload.ts +5 -5
  245. package/src/schema/permission-set.test.ts +679 -0
  246. package/src/schema/permission-set.ts +6 -8
  247. package/src/schema/permission.test.ts +536 -0
  248. package/src/schema/permission.ts +0 -2
  249. package/src/schema/procedure.test.ts +443 -0
  250. package/src/schema/procedure.ts +11 -13
  251. package/src/schema/query.test.ts +408 -0
  252. package/src/schema/query.ts +9 -11
  253. package/src/schema/record.test.ts +694 -0
  254. package/src/schema/record.ts +38 -36
  255. package/src/schema/ref.test.ts +365 -0
  256. package/src/schema/ref.ts +8 -5
  257. package/src/schema/refine.test.ts +578 -0
  258. package/src/schema/refine.ts +85 -0
  259. package/src/schema/regexp.test.ts +580 -0
  260. package/src/schema/regexp.ts +22 -0
  261. package/src/schema/string.test.ts +612 -0
  262. package/src/schema/string.ts +11 -17
  263. package/src/schema/subscription.test.ts +689 -0
  264. package/src/schema/subscription.ts +13 -8
  265. package/src/schema/token.test.ts +428 -0
  266. package/src/schema/token.ts +3 -5
  267. package/src/schema/typed-object.test.ts +612 -0
  268. package/src/schema/typed-object.ts +23 -20
  269. package/src/schema/typed-ref.test.ts +823 -0
  270. package/src/schema/typed-ref.ts +10 -5
  271. package/src/schema/typed-union.test.ts +378 -0
  272. package/src/schema/typed-union.ts +6 -15
  273. package/src/schema/union.test.ts +200 -0
  274. package/src/schema/union.ts +5 -4
  275. package/src/schema/unknown-object.test.ts +592 -0
  276. package/src/schema/unknown-object.ts +3 -5
  277. package/src/schema/unknown.test.ts +312 -0
  278. package/src/schema/unknown.ts +3 -3
  279. package/src/schema.ts +7 -1
  280. package/src/util/array-agg.ts +1 -0
  281. package/src/util/lazy-property.ts +14 -0
  282. package/src/validation/schema.ts +92 -0
  283. package/src/validation/validation-error.ts +60 -9
  284. package/src/validation/validation-issue.ts +141 -144
  285. package/src/validation/validator.ts +67 -206
  286. package/src/validation.ts +1 -0
  287. package/tsconfig.build.json +12 -0
  288. package/tsconfig.json +7 -0
  289. package/tsconfig.tests.json +9 -0
@@ -0,0 +1,408 @@
1
+ import { asNsid } from '../core.js'
2
+ import { IntegerSchema } from './integer.js'
3
+ import { ObjectSchema } from './object.js'
4
+ import { OptionalSchema } from './optional.js'
5
+ import { ParamsSchema } from './params.js'
6
+ import { Payload } from './payload.js'
7
+ import { InferQueryOutputBody, InferQueryParameters, Query } from './query.js'
8
+ import { StringSchema } from './string.js'
9
+
10
+ describe('Query', () => {
11
+ describe('constructor', () => {
12
+ it('creates a Query instance with all parameters', () => {
13
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
14
+ const parameters = new ParamsSchema({
15
+ feed: new StringSchema({ format: 'at-uri' }),
16
+ limit: new OptionalSchema(
17
+ new IntegerSchema({ minimum: 1, maximum: 100 }),
18
+ ),
19
+ })
20
+ const output = new Payload(
21
+ 'application/json',
22
+ new ObjectSchema({
23
+ feed: new StringSchema({ format: 'at-uri' }),
24
+ }),
25
+ )
26
+ const errors = ['NotFound', 'RateLimitExceeded'] as const
27
+
28
+ const query = new Query(nsid, parameters, output, errors)
29
+
30
+ expect(query).toBeInstanceOf(Query)
31
+ expect(query.nsid).toBe(nsid)
32
+ expect(query.parameters).toBe(parameters)
33
+ expect(query.output).toBe(output)
34
+ expect(query.errors).toBe(errors)
35
+ })
36
+
37
+ it('creates a Query instance without errors', () => {
38
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
39
+ const parameters = new ParamsSchema({
40
+ feed: new StringSchema({ format: 'at-uri' }),
41
+ })
42
+ const output = new Payload(
43
+ 'application/json',
44
+ new ObjectSchema({
45
+ feed: new StringSchema({ format: 'at-uri' }),
46
+ }),
47
+ )
48
+
49
+ const query = new Query(nsid, parameters, output, undefined)
50
+
51
+ expect(query).toBeInstanceOf(Query)
52
+ expect(query.nsid).toBe(nsid)
53
+ expect(query.parameters).toBe(parameters)
54
+ expect(query.output).toBe(output)
55
+ expect(query.errors).toBeUndefined()
56
+ })
57
+
58
+ it('creates a Query instance with empty parameters', () => {
59
+ const nsid = asNsid('app.bsky.actor.getProfile')
60
+ const parameters = new ParamsSchema({})
61
+ const output = new Payload(
62
+ 'application/json',
63
+ new ObjectSchema({
64
+ did: new StringSchema({ format: 'did' }),
65
+ }),
66
+ )
67
+
68
+ const query = new Query(nsid, parameters, output, undefined)
69
+
70
+ expect(query).toBeInstanceOf(Query)
71
+ expect(query.parameters).toBe(parameters)
72
+ })
73
+ })
74
+
75
+ describe('properties', () => {
76
+ it('has nsid property', () => {
77
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
78
+ const parameters = new ParamsSchema({})
79
+ const output = new Payload('application/json', undefined)
80
+
81
+ const query = new Query(nsid, parameters, output, undefined)
82
+
83
+ expect(query.nsid).toBe(nsid)
84
+ expect(query.nsid).toBe('app.bsky.feed.getFeedSkeleton')
85
+ })
86
+
87
+ it('has parameters property', () => {
88
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
89
+ const parameters = new ParamsSchema({
90
+ feed: new StringSchema({ format: 'at-uri' }),
91
+ })
92
+ const output = new Payload('application/json', undefined)
93
+
94
+ const query = new Query(nsid, parameters, output, undefined)
95
+
96
+ expect(query.parameters).toBe(parameters)
97
+ expect(query.parameters).toBeInstanceOf(ParamsSchema)
98
+ })
99
+
100
+ it('has output property', () => {
101
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
102
+ const parameters = new ParamsSchema({})
103
+ const output = new Payload('application/json', undefined)
104
+
105
+ const query = new Query(nsid, parameters, output, undefined)
106
+
107
+ expect(query.output).toBe(output)
108
+ expect(query.output).toBeInstanceOf(Payload)
109
+ })
110
+
111
+ it('has errors property', () => {
112
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
113
+ const parameters = new ParamsSchema({})
114
+ const output = new Payload('application/json', undefined)
115
+ const errors = ['NotFound', 'RateLimitExceeded'] as const
116
+
117
+ const query = new Query(nsid, parameters, output, errors)
118
+
119
+ expect(query.errors).toBe(errors)
120
+ expect(query.errors).toEqual(['NotFound', 'RateLimitExceeded'])
121
+ })
122
+ })
123
+
124
+ describe('with complex parameters', () => {
125
+ it('creates a Query with multiple parameter types', () => {
126
+ const nsid = asNsid('app.bsky.feed.searchPosts')
127
+ const parameters = new ParamsSchema({
128
+ q: new StringSchema({ minLength: 1 }),
129
+ limit: new OptionalSchema(
130
+ new IntegerSchema({ minimum: 1, maximum: 100 }),
131
+ ),
132
+ cursor: new OptionalSchema(new StringSchema({})),
133
+ author: new OptionalSchema(new StringSchema({ format: 'did' })),
134
+ })
135
+ const output = new Payload(
136
+ 'application/json',
137
+ new ObjectSchema({
138
+ cursor: new OptionalSchema(new StringSchema({})),
139
+ posts: new ObjectSchema({}),
140
+ }),
141
+ )
142
+ const errors = ['BadRequest', 'RateLimitExceeded'] as const
143
+
144
+ const query = new Query(nsid, parameters, output, errors)
145
+
146
+ expect(query).toBeInstanceOf(Query)
147
+ expect(query.parameters).toBe(parameters)
148
+ expect(query.errors).toEqual(['BadRequest', 'RateLimitExceeded'])
149
+ })
150
+ })
151
+
152
+ describe('with various output payloads', () => {
153
+ it('creates a Query with undefined output payload', () => {
154
+ const nsid = asNsid('app.bsky.actor.getProfile')
155
+ const parameters = new ParamsSchema({
156
+ actor: new StringSchema({ format: 'at-identifier' }),
157
+ })
158
+ const output = new Payload(undefined, undefined)
159
+
160
+ const query = new Query(nsid, parameters, output, undefined)
161
+
162
+ expect(query).toBeInstanceOf(Query)
163
+ expect(query.output.encoding).toBeUndefined()
164
+ expect(query.output.schema).toBeUndefined()
165
+ })
166
+
167
+ it('creates a Query with JSON payload', () => {
168
+ const nsid = asNsid('app.bsky.actor.getProfile')
169
+ const parameters = new ParamsSchema({
170
+ actor: new StringSchema({ format: 'at-identifier' }),
171
+ })
172
+ const output = new Payload(
173
+ 'application/json',
174
+ new ObjectSchema({
175
+ did: new StringSchema({ format: 'did' }),
176
+ handle: new StringSchema({ format: 'handle' }),
177
+ }),
178
+ )
179
+
180
+ const query = new Query(nsid, parameters, output, undefined)
181
+
182
+ expect(query).toBeInstanceOf(Query)
183
+ expect(query.output.encoding).toBe('application/json')
184
+ expect(query.output.schema).toBeInstanceOf(ObjectSchema)
185
+ })
186
+
187
+ it('creates a Query with text payload', () => {
188
+ const nsid = asNsid('app.bsky.feed.getPost')
189
+ const parameters = new ParamsSchema({
190
+ uri: new StringSchema({ format: 'at-uri' }),
191
+ })
192
+ const output = new Payload('text/plain', undefined)
193
+
194
+ const query = new Query(nsid, parameters, output, undefined)
195
+
196
+ expect(query).toBeInstanceOf(Query)
197
+ expect(query.output.encoding).toBe('text/plain')
198
+ })
199
+ })
200
+
201
+ describe('with different error configurations', () => {
202
+ it('creates a Query with a single error', () => {
203
+ const nsid = asNsid('app.bsky.feed.getPost')
204
+ const parameters = new ParamsSchema({})
205
+ const output = new Payload('application/json', undefined)
206
+ const errors = ['NotFound'] as const
207
+
208
+ const query = new Query(nsid, parameters, output, errors)
209
+
210
+ expect(query.errors).toEqual(['NotFound'])
211
+ })
212
+
213
+ it('creates a Query with multiple errors', () => {
214
+ const nsid = asNsid('app.bsky.feed.getPost')
215
+ const parameters = new ParamsSchema({})
216
+ const output = new Payload('application/json', undefined)
217
+ const errors = ['NotFound', 'Unauthorized', 'RateLimitExceeded'] as const
218
+
219
+ const query = new Query(nsid, parameters, output, errors)
220
+
221
+ expect(query.errors).toEqual([
222
+ 'NotFound',
223
+ 'Unauthorized',
224
+ 'RateLimitExceeded',
225
+ ])
226
+ })
227
+
228
+ it('creates a Query with empty errors array', () => {
229
+ const nsid = asNsid('app.bsky.feed.getPost')
230
+ const parameters = new ParamsSchema({})
231
+ const output = new Payload('application/json', undefined)
232
+ const errors = [] as const
233
+
234
+ const query = new Query(nsid, parameters, output, errors)
235
+
236
+ expect(query.errors).toEqual([])
237
+ })
238
+ })
239
+
240
+ describe('type inference', () => {
241
+ it('InferQueryParameters correctly infers parameter types', () => {
242
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
243
+ const parameters = new ParamsSchema({
244
+ feed: new StringSchema({ format: 'at-uri' }),
245
+ limit: new OptionalSchema(new IntegerSchema({})),
246
+ })
247
+ const output = new Payload('application/json', undefined)
248
+
249
+ const query = new Query(nsid, parameters, output, undefined)
250
+
251
+ type Params = InferQueryParameters<typeof query>
252
+
253
+ // Type-level test - this should compile without errors
254
+ const params: Params = {
255
+ feed: 'at://did:plc:abc123/app.bsky.feed.post/xyz',
256
+ limit: 50,
257
+ }
258
+
259
+ expect(params.feed).toBeDefined()
260
+ })
261
+
262
+ it('InferQueryOutputBody correctly infers output body type', () => {
263
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
264
+ const parameters = new ParamsSchema({})
265
+ const output = new Payload(
266
+ 'application/json',
267
+ new ObjectSchema({
268
+ cursor: new OptionalSchema(new StringSchema({})),
269
+ feed: new StringSchema({ format: 'at-uri' }),
270
+ }),
271
+ )
272
+
273
+ const query = new Query(nsid, parameters, output, undefined)
274
+
275
+ type OutputBody = InferQueryOutputBody<typeof query>
276
+
277
+ // Type-level test - this should compile without errors
278
+ const outputBody: OutputBody = {
279
+ cursor: 'abc123',
280
+ feed: 'at://did:plc:abc123/app.bsky.feed.post/xyz',
281
+ }
282
+
283
+ expect(outputBody.feed).toBeDefined()
284
+ })
285
+ })
286
+
287
+ describe('edge cases', () => {
288
+ it('handles very long NSID', () => {
289
+ const nsid = asNsid(
290
+ 'com.example.very.long.namespace.identifier.method.name',
291
+ )
292
+ const parameters = new ParamsSchema({})
293
+ const output = new Payload('application/json', undefined)
294
+
295
+ const query = new Query(nsid, parameters, output, undefined)
296
+
297
+ expect(query.nsid).toBe(nsid)
298
+ })
299
+
300
+ it('handles query with all optional parameters', () => {
301
+ const nsid = asNsid('app.bsky.feed.search')
302
+ const parameters = new ParamsSchema({
303
+ q: new OptionalSchema(new StringSchema({})),
304
+ limit: new OptionalSchema(new IntegerSchema({})),
305
+ cursor: new OptionalSchema(new StringSchema({})),
306
+ })
307
+ const output = new Payload('application/json', undefined)
308
+
309
+ const query = new Query(nsid, parameters, output, undefined)
310
+
311
+ expect(query.parameters).toBe(parameters)
312
+ })
313
+
314
+ it('handles query with complex nested output schema', () => {
315
+ const nsid = asNsid('app.bsky.feed.getTimeline')
316
+ const parameters = new ParamsSchema({})
317
+ const output = new Payload(
318
+ 'application/json',
319
+ new ObjectSchema({
320
+ cursor: new OptionalSchema(new StringSchema({})),
321
+ feed: new ObjectSchema({
322
+ post: new ObjectSchema({
323
+ uri: new StringSchema({ format: 'at-uri' }),
324
+ cid: new StringSchema({ format: 'cid' }),
325
+ }),
326
+ }),
327
+ }),
328
+ )
329
+
330
+ const query = new Query(nsid, parameters, output, undefined)
331
+
332
+ expect(query.output.schema).toBeInstanceOf(ObjectSchema)
333
+ })
334
+ })
335
+
336
+ describe('real-world query examples', () => {
337
+ it('creates a getFeedSkeleton query', () => {
338
+ const nsid = asNsid('app.bsky.feed.getFeedSkeleton')
339
+ const parameters = new ParamsSchema({
340
+ feed: new StringSchema({ format: 'at-uri' }),
341
+ limit: new OptionalSchema(
342
+ new IntegerSchema({ minimum: 1, maximum: 100, default: 50 }),
343
+ ),
344
+ cursor: new OptionalSchema(new StringSchema({})),
345
+ })
346
+ const output = new Payload(
347
+ 'application/json',
348
+ new ObjectSchema({
349
+ cursor: new OptionalSchema(new StringSchema({})),
350
+ feed: new ObjectSchema({}),
351
+ }),
352
+ )
353
+
354
+ const query = new Query(nsid, parameters, output, undefined)
355
+
356
+ expect(query.nsid).toBe('app.bsky.feed.getFeedSkeleton')
357
+ })
358
+
359
+ it('creates a searchPosts query', () => {
360
+ const nsid = asNsid('app.bsky.feed.searchPosts')
361
+ const parameters = new ParamsSchema({
362
+ q: new StringSchema({ minLength: 1, maxLength: 300 }),
363
+ limit: new OptionalSchema(
364
+ new IntegerSchema({ minimum: 1, maximum: 100, default: 25 }),
365
+ ),
366
+ cursor: new OptionalSchema(new StringSchema({})),
367
+ })
368
+ const output = new Payload(
369
+ 'application/json',
370
+ new ObjectSchema({
371
+ cursor: new OptionalSchema(new StringSchema({})),
372
+ hitsTotal: new OptionalSchema(new IntegerSchema({})),
373
+ posts: new ObjectSchema({}),
374
+ }),
375
+ )
376
+ const errors = ['BadRequest'] as const
377
+
378
+ const query = new Query(nsid, parameters, output, errors)
379
+
380
+ expect(query.nsid).toBe('app.bsky.feed.searchPosts')
381
+ expect(query.errors).toEqual(['BadRequest'])
382
+ })
383
+
384
+ it('creates a getProfile query', () => {
385
+ const nsid = asNsid('app.bsky.actor.getProfile')
386
+ const parameters = new ParamsSchema({
387
+ actor: new StringSchema({ format: 'at-identifier' }),
388
+ })
389
+ const output = new Payload(
390
+ 'application/json',
391
+ new ObjectSchema({
392
+ did: new StringSchema({ format: 'did' }),
393
+ handle: new StringSchema({ format: 'handle' }),
394
+ displayName: new OptionalSchema(
395
+ new StringSchema({ maxGraphemes: 64 }),
396
+ ),
397
+ description: new OptionalSchema(
398
+ new StringSchema({ maxGraphemes: 256 }),
399
+ ),
400
+ }),
401
+ )
402
+
403
+ const query = new Query(nsid, parameters, output, undefined)
404
+
405
+ expect(query.nsid).toBe('app.bsky.actor.getProfile')
406
+ })
407
+ })
408
+ })
@@ -1,4 +1,4 @@
1
- import { Nsid } from '../core.js'
1
+ import { NsidString } from '../core.js'
2
2
  import { Infer } from '../validation.js'
3
3
  import { ParamsSchema } from './params.js'
4
4
  import { InferPayloadBody, Payload } from './payload.js'
@@ -12,17 +12,15 @@ export type InferQueryOutputBody<Q extends Query> =
12
12
  : never
13
13
 
14
14
  export class Query<
15
- N extends Nsid = any,
16
- P extends ParamsSchema = any,
17
- O extends Payload = any,
18
- E extends undefined | readonly string[] = any,
15
+ TNsid extends NsidString = any,
16
+ TParameters extends ParamsSchema = any,
17
+ TOutputPayload extends Payload = any,
18
+ TErrors extends undefined | readonly string[] = any,
19
19
  > {
20
- readonly lexiconType = 'query' as const
21
-
22
20
  constructor(
23
- readonly nsid: N,
24
- readonly parameters: P,
25
- readonly output: O,
26
- readonly errors: E,
21
+ readonly nsid: TNsid,
22
+ readonly parameters: TParameters,
23
+ readonly output: TOutputPayload,
24
+ readonly errors: TErrors,
27
25
  ) {}
28
26
  }