import type { CodeKeywordDefinition , ErrorObject , KeywordErrorDefinition , SchemaMap , AnySchema , } from "../../types" ; import type { KeywordCxt } from "../../compile/validate" ; import { _ , str } from "../../compile/codegen" ; import { alwaysValidSchema } from "../../compile/util" ; import { checkReportMissingProp , checkMissingProp , reportMissingProp , propertyInData } from "../code" ; export type PropertyDependencies = { [ K in string ] ? : string [ ] ; } ; export interface DependenciesErrorParams { property : string ; missingProperty : string ; depsCount : number ; deps : string ; } type SchemaDependencies = SchemaMap ; export type DependenciesError = ErrorObject < "dependencies" , DependenciesErrorParams , { [ K in string ] ? : string [ ] | AnySchema ; } > ; export const error = { message : ( { params : { property , depsCount , deps } } ) => { const property_ies = depsCount === 1 ? "property" : "properties" ; return str `must have ${ property_ies } ${ deps } when property ${ property } is present` ; } , params : ( { params : { property , depsCount , deps , missingProperty } } ) => _ `{property: ${ property },
    missingProperty: ${ missingProperty },
    depsCount: ${ depsCount },
    deps: ${ deps }}` , } ; const def = { keyword : "dependencies" , type : "object" , schemaType : "object" , error , code ( cxt ) { const [ propDeps , schDeps ] = splitDependencies ( cxt ) ; validatePropertyDeps ( cxt , propDeps ) ; validateSchemaDeps ( cxt , schDeps ) ; } , } ; function splitDependencies ( { schema } ) { const propertyDeps = { } ; const schemaDeps = { } ; for ( const key in schema ) { if ( key === "__proto__" ) continue ; const deps = Array . isArray ( schema [ key ] ) ? propertyDeps : schemaDeps ; deps [ key ] = schema [ key ] ; } return [ propertyDeps , schemaDeps ] ; } export function validatePropertyDeps ( cxt , propertyDeps = cxt . schema ) { const { gen , data , it } = cxt ; if ( Object . keys ( propertyDeps ) . length === 0 ) return ; const missing = gen . let ( "missing" ) ; for ( const prop in propertyDeps ) { const deps = propertyDeps [ prop ] as string [ ] ; if ( deps . length === 0 ) continue ; const hasProperty = propertyInData ( gen , data , prop , it . opts . ownProperties ) ; cxt . setParams ( { property : prop , depsCount : deps . length , deps : deps . join ( ", " ) , } ) ; if ( it . allErrors ) { gen . if ( hasProperty , ( ) => { for ( const depProp of deps ) { checkReportMissingProp ( cxt , depProp ) ; } } ) ; } else { gen . if ( _ `${ hasProperty } && (${ checkMissingProp ( cxt , deps , missing ) })` ) ; reportMissingProp ( cxt , missing ) ; gen . else ( ) ; } } } export function validateSchemaDeps ( cxt , schemaDeps = cxt . schema ) { const { gen , data , keyword , it } = cxt ; const valid = gen . name ( "valid" ) ; for ( const prop in schemaDeps ) { if ( alwaysValidSchema ( it , schemaDeps [ prop ] as AnySchema ) ) continue ; gen . if ( propertyInData ( gen , data , prop , it . opts . ownProperties ) , ( ) => { const schCxt = cxt . subschema ( { keyword , schemaProp : prop } , valid ) ; cxt . mergeValidEvaluated ( schCxt , valid ) ; } , ( ) => gen . var ( valid , true ) ) ; cxt . ok ( valid ) ; } } export default def ;