@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.
- package/CHANGELOG.md +16 -0
- package/dist/lexicons.d.ts +1 -1
- package/dist/lexicons.d.ts.map +1 -1
- package/dist/lexicons.js.map +1 -1
- package/dist/serialize.d.ts +1 -1
- package/dist/serialize.d.ts.map +1 -1
- package/dist/serialize.js +8 -7
- package/dist/serialize.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +1 -0
- package/dist/validation.js.map +1 -1
- package/dist/validators/blob.d.ts +1 -1
- package/dist/validators/blob.d.ts.map +1 -1
- package/dist/validators/blob.js +1 -0
- package/dist/validators/blob.js.map +1 -1
- package/dist/validators/complex.d.ts +1 -1
- package/dist/validators/complex.d.ts.map +1 -1
- package/dist/validators/complex.js +2 -1
- package/dist/validators/complex.js.map +1 -1
- package/dist/validators/formats.d.ts +1 -1
- package/dist/validators/formats.d.ts.map +1 -1
- package/dist/validators/formats.js.map +1 -1
- package/dist/validators/primitives.d.ts +1 -1
- package/dist/validators/primitives.d.ts.map +1 -1
- package/dist/validators/primitives.js +2 -1
- package/dist/validators/primitives.js.map +1 -1
- package/dist/validators/xrpc.d.ts +1 -1
- package/dist/validators/xrpc.d.ts.map +1 -1
- package/dist/validators/xrpc.js +3 -2
- package/dist/validators/xrpc.js.map +1 -1
- package/package.json +18 -13
- package/jest.config.cjs +0 -21
- package/src/blob-refs.ts +0 -65
- package/src/index.ts +0 -4
- package/src/lexicons.ts +0 -253
- package/src/serialize.ts +0 -102
- package/src/types.ts +0 -483
- package/src/util.ts +0 -58
- package/src/validation.ts +0 -84
- package/src/validators/blob.ts +0 -19
- package/src/validators/complex.ts +0 -212
- package/src/validators/formats.ts +0 -72
- package/src/validators/primitives.ts +0 -416
- package/src/validators/xrpc.ts +0 -53
- package/tests/_scaffolds/lexicons.ts +0 -545
- package/tests/general.test.ts +0 -1243
- package/tsconfig.build.json +0 -8
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -7
- 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
|
-
}
|