import type { KeywordErrorCxt , KeywordErrorDefinition } from "../types" ; import type { SchemaCxt } from "./index" ; import { CodeGen , _ , str , strConcat , Code , Name } from "./codegen" ; import { SafeExpr } from "./codegen/code" ; import { getErrorPath , Type } from "./util" ; import N from "./names" ; export const keywordError = { message : ( { keyword } ) => str `must pass "${ keyword }" keyword validation` , } ; export const keyword$DataError = { message : ( { keyword , schemaType } ) => schemaType ? str `"${ keyword }" keyword must be ${ schemaType } ($data)` : str `"${ keyword }" keyword is invalid ($data)` , } ; export interface ErrorPaths { instancePath ? : Code ; schemaPath ? : string ; parentSchema ? : boolean ; } export function reportError ( cxt , error = keywordError , errorPaths ? , overrideAllErrors ? ) { const { it } = cxt ; const { gen , compositeRule , allErrors } = it ; const errObj = errorObjectCode ( cxt , error , errorPaths ) ; if ( overrideAllErrors ?? ( compositeRule || allErrors ) ) { addError ( gen , errObj ) ; } else { returnErrors ( it , _ `[${ errObj }]` ) ; } } export function reportExtraError ( cxt , error = keywordError , errorPaths ? ) { const { it } = cxt ; const { gen , compositeRule , allErrors } = it ; const errObj = errorObjectCode ( cxt , error , errorPaths ) ; addError ( gen , errObj ) ; if ( ! ( compositeRule || allErrors ) ) { returnErrors ( it , N . vErrors ) ; } } export function resetErrorsCount ( gen , errsCount ) { gen . assign ( N . errors , errsCount ) ; gen . if ( _ `${ N . vErrors } !== null` , ( ) => gen . if ( errsCount , ( ) => gen . assign ( _ `${ N . vErrors }.length` , errsCount ) , ( ) => gen . assign ( N . vErrors , null ) ) ) ; } export function extendErrors ( { gen , keyword , schemaValue , data , errsCount , it , } ) { if ( errsCount === undefined ) throw new Error ( "ajv implementation error" ) ; const err = gen . name ( "err" ) ; gen . forRange ( "i" , errsCount , N . errors , ( i ) => { gen . const ( err , _ `${ N . vErrors }[${ i }]` ) ; gen . if ( _ `${ err }.instancePath === undefined` , ( ) => gen . assign ( _ `${ err }.instancePath` , strConcat ( N . instancePath , it . errorPath ) ) ) ; gen . assign ( _ `${ err }.schemaPath` , str `${ it . errSchemaPath }/${ keyword }` ) ; if ( it . opts . verbose ) { gen . assign ( _ `${ err }.schema` , schemaValue ) ; gen . assign ( _ `${ err }.data` , data ) ; } } ) ; } function addError ( gen , errObj ) { const err = gen . const ( "err" , errObj ) ; gen . if ( _ `${ N . vErrors } === null` , ( ) => gen . assign ( N . vErrors , _ `[${ err }]` ) , _ `${ N . vErrors }.push(${ err })` ) ; gen . code ( _ `${ N . errors }++` ) ; } function returnErrors ( it , errs ) { const { gen , validateName , schemaEnv } = it ; if ( schemaEnv . $async ) { gen . throw ( _ `new ${ it . ValidationError as Name }(${ errs })` ) ; } else { gen . assign ( _ `${ validateName }.errors` , errs ) ; gen . return ( false ) ; } } const E = { keyword : new Name ( "keyword" ) , schemaPath : new Name ( "schemaPath" ) , params : new Name ( "params" ) , propertyName : new Name ( "propertyName" ) , message : new Name ( "message" ) , schema : new Name ( "schema" ) , parentSchema : new Name ( "parentSchema" ) , } ; function errorObjectCode ( cxt , error , errorPaths ? ) { const { createErrors } = cxt . it ; if ( createErrors === false ) return _ `{}` ; return errorObject ( cxt , error , errorPaths ) ; } function errorObject ( cxt , error , errorPaths = { } ) { const { gen , it } = cxt ; const keyValues = [ errorInstancePath ( it , errorPaths ) , errorSchemaPath ( cxt , errorPaths ) , ] ; extraErrorProps ( cxt , error , keyValues ) ; return gen . object ( ... keyValues ) ; } function errorInstancePath ( { errorPath } , { instancePath } ) { const instPath = instancePath ? str `${ errorPath }${ getErrorPath ( instancePath , Type . Str ) }` : errorPath ; return [ N . instancePath , strConcat ( N . instancePath , instPath ) ] ; } function errorSchemaPath ( { keyword , it : { errSchemaPath } } , { schemaPath , parentSchema } ) { let schPath = parentSchema ? errSchemaPath : str `${ errSchemaPath }/${ keyword }` ; if ( schemaPath ) { schPath = str `${ schPath }${ getErrorPath ( schemaPath , Type . Str ) }` ; } return [ E . schemaPath , schPath ] ; } function extraErrorProps ( cxt , { params , message } , keyValues ) { const { keyword , data , schemaValue , it } = cxt ; const { opts , propertyName , topSchemaRef , schemaPath } = it ; keyValues . push ( [ E . keyword , keyword ] , [ E . params , typeof params == "function" ? params ( cxt ) : params || _ `{}` ] ) ; if ( opts . messages ) { keyValues . push ( [ E . message , typeof message == "function" ? message ( cxt ) : message ] ) ; } if ( opts . verbose ) { keyValues . push ( [ E . schema , schemaValue ] , [ E . parentSchema , _ `${ topSchemaRef }${ schemaPath }` ] , [ N . data , data ] ) ; } if ( propertyName ) keyValues . push ( [ E . propertyName , propertyName ] ) ; }