@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/validation.ts DELETED
@@ -1,84 +0,0 @@
1
- import { Lexicons } from './lexicons.js'
2
- import {
3
- LexRecord,
4
- LexRefVariant,
5
- LexUserType,
6
- LexXrpcProcedure,
7
- LexXrpcQuery,
8
- LexXrpcSubscription,
9
- } from './types.js'
10
- import { object, validateOneOf } from './validators/complex.js'
11
- import { params } from './validators/xrpc.js'
12
-
13
- export function assertValidRecord(
14
- lexicons: Lexicons,
15
- def: LexRecord,
16
- value: unknown,
17
- ) {
18
- const res = object(lexicons, 'Record', def.record, value)
19
- if (!res.success) throw res.error
20
- return res.value
21
- }
22
-
23
- export function assertValidXrpcParams(
24
- lexicons: Lexicons,
25
- def: LexXrpcProcedure | LexXrpcQuery | LexXrpcSubscription,
26
- value: unknown,
27
- ) {
28
- if (def.parameters) {
29
- const res = params(lexicons, 'Params', def.parameters, value)
30
- if (!res.success) throw res.error
31
- return res.value
32
- }
33
- }
34
-
35
- export function assertValidXrpcInput(
36
- lexicons: Lexicons,
37
- def: LexXrpcProcedure,
38
- value: unknown,
39
- ) {
40
- if (def.input?.schema) {
41
- // loop: all input schema definitions
42
- return assertValidOneOf(lexicons, 'Input', def.input.schema, value, true)
43
- }
44
- }
45
-
46
- export function assertValidXrpcOutput(
47
- lexicons: Lexicons,
48
- def: LexXrpcProcedure | LexXrpcQuery,
49
- value: unknown,
50
- ) {
51
- if (def.output?.schema) {
52
- // loop: all output schema definitions
53
- return assertValidOneOf(lexicons, 'Output', def.output.schema, value, true)
54
- }
55
- }
56
-
57
- export function assertValidXrpcMessage(
58
- lexicons: Lexicons,
59
- def: LexXrpcSubscription,
60
- value: unknown,
61
- ) {
62
- if (def.message?.schema) {
63
- // loop: all output schema definitions
64
- return assertValidOneOf(
65
- lexicons,
66
- 'Message',
67
- def.message.schema,
68
- value,
69
- true,
70
- )
71
- }
72
- }
73
-
74
- function assertValidOneOf(
75
- lexicons: Lexicons,
76
- path: string,
77
- def: LexRefVariant | LexUserType,
78
- value: unknown,
79
- mustBeObj = false,
80
- ) {
81
- const res = validateOneOf(lexicons, path, def, value, mustBeObj)
82
- if (!res.success) throw res.error
83
- return res.value
84
- }
@@ -1,19 +0,0 @@
1
- import { BlobRef } from '../blob-refs.js'
2
- import { Lexicons } from '../lexicons.js'
3
- import { LexUserType, ValidationError, ValidationResult } from '../types.js'
4
-
5
- export function blob(
6
- lexicons: Lexicons,
7
- path: string,
8
- def: LexUserType,
9
- value: unknown,
10
- ): ValidationResult {
11
- // check
12
- if (!value || !(value instanceof BlobRef)) {
13
- return {
14
- success: false,
15
- error: new ValidationError(`${path} should be a blob ref`),
16
- }
17
- }
18
- return { success: true, value }
19
- }
@@ -1,212 +0,0 @@
1
- import { Lexicons } from '../lexicons.js'
2
- import {
3
- LexArray,
4
- LexRefVariant,
5
- LexUserType,
6
- ValidationError,
7
- ValidationResult,
8
- isDiscriminatedObject,
9
- isObj,
10
- } from '../types.js'
11
- import { toLexUri } from '../util.js'
12
- import { blob } from './blob.js'
13
- import { validate as validatePrimitive } from './primitives.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 'object':
23
- return object(lexicons, path, def, value)
24
- case 'array':
25
- return array(lexicons, path, def, value)
26
- case 'blob':
27
- return blob(lexicons, path, def, value)
28
- default:
29
- return validatePrimitive(lexicons, path, def, value)
30
- }
31
- }
32
-
33
- export function array(
34
- lexicons: Lexicons,
35
- path: string,
36
- def: LexArray,
37
- value: unknown,
38
- ): ValidationResult {
39
- // type
40
- if (!Array.isArray(value)) {
41
- return {
42
- success: false,
43
- error: new ValidationError(`${path} must be an array`),
44
- }
45
- }
46
-
47
- // maxLength
48
- if (typeof def.maxLength === 'number') {
49
- if ((value as Array<unknown>).length > def.maxLength) {
50
- return {
51
- success: false,
52
- error: new ValidationError(
53
- `${path} must not have more than ${def.maxLength} elements`,
54
- ),
55
- }
56
- }
57
- }
58
-
59
- // minLength
60
- if (typeof def.minLength === 'number') {
61
- if ((value as Array<unknown>).length < def.minLength) {
62
- return {
63
- success: false,
64
- error: new ValidationError(
65
- `${path} must not have fewer than ${def.minLength} elements`,
66
- ),
67
- }
68
- }
69
- }
70
-
71
- // items
72
- const itemsDef = def.items
73
- for (let i = 0; i < (value as Array<unknown>).length; i++) {
74
- const itemValue = value[i]
75
- const itemPath = `${path}/${i}`
76
- const res = validateOneOf(lexicons, itemPath, itemsDef, itemValue)
77
- if (!res.success) {
78
- return res
79
- }
80
- }
81
-
82
- return { success: true, value }
83
- }
84
-
85
- export function object(
86
- lexicons: Lexicons,
87
- path: string,
88
- def: LexUserType,
89
- value: unknown,
90
- ): ValidationResult {
91
- // type
92
- if (!isObj(value)) {
93
- return {
94
- success: false,
95
- error: new ValidationError(`${path} must be an object`),
96
- }
97
- }
98
-
99
- // properties
100
- let resultValue = value
101
- if ('properties' in def && def.properties != null) {
102
- for (const key in def.properties) {
103
- const keyValue = value[key]
104
- if (keyValue === null && def.nullable?.includes(key)) {
105
- continue
106
- }
107
- const propDef = def.properties[key]
108
- if (keyValue === undefined && !def.required?.includes(key)) {
109
- // Fast path for non-required undefined props.
110
- if (
111
- propDef.type === 'integer' ||
112
- propDef.type === 'boolean' ||
113
- propDef.type === 'string'
114
- ) {
115
- if (propDef.default === undefined) {
116
- continue
117
- }
118
- } else {
119
- // Other types have no defaults.
120
- continue
121
- }
122
- }
123
- const propPath = `${path}/${key}`
124
- const validated = validateOneOf(lexicons, propPath, propDef, keyValue)
125
- const propValue = validated.success ? validated.value : keyValue
126
-
127
- // Return error for bad validation, giving required rule precedence
128
- if (propValue === undefined) {
129
- if (def.required?.includes(key)) {
130
- return {
131
- success: false,
132
- error: new ValidationError(
133
- `${path} must have the property "${key}"`,
134
- ),
135
- }
136
- }
137
- } else {
138
- if (!validated.success) {
139
- return validated
140
- }
141
- }
142
-
143
- // Adjust value based on e.g. applied defaults, cloning shallowly if there was a changed value
144
- if (propValue !== keyValue) {
145
- if (resultValue === value) {
146
- // Lazy shallow clone
147
- resultValue = { ...value }
148
- }
149
- resultValue[key] = propValue
150
- }
151
- }
152
- }
153
-
154
- return { success: true, value: resultValue }
155
- }
156
-
157
- export function validateOneOf(
158
- lexicons: Lexicons,
159
- path: string,
160
- def: LexRefVariant | LexUserType,
161
- value: unknown,
162
- mustBeObj = false, // this is the only type constraint we need currently (used by xrpc body schema validators)
163
- ): ValidationResult {
164
- let concreteDef: LexUserType
165
-
166
- if (def.type === 'union') {
167
- if (!isDiscriminatedObject(value)) {
168
- return {
169
- success: false,
170
- error: new ValidationError(
171
- `${path} must be an object which includes the "$type" property`,
172
- ),
173
- }
174
- }
175
- if (!refsContainType(def.refs, value.$type)) {
176
- if (def.closed) {
177
- return {
178
- success: false,
179
- error: new ValidationError(
180
- `${path} $type must be one of ${def.refs.join(', ')}`,
181
- ),
182
- }
183
- }
184
- return { success: true, value }
185
- } else {
186
- concreteDef = lexicons.getDefOrThrow(value.$type)
187
- }
188
- } else if (def.type === 'ref') {
189
- concreteDef = lexicons.getDefOrThrow(def.ref)
190
- } else {
191
- concreteDef = def
192
- }
193
-
194
- return mustBeObj
195
- ? object(lexicons, path, concreteDef, value)
196
- : validate(lexicons, path, concreteDef, value)
197
- }
198
-
199
- // to avoid bugs like #0189 this needs to handle both
200
- // explicit and implicit #main
201
- const refsContainType = (refs: string[], type: string) => {
202
- const lexUri = toLexUri(type)
203
- if (refs.includes(lexUri)) {
204
- return true
205
- }
206
-
207
- if (lexUri.endsWith('#main')) {
208
- return refs.includes(lexUri.slice(0, -5))
209
- } else {
210
- return !lexUri.includes('#') && refs.includes(`${lexUri}#main`)
211
- }
212
- }
@@ -1,72 +0,0 @@
1
- import { CID } from 'multiformats/cid'
2
- import {
3
- isAtIdentifierString,
4
- isAtUriString,
5
- isDatetimeStringLenient,
6
- isValidDid,
7
- isValidHandle,
8
- isValidLanguage,
9
- isValidNsid,
10
- isValidRecordKey,
11
- isValidTid,
12
- isValidUri,
13
- } from '@atproto/syntax'
14
- import { ValidationError, ValidationResult } from '../types.js'
15
-
16
- export const datetime = createValidator(
17
- isDatetimeStringLenient,
18
- 'must be an valid atproto datetime (both RFC-3339 and ISO-8601)',
19
- )
20
- export const uri = createValidator(isValidUri, 'must be a uri')
21
- export const atUri = createValidator(isAtUriString, 'must be a valid at-uri')
22
- export const did = createValidator(isValidDid, 'must be a valid did')
23
- export const handle = createValidator(isValidHandle, 'must be a valid handle')
24
- export const atIdentifier = createValidator(
25
- isAtIdentifierString,
26
- 'must be a valid did or a handle',
27
- )
28
- export const nsid = createValidator(isValidNsid, 'must be a valid nsid')
29
- export const cid = createValidator(isCidString, 'must be a cid string')
30
- export const language = createValidator(
31
- isValidLanguage,
32
- 'must be a well-formed BCP 47 language tag',
33
- )
34
- export const tid = createValidator(isValidTid, 'must be a valid TID')
35
- export const recordKey = createValidator(
36
- isValidRecordKey,
37
- 'must be a valid Record Key',
38
- )
39
-
40
- // Internal helpers
41
-
42
- function createValidator<T extends string>(
43
- assertionFn: (value: string) => value is T,
44
- errorMessage: string,
45
- ): <V extends string>(path: string, value: V) => ValidationResult<V & T>
46
- function createValidator(
47
- assertionFn: (value: string) => boolean,
48
- errorMessage: string,
49
- ): (path: string, value: string) => ValidationResult<string>
50
- function createValidator(
51
- assertionFn: (value: string) => boolean,
52
- errorMessage: string,
53
- ) {
54
- return (path: string, value: string): ValidationResult => {
55
- if (assertionFn(value)) {
56
- return { success: true, value }
57
- }
58
- return {
59
- success: false,
60
- error: new ValidationError(`${path} ${errorMessage}`),
61
- }
62
- }
63
- }
64
-
65
- function isCidString(v: string): v is string {
66
- try {
67
- CID.parse(v)
68
- return true
69
- } catch {
70
- return false
71
- }
72
- }