@atproto/lexicon
Version:
atproto Lexicon schema language library
50 lines (45 loc) • 1.71 kB
text/typescript
import { Lexicons } from '../lexicons'
import { LexXrpcParameters, ValidationError, ValidationResult } from '../types'
import { array } from './complex'
import * as PrimitiveValidators from './primitives'
export function params(
lexicons: Lexicons,
path: string,
def: LexXrpcParameters,
val: unknown,
): ValidationResult<Record<string, unknown>> {
// type
const value = val && typeof val === 'object' ? val : {}
const requiredProps = new Set(def.required ?? [])
// properties
let resultValue = value as Record<string, unknown>
if (typeof def.properties === 'object') {
for (const key in def.properties) {
const propDef = def.properties[key]
const validated =
propDef.type === 'array'
? array(lexicons, key, propDef, value[key])
: PrimitiveValidators.validate(lexicons, key, propDef, value[key])
const propValue = validated.success ? validated.value : value[key]
const propIsUndefined = typeof propValue === 'undefined'
// Return error for bad validation, giving required rule precedence
if (propIsUndefined && requiredProps.has(key)) {
return {
success: false,
error: new ValidationError(`${path} must have the property "${key}"`),
}
} else if (!propIsUndefined && !validated.success) {
return validated
}
// Adjust value based on e.g. applied defaults, cloning shallowly if there was a changed value
if (propValue !== value[key]) {
if (resultValue === value) {
// Lazy shallow clone
resultValue = { ...value }
}
resultValue[key] = propValue
}
}
}
return { success: true, value: resultValue }
}