@atproto/lexicon 0.0.1
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/README.md +31 -0
- package/build.js +22 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.js +3897 -0
- package/dist/index.js.map +7 -0
- 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/record-validator.d.ts +17 -0
- package/dist/src/schema.d.ts +9 -0
- package/dist/src/schemas.d.ts +10 -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/src/view-validator.d.ts +13 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types.d.ts +73 -0
- package/dist/types.js +35 -0
- package/jest.config.js +6 -0
- package/package.json +21 -0
- package/src/index.ts +2 -0
- package/src/lexicons.ts +203 -0
- package/src/types.ts +318 -0
- package/src/util.ts +107 -0
- package/src/validation.ts +48 -0
- package/src/validators/blob.ts +57 -0
- package/src/validators/complex.ts +152 -0
- package/src/validators/primitives.ts +300 -0
- package/src/validators/xrpc.ts +50 -0
- package/tests/_scaffolds/lexicons.ts +379 -0
- package/tests/general.test.ts +611 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
import { Lexicons } from '../src/index'
|
|
2
|
+
import LexiconDocs from './_scaffolds/lexicons'
|
|
3
|
+
|
|
4
|
+
describe('Lexicons collection', () => {
|
|
5
|
+
const lex = new Lexicons(LexiconDocs)
|
|
6
|
+
|
|
7
|
+
it('Adds schemas', () => {
|
|
8
|
+
expect(() => lex.add(LexiconDocs[0])).toThrow()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('Correctly references all definitions', () => {
|
|
12
|
+
expect(lex.getDef('com.example.kitchenSink')).toEqual(
|
|
13
|
+
LexiconDocs[0].defs.main,
|
|
14
|
+
)
|
|
15
|
+
expect(lex.getDef('lex:com.example.kitchenSink')).toEqual(
|
|
16
|
+
LexiconDocs[0].defs.main,
|
|
17
|
+
)
|
|
18
|
+
expect(lex.getDef('com.example.kitchenSink#main')).toEqual(
|
|
19
|
+
LexiconDocs[0].defs.main,
|
|
20
|
+
)
|
|
21
|
+
expect(lex.getDef('lex:com.example.kitchenSink#main')).toEqual(
|
|
22
|
+
LexiconDocs[0].defs.main,
|
|
23
|
+
)
|
|
24
|
+
expect(lex.getDef('com.example.kitchenSink#object')).toEqual(
|
|
25
|
+
LexiconDocs[0].defs.object,
|
|
26
|
+
)
|
|
27
|
+
expect(lex.getDef('lex:com.example.kitchenSink#object')).toEqual(
|
|
28
|
+
LexiconDocs[0].defs.object,
|
|
29
|
+
)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('Record validation', () => {
|
|
34
|
+
const lex = new Lexicons(LexiconDocs)
|
|
35
|
+
|
|
36
|
+
it('Passes valid schemas', () => {
|
|
37
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
38
|
+
$type: 'com.example.kitchenSink',
|
|
39
|
+
object: {
|
|
40
|
+
object: { boolean: true },
|
|
41
|
+
array: ['one', 'two'],
|
|
42
|
+
boolean: true,
|
|
43
|
+
number: 123.45,
|
|
44
|
+
integer: 123,
|
|
45
|
+
string: 'string',
|
|
46
|
+
},
|
|
47
|
+
array: ['one', 'two'],
|
|
48
|
+
boolean: true,
|
|
49
|
+
number: 123.45,
|
|
50
|
+
integer: 123,
|
|
51
|
+
string: 'string',
|
|
52
|
+
datetime: new Date().toISOString(),
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('Fails invalid input types', () => {
|
|
57
|
+
expect(() =>
|
|
58
|
+
lex.assertValidRecord('com.example.kitchenSink', undefined),
|
|
59
|
+
).toThrow('Record must be an object')
|
|
60
|
+
expect(() =>
|
|
61
|
+
lex.assertValidRecord('com.example.kitchenSink', 1234),
|
|
62
|
+
).toThrow('Record must be an object')
|
|
63
|
+
expect(() =>
|
|
64
|
+
lex.assertValidRecord('com.example.kitchenSink', 'string'),
|
|
65
|
+
).toThrow('Record must be an object')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('Fails incorrect $type', () => {
|
|
69
|
+
expect(() => lex.assertValidRecord('com.example.kitchenSink', {})).toThrow(
|
|
70
|
+
'Record/$type must be a string',
|
|
71
|
+
)
|
|
72
|
+
expect(() =>
|
|
73
|
+
lex.assertValidRecord('com.example.kitchenSink', { $type: 'foo' }),
|
|
74
|
+
).toThrow('Invalid $type: must be lex:com.example.kitchenSink, got foo')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('Fails missing required', () => {
|
|
78
|
+
expect(() =>
|
|
79
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
80
|
+
$type: 'com.example.kitchenSink',
|
|
81
|
+
array: ['one', 'two'],
|
|
82
|
+
boolean: true,
|
|
83
|
+
number: 123.45,
|
|
84
|
+
integer: 123,
|
|
85
|
+
string: 'string',
|
|
86
|
+
datetime: new Date().toISOString(),
|
|
87
|
+
}),
|
|
88
|
+
).toThrow('Record must have the property "object"')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('Fails incorrect types', () => {
|
|
92
|
+
expect(() =>
|
|
93
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
94
|
+
$type: 'com.example.kitchenSink',
|
|
95
|
+
object: {
|
|
96
|
+
object: { boolean: '1234' },
|
|
97
|
+
array: ['one', 'two'],
|
|
98
|
+
boolean: true,
|
|
99
|
+
number: 123.45,
|
|
100
|
+
integer: 123,
|
|
101
|
+
string: 'string',
|
|
102
|
+
},
|
|
103
|
+
array: ['one', 'two'],
|
|
104
|
+
boolean: true,
|
|
105
|
+
number: 123.45,
|
|
106
|
+
integer: 123,
|
|
107
|
+
string: 'string',
|
|
108
|
+
datetime: new Date().toISOString(),
|
|
109
|
+
}),
|
|
110
|
+
).toThrow('Record/object/object/boolean must be a boolean')
|
|
111
|
+
expect(() =>
|
|
112
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
113
|
+
$type: 'com.example.kitchenSink',
|
|
114
|
+
object: true,
|
|
115
|
+
array: ['one', 'two'],
|
|
116
|
+
boolean: true,
|
|
117
|
+
number: 123.45,
|
|
118
|
+
integer: 123,
|
|
119
|
+
string: 'string',
|
|
120
|
+
datetime: new Date().toISOString(),
|
|
121
|
+
}),
|
|
122
|
+
).toThrow('Record/object must be an object')
|
|
123
|
+
expect(() =>
|
|
124
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
125
|
+
$type: 'com.example.kitchenSink',
|
|
126
|
+
object: {
|
|
127
|
+
object: { boolean: true },
|
|
128
|
+
array: ['one', 'two'],
|
|
129
|
+
boolean: true,
|
|
130
|
+
number: 123.45,
|
|
131
|
+
integer: 123,
|
|
132
|
+
string: 'string',
|
|
133
|
+
},
|
|
134
|
+
array: 1234,
|
|
135
|
+
boolean: true,
|
|
136
|
+
number: 123.45,
|
|
137
|
+
integer: 123,
|
|
138
|
+
string: 'string',
|
|
139
|
+
datetime: new Date().toISOString(),
|
|
140
|
+
}),
|
|
141
|
+
).toThrow('Record/array must be an array')
|
|
142
|
+
expect(() =>
|
|
143
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
144
|
+
$type: 'com.example.kitchenSink',
|
|
145
|
+
object: {
|
|
146
|
+
object: { boolean: true },
|
|
147
|
+
array: ['one', 'two'],
|
|
148
|
+
boolean: true,
|
|
149
|
+
number: 123.45,
|
|
150
|
+
integer: 123,
|
|
151
|
+
string: 'string',
|
|
152
|
+
},
|
|
153
|
+
array: ['one', 'two'],
|
|
154
|
+
boolean: true,
|
|
155
|
+
number: 'string',
|
|
156
|
+
integer: 123,
|
|
157
|
+
string: 'string',
|
|
158
|
+
datetime: new Date().toISOString(),
|
|
159
|
+
}),
|
|
160
|
+
).toThrow('Record/number must be a number')
|
|
161
|
+
expect(() =>
|
|
162
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
163
|
+
$type: 'com.example.kitchenSink',
|
|
164
|
+
object: {
|
|
165
|
+
object: { boolean: true },
|
|
166
|
+
array: ['one', 'two'],
|
|
167
|
+
boolean: true,
|
|
168
|
+
number: 123.45,
|
|
169
|
+
integer: 123,
|
|
170
|
+
string: 'string',
|
|
171
|
+
},
|
|
172
|
+
array: ['one', 'two'],
|
|
173
|
+
boolean: true,
|
|
174
|
+
number: 123.45,
|
|
175
|
+
integer: true,
|
|
176
|
+
string: 'string',
|
|
177
|
+
datetime: new Date().toISOString(),
|
|
178
|
+
}),
|
|
179
|
+
).toThrow('Record/integer must be a number')
|
|
180
|
+
expect(() =>
|
|
181
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
182
|
+
$type: 'com.example.kitchenSink',
|
|
183
|
+
object: {
|
|
184
|
+
object: { boolean: true },
|
|
185
|
+
array: ['one', 'two'],
|
|
186
|
+
boolean: true,
|
|
187
|
+
number: 123.45,
|
|
188
|
+
integer: 123,
|
|
189
|
+
string: 'string',
|
|
190
|
+
},
|
|
191
|
+
array: ['one', 'two'],
|
|
192
|
+
boolean: true,
|
|
193
|
+
number: 123.45,
|
|
194
|
+
integer: 123,
|
|
195
|
+
string: {},
|
|
196
|
+
datetime: new Date().toISOString(),
|
|
197
|
+
}),
|
|
198
|
+
).toThrow('Record/string must be a string')
|
|
199
|
+
expect(() =>
|
|
200
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
201
|
+
$type: 'com.example.kitchenSink',
|
|
202
|
+
object: {
|
|
203
|
+
object: { boolean: true },
|
|
204
|
+
array: ['one', 'two'],
|
|
205
|
+
boolean: true,
|
|
206
|
+
number: 123.45,
|
|
207
|
+
integer: 123,
|
|
208
|
+
string: 'string',
|
|
209
|
+
},
|
|
210
|
+
array: ['one', 'two'],
|
|
211
|
+
boolean: true,
|
|
212
|
+
number: 123.45,
|
|
213
|
+
integer: 123,
|
|
214
|
+
string: 'string',
|
|
215
|
+
datetime: 1234,
|
|
216
|
+
}),
|
|
217
|
+
).toThrow('Record/datetime must be a string')
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
it('Handles optional properties correctly', () => {
|
|
221
|
+
lex.assertValidRecord('com.example.optional', {
|
|
222
|
+
$type: 'com.example.optional',
|
|
223
|
+
})
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
it('Handles unions correctly', () => {
|
|
227
|
+
lex.assertValidRecord('com.example.union', {
|
|
228
|
+
$type: 'com.example.union',
|
|
229
|
+
unionOpen: {
|
|
230
|
+
$type: 'com.example.kitchenSink#object',
|
|
231
|
+
object: { boolean: true },
|
|
232
|
+
array: ['one', 'two'],
|
|
233
|
+
boolean: true,
|
|
234
|
+
number: 123.45,
|
|
235
|
+
integer: 123,
|
|
236
|
+
string: 'string',
|
|
237
|
+
},
|
|
238
|
+
unionClosed: {
|
|
239
|
+
$type: 'com.example.kitchenSink#subobject',
|
|
240
|
+
boolean: true,
|
|
241
|
+
},
|
|
242
|
+
})
|
|
243
|
+
lex.assertValidRecord('com.example.union', {
|
|
244
|
+
$type: 'com.example.union',
|
|
245
|
+
unionOpen: {
|
|
246
|
+
$type: 'com.example.other',
|
|
247
|
+
},
|
|
248
|
+
unionClosed: {
|
|
249
|
+
$type: 'com.example.kitchenSink#subobject',
|
|
250
|
+
boolean: true,
|
|
251
|
+
},
|
|
252
|
+
})
|
|
253
|
+
expect(() =>
|
|
254
|
+
lex.assertValidRecord('com.example.union', {
|
|
255
|
+
$type: 'com.example.union',
|
|
256
|
+
unionOpen: {},
|
|
257
|
+
unionClosed: {},
|
|
258
|
+
}),
|
|
259
|
+
).toThrow(
|
|
260
|
+
'Record/unionOpen must be an object which includes the "$type" property',
|
|
261
|
+
)
|
|
262
|
+
expect(() =>
|
|
263
|
+
lex.assertValidRecord('com.example.union', {
|
|
264
|
+
$type: 'com.example.union',
|
|
265
|
+
unionOpen: {
|
|
266
|
+
$type: 'com.example.other',
|
|
267
|
+
},
|
|
268
|
+
unionClosed: {
|
|
269
|
+
$type: 'com.example.other',
|
|
270
|
+
boolean: true,
|
|
271
|
+
},
|
|
272
|
+
}),
|
|
273
|
+
).toThrow(
|
|
274
|
+
'Record/unionClosed $type must be one of lex:com.example.kitchenSink#object, lex:com.example.kitchenSink#subobject',
|
|
275
|
+
)
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
it('Handles unknowns correctly', () => {
|
|
279
|
+
lex.assertValidRecord('com.example.unknown', {
|
|
280
|
+
$type: 'com.example.unknown',
|
|
281
|
+
unknown: { foo: 'bar' },
|
|
282
|
+
})
|
|
283
|
+
expect(() =>
|
|
284
|
+
lex.assertValidRecord('com.example.unknown', {
|
|
285
|
+
$type: 'com.example.unknown',
|
|
286
|
+
}),
|
|
287
|
+
).toThrow('Record must have the property "unknown"')
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('Applies array length constraints', () => {
|
|
291
|
+
lex.assertValidRecord('com.example.arrayLength', {
|
|
292
|
+
$type: 'com.example.arrayLength',
|
|
293
|
+
array: [1, 2, 3],
|
|
294
|
+
})
|
|
295
|
+
expect(() =>
|
|
296
|
+
lex.assertValidRecord('com.example.arrayLength', {
|
|
297
|
+
$type: 'com.example.arrayLength',
|
|
298
|
+
array: [1],
|
|
299
|
+
}),
|
|
300
|
+
).toThrow('Record/array must not have fewer than 2 elements')
|
|
301
|
+
expect(() =>
|
|
302
|
+
lex.assertValidRecord('com.example.arrayLength', {
|
|
303
|
+
$type: 'com.example.arrayLength',
|
|
304
|
+
array: [1, 2, 3, 4, 5],
|
|
305
|
+
}),
|
|
306
|
+
).toThrow('Record/array must not have more than 4 elements')
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
it('Applies boolean const constraint', () => {
|
|
310
|
+
lex.assertValidRecord('com.example.boolConst', {
|
|
311
|
+
$type: 'com.example.boolConst',
|
|
312
|
+
boolean: false,
|
|
313
|
+
})
|
|
314
|
+
expect(() =>
|
|
315
|
+
lex.assertValidRecord('com.example.boolConst', {
|
|
316
|
+
$type: 'com.example.boolConst',
|
|
317
|
+
boolean: true,
|
|
318
|
+
}),
|
|
319
|
+
).toThrow('Record/boolean must be false')
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
it('Applies number range constraint', () => {
|
|
323
|
+
lex.assertValidRecord('com.example.numberRange', {
|
|
324
|
+
$type: 'com.example.numberRange',
|
|
325
|
+
number: 2.5,
|
|
326
|
+
})
|
|
327
|
+
expect(() =>
|
|
328
|
+
lex.assertValidRecord('com.example.numberRange', {
|
|
329
|
+
$type: 'com.example.numberRange',
|
|
330
|
+
number: 1,
|
|
331
|
+
}),
|
|
332
|
+
).toThrow('Record/number can not be less than 2')
|
|
333
|
+
expect(() =>
|
|
334
|
+
lex.assertValidRecord('com.example.numberRange', {
|
|
335
|
+
$type: 'com.example.numberRange',
|
|
336
|
+
number: 5,
|
|
337
|
+
}),
|
|
338
|
+
).toThrow('Record/number can not be greater than 4')
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
it('Applies number enum constraint', () => {
|
|
342
|
+
lex.assertValidRecord('com.example.numberEnum', {
|
|
343
|
+
$type: 'com.example.numberEnum',
|
|
344
|
+
number: 1.5,
|
|
345
|
+
})
|
|
346
|
+
expect(() =>
|
|
347
|
+
lex.assertValidRecord('com.example.numberEnum', {
|
|
348
|
+
$type: 'com.example.numberEnum',
|
|
349
|
+
number: 0,
|
|
350
|
+
}),
|
|
351
|
+
).toThrow('Record/number must be one of (1|1.5|2)')
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
it('Applies number const constraint', () => {
|
|
355
|
+
lex.assertValidRecord('com.example.numberConst', {
|
|
356
|
+
$type: 'com.example.numberConst',
|
|
357
|
+
number: 0,
|
|
358
|
+
})
|
|
359
|
+
expect(() =>
|
|
360
|
+
lex.assertValidRecord('com.example.numberConst', {
|
|
361
|
+
$type: 'com.example.numberConst',
|
|
362
|
+
number: 1,
|
|
363
|
+
}),
|
|
364
|
+
).toThrow('Record/number must be 0')
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
it('Applies integer range constraint', () => {
|
|
368
|
+
lex.assertValidRecord('com.example.integerRange', {
|
|
369
|
+
$type: 'com.example.integerRange',
|
|
370
|
+
integer: 2,
|
|
371
|
+
})
|
|
372
|
+
expect(() =>
|
|
373
|
+
lex.assertValidRecord('com.example.integerRange', {
|
|
374
|
+
$type: 'com.example.integerRange',
|
|
375
|
+
integer: 1,
|
|
376
|
+
}),
|
|
377
|
+
).toThrow('Record/integer can not be less than 2')
|
|
378
|
+
expect(() =>
|
|
379
|
+
lex.assertValidRecord('com.example.integerRange', {
|
|
380
|
+
$type: 'com.example.integerRange',
|
|
381
|
+
integer: 5,
|
|
382
|
+
}),
|
|
383
|
+
).toThrow('Record/integer can not be greater than 4')
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('Applies integer enum constraint', () => {
|
|
387
|
+
lex.assertValidRecord('com.example.integerEnum', {
|
|
388
|
+
$type: 'com.example.integerEnum',
|
|
389
|
+
integer: 2,
|
|
390
|
+
})
|
|
391
|
+
expect(() =>
|
|
392
|
+
lex.assertValidRecord('com.example.integerEnum', {
|
|
393
|
+
$type: 'com.example.integerEnum',
|
|
394
|
+
integer: 0,
|
|
395
|
+
}),
|
|
396
|
+
).toThrow('Record/integer must be one of (1|2)')
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
it('Applies integer const constraint', () => {
|
|
400
|
+
lex.assertValidRecord('com.example.integerConst', {
|
|
401
|
+
$type: 'com.example.integerConst',
|
|
402
|
+
integer: 0,
|
|
403
|
+
})
|
|
404
|
+
expect(() =>
|
|
405
|
+
lex.assertValidRecord('com.example.integerConst', {
|
|
406
|
+
$type: 'com.example.integerConst',
|
|
407
|
+
integer: 1,
|
|
408
|
+
}),
|
|
409
|
+
).toThrow('Record/integer must be 0')
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
it('Applies integer whole-number constraint', () => {
|
|
413
|
+
expect(() =>
|
|
414
|
+
lex.assertValidRecord('com.example.integerRange', {
|
|
415
|
+
$type: 'com.example.integerRange',
|
|
416
|
+
integer: 2.5,
|
|
417
|
+
}),
|
|
418
|
+
).toThrow('Record/integer must be an integer')
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
it('Applies string length constraint', () => {
|
|
422
|
+
lex.assertValidRecord('com.example.stringLength', {
|
|
423
|
+
$type: 'com.example.stringLength',
|
|
424
|
+
string: '123',
|
|
425
|
+
})
|
|
426
|
+
expect(() =>
|
|
427
|
+
lex.assertValidRecord('com.example.stringLength', {
|
|
428
|
+
$type: 'com.example.stringLength',
|
|
429
|
+
string: '1',
|
|
430
|
+
}),
|
|
431
|
+
).toThrow('Record/string must not be shorter than 2 characters')
|
|
432
|
+
expect(() =>
|
|
433
|
+
lex.assertValidRecord('com.example.stringLength', {
|
|
434
|
+
$type: 'com.example.stringLength',
|
|
435
|
+
string: '12345',
|
|
436
|
+
}),
|
|
437
|
+
).toThrow('Record/string must not be longer than 4 characters')
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
it('Applies string enum constraint', () => {
|
|
441
|
+
lex.assertValidRecord('com.example.stringEnum', {
|
|
442
|
+
$type: 'com.example.stringEnum',
|
|
443
|
+
string: 'a',
|
|
444
|
+
})
|
|
445
|
+
expect(() =>
|
|
446
|
+
lex.assertValidRecord('com.example.stringEnum', {
|
|
447
|
+
$type: 'com.example.stringEnum',
|
|
448
|
+
string: 'c',
|
|
449
|
+
}),
|
|
450
|
+
).toThrow('Record/string must be one of (a|b)')
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
it('Applies string const constraint', () => {
|
|
454
|
+
lex.assertValidRecord('com.example.stringConst', {
|
|
455
|
+
$type: 'com.example.stringConst',
|
|
456
|
+
string: 'a',
|
|
457
|
+
})
|
|
458
|
+
expect(() =>
|
|
459
|
+
lex.assertValidRecord('com.example.stringConst', {
|
|
460
|
+
$type: 'com.example.stringConst',
|
|
461
|
+
string: 'b',
|
|
462
|
+
}),
|
|
463
|
+
).toThrow('Record/string must be a')
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
it('Applies datetime formatting constraint', () => {
|
|
467
|
+
expect(() =>
|
|
468
|
+
lex.assertValidRecord('com.example.kitchenSink', {
|
|
469
|
+
$type: 'com.example.kitchenSink',
|
|
470
|
+
object: {
|
|
471
|
+
object: { boolean: true },
|
|
472
|
+
array: ['one', 'two'],
|
|
473
|
+
boolean: true,
|
|
474
|
+
number: 123.45,
|
|
475
|
+
integer: 123,
|
|
476
|
+
string: 'string',
|
|
477
|
+
},
|
|
478
|
+
array: ['one', 'two'],
|
|
479
|
+
boolean: true,
|
|
480
|
+
number: 123.45,
|
|
481
|
+
integer: 123,
|
|
482
|
+
string: 'string',
|
|
483
|
+
datetime: 'bad date',
|
|
484
|
+
}),
|
|
485
|
+
).toThrow('Record/datetime must be an iso8601 formatted datetime')
|
|
486
|
+
})
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
describe('XRPC parameter validation', () => {
|
|
490
|
+
const lex = new Lexicons(LexiconDocs)
|
|
491
|
+
|
|
492
|
+
it('Passes valid parameters', () => {
|
|
493
|
+
lex.assertValidXrpcParams('com.example.query', {
|
|
494
|
+
boolean: true,
|
|
495
|
+
number: 123.45,
|
|
496
|
+
integer: 123,
|
|
497
|
+
string: 'string',
|
|
498
|
+
})
|
|
499
|
+
lex.assertValidXrpcParams('com.example.procedure', {
|
|
500
|
+
boolean: true,
|
|
501
|
+
number: 123.45,
|
|
502
|
+
integer: 123,
|
|
503
|
+
string: 'string',
|
|
504
|
+
})
|
|
505
|
+
})
|
|
506
|
+
|
|
507
|
+
it('Handles required correctly', () => {
|
|
508
|
+
lex.assertValidXrpcParams('com.example.query', {
|
|
509
|
+
boolean: true,
|
|
510
|
+
number: 123.45,
|
|
511
|
+
integer: 123,
|
|
512
|
+
})
|
|
513
|
+
expect(() =>
|
|
514
|
+
lex.assertValidXrpcParams('com.example.query', {
|
|
515
|
+
boolean: true,
|
|
516
|
+
number: 123.45,
|
|
517
|
+
}),
|
|
518
|
+
).toThrow('Params must have the property "integer"')
|
|
519
|
+
})
|
|
520
|
+
|
|
521
|
+
it('Validates parameter types', () => {
|
|
522
|
+
expect(() =>
|
|
523
|
+
lex.assertValidXrpcParams('com.example.query', {
|
|
524
|
+
boolean: 'string',
|
|
525
|
+
number: 123.45,
|
|
526
|
+
integer: 123,
|
|
527
|
+
string: 'string',
|
|
528
|
+
}),
|
|
529
|
+
).toThrow('boolean must be a boolean')
|
|
530
|
+
expect(() =>
|
|
531
|
+
lex.assertValidXrpcParams('com.example.procedure', {
|
|
532
|
+
boolean: true,
|
|
533
|
+
number: true,
|
|
534
|
+
integer: 123,
|
|
535
|
+
string: 'string',
|
|
536
|
+
}),
|
|
537
|
+
).toThrow('number must be a number')
|
|
538
|
+
})
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
describe('XRPC input validation', () => {
|
|
542
|
+
const lex = new Lexicons(LexiconDocs)
|
|
543
|
+
|
|
544
|
+
it('Passes valid inputs', () => {
|
|
545
|
+
lex.assertValidXrpcInput('com.example.procedure', {
|
|
546
|
+
object: { boolean: true },
|
|
547
|
+
array: ['one', 'two'],
|
|
548
|
+
boolean: true,
|
|
549
|
+
number: 123.45,
|
|
550
|
+
integer: 123,
|
|
551
|
+
string: 'string',
|
|
552
|
+
})
|
|
553
|
+
})
|
|
554
|
+
|
|
555
|
+
it('Validates the input', () => {
|
|
556
|
+
// dont need to check this extensively since it's the same logic as tested in record validation
|
|
557
|
+
expect(() =>
|
|
558
|
+
lex.assertValidXrpcInput('com.example.procedure', {
|
|
559
|
+
object: { boolean: 'string' },
|
|
560
|
+
array: ['one', 'two'],
|
|
561
|
+
boolean: true,
|
|
562
|
+
number: 123.45,
|
|
563
|
+
integer: 123,
|
|
564
|
+
string: 'string',
|
|
565
|
+
}),
|
|
566
|
+
).toThrow('Input/object/boolean must be a boolean')
|
|
567
|
+
expect(() => lex.assertValidXrpcInput('com.example.procedure', {})).toThrow(
|
|
568
|
+
'Input must have the property "object"',
|
|
569
|
+
)
|
|
570
|
+
})
|
|
571
|
+
})
|
|
572
|
+
|
|
573
|
+
describe('XRPC output validation', () => {
|
|
574
|
+
const lex = new Lexicons(LexiconDocs)
|
|
575
|
+
|
|
576
|
+
it('Passes valid outputs', () => {
|
|
577
|
+
lex.assertValidXrpcOutput('com.example.query', {
|
|
578
|
+
object: { boolean: true },
|
|
579
|
+
array: ['one', 'two'],
|
|
580
|
+
boolean: true,
|
|
581
|
+
number: 123.45,
|
|
582
|
+
integer: 123,
|
|
583
|
+
string: 'string',
|
|
584
|
+
})
|
|
585
|
+
lex.assertValidXrpcOutput('com.example.procedure', {
|
|
586
|
+
object: { boolean: true },
|
|
587
|
+
array: ['one', 'two'],
|
|
588
|
+
boolean: true,
|
|
589
|
+
number: 123.45,
|
|
590
|
+
integer: 123,
|
|
591
|
+
string: 'string',
|
|
592
|
+
})
|
|
593
|
+
})
|
|
594
|
+
|
|
595
|
+
it('Validates the output', () => {
|
|
596
|
+
// dont need to check this extensively since it's the same logic as tested in record validation
|
|
597
|
+
expect(() =>
|
|
598
|
+
lex.assertValidXrpcOutput('com.example.query', {
|
|
599
|
+
object: { boolean: 'string' },
|
|
600
|
+
array: ['one', 'two'],
|
|
601
|
+
boolean: true,
|
|
602
|
+
number: 123.45,
|
|
603
|
+
integer: 123,
|
|
604
|
+
string: 'string',
|
|
605
|
+
}),
|
|
606
|
+
).toThrow('Output/object/boolean must be a boolean')
|
|
607
|
+
expect(() =>
|
|
608
|
+
lex.assertValidXrpcOutput('com.example.procedure', {}),
|
|
609
|
+
).toThrow('Output must have the property "object"')
|
|
610
|
+
})
|
|
611
|
+
})
|