@atproto/lexicon 0.7.3 → 0.7.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/lexicons.d.ts +1 -1
  3. package/dist/lexicons.d.ts.map +1 -1
  4. package/dist/lexicons.js.map +1 -1
  5. package/dist/serialize.d.ts +1 -1
  6. package/dist/serialize.d.ts.map +1 -1
  7. package/dist/serialize.js +8 -7
  8. package/dist/serialize.js.map +1 -1
  9. package/dist/types.d.ts +1 -1
  10. package/dist/types.d.ts.map +1 -1
  11. package/dist/types.js.map +1 -1
  12. package/dist/validation.d.ts +1 -1
  13. package/dist/validation.d.ts.map +1 -1
  14. package/dist/validation.js +1 -0
  15. package/dist/validation.js.map +1 -1
  16. package/dist/validators/blob.d.ts +1 -1
  17. package/dist/validators/blob.d.ts.map +1 -1
  18. package/dist/validators/blob.js +1 -0
  19. package/dist/validators/blob.js.map +1 -1
  20. package/dist/validators/complex.d.ts +1 -1
  21. package/dist/validators/complex.d.ts.map +1 -1
  22. package/dist/validators/complex.js +2 -1
  23. package/dist/validators/complex.js.map +1 -1
  24. package/dist/validators/formats.d.ts +1 -1
  25. package/dist/validators/formats.d.ts.map +1 -1
  26. package/dist/validators/formats.js.map +1 -1
  27. package/dist/validators/primitives.d.ts +1 -1
  28. package/dist/validators/primitives.d.ts.map +1 -1
  29. package/dist/validators/primitives.js +2 -1
  30. package/dist/validators/primitives.js.map +1 -1
  31. package/dist/validators/xrpc.d.ts +1 -1
  32. package/dist/validators/xrpc.d.ts.map +1 -1
  33. package/dist/validators/xrpc.js +3 -2
  34. package/dist/validators/xrpc.js.map +1 -1
  35. package/package.json +18 -13
  36. package/jest.config.cjs +0 -21
  37. package/src/blob-refs.ts +0 -65
  38. package/src/index.ts +0 -4
  39. package/src/lexicons.ts +0 -253
  40. package/src/serialize.ts +0 -102
  41. package/src/types.ts +0 -483
  42. package/src/util.ts +0 -58
  43. package/src/validation.ts +0 -84
  44. package/src/validators/blob.ts +0 -19
  45. package/src/validators/complex.ts +0 -212
  46. package/src/validators/formats.ts +0 -72
  47. package/src/validators/primitives.ts +0 -416
  48. package/src/validators/xrpc.ts +0 -53
  49. package/tests/_scaffolds/lexicons.ts +0 -545
  50. package/tests/general.test.ts +0 -1243
  51. package/tsconfig.build.json +0 -8
  52. package/tsconfig.build.tsbuildinfo +0 -1
  53. package/tsconfig.json +0 -7
  54. package/tsconfig.tests.json +0 -7
package/src/serialize.ts DELETED
@@ -1,102 +0,0 @@
1
- import { CID } from 'multiformats/cid'
2
- import {
3
- IpldValue,
4
- JsonValue,
5
- check,
6
- ipldToJson,
7
- jsonToIpld,
8
- } from '@atproto/common-web'
9
- import { BlobRef, jsonBlobRef } from './blob-refs.js'
10
-
11
- /**
12
- * @note this is equivalent to `unknown` because of {@link IpldValue} being `unknown`.
13
- * @deprecated Use {@link Lex} from `@atproto/lex-data` instead.
14
- */
15
- export type LexValue = unknown
16
-
17
- /**
18
- * @deprecated Use {@link TypedLexMap} from `@atproto/lex-data` instead.
19
- */
20
- export type RepoRecord = Record<string, LexValue>
21
-
22
- // @NOTE avoiding use of check.is() here only because it makes
23
- // these implementations slow, and they often live in hot paths.
24
-
25
- /**
26
- * @deprecated Use `LexValue` from `@atproto/lex-data` instead (which doesn't need conversion to IPLD).
27
- */
28
- export const lexToIpld = (val: LexValue): IpldValue => {
29
- // walk arrays
30
- if (Array.isArray(val)) {
31
- return val.map((item) => lexToIpld(item))
32
- }
33
- // objects
34
- if (val && typeof val === 'object') {
35
- // convert blobs, leaving the original encoding so that we don't change CIDs on re-encode
36
- if (val instanceof BlobRef) {
37
- return val.original
38
- }
39
- // retain cids & bytes
40
- if (CID.asCID(val) || val instanceof Uint8Array) {
41
- return val
42
- }
43
- // walk plain objects
44
- const toReturn = {}
45
- for (const key of Object.keys(val)) {
46
- toReturn[key] = lexToIpld(val[key])
47
- }
48
- return toReturn
49
- }
50
- // pass through
51
- return val
52
- }
53
-
54
- /**
55
- * @deprecated Use `LexValue` from `@atproto/lex-data` instead instead (which doesn't need conversion to IPLD).
56
- */
57
- export const ipldToLex = (val: IpldValue): LexValue => {
58
- // map arrays
59
- if (Array.isArray(val)) {
60
- return val.map((item) => ipldToLex(item))
61
- }
62
- // objects
63
- if (val && typeof val === 'object') {
64
- // convert blobs, using hints to avoid expensive is() check
65
- if (
66
- (val['$type'] === 'blob' ||
67
- (typeof val['cid'] === 'string' &&
68
- typeof val['mimeType'] === 'string')) &&
69
- check.is(val, jsonBlobRef)
70
- ) {
71
- return BlobRef.fromJsonRef(val)
72
- }
73
- // retain cids, bytes
74
- if (CID.asCID(val) || val instanceof Uint8Array) {
75
- return val
76
- }
77
- // map plain objects
78
- const toReturn = {}
79
- for (const key of Object.keys(val)) {
80
- toReturn[key] = ipldToLex(val[key])
81
- }
82
- return toReturn
83
- }
84
- // pass through
85
- return val
86
- }
87
-
88
- export const lexToJson = (val: LexValue): JsonValue => {
89
- return ipldToJson(lexToIpld(val))
90
- }
91
-
92
- export const stringifyLex = (val: LexValue): string => {
93
- return JSON.stringify(lexToJson(val))
94
- }
95
-
96
- export const jsonToLex = (val: JsonValue): LexValue => {
97
- return ipldToLex(jsonToIpld(val))
98
- }
99
-
100
- export const jsonStringToLex = (val: string): LexValue => {
101
- return jsonToLex(JSON.parse(val))
102
- }
package/src/types.ts DELETED
@@ -1,483 +0,0 @@
1
- import { z } from 'zod'
2
- import { validateLanguage } from '@atproto/common-web'
3
- import { isValidNsid } from '@atproto/syntax'
4
- import { requiredPropertiesRefinement } from './util.js'
5
-
6
- export const languageSchema = z
7
- .string()
8
- .refine(validateLanguage, 'Invalid BCP47 language tag')
9
-
10
- export const lexLang = z.record(languageSchema, z.string().optional())
11
-
12
- export type LexLang = z.infer<typeof lexLang>
13
-
14
- // primitives
15
- // =
16
-
17
- export const lexBoolean = z.object({
18
- type: z.literal('boolean'),
19
- description: z.string().optional(),
20
- default: z.boolean().optional(),
21
- const: z.boolean().optional(),
22
- })
23
- export type LexBoolean = z.infer<typeof lexBoolean>
24
-
25
- export const lexInteger = z.object({
26
- type: z.literal('integer'),
27
- description: z.string().optional(),
28
- default: z.number().int().optional(),
29
- minimum: z.number().int().optional(),
30
- maximum: z.number().int().optional(),
31
- enum: z.number().int().array().optional(),
32
- const: z.number().int().optional(),
33
- })
34
- export type LexInteger = z.infer<typeof lexInteger>
35
-
36
- export const lexStringFormat = z.enum([
37
- 'datetime',
38
- 'uri',
39
- 'at-uri',
40
- 'did',
41
- 'handle',
42
- 'at-identifier',
43
- 'nsid',
44
- 'cid',
45
- 'language',
46
- 'tid',
47
- 'record-key',
48
- ])
49
- export type LexStringFormat = z.infer<typeof lexStringFormat>
50
-
51
- export const lexString = z.object({
52
- type: z.literal('string'),
53
- format: lexStringFormat.optional(),
54
- description: z.string().optional(),
55
- default: z.string().optional(),
56
- minLength: z.number().int().optional(),
57
- maxLength: z.number().int().optional(),
58
- minGraphemes: z.number().int().optional(),
59
- maxGraphemes: z.number().int().optional(),
60
- enum: z.string().array().optional(),
61
- const: z.string().optional(),
62
- knownValues: z.string().array().optional(),
63
- })
64
- export type LexString = z.infer<typeof lexString>
65
-
66
- export const lexUnknown = z.object({
67
- type: z.literal('unknown'),
68
- description: z.string().optional(),
69
- })
70
- export type LexUnknown = z.infer<typeof lexUnknown>
71
-
72
- export const lexPrimitive = z.discriminatedUnion('type', [
73
- lexBoolean,
74
- lexInteger,
75
- lexString,
76
- lexUnknown,
77
- ])
78
- export type LexPrimitive = z.infer<typeof lexPrimitive>
79
-
80
- // ipld types
81
- // =
82
-
83
- export const lexBytes = z.object({
84
- type: z.literal('bytes'),
85
- description: z.string().optional(),
86
- maxLength: z.number().optional(),
87
- minLength: z.number().optional(),
88
- })
89
- export type LexBytes = z.infer<typeof lexBytes>
90
-
91
- export const lexCidLink = z.object({
92
- type: z.literal('cid-link'),
93
- description: z.string().optional(),
94
- })
95
- export type LexCidLink = z.infer<typeof lexCidLink>
96
-
97
- export const lexIpldType = z.discriminatedUnion('type', [lexBytes, lexCidLink])
98
- export type LexIpldType = z.infer<typeof lexIpldType>
99
-
100
- // references
101
- // =
102
-
103
- export const lexRef = z.object({
104
- type: z.literal('ref'),
105
- description: z.string().optional(),
106
- ref: z.string(),
107
- })
108
- export type LexRef = z.infer<typeof lexRef>
109
-
110
- export const lexRefUnion = z.object({
111
- type: z.literal('union'),
112
- description: z.string().optional(),
113
- refs: z.string().array(),
114
- closed: z.boolean().optional(),
115
- })
116
- export type LexRefUnion = z.infer<typeof lexRefUnion>
117
-
118
- export const lexRefVariant = z.discriminatedUnion('type', [lexRef, lexRefUnion])
119
- export type LexRefVariant = z.infer<typeof lexRefVariant>
120
-
121
- // blobs
122
- // =
123
-
124
- export const lexBlob = z.object({
125
- type: z.literal('blob'),
126
- description: z.string().optional(),
127
- accept: z.string().array().optional(),
128
- maxSize: z.number().optional(),
129
- })
130
- export type LexBlob = z.infer<typeof lexBlob>
131
-
132
- // complex types
133
- // =
134
-
135
- export const lexArray = z.object({
136
- type: z.literal('array'),
137
- description: z.string().optional(),
138
- items: z.discriminatedUnion('type', [
139
- // lexPrimitive
140
- lexBoolean,
141
- lexInteger,
142
- lexString,
143
- lexUnknown,
144
- // lexIpldType
145
- lexBytes,
146
- lexCidLink,
147
- // lexRefVariant
148
- lexRef,
149
- lexRefUnion,
150
- // other
151
- lexBlob,
152
- ]),
153
- minLength: z.number().int().optional(),
154
- maxLength: z.number().int().optional(),
155
- })
156
- export type LexArray = z.infer<typeof lexArray>
157
-
158
- export const lexPrimitiveArray = lexArray.merge(
159
- z.object({
160
- items: lexPrimitive,
161
- }),
162
- )
163
- export type LexPrimitiveArray = z.infer<typeof lexPrimitiveArray>
164
-
165
- export const lexToken = z.object({
166
- type: z.literal('token'),
167
- description: z.string().optional(),
168
- })
169
- export type LexToken = z.infer<typeof lexToken>
170
-
171
- export const lexObject = z
172
- .object({
173
- type: z.literal('object'),
174
- description: z.string().optional(),
175
- required: z.string().array().optional(),
176
- nullable: z.string().array().optional(),
177
- properties: z.record(
178
- z.string(),
179
- z.discriminatedUnion('type', [
180
- lexArray,
181
-
182
- // lexPrimitive
183
- lexBoolean,
184
- lexInteger,
185
- lexString,
186
- lexUnknown,
187
- // lexIpldType
188
- lexBytes,
189
- lexCidLink,
190
- // lexRefVariant
191
- lexRef,
192
- lexRefUnion,
193
- // other
194
- lexBlob,
195
- ]),
196
- ),
197
- })
198
- .superRefine(requiredPropertiesRefinement)
199
- export type LexObject = z.infer<typeof lexObject>
200
-
201
- // permissions
202
- // =
203
-
204
- const lexPermission = z.intersection(
205
- z.object({
206
- type: z.literal('permission'),
207
- resource: z.string().nonempty(),
208
- }),
209
- z.record(
210
- z.string(),
211
- z
212
- .union([
213
- z.array(z.union([z.string(), z.number().int(), z.boolean()])),
214
-
215
- z.boolean(),
216
- z.number().int(),
217
- z.string(),
218
- ])
219
- .optional(),
220
- ),
221
- )
222
-
223
- export type LexPermission = z.infer<typeof lexPermission>
224
-
225
- export const lexPermissionSet = z.object({
226
- type: z.literal('permission-set'),
227
- description: z.string().optional(),
228
- title: z.string().optional(),
229
- 'title:lang': lexLang.optional(),
230
- detail: z.string().optional(),
231
- 'detail:lang': lexLang.optional(),
232
- permissions: z.array(lexPermission),
233
- })
234
-
235
- export type LexPermissionSet = z.infer<typeof lexPermissionSet>
236
-
237
- // xrpc
238
- // =
239
-
240
- export const lexXrpcParameters = z
241
- .object({
242
- type: z.literal('params'),
243
- description: z.string().optional(),
244
- required: z.string().array().optional(),
245
- properties: z.record(
246
- z.string(),
247
- z.discriminatedUnion('type', [
248
- lexPrimitiveArray,
249
-
250
- // lexPrimitive
251
- lexBoolean,
252
- lexInteger,
253
- lexString,
254
- lexUnknown,
255
- ]),
256
- ),
257
- })
258
- .superRefine(requiredPropertiesRefinement)
259
- export type LexXrpcParameters = z.infer<typeof lexXrpcParameters>
260
-
261
- export const lexXrpcBody = z.object({
262
- description: z.string().optional(),
263
- encoding: z.string(),
264
- // @NOTE using discriminatedUnion with a refined schema requires zod >= 4
265
- schema: z.union([lexRefVariant, lexObject]).optional(),
266
- })
267
- export type LexXrpcBody = z.infer<typeof lexXrpcBody>
268
-
269
- export const lexXrpcError = z.object({
270
- name: z.string(),
271
- description: z.string().optional(),
272
- })
273
- export type LexXrpcError = z.infer<typeof lexXrpcError>
274
-
275
- export const lexXrpcQuery = z.object({
276
- type: z.literal('query'),
277
- description: z.string().optional(),
278
- parameters: lexXrpcParameters.optional(),
279
- output: lexXrpcBody.optional(),
280
- errors: lexXrpcError.array().optional(),
281
- })
282
- export type LexXrpcQuery = z.infer<typeof lexXrpcQuery>
283
-
284
- export const lexXrpcProcedure = z.object({
285
- type: z.literal('procedure'),
286
- description: z.string().optional(),
287
- parameters: lexXrpcParameters.optional(),
288
- input: lexXrpcBody.optional(),
289
- output: lexXrpcBody.optional(),
290
- errors: lexXrpcError.array().optional(),
291
- })
292
- export type LexXrpcProcedure = z.infer<typeof lexXrpcProcedure>
293
-
294
- export const lexXrpcSubscription = z.object({
295
- type: z.literal('subscription'),
296
- description: z.string().optional(),
297
- parameters: lexXrpcParameters.optional(),
298
- message: z.object({
299
- description: z.string().optional(),
300
- schema: lexRefUnion,
301
- }),
302
- errors: lexXrpcError.array().optional(),
303
- })
304
- export type LexXrpcSubscription = z.infer<typeof lexXrpcSubscription>
305
-
306
- // database
307
- // =
308
-
309
- export const lexRecord = z.object({
310
- type: z.literal('record'),
311
- description: z.string().optional(),
312
- key: z.string().optional(),
313
- record: lexObject,
314
- })
315
- export type LexRecord = z.infer<typeof lexRecord>
316
-
317
- // core
318
- // =
319
-
320
- // We need to use `z.custom` here because
321
- // lexXrpcProperty and lexObject are refined
322
- // `z.union` would work, but it's too slow
323
- // see #915 for details
324
- export const lexUserType = z.custom<
325
- | LexRecord
326
- | LexPermissionSet
327
- | LexXrpcQuery
328
- | LexXrpcProcedure
329
- | LexXrpcSubscription
330
- | LexBlob
331
- | LexArray
332
- | LexToken
333
- | LexObject
334
- | LexBoolean
335
- | LexInteger
336
- | LexString
337
- | LexBytes
338
- | LexCidLink
339
- | LexUnknown
340
- >(
341
- (val) => {
342
- if (!val || typeof val !== 'object') {
343
- return
344
- }
345
-
346
- if (val['type'] === undefined) {
347
- return
348
- }
349
-
350
- switch (val['type']) {
351
- case 'record':
352
- return lexRecord.parse(val)
353
-
354
- case 'permission-set':
355
- return lexPermissionSet.parse(val)
356
-
357
- case 'query':
358
- return lexXrpcQuery.parse(val)
359
- case 'procedure':
360
- return lexXrpcProcedure.parse(val)
361
- case 'subscription':
362
- return lexXrpcSubscription.parse(val)
363
-
364
- case 'blob':
365
- return lexBlob.parse(val)
366
-
367
- case 'array':
368
- return lexArray.parse(val)
369
- case 'token':
370
- return lexToken.parse(val)
371
- case 'object':
372
- return lexObject.parse(val)
373
-
374
- case 'boolean':
375
- return lexBoolean.parse(val)
376
- case 'integer':
377
- return lexInteger.parse(val)
378
- case 'string':
379
- return lexString.parse(val)
380
- case 'bytes':
381
- return lexBytes.parse(val)
382
- case 'cid-link':
383
- return lexCidLink.parse(val)
384
- case 'unknown':
385
- return lexUnknown.parse(val)
386
- }
387
- },
388
- (val) => {
389
- if (!val || typeof val !== 'object') {
390
- return {
391
- message: 'Must be an object',
392
- fatal: true,
393
- }
394
- }
395
-
396
- if (val['type'] === undefined) {
397
- return {
398
- message: 'Must have a type',
399
- fatal: true,
400
- }
401
- }
402
-
403
- if (typeof val['type'] !== 'string') {
404
- return {
405
- message: 'Type property must be a string',
406
- fatal: true,
407
- }
408
- }
409
-
410
- return {
411
- message: `Invalid type: ${val['type']} must be one of: record, query, procedure, subscription, blob, array, token, object, boolean, integer, string, bytes, cid-link, unknown`,
412
- fatal: true,
413
- }
414
- },
415
- )
416
- export type LexUserType = z.infer<typeof lexUserType>
417
-
418
- export const lexiconDoc = z
419
- .object({
420
- lexicon: z.literal(1),
421
- id: z.string().refine(isValidNsid, {
422
- message: 'Must be a valid NSID',
423
- }),
424
- revision: z.number().optional(),
425
- description: z.string().optional(),
426
- defs: z.record(z.string(), lexUserType),
427
- })
428
- .refine(
429
- (doc) => {
430
- for (const [defId, def] of Object.entries(doc.defs)) {
431
- if (
432
- defId !== 'main' &&
433
- (def.type === 'record' ||
434
- def.type === 'permission-set' ||
435
- def.type === 'procedure' ||
436
- def.type === 'query' ||
437
- def.type === 'subscription')
438
- ) {
439
- return false
440
- }
441
- }
442
- return true
443
- },
444
- {
445
- message: `Records, permission sets, procedures, queries, and subscriptions must be the main definition.`,
446
- },
447
- )
448
- export type LexiconDoc = z.infer<typeof lexiconDoc>
449
-
450
- // helpers
451
- // =
452
-
453
- export function isValidLexiconDoc(v: unknown): v is LexiconDoc {
454
- return lexiconDoc.safeParse(v).success
455
- }
456
-
457
- export function isObj<V>(v: V): v is V & object {
458
- return v != null && typeof v === 'object'
459
- }
460
-
461
- export type DiscriminatedObject = { $type: string }
462
- export function isDiscriminatedObject(v: unknown): v is DiscriminatedObject {
463
- return isObj(v) && '$type' in v && typeof v.$type === 'string'
464
- }
465
-
466
- export function parseLexiconDoc(v: unknown): LexiconDoc {
467
- lexiconDoc.parse(v)
468
- return v as LexiconDoc
469
- }
470
-
471
- export type ValidationResult<V = unknown> =
472
- | {
473
- success: true
474
- value: V
475
- }
476
- | {
477
- success: false
478
- error: ValidationError
479
- }
480
-
481
- export class ValidationError extends Error {}
482
- export class InvalidLexiconError extends Error {}
483
- export class LexiconDefNotFoundError extends Error {}
package/src/util.ts DELETED
@@ -1,58 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export function toLexUri(str: string, baseUri?: string): string {
4
- if (str.split('#').length > 2) {
5
- throw new Error('Uri can only have one hash segment')
6
- }
7
-
8
- if (str.startsWith('lex:')) {
9
- return str
10
- }
11
- if (str.startsWith('#')) {
12
- if (!baseUri) {
13
- throw new Error(`Unable to resolve uri without anchor: ${str}`)
14
- }
15
- return `${baseUri}${str}`
16
- }
17
- return `lex:${str}`
18
- }
19
-
20
- export function requiredPropertiesRefinement<
21
- ObjectType extends {
22
- required?: string[]
23
- properties?: Record<string, unknown>
24
- },
25
- >(object: ObjectType, ctx: z.RefinementCtx) {
26
- // Required fields check
27
- if (object.required === undefined) {
28
- return
29
- }
30
-
31
- if (!Array.isArray(object.required)) {
32
- ctx.addIssue({
33
- code: z.ZodIssueCode.invalid_type,
34
- received: typeof object.required,
35
- expected: 'array',
36
- })
37
- return
38
- }
39
-
40
- if (object.properties === undefined) {
41
- if (object.required.length > 0) {
42
- ctx.addIssue({
43
- code: z.ZodIssueCode.custom,
44
- message: `Required fields defined but no properties defined`,
45
- })
46
- }
47
- return
48
- }
49
-
50
- for (const field of object.required) {
51
- if (object.properties[field] === undefined) {
52
- ctx.addIssue({
53
- code: z.ZodIssueCode.custom,
54
- message: `Required field "${field}" not defined`,
55
- })
56
- }
57
- }
58
- }