@atproto/lexicon 0.1.0 → 0.2.0
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/dist/blob-refs.d.ts +8 -8
- package/dist/index.js +10063 -479
- package/dist/index.js.map +4 -4
- package/dist/src/index.d.ts +2 -0
- package/dist/src/lexicons.d.ts +15 -0
- package/dist/src/record/index.d.ts +4 -0
- package/dist/src/record/schema.d.ts +9 -0
- package/dist/src/record/schemas.d.ts +10 -0
- package/dist/src/record/util.d.ts +1 -0
- package/dist/src/record/validation.d.ts +24 -0
- package/dist/src/record/validator.d.ts +17 -0
- package/dist/src/types.d.ts +30268 -0
- package/dist/src/util.d.ts +6 -0
- package/dist/src/validation.d.ts +6 -0
- package/dist/src/validators/blob.d.ts +6 -0
- package/dist/src/validators/complex.d.ts +5 -0
- package/dist/src/validators/primitives.d.ts +9 -0
- package/dist/src/validators/xrpc.d.ts +3 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types.d.ts +13952 -30982
- package/dist/util.d.ts +5 -0
- package/dist/validators/formats.d.ts +1 -0
- package/dist/validators/primitives.d.ts +0 -1
- package/package.json +9 -4
- package/src/types.ts +263 -165
- package/src/util.ts +61 -1
- package/src/validators/complex.ts +0 -2
- package/src/validators/formats.ts +14 -0
- package/src/validators/primitives.ts +7 -35
- package/tests/_scaffolds/lexicons.ts +19 -67
- package/tests/general.test.ts +188 -80
- package/tsconfig.build.tsbuildinfo +1 -1
package/dist/util.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { Lexicons } from './lexicons';
|
|
2
2
|
import { LexUserType, LexRefVariant, ValidationResult } from './types';
|
|
3
|
+
import { z } from 'zod';
|
|
3
4
|
export declare function toLexUri(str: string, baseUri?: string): string;
|
|
4
5
|
export declare function validateOneOf(lexicons: Lexicons, path: string, def: LexRefVariant | LexUserType, value: unknown, mustBeObj?: boolean): ValidationResult;
|
|
5
6
|
export declare function assertValidOneOf(lexicons: Lexicons, path: string, def: LexRefVariant | LexUserType, value: unknown, mustBeObj?: boolean): unknown;
|
|
6
7
|
export declare function toConcreteTypes(lexicons: Lexicons, def: LexRefVariant | LexUserType): LexUserType[];
|
|
8
|
+
export declare function requiredPropertiesRefinement<ObjectType extends {
|
|
9
|
+
required?: string[];
|
|
10
|
+
properties?: Record<string, unknown>;
|
|
11
|
+
}>(object: ObjectType, ctx: z.RefinementCtx): void;
|
|
@@ -7,3 +7,4 @@ export declare function handle(path: string, value: string): ValidationResult;
|
|
|
7
7
|
export declare function atIdentifier(path: string, value: string): ValidationResult;
|
|
8
8
|
export declare function nsid(path: string, value: string): ValidationResult;
|
|
9
9
|
export declare function cid(path: string, value: string): ValidationResult;
|
|
10
|
+
export declare function language(path: string, value: string): ValidationResult;
|
|
@@ -2,7 +2,6 @@ import { Lexicons } from '../lexicons';
|
|
|
2
2
|
import { LexUserType, ValidationResult } from '../types';
|
|
3
3
|
export declare function validate(lexicons: Lexicons, path: string, def: LexUserType, value: unknown): ValidationResult;
|
|
4
4
|
export declare function boolean(lexicons: Lexicons, path: string, def: LexUserType, value: unknown): ValidationResult;
|
|
5
|
-
export declare function float(lexicons: Lexicons, path: string, def: LexUserType, value: unknown): ValidationResult;
|
|
6
5
|
export declare function integer(lexicons: Lexicons, path: string, def: LexUserType, value: unknown): ValidationResult;
|
|
7
6
|
export declare function string(lexicons: Lexicons, path: string, def: LexUserType, value: unknown): ValidationResult;
|
|
8
7
|
export declare function bytes(lexicons: Lexicons, path: string, def: LexUserType, value: unknown): ValidationResult;
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/lexicon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "jest",
|
|
7
|
-
"prettier": "prettier --check src/",
|
|
8
|
-
"prettier:fix": "prettier --write src/",
|
|
7
|
+
"prettier": "prettier --check src/ tests/",
|
|
8
|
+
"prettier:fix": "prettier --write src/ tests/",
|
|
9
9
|
"lint": "eslint . --ext .ts,.tsx",
|
|
10
10
|
"lint:fix": "yarn lint --fix",
|
|
11
11
|
"verify": "run-p prettier lint",
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"postpublish": "npm run update-main-to-src"
|
|
19
19
|
},
|
|
20
20
|
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/bluesky-social/atproto.git",
|
|
24
|
+
"directory": "packages/lexicon"
|
|
25
|
+
},
|
|
21
26
|
"dependencies": {
|
|
22
27
|
"@atproto/common-web": "*",
|
|
23
28
|
"@atproto/identifier": "*",
|
|
@@ -25,6 +30,6 @@
|
|
|
25
30
|
"@atproto/uri": "*",
|
|
26
31
|
"iso-datestring-validator": "^2.2.2",
|
|
27
32
|
"multiformats": "^9.6.4",
|
|
28
|
-
"zod": "^3.
|
|
33
|
+
"zod": "^3.21.4"
|
|
29
34
|
}
|
|
30
35
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,37 +1,31 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import { NSID } from '@atproto/nsid'
|
|
3
|
+
import { requiredPropertiesRefinement } from './util'
|
|
3
4
|
|
|
4
5
|
// primitives
|
|
5
6
|
// =
|
|
6
7
|
|
|
7
|
-
export const lexBoolean = z
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
export const lexBoolean = z
|
|
9
|
+
.object({
|
|
10
|
+
type: z.literal('boolean'),
|
|
11
|
+
description: z.string().optional(),
|
|
12
|
+
default: z.boolean().optional(),
|
|
13
|
+
const: z.boolean().optional(),
|
|
14
|
+
})
|
|
15
|
+
.strict()
|
|
13
16
|
export type LexBoolean = z.infer<typeof lexBoolean>
|
|
14
17
|
|
|
15
|
-
export const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export const lexInteger = z.object({
|
|
27
|
-
type: z.literal('integer'),
|
|
28
|
-
description: z.string().optional(),
|
|
29
|
-
default: z.number().int().optional(),
|
|
30
|
-
minimum: z.number().int().optional(),
|
|
31
|
-
maximum: z.number().int().optional(),
|
|
32
|
-
enum: z.number().int().array().optional(),
|
|
33
|
-
const: z.number().int().optional(),
|
|
34
|
-
})
|
|
18
|
+
export const lexInteger = z
|
|
19
|
+
.object({
|
|
20
|
+
type: z.literal('integer'),
|
|
21
|
+
description: z.string().optional(),
|
|
22
|
+
default: z.number().int().optional(),
|
|
23
|
+
minimum: z.number().int().optional(),
|
|
24
|
+
maximum: z.number().int().optional(),
|
|
25
|
+
enum: z.number().int().array().optional(),
|
|
26
|
+
const: z.number().int().optional(),
|
|
27
|
+
})
|
|
28
|
+
.strict()
|
|
35
29
|
export type LexInteger = z.infer<typeof lexInteger>
|
|
36
30
|
|
|
37
31
|
export const lexStringFormat = z.enum([
|
|
@@ -43,33 +37,37 @@ export const lexStringFormat = z.enum([
|
|
|
43
37
|
'at-identifier',
|
|
44
38
|
'nsid',
|
|
45
39
|
'cid',
|
|
40
|
+
'language',
|
|
46
41
|
])
|
|
47
42
|
export type LexStringFormat = z.infer<typeof lexStringFormat>
|
|
48
43
|
|
|
49
|
-
export const lexString = z
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
44
|
+
export const lexString = z
|
|
45
|
+
.object({
|
|
46
|
+
type: z.literal('string'),
|
|
47
|
+
format: lexStringFormat.optional(),
|
|
48
|
+
description: z.string().optional(),
|
|
49
|
+
default: z.string().optional(),
|
|
50
|
+
minLength: z.number().int().optional(),
|
|
51
|
+
maxLength: z.number().int().optional(),
|
|
52
|
+
minGraphemes: z.number().int().optional(),
|
|
53
|
+
maxGraphemes: z.number().int().optional(),
|
|
54
|
+
enum: z.string().array().optional(),
|
|
55
|
+
const: z.string().optional(),
|
|
56
|
+
knownValues: z.string().array().optional(),
|
|
57
|
+
})
|
|
58
|
+
.strict()
|
|
62
59
|
export type LexString = z.infer<typeof lexString>
|
|
63
60
|
|
|
64
|
-
export const lexUnknown = z
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
export const lexUnknown = z
|
|
62
|
+
.object({
|
|
63
|
+
type: z.literal('unknown'),
|
|
64
|
+
description: z.string().optional(),
|
|
65
|
+
})
|
|
66
|
+
.strict()
|
|
68
67
|
export type LexUnknown = z.infer<typeof lexUnknown>
|
|
69
68
|
|
|
70
|
-
export const lexPrimitive = z.
|
|
69
|
+
export const lexPrimitive = z.discriminatedUnion('type', [
|
|
71
70
|
lexBoolean,
|
|
72
|
-
lexFloat,
|
|
73
71
|
lexInteger,
|
|
74
72
|
lexString,
|
|
75
73
|
lexUnknown,
|
|
@@ -79,189 +77,288 @@ export type LexPrimitive = z.infer<typeof lexPrimitive>
|
|
|
79
77
|
// ipld types
|
|
80
78
|
// =
|
|
81
79
|
|
|
82
|
-
export const lexBytes = z
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
export const lexBytes = z
|
|
81
|
+
.object({
|
|
82
|
+
type: z.literal('bytes'),
|
|
83
|
+
description: z.string().optional(),
|
|
84
|
+
maxLength: z.number().optional(),
|
|
85
|
+
minLength: z.number().optional(),
|
|
86
|
+
})
|
|
87
|
+
.strict()
|
|
88
88
|
export type LexBytes = z.infer<typeof lexBytes>
|
|
89
89
|
|
|
90
|
-
export const lexCidLink = z
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
export const lexCidLink = z
|
|
91
|
+
.object({
|
|
92
|
+
type: z.literal('cid-link'),
|
|
93
|
+
description: z.string().optional(),
|
|
94
|
+
})
|
|
95
|
+
.strict()
|
|
94
96
|
export type LexCidLink = z.infer<typeof lexCidLink>
|
|
95
97
|
|
|
96
|
-
export const lexIpldType = z.
|
|
98
|
+
export const lexIpldType = z.discriminatedUnion('type', [lexBytes, lexCidLink])
|
|
97
99
|
export type LexIpldType = z.infer<typeof lexIpldType>
|
|
98
100
|
|
|
99
101
|
// references
|
|
100
102
|
// =
|
|
101
103
|
|
|
102
|
-
export const lexRef = z
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
export const lexRef = z
|
|
105
|
+
.object({
|
|
106
|
+
type: z.literal('ref'),
|
|
107
|
+
description: z.string().optional(),
|
|
108
|
+
ref: z.string(),
|
|
109
|
+
})
|
|
110
|
+
.strict()
|
|
107
111
|
export type LexRef = z.infer<typeof lexRef>
|
|
108
112
|
|
|
109
|
-
export const lexRefUnion = z
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
export const lexRefUnion = z
|
|
114
|
+
.object({
|
|
115
|
+
type: z.literal('union'),
|
|
116
|
+
description: z.string().optional(),
|
|
117
|
+
refs: z.string().array(),
|
|
118
|
+
closed: z.boolean().optional(),
|
|
119
|
+
})
|
|
120
|
+
.strict()
|
|
115
121
|
export type LexRefUnion = z.infer<typeof lexRefUnion>
|
|
116
122
|
|
|
117
|
-
export const lexRefVariant = z.
|
|
123
|
+
export const lexRefVariant = z.discriminatedUnion('type', [lexRef, lexRefUnion])
|
|
118
124
|
export type LexRefVariant = z.infer<typeof lexRefVariant>
|
|
119
125
|
|
|
120
126
|
// blobs
|
|
121
127
|
// =
|
|
122
128
|
|
|
123
|
-
export const lexBlob = z
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
export const lexBlob = z
|
|
130
|
+
.object({
|
|
131
|
+
type: z.literal('blob'),
|
|
132
|
+
description: z.string().optional(),
|
|
133
|
+
accept: z.string().array().optional(),
|
|
134
|
+
maxSize: z.number().optional(),
|
|
135
|
+
})
|
|
136
|
+
.strict()
|
|
129
137
|
export type LexBlob = z.infer<typeof lexBlob>
|
|
130
138
|
|
|
131
139
|
// complex types
|
|
132
140
|
// =
|
|
133
141
|
|
|
134
|
-
export const lexArray = z
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
142
|
+
export const lexArray = z
|
|
143
|
+
.object({
|
|
144
|
+
type: z.literal('array'),
|
|
145
|
+
description: z.string().optional(),
|
|
146
|
+
items: z.union([lexPrimitive, lexIpldType, lexBlob, lexRefVariant]),
|
|
147
|
+
minLength: z.number().int().optional(),
|
|
148
|
+
maxLength: z.number().int().optional(),
|
|
149
|
+
})
|
|
150
|
+
.strict()
|
|
141
151
|
export type LexArray = z.infer<typeof lexArray>
|
|
142
152
|
|
|
143
153
|
export const lexPrimitiveArray = lexArray.merge(
|
|
144
|
-
z
|
|
145
|
-
|
|
146
|
-
|
|
154
|
+
z
|
|
155
|
+
.object({
|
|
156
|
+
items: lexPrimitive,
|
|
157
|
+
})
|
|
158
|
+
.strict(),
|
|
147
159
|
)
|
|
148
160
|
export type LexPrimitiveArray = z.infer<typeof lexPrimitiveArray>
|
|
149
161
|
|
|
150
|
-
export const lexToken = z
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
162
|
+
export const lexToken = z
|
|
163
|
+
.object({
|
|
164
|
+
type: z.literal('token'),
|
|
165
|
+
description: z.string().optional(),
|
|
166
|
+
})
|
|
167
|
+
.strict()
|
|
154
168
|
export type LexToken = z.infer<typeof lexToken>
|
|
155
169
|
|
|
156
|
-
export const lexObject = z
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
170
|
+
export const lexObject = z
|
|
171
|
+
.object({
|
|
172
|
+
type: z.literal('object'),
|
|
173
|
+
description: z.string().optional(),
|
|
174
|
+
required: z.string().array().optional(),
|
|
175
|
+
nullable: z.string().array().optional(),
|
|
176
|
+
properties: z
|
|
177
|
+
.record(
|
|
178
|
+
z.union([lexRefVariant, lexIpldType, lexArray, lexBlob, lexPrimitive]),
|
|
179
|
+
)
|
|
180
|
+
.optional(),
|
|
181
|
+
})
|
|
182
|
+
.strict()
|
|
183
|
+
.superRefine(requiredPropertiesRefinement)
|
|
167
184
|
export type LexObject = z.infer<typeof lexObject>
|
|
168
185
|
|
|
169
186
|
// xrpc
|
|
170
187
|
// =
|
|
171
188
|
|
|
172
|
-
export const lexXrpcParameters = z
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
189
|
+
export const lexXrpcParameters = z
|
|
190
|
+
.object({
|
|
191
|
+
type: z.literal('params'),
|
|
192
|
+
description: z.string().optional(),
|
|
193
|
+
required: z.string().array().optional(),
|
|
194
|
+
properties: z.record(z.union([lexPrimitive, lexPrimitiveArray])),
|
|
195
|
+
})
|
|
196
|
+
.strict()
|
|
197
|
+
.superRefine(requiredPropertiesRefinement)
|
|
178
198
|
export type LexXrpcParameters = z.infer<typeof lexXrpcParameters>
|
|
179
199
|
|
|
180
|
-
export const lexXrpcBody = z
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
200
|
+
export const lexXrpcBody = z
|
|
201
|
+
.object({
|
|
202
|
+
description: z.string().optional(),
|
|
203
|
+
encoding: z.string(),
|
|
204
|
+
schema: z.union([lexRefVariant, lexObject]).optional(),
|
|
205
|
+
})
|
|
206
|
+
.strict()
|
|
185
207
|
export type LexXrpcBody = z.infer<typeof lexXrpcBody>
|
|
186
208
|
|
|
187
|
-
export const lexXrpcSubscriptionMessage = z
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
209
|
+
export const lexXrpcSubscriptionMessage = z
|
|
210
|
+
.object({
|
|
211
|
+
description: z.string().optional(),
|
|
212
|
+
schema: z.union([lexRefVariant, lexObject]).optional(),
|
|
213
|
+
})
|
|
214
|
+
.strict()
|
|
191
215
|
export type LexXrpcSubscriptionMessage = z.infer<
|
|
192
216
|
typeof lexXrpcSubscriptionMessage
|
|
193
217
|
>
|
|
194
218
|
|
|
195
|
-
export const lexXrpcError = z
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
219
|
+
export const lexXrpcError = z
|
|
220
|
+
.object({
|
|
221
|
+
name: z.string(),
|
|
222
|
+
description: z.string().optional(),
|
|
223
|
+
})
|
|
224
|
+
.strict()
|
|
199
225
|
export type LexXrpcError = z.infer<typeof lexXrpcError>
|
|
200
226
|
|
|
201
|
-
export const lexXrpcQuery = z
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
227
|
+
export const lexXrpcQuery = z
|
|
228
|
+
.object({
|
|
229
|
+
type: z.literal('query'),
|
|
230
|
+
description: z.string().optional(),
|
|
231
|
+
parameters: lexXrpcParameters.optional(),
|
|
232
|
+
output: lexXrpcBody.optional(),
|
|
233
|
+
errors: lexXrpcError.array().optional(),
|
|
234
|
+
})
|
|
235
|
+
.strict()
|
|
208
236
|
export type LexXrpcQuery = z.infer<typeof lexXrpcQuery>
|
|
209
237
|
|
|
210
|
-
export const lexXrpcProcedure = z
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
238
|
+
export const lexXrpcProcedure = z
|
|
239
|
+
.object({
|
|
240
|
+
type: z.literal('procedure'),
|
|
241
|
+
description: z.string().optional(),
|
|
242
|
+
parameters: lexXrpcParameters.optional(),
|
|
243
|
+
input: lexXrpcBody.optional(),
|
|
244
|
+
output: lexXrpcBody.optional(),
|
|
245
|
+
errors: lexXrpcError.array().optional(),
|
|
246
|
+
})
|
|
247
|
+
.strict()
|
|
218
248
|
export type LexXrpcProcedure = z.infer<typeof lexXrpcProcedure>
|
|
219
249
|
|
|
220
|
-
export const lexXrpcSubscription = z
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
})
|
|
250
|
+
export const lexXrpcSubscription = z
|
|
251
|
+
.object({
|
|
252
|
+
type: z.literal('subscription'),
|
|
253
|
+
description: z.string().optional(),
|
|
254
|
+
parameters: lexXrpcParameters.optional(),
|
|
255
|
+
message: lexXrpcSubscriptionMessage.optional(),
|
|
256
|
+
errors: lexXrpcError.array().optional(),
|
|
257
|
+
})
|
|
258
|
+
.strict()
|
|
228
259
|
export type LexXrpcSubscription = z.infer<typeof lexXrpcSubscription>
|
|
229
260
|
|
|
230
261
|
// database
|
|
231
262
|
// =
|
|
232
263
|
|
|
233
|
-
export const lexRecord = z
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
264
|
+
export const lexRecord = z
|
|
265
|
+
.object({
|
|
266
|
+
type: z.literal('record'),
|
|
267
|
+
description: z.string().optional(),
|
|
268
|
+
key: z.string().optional(),
|
|
269
|
+
record: lexObject,
|
|
270
|
+
})
|
|
271
|
+
.strict()
|
|
239
272
|
export type LexRecord = z.infer<typeof lexRecord>
|
|
240
273
|
|
|
241
274
|
// core
|
|
242
275
|
// =
|
|
243
276
|
|
|
244
|
-
|
|
245
|
-
|
|
277
|
+
// We need to use `z.custom` here because
|
|
278
|
+
// lexXrpcProperty and lexObject are refined
|
|
279
|
+
// `z.union` would work, but it's too slow
|
|
280
|
+
// see #915 for details
|
|
281
|
+
export const lexUserType = z.custom<
|
|
282
|
+
| LexRecord
|
|
283
|
+
| LexXrpcQuery
|
|
284
|
+
| LexXrpcProcedure
|
|
285
|
+
| LexXrpcSubscription
|
|
286
|
+
| LexBlob
|
|
287
|
+
| LexArray
|
|
288
|
+
| LexToken
|
|
289
|
+
| LexObject
|
|
290
|
+
| LexBoolean
|
|
291
|
+
| LexInteger
|
|
292
|
+
| LexString
|
|
293
|
+
| LexBytes
|
|
294
|
+
| LexCidLink
|
|
295
|
+
| LexUnknown
|
|
296
|
+
>(
|
|
297
|
+
(val) => {
|
|
298
|
+
if (!val || typeof val !== 'object') {
|
|
299
|
+
return
|
|
300
|
+
}
|
|
246
301
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
302
|
+
if (val['type'] === undefined) {
|
|
303
|
+
return
|
|
304
|
+
}
|
|
250
305
|
|
|
251
|
-
|
|
306
|
+
switch (val['type']) {
|
|
307
|
+
case 'record':
|
|
308
|
+
return lexRecord.parse(val)
|
|
309
|
+
|
|
310
|
+
case 'query':
|
|
311
|
+
return lexXrpcQuery.parse(val)
|
|
312
|
+
case 'procedure':
|
|
313
|
+
return lexXrpcProcedure.parse(val)
|
|
314
|
+
case 'subscription':
|
|
315
|
+
return lexXrpcSubscription.parse(val)
|
|
316
|
+
|
|
317
|
+
case 'blob':
|
|
318
|
+
return lexBlob.parse(val)
|
|
319
|
+
|
|
320
|
+
case 'array':
|
|
321
|
+
return lexArray.parse(val)
|
|
322
|
+
case 'token':
|
|
323
|
+
return lexToken.parse(val)
|
|
324
|
+
case 'object':
|
|
325
|
+
return lexObject.parse(val)
|
|
326
|
+
|
|
327
|
+
case 'boolean':
|
|
328
|
+
return lexBoolean.parse(val)
|
|
329
|
+
case 'integer':
|
|
330
|
+
return lexInteger.parse(val)
|
|
331
|
+
case 'string':
|
|
332
|
+
return lexString.parse(val)
|
|
333
|
+
case 'bytes':
|
|
334
|
+
return lexBytes.parse(val)
|
|
335
|
+
case 'cid-link':
|
|
336
|
+
return lexCidLink.parse(val)
|
|
337
|
+
case 'unknown':
|
|
338
|
+
return lexUnknown.parse(val)
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
(val) => {
|
|
342
|
+
if (!val || typeof val !== 'object') {
|
|
343
|
+
return {
|
|
344
|
+
message: 'Must be an object',
|
|
345
|
+
fatal: true,
|
|
346
|
+
}
|
|
347
|
+
}
|
|
252
348
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
349
|
+
if (val['type'] === undefined) {
|
|
350
|
+
return {
|
|
351
|
+
message: 'Must have a type',
|
|
352
|
+
fatal: true,
|
|
353
|
+
}
|
|
354
|
+
}
|
|
256
355
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
lexUnknown,
|
|
264
|
-
])
|
|
356
|
+
return {
|
|
357
|
+
message: `Invalid type: ${val['type']} must be one of: record, query, procedure, subscription, blob, array, token, object, boolean, integer, string, bytes, cid-link, unknown`,
|
|
358
|
+
fatal: true,
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
)
|
|
265
362
|
export type LexUserType = z.infer<typeof lexUserType>
|
|
266
363
|
|
|
267
364
|
export const lexiconDoc = z
|
|
@@ -274,7 +371,8 @@ export const lexiconDoc = z
|
|
|
274
371
|
description: z.string().optional(),
|
|
275
372
|
defs: z.record(lexUserType),
|
|
276
373
|
})
|
|
277
|
-
.
|
|
374
|
+
.strict()
|
|
375
|
+
.superRefine((doc, ctx) => {
|
|
278
376
|
for (const defId in doc.defs) {
|
|
279
377
|
const def = doc.defs[defId]
|
|
280
378
|
if (
|
package/src/util.ts
CHANGED
|
@@ -7,8 +7,13 @@ import {
|
|
|
7
7
|
ValidationResult,
|
|
8
8
|
isDiscriminatedObject,
|
|
9
9
|
} from './types'
|
|
10
|
+
import { z } from 'zod'
|
|
10
11
|
|
|
11
12
|
export function toLexUri(str: string, baseUri?: string): string {
|
|
13
|
+
if (str.split('#').length > 2) {
|
|
14
|
+
throw new Error('Uri can only have one hash segment')
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
if (str.startsWith('lex:')) {
|
|
13
18
|
return str
|
|
14
19
|
}
|
|
@@ -40,7 +45,7 @@ export function validateOneOf(
|
|
|
40
45
|
),
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
|
-
if (!def.refs
|
|
48
|
+
if (!refsContainType(def.refs, value.$type)) {
|
|
44
49
|
if (def.closed) {
|
|
45
50
|
return {
|
|
46
51
|
success: false,
|
|
@@ -104,3 +109,58 @@ export function toConcreteTypes(
|
|
|
104
109
|
return [def]
|
|
105
110
|
}
|
|
106
111
|
}
|
|
112
|
+
|
|
113
|
+
export function requiredPropertiesRefinement<
|
|
114
|
+
ObjectType extends {
|
|
115
|
+
required?: string[]
|
|
116
|
+
properties?: Record<string, unknown>
|
|
117
|
+
},
|
|
118
|
+
>(object: ObjectType, ctx: z.RefinementCtx) {
|
|
119
|
+
// Required fields check
|
|
120
|
+
if (object.required === undefined) {
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!Array.isArray(object.required)) {
|
|
125
|
+
ctx.addIssue({
|
|
126
|
+
code: z.ZodIssueCode.invalid_type,
|
|
127
|
+
received: typeof object.required,
|
|
128
|
+
expected: 'array',
|
|
129
|
+
})
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (object.properties === undefined) {
|
|
134
|
+
if (object.required.length > 0) {
|
|
135
|
+
ctx.addIssue({
|
|
136
|
+
code: z.ZodIssueCode.custom,
|
|
137
|
+
message: `Required fields defined but no properties defined`,
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
for (const field of object.required) {
|
|
144
|
+
if (object.properties[field] === undefined) {
|
|
145
|
+
ctx.addIssue({
|
|
146
|
+
code: z.ZodIssueCode.custom,
|
|
147
|
+
message: `Required field "${field}" not defined`,
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// to avoid bugs like #0189 this needs to handle both
|
|
154
|
+
// explicit and implicit #main
|
|
155
|
+
const refsContainType = (refs: string[], type: string) => {
|
|
156
|
+
const lexUri = toLexUri(type)
|
|
157
|
+
if (refs.includes(lexUri)) {
|
|
158
|
+
return true
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (lexUri.endsWith('#main')) {
|
|
162
|
+
return refs.includes(lexUri.replace('#main', ''))
|
|
163
|
+
} else {
|
|
164
|
+
return refs.includes(lexUri + '#main')
|
|
165
|
+
}
|
|
166
|
+
}
|