@atproto/lex-document 0.0.3 → 0.0.4

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.
@@ -1,98 +1,75 @@
1
1
  import { l } from '@atproto/lex-schema'
2
2
 
3
+ // Re-usable shortcuts (avoid creating too many schemas)
4
+
5
+ const bool = l.boolean()
6
+ const int = l.integer()
7
+ const str = l.string()
8
+
9
+ const boopOpt = l.optional(bool)
10
+ const intOpt = l.optional(int)
11
+ const strOpt = l.optional(str)
12
+
13
+ const strArrOpt = l.optional(l.array(str))
14
+
3
15
  // https://atproto.com/specs/lexicon
4
16
 
5
17
  // "Concrete" Types
6
18
 
7
- export const lexiconBooleanSchema = l.object(
8
- {
9
- type: l.literal('boolean'),
10
- description: l.string(),
11
- default: l.boolean(),
12
- const: l.boolean(),
13
- },
14
- {
15
- required: ['type'],
16
- },
17
- )
19
+ export const lexiconBooleanSchema = l.object({
20
+ type: l.literal('boolean'),
21
+ default: boopOpt,
22
+ const: boopOpt,
23
+ description: strOpt,
24
+ })
18
25
  export type LexiconBoolean = l.Infer<typeof lexiconBooleanSchema>
19
26
 
20
- export const lexiconIntegerSchema = l.object(
21
- {
22
- type: l.literal('integer'),
23
- description: l.string(),
24
- default: l.integer(),
25
- minimum: l.integer(),
26
- maximum: l.integer(),
27
- enum: l.array(l.integer()),
28
- const: l.integer(),
29
- },
30
- {
31
- required: ['type'],
32
- },
33
- )
27
+ export const lexiconIntegerSchema = l.object({
28
+ type: l.literal('integer'),
29
+ default: intOpt,
30
+ minimum: intOpt,
31
+ maximum: intOpt,
32
+ enum: l.optional(l.array(l.integer())),
33
+ const: intOpt,
34
+ description: strOpt,
35
+ })
34
36
  export type LexiconInteger = l.Infer<typeof lexiconIntegerSchema>
35
37
 
36
- export type LexiconStringFormat = l.StringFormat
37
- export const lexiconStringFormatSchema = l.enum<LexiconStringFormat>(
38
- l.STRING_FORMATS,
39
- )
40
-
41
- export const lexiconStringSchema = l.object(
42
- {
43
- type: l.literal('string'),
44
- format: lexiconStringFormatSchema,
45
- description: l.string(),
46
- default: l.string(),
47
- minLength: l.integer(),
48
- maxLength: l.integer(),
49
- minGraphemes: l.integer(),
50
- maxGraphemes: l.integer(),
51
- enum: l.array(l.string()),
52
- const: l.string(),
53
- knownValues: l.array(l.string()),
54
- },
55
- {
56
- required: ['type'],
57
- },
58
- )
38
+ export const lexiconStringSchema = l.object({
39
+ type: l.literal('string'),
40
+ format: l.optional(l.enum<l.StringFormat>(l.STRING_FORMATS)),
41
+ default: strOpt,
42
+ minLength: intOpt,
43
+ maxLength: intOpt,
44
+ minGraphemes: intOpt,
45
+ maxGraphemes: intOpt,
46
+ enum: strArrOpt,
47
+ const: strOpt,
48
+ knownValues: strArrOpt,
49
+ description: strOpt,
50
+ })
59
51
  export type LexiconString = l.Infer<typeof lexiconStringSchema>
60
52
 
61
- export const lexiconBytesSchema = l.object(
62
- {
63
- type: l.literal('bytes'),
64
- description: l.string(),
65
- maxLength: l.integer(),
66
- minLength: l.integer(),
67
- },
68
- {
69
- required: ['type'],
70
- },
71
- )
53
+ export const lexiconBytesSchema = l.object({
54
+ type: l.literal('bytes'),
55
+ maxLength: intOpt,
56
+ minLength: intOpt,
57
+ description: strOpt,
58
+ })
72
59
  export type LexiconBytes = l.Infer<typeof lexiconBytesSchema>
73
60
 
74
- export const lexiconCidLinkSchema = l.object(
75
- {
76
- type: l.literal('cid-link'),
77
- description: l.string(),
78
- },
79
- {
80
- required: ['type'],
81
- },
82
- )
61
+ export const lexiconCidLinkSchema = l.object({
62
+ type: l.literal('cid-link'),
63
+ description: strOpt,
64
+ })
83
65
  export type LexiconCid = l.Infer<typeof lexiconCidLinkSchema>
84
66
 
85
- export const lexiconBlobSchema = l.object(
86
- {
87
- type: l.literal('blob'),
88
- description: l.string(),
89
- accept: l.array(l.string()),
90
- maxSize: l.integer(),
91
- },
92
- {
93
- required: ['type'],
94
- },
95
- )
67
+ export const lexiconBlobSchema = l.object({
68
+ type: l.literal('blob'),
69
+ accept: strArrOpt,
70
+ maxSize: intOpt,
71
+ description: strOpt,
72
+ })
96
73
  export type LexiconBlob = l.Infer<typeof lexiconBlobSchema>
97
74
 
98
75
  const CONCRETE_TYPES = [
@@ -108,51 +85,31 @@ const CONCRETE_TYPES = [
108
85
 
109
86
  // Meta types
110
87
 
111
- export const lexiconUnknownSchema = l.object(
112
- {
113
- type: l.literal('unknown'),
114
- description: l.string(),
115
- },
116
- {
117
- required: ['type'],
118
- },
119
- )
88
+ export const lexiconUnknownSchema = l.object({
89
+ type: l.literal('unknown'),
90
+ description: strOpt,
91
+ })
120
92
  export type LexiconUnknown = l.Infer<typeof lexiconUnknownSchema>
121
93
 
122
- export const lexiconTokenSchema = l.object(
123
- {
124
- type: l.literal('token'),
125
- description: l.string(),
126
- },
127
- {
128
- required: ['type'],
129
- },
130
- )
94
+ export const lexiconTokenSchema = l.object({
95
+ type: l.literal('token'),
96
+ description: strOpt,
97
+ })
131
98
  export type LexiconToken = l.Infer<typeof lexiconTokenSchema>
132
99
 
133
- export const lexiconRefSchema = l.object(
134
- {
135
- type: l.literal('ref'),
136
- description: l.string(),
137
- ref: l.string(),
138
- },
139
- {
140
- required: ['type', 'ref'],
141
- },
142
- )
100
+ export const lexiconRefSchema = l.object({
101
+ type: l.literal('ref'),
102
+ ref: str,
103
+ description: strOpt,
104
+ })
143
105
  export type LexiconRef = l.Infer<typeof lexiconRefSchema>
144
106
 
145
- export const lexiconRefUnionSchema = l.object(
146
- {
147
- type: l.literal('union'),
148
- description: l.string(),
149
- refs: l.array(l.string()),
150
- closed: l.boolean(),
151
- },
152
- {
153
- required: ['type', 'refs'],
154
- },
155
- )
107
+ export const lexiconRefUnionSchema = l.object({
108
+ type: l.literal('union'),
109
+ refs: l.array(str),
110
+ closed: boopOpt,
111
+ description: strOpt,
112
+ })
156
113
  export type LexiconRefUnion = l.Infer<typeof lexiconRefUnionSchema>
157
114
 
158
115
  // Complex Types
@@ -167,171 +124,149 @@ const ARRAY_ITEMS_SCHEMAS = [
167
124
 
168
125
  export type LexiconArrayItems = l.Infer<(typeof ARRAY_ITEMS_SCHEMAS)[number]>
169
126
 
170
- export const lexiconArraySchema = l.object(
171
- {
172
- type: l.literal('array'),
173
- description: l.string(),
174
- items: l.discriminatedUnion('type', ARRAY_ITEMS_SCHEMAS),
175
- minLength: l.integer(),
176
- maxLength: l.integer(),
177
- },
178
- {
179
- required: ['type', 'items'],
180
- },
181
- )
127
+ export const lexiconArraySchema = l.object({
128
+ type: l.literal('array'),
129
+ items: l.discriminatedUnion('type', ARRAY_ITEMS_SCHEMAS),
130
+ minLength: intOpt,
131
+ maxLength: intOpt,
132
+ description: strOpt,
133
+ })
182
134
  export type LexiconArray = l.Infer<typeof lexiconArraySchema>
183
135
 
184
- export const lexiconObjectSchema = l.object(
185
- {
136
+ const requirePropertiesRefinement: l.RefinementCheck<{
137
+ required?: string[]
138
+ properties: Record<string, unknown>
139
+ }> = {
140
+ check: (v) => !v.required || v.required.every((k) => k in v.properties),
141
+ message: 'All required parameters must be defined in properties',
142
+ path: 'required',
143
+ }
144
+
145
+ export const lexiconObjectSchema = l.refine(
146
+ l.object({
186
147
  type: l.literal('object'),
187
- description: l.string(),
188
- required: l.array(l.string()),
189
- nullable: l.array(l.string()),
190
148
  properties: l.dict(
191
- l.string(),
149
+ str,
192
150
  l.discriminatedUnion('type', [
193
151
  ...ARRAY_ITEMS_SCHEMAS,
194
152
  lexiconArraySchema,
195
153
  ]),
196
154
  ),
197
- },
198
- {
199
- required: ['type', 'properties'],
200
- },
155
+ required: strArrOpt,
156
+ nullable: strArrOpt,
157
+ description: strOpt,
158
+ }),
159
+ requirePropertiesRefinement,
201
160
  )
202
161
  export type LexiconObject = l.Infer<typeof lexiconObjectSchema>
203
162
 
204
163
  // Records
205
164
 
206
- export const lexiconRecordSchema = l.object(
207
- {
208
- type: l.literal('record'),
209
- description: l.string(),
210
- key: l.string(),
211
- record: lexiconObjectSchema,
212
- },
213
- { required: ['type', 'record'] },
165
+ export const lexiconRecordKeySchema = l.custom(
166
+ l.isLexiconRecordKey,
167
+ 'Invalid record key definition (must be "any", "nsid", "tid", or "literal:<string>")',
214
168
  )
169
+
170
+ export type LexiconRecordKey = l.LexiconRecordKey
171
+
172
+ export const lexiconRecordSchema = l.object({
173
+ type: l.literal('record'),
174
+ record: lexiconObjectSchema,
175
+ description: strOpt,
176
+ key: lexiconRecordKeySchema,
177
+ })
215
178
  export type LexiconRecord = l.Infer<typeof lexiconRecordSchema>
216
179
 
217
180
  // XRPC Methods
218
181
 
219
- export const lexiconParameters = l.object(
220
- {
182
+ export const lexiconParameters = l.refine(
183
+ l.object({
221
184
  type: l.literal('params'),
222
- description: l.string(),
223
- required: l.array(l.string()),
224
185
  properties: l.dict(
225
- l.string(),
186
+ str,
226
187
  l.discriminatedUnion('type', [
227
188
  lexiconBooleanSchema,
228
189
  lexiconIntegerSchema,
229
190
  lexiconStringSchema,
230
- l.object(
231
- {
232
- type: l.literal('array'),
233
- description: l.string(),
234
- items: l.discriminatedUnion('type', [
235
- lexiconBooleanSchema,
236
- lexiconIntegerSchema,
237
- lexiconStringSchema,
238
- ]),
239
- minLength: l.integer(),
240
- maxLength: l.integer(),
241
- },
242
- {
243
- required: ['type', 'items'],
244
- },
245
- ),
191
+ l.object({
192
+ type: l.literal('array'),
193
+ items: l.discriminatedUnion('type', [
194
+ lexiconBooleanSchema,
195
+ lexiconIntegerSchema,
196
+ lexiconStringSchema,
197
+ ]),
198
+ minLength: intOpt,
199
+ maxLength: intOpt,
200
+ description: strOpt,
201
+ }),
246
202
  ]),
247
203
  ),
248
- },
249
- {
250
- required: ['type', 'properties'],
251
- },
204
+ required: strArrOpt,
205
+ description: strOpt,
206
+ }),
207
+ requirePropertiesRefinement,
252
208
  )
253
209
  export type LexiconParameters = l.Infer<typeof lexiconParameters>
254
210
 
255
- export const lexiconPayload = l.object(
256
- {
257
- description: l.string(),
258
- encoding: l.string(),
259
- schema: l.discriminatedUnion('type', [
211
+ export const lexiconPayload = l.object({
212
+ encoding: str,
213
+ schema: l.optional(
214
+ l.discriminatedUnion('type', [
260
215
  lexiconRefSchema,
261
216
  lexiconRefUnionSchema,
262
217
  lexiconObjectSchema,
263
218
  ]),
264
- },
265
- {
266
- required: ['encoding'],
267
- },
268
- )
219
+ ),
220
+ description: strOpt,
221
+ })
269
222
  export type LexiconPayload = l.Infer<typeof lexiconPayload>
270
223
 
271
224
  export const lexiconSubscriptionMessage = l.object({
272
- description: l.string(),
273
- schema: l.discriminatedUnion('type', [
274
- lexiconRefSchema,
275
- lexiconRefUnionSchema,
276
- lexiconObjectSchema,
277
- ]),
225
+ description: strOpt,
226
+ schema: l.optional(
227
+ l.discriminatedUnion('type', [
228
+ lexiconRefSchema,
229
+ lexiconRefUnionSchema,
230
+ lexiconObjectSchema,
231
+ ]),
232
+ ),
278
233
  })
279
234
  export type LexiconSubscriptionMessage = l.Infer<
280
235
  typeof lexiconSubscriptionMessage
281
236
  >
282
237
 
283
- export const lexiconError = l.object(
284
- {
285
- name: l.string({ minLength: 1 }),
286
- description: l.string(),
287
- },
288
- {
289
- required: ['name'],
290
- },
291
- )
238
+ export const lexiconError = l.object({
239
+ name: l.string({ minLength: 1 }),
240
+ description: strOpt,
241
+ })
292
242
  export type LexiconError = l.Infer<typeof lexiconError>
293
243
 
294
- export const lexiconQuerySchema = l.object(
295
- {
296
- type: l.literal('query'),
297
- description: l.string(),
298
- parameters: lexiconParameters,
299
- output: lexiconPayload,
300
- errors: l.array(lexiconError),
301
- },
302
- {
303
- required: ['type'],
304
- },
305
- )
244
+ export const lexiconQuerySchema = l.object({
245
+ type: l.literal('query'),
246
+ parameters: l.optional(lexiconParameters),
247
+ output: l.optional(lexiconPayload),
248
+ errors: l.optional(l.array(lexiconError)),
249
+ description: strOpt,
250
+ })
306
251
  export type LexiconQuery = l.Infer<typeof lexiconQuerySchema>
307
252
 
308
- export const lexiconProcedureSchema = l.object(
309
- {
310
- type: l.literal('procedure'),
311
- description: l.string(),
312
- parameters: lexiconParameters,
313
- input: lexiconPayload,
314
- output: lexiconPayload,
315
- errors: l.array(lexiconError),
316
- },
317
- {
318
- required: ['type'],
319
- },
320
- )
253
+ export const lexiconProcedureSchema = l.object({
254
+ type: l.literal('procedure'),
255
+ parameters: l.optional(lexiconParameters),
256
+ input: l.optional(lexiconPayload),
257
+ output: l.optional(lexiconPayload),
258
+ errors: l.optional(l.array(lexiconError)),
259
+ description: strOpt,
260
+ })
321
261
  export type LexiconProcedure = l.Infer<typeof lexiconProcedureSchema>
322
262
 
323
- export const lexiconSubscriptionSchema = l.object(
324
- {
325
- type: l.literal('subscription'),
326
- description: l.string(),
327
- parameters: lexiconParameters,
328
- message: lexiconSubscriptionMessage,
329
- errors: l.array(lexiconError),
330
- },
331
- {
332
- required: ['type'],
333
- },
334
- )
263
+ export const lexiconSubscriptionSchema = l.object({
264
+ type: l.literal('subscription'),
265
+ description: strOpt,
266
+ parameters: l.optional(lexiconParameters),
267
+ message: l.optional(lexiconSubscriptionMessage),
268
+ errors: l.optional(l.array(lexiconError)),
269
+ })
335
270
 
336
271
  export type LexiconSubscription = l.Infer<typeof lexiconSubscriptionSchema>
337
272
 
@@ -341,37 +276,29 @@ const lexiconLanguageSchema = l.string({ format: 'language' })
341
276
 
342
277
  export type LexiconLanguage = l.Infer<typeof lexiconLanguageSchema>
343
278
 
344
- const lexiconLanguageDict = l.dict(lexiconLanguageSchema, l.string())
279
+ const lexiconLanguageDict = l.dict(lexiconLanguageSchema, str)
345
280
 
346
281
  export type LexiconLanguageDict = l.Infer<typeof lexiconLanguageDict>
347
282
 
348
- const lexiconPermissionSchema = l.object(
349
- {
283
+ const lexiconPermissionSchema = l.intersection(
284
+ l.object({
350
285
  type: l.literal('permission'),
351
286
  resource: l.string({ minLength: 1 }),
352
- },
353
- {
354
- required: ['type', 'resource'],
355
- unknownProperties: l.paramsSchema,
356
- },
287
+ }),
288
+ l.paramsSchema,
357
289
  )
358
290
 
359
291
  export type LexiconPermission = l.Infer<typeof lexiconPermissionSchema>
360
292
 
361
- const lexiconPermissionSetSchema = l.object(
362
- {
363
- type: l.literal('permission-set'),
364
- description: l.string(),
365
- title: l.string(),
366
- 'title:lang': lexiconLanguageDict,
367
- detail: l.string(),
368
- 'detail:lang': lexiconLanguageDict,
369
- permissions: l.array(lexiconPermissionSchema),
370
- },
371
- {
372
- required: ['type', 'permissions'],
373
- },
374
- )
293
+ const lexiconPermissionSetSchema = l.object({
294
+ type: l.literal('permission-set'),
295
+ permissions: l.array(lexiconPermissionSchema),
296
+ title: strOpt,
297
+ 'title:lang': l.optional(lexiconLanguageDict),
298
+ detail: strOpt,
299
+ 'detail:lang': l.optional(lexiconLanguageDict),
300
+ description: strOpt,
301
+ })
375
302
 
376
303
  export type LexiconPermissionSet = l.Infer<typeof lexiconPermissionSetSchema>
377
304
 
@@ -404,24 +331,19 @@ export type MainLexiconDefinition = l.Infer<
404
331
  export const lexiconIdentifierSchema = l.string({ format: 'nsid' })
405
332
  export type LexiconIdentifier = l.Infer<typeof lexiconIdentifierSchema>
406
333
 
407
- export const lexiconDocumentSchema = l.object(
408
- {
409
- lexicon: l.literal(1),
410
- id: lexiconIdentifierSchema,
411
- revision: l.integer(),
412
- description: l.string(),
413
- defs: l.object(
414
- { main: l.discriminatedUnion('type', MAIN_LEXICON_SCHEMAS) },
415
- {
416
- unknownProperties: l.dict(
417
- l.string({ minLength: 1 }),
418
- l.discriminatedUnion('type', NAMED_LEXICON_SCHEMAS),
419
- ),
420
- },
334
+ export const lexiconDocumentSchema = l.object({
335
+ lexicon: l.literal(1),
336
+ id: lexiconIdentifierSchema,
337
+ revision: intOpt,
338
+ description: strOpt,
339
+ defs: l.intersection(
340
+ l.object({
341
+ main: l.optional(l.discriminatedUnion('type', MAIN_LEXICON_SCHEMAS)),
342
+ }),
343
+ l.dict(
344
+ l.string({ minLength: 1 }),
345
+ l.discriminatedUnion('type', NAMED_LEXICON_SCHEMAS),
421
346
  ),
422
- },
423
- {
424
- required: ['lexicon', 'id', 'defs'],
425
- },
426
- )
347
+ ),
348
+ })
427
349
  export type LexiconDocument = l.Infer<typeof lexiconDocumentSchema>