import { Inject , Injectable , NgZone } from '@angular/core' ; import Ajv from 'ajv' ; import addFormats from 'ajv-formats' ; import { AlainConfigService , AlainSFConfig } from '@delon/util/config' ; import { REGEX } from '@delon/util/format' ; import type { NzSafeAny } from 'ng-zorro-antd/core/types' ; import { mergeConfig } from './config' ; import { ErrorData } from './errors' ; import { SFValue } from './interface' ; import { SFSchema } from './schema' ; @ Injectable ( ) export abstract class SchemaValidatorFactory { abstract createValidatorFn ( schema , extraOptions ) ; } @ Injectable ( ) export class AjvSchemaValidatorFactory extends SchemaValidatorFactory { protected ajv ! : Ajv ; protected options ! : AlainSFConfig ; constructor ( @ Inject ( AlainConfigService ) cogSrv , private ngZone ) { super ( ) ; if ( ! ( typeof document === 'object' && ! ! document ) ) { return ; } this . options = mergeConfig ( cogSrv ) ; const customOptions = this . options . ajv || { } ; this . ngZone . runOutsideAngular ( ( ) => { this . ajv = new Ajv ( { allErrors : true , loopEnum : 50 , ... customOptions , formats : { 'data-url' : /^data:([a-z]+\/[a-z0-9-+.]+)?;name=(.*);base64,(.*)$/ , color : REGEX . color , mobile : REGEX . mobile , 'id-card' : REGEX . idCard , ... customOptions . formats } } ) ; addFormats ( this . ajv as NzSafeAny ) ; } ) ; } createValidatorFn ( schema , extraOptions ) { const ingoreKeywords = [ ... ( this . options . ingoreKeywords as string [ ] ) , ... ( ( extraOptions . ingoreKeywords as string [ ] ) || [ ] ) ] ; return ( value ) : ErrorData [ ] => { try { this . ngZone . runOutsideAngular ( ( ) => this . ajv . validate ( schema , value ) ) ; } catch ( e ) { if ( typeof ngDevMode === 'undefined' || ngDevMode ) { if ( extraOptions . debug ) { console . warn ( e ) ; } } } let errors = this . ajv . errors ; if ( this . options && ingoreKeywords && errors ) { errors = errors . filter ( w => ingoreKeywords . indexOf ( w . keyword ) === - 1 ) ; } return errors as ErrorData [ ] ; } ; } }