@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
@@ -1,416 +0,0 @@
1
- import { CID } from 'multiformats/cid'
2
- import { graphemeLen, utf8Len } from '@atproto/common-web'
3
- import { Lexicons } from '../lexicons.js'
4
- import {
5
- LexBoolean,
6
- LexBytes,
7
- LexInteger,
8
- LexString,
9
- LexUserType,
10
- ValidationError,
11
- ValidationResult,
12
- } from '../types.js'
13
- import * as formats from './formats.js'
14
-
15
- export function validate(
16
- lexicons: Lexicons,
17
- path: string,
18
- def: LexUserType,
19
- value: unknown,
20
- ): ValidationResult {
21
- switch (def.type) {
22
- case 'boolean':
23
- return boolean(lexicons, path, def, value)
24
- case 'integer':
25
- return integer(lexicons, path, def, value)
26
- case 'string':
27
- return string(lexicons, path, def, value)
28
- case 'bytes':
29
- return bytes(lexicons, path, def, value)
30
- case 'cid-link':
31
- return cidLink(lexicons, path, def, value)
32
- case 'unknown':
33
- return unknown(lexicons, path, def, value)
34
- default:
35
- return {
36
- success: false,
37
- error: new ValidationError(`Unexpected lexicon type: ${def.type}`),
38
- }
39
- }
40
- }
41
-
42
- function boolean(
43
- lexicons: Lexicons,
44
- path: string,
45
- def: LexUserType,
46
- value: unknown,
47
- ): ValidationResult {
48
- def = def as LexBoolean
49
-
50
- // type
51
- const type = typeof value
52
- if (type === 'undefined') {
53
- if (typeof def.default === 'boolean') {
54
- return { success: true, value: def.default }
55
- }
56
- return {
57
- success: false,
58
- error: new ValidationError(`${path} must be a boolean`),
59
- }
60
- } else if (type !== 'boolean') {
61
- return {
62
- success: false,
63
- error: new ValidationError(`${path} must be a boolean`),
64
- }
65
- }
66
-
67
- // const
68
- if (typeof def.const === 'boolean') {
69
- if (value !== def.const) {
70
- return {
71
- success: false,
72
- error: new ValidationError(`${path} must be ${def.const}`),
73
- }
74
- }
75
- }
76
-
77
- return { success: true, value }
78
- }
79
-
80
- function integer(
81
- lexicons: Lexicons,
82
- path: string,
83
- def: LexUserType,
84
- value: unknown,
85
- ): ValidationResult {
86
- def = def as LexInteger
87
-
88
- // type
89
- const type = typeof value
90
- if (type === 'undefined') {
91
- if (typeof def.default === 'number') {
92
- return { success: true, value: def.default }
93
- }
94
- return {
95
- success: false,
96
- error: new ValidationError(`${path} must be an integer`),
97
- }
98
- } else if (!Number.isInteger(value)) {
99
- return {
100
- success: false,
101
- error: new ValidationError(`${path} must be an integer`),
102
- }
103
- }
104
-
105
- // const
106
- if (typeof def.const === 'number') {
107
- if (value !== def.const) {
108
- return {
109
- success: false,
110
- error: new ValidationError(`${path} must be ${def.const}`),
111
- }
112
- }
113
- }
114
-
115
- // enum
116
- if (Array.isArray(def.enum)) {
117
- if (!def.enum.includes(value as number)) {
118
- return {
119
- success: false,
120
- error: new ValidationError(
121
- `${path} must be one of (${def.enum.join('|')})`,
122
- ),
123
- }
124
- }
125
- }
126
-
127
- // maximum
128
- if (typeof def.maximum === 'number') {
129
- if ((value as number) > def.maximum) {
130
- return {
131
- success: false,
132
- error: new ValidationError(
133
- `${path} can not be greater than ${def.maximum}`,
134
- ),
135
- }
136
- }
137
- }
138
-
139
- // minimum
140
- if (typeof def.minimum === 'number') {
141
- if ((value as number) < def.minimum) {
142
- return {
143
- success: false,
144
- error: new ValidationError(
145
- `${path} can not be less than ${def.minimum}`,
146
- ),
147
- }
148
- }
149
- }
150
-
151
- return { success: true, value }
152
- }
153
-
154
- function string(
155
- lexicons: Lexicons,
156
- path: string,
157
- def: LexUserType,
158
- value: unknown,
159
- ): ValidationResult<string> {
160
- def = def as LexString
161
-
162
- // type
163
- if (typeof value === 'undefined') {
164
- if (typeof def.default === 'string') {
165
- return { success: true, value: def.default }
166
- }
167
- return {
168
- success: false,
169
- error: new ValidationError(`${path} must be a string`),
170
- }
171
- } else if (typeof value !== 'string') {
172
- return {
173
- success: false,
174
- error: new ValidationError(`${path} must be a string`),
175
- }
176
- }
177
-
178
- // const
179
- if (typeof def.const === 'string') {
180
- if (value !== def.const) {
181
- return {
182
- success: false,
183
- error: new ValidationError(`${path} must be ${def.const}`),
184
- }
185
- }
186
- }
187
-
188
- // enum
189
- if (Array.isArray(def.enum)) {
190
- if (!def.enum.includes(value as string)) {
191
- return {
192
- success: false,
193
- error: new ValidationError(
194
- `${path} must be one of (${def.enum.join('|')})`,
195
- ),
196
- }
197
- }
198
- }
199
-
200
- // maxLength and minLength
201
- if (typeof def.minLength === 'number' || typeof def.maxLength === 'number') {
202
- // If the JavaScript string length * 3 is below the maximum limit,
203
- // its UTF8 length (which <= .length * 3) will also be below.
204
- if (typeof def.minLength === 'number' && value.length * 3 < def.minLength) {
205
- return {
206
- success: false,
207
- error: new ValidationError(
208
- `${path} must not be shorter than ${def.minLength} characters`,
209
- ),
210
- }
211
- }
212
-
213
- // If the JavaScript string length * 3 is within the maximum limit,
214
- // its UTF8 length (which <= .length * 3) will also be within.
215
- // When there's no minimal length, this lets us skip the UTF8 length check.
216
- let canSkipUtf8LenChecks = false
217
- if (
218
- typeof def.minLength === 'undefined' &&
219
- typeof def.maxLength === 'number' &&
220
- value.length * 3 <= def.maxLength
221
- ) {
222
- canSkipUtf8LenChecks = true
223
- }
224
-
225
- if (!canSkipUtf8LenChecks) {
226
- const len = utf8Len(value)
227
-
228
- if (typeof def.maxLength === 'number') {
229
- if (len > def.maxLength) {
230
- return {
231
- success: false,
232
- error: new ValidationError(
233
- `${path} must not be longer than ${def.maxLength} characters`,
234
- ),
235
- }
236
- }
237
- }
238
-
239
- if (typeof def.minLength === 'number') {
240
- if (len < def.minLength) {
241
- return {
242
- success: false,
243
- error: new ValidationError(
244
- `${path} must not be shorter than ${def.minLength} characters`,
245
- ),
246
- }
247
- }
248
- }
249
- }
250
- }
251
-
252
- // maxGraphemes and minGraphemes
253
- if (
254
- typeof def.maxGraphemes === 'number' ||
255
- typeof def.minGraphemes === 'number'
256
- ) {
257
- let needsMaxGraphemesCheck = false
258
- let needsMinGraphemesCheck = false
259
-
260
- if (typeof def.maxGraphemes === 'number') {
261
- if (value.length <= def.maxGraphemes) {
262
- // If the JavaScript string length (UTF-16) is within the maximum limit,
263
- // its grapheme length (which <= .length) will also be within.
264
- needsMaxGraphemesCheck = false
265
- } else {
266
- needsMaxGraphemesCheck = true
267
- }
268
- }
269
-
270
- if (typeof def.minGraphemes === 'number') {
271
- if (value.length < def.minGraphemes) {
272
- // If the JavaScript string length (UTF-16) is below the minimal limit,
273
- // its grapheme length (which <= .length) will also be below.
274
- // Fail early.
275
- return {
276
- success: false,
277
- error: new ValidationError(
278
- `${path} must not be shorter than ${def.minGraphemes} graphemes`,
279
- ),
280
- }
281
- } else {
282
- needsMinGraphemesCheck = true
283
- }
284
- }
285
-
286
- if (needsMaxGraphemesCheck || needsMinGraphemesCheck) {
287
- const len = graphemeLen(value)
288
-
289
- if (typeof def.maxGraphemes === 'number') {
290
- if (len > def.maxGraphemes) {
291
- return {
292
- success: false,
293
- error: new ValidationError(
294
- `${path} must not be longer than ${def.maxGraphemes} graphemes`,
295
- ),
296
- }
297
- }
298
- }
299
-
300
- if (typeof def.minGraphemes === 'number') {
301
- if (len < def.minGraphemes) {
302
- return {
303
- success: false,
304
- error: new ValidationError(
305
- `${path} must not be shorter than ${def.minGraphemes} graphemes`,
306
- ),
307
- }
308
- }
309
- }
310
- }
311
- }
312
-
313
- if (typeof def.format === 'string') {
314
- switch (def.format) {
315
- case 'datetime':
316
- return formats.datetime(path, value)
317
- case 'uri':
318
- return formats.uri(path, value)
319
- case 'at-uri':
320
- return formats.atUri(path, value)
321
- case 'did':
322
- return formats.did(path, value)
323
- case 'handle':
324
- return formats.handle(path, value)
325
- case 'at-identifier':
326
- return formats.atIdentifier(path, value)
327
- case 'nsid':
328
- return formats.nsid(path, value)
329
- case 'cid':
330
- return formats.cid(path, value)
331
- case 'language':
332
- return formats.language(path, value)
333
- case 'tid':
334
- return formats.tid(path, value)
335
- case 'record-key':
336
- return formats.recordKey(path, value)
337
- }
338
- }
339
-
340
- return { success: true, value }
341
- }
342
-
343
- function bytes(
344
- lexicons: Lexicons,
345
- path: string,
346
- def: LexUserType,
347
- value: unknown,
348
- ): ValidationResult {
349
- def = def as LexBytes
350
-
351
- if (!value || !(value instanceof Uint8Array)) {
352
- return {
353
- success: false,
354
- error: new ValidationError(`${path} must be a byte array`),
355
- }
356
- }
357
-
358
- // maxLength
359
- if (typeof def.maxLength === 'number') {
360
- if (value.byteLength > def.maxLength) {
361
- return {
362
- success: false,
363
- error: new ValidationError(
364
- `${path} must not be larger than ${def.maxLength} bytes`,
365
- ),
366
- }
367
- }
368
- }
369
-
370
- // minLength
371
- if (typeof def.minLength === 'number') {
372
- if (value.byteLength < def.minLength) {
373
- return {
374
- success: false,
375
- error: new ValidationError(
376
- `${path} must not be smaller than ${def.minLength} bytes`,
377
- ),
378
- }
379
- }
380
- }
381
-
382
- return { success: true, value }
383
- }
384
-
385
- function cidLink(
386
- lexicons: Lexicons,
387
- path: string,
388
- def: LexUserType,
389
- value: unknown,
390
- ): ValidationResult {
391
- if (CID.asCID(value) === null) {
392
- return {
393
- success: false,
394
- error: new ValidationError(`${path} must be a CID`),
395
- }
396
- }
397
-
398
- return { success: true, value }
399
- }
400
-
401
- function unknown(
402
- lexicons: Lexicons,
403
- path: string,
404
- def: LexUserType,
405
- value: unknown,
406
- ): ValidationResult {
407
- // type
408
- if (!value || typeof value !== 'object') {
409
- return {
410
- success: false,
411
- error: new ValidationError(`${path} must be an object`),
412
- }
413
- }
414
-
415
- return { success: true, value }
416
- }
@@ -1,53 +0,0 @@
1
- import { Lexicons } from '../lexicons.js'
2
- import {
3
- LexXrpcParameters,
4
- ValidationError,
5
- ValidationResult,
6
- } from '../types.js'
7
- import { array } from './complex.js'
8
- import * as PrimitiveValidators from './primitives.js'
9
-
10
- export function params(
11
- lexicons: Lexicons,
12
- path: string,
13
- def: LexXrpcParameters,
14
- val: unknown,
15
- ): ValidationResult<Record<string, unknown>> {
16
- // type
17
- const value = val && typeof val === 'object' ? val : {}
18
-
19
- const requiredProps = new Set(def.required ?? [])
20
-
21
- // properties
22
- let resultValue = value as Record<string, unknown>
23
- if (typeof def.properties === 'object') {
24
- for (const key in def.properties) {
25
- const propDef = def.properties[key]
26
- const validated =
27
- propDef.type === 'array'
28
- ? array(lexicons, key, propDef, value[key])
29
- : PrimitiveValidators.validate(lexicons, key, propDef, value[key])
30
- const propValue = validated.success ? validated.value : value[key]
31
- const propIsUndefined = typeof propValue === 'undefined'
32
- // Return error for bad validation, giving required rule precedence
33
- if (propIsUndefined && requiredProps.has(key)) {
34
- return {
35
- success: false,
36
- error: new ValidationError(`${path} must have the property "${key}"`),
37
- }
38
- } else if (!propIsUndefined && !validated.success) {
39
- return validated
40
- }
41
- // Adjust value based on e.g. applied defaults, cloning shallowly if there was a changed value
42
- if (propValue !== value[key]) {
43
- if (resultValue === value) {
44
- // Lazy shallow clone
45
- resultValue = { ...value }
46
- }
47
- resultValue[key] = propValue
48
- }
49
- }
50
- }
51
-
52
- return { success: true, value: resultValue }
53
- }