import { Ajv } from "ajv" ; import { uiSchemaSchema , UiSchema } from "../models/uischema" ; import { schemaFieldFactory , schemaKeysFactory } from "../factory" ; import { getDataKeys , getSchemaId } from "./resolve" ; import { FxJsonSchema } from "../models/jsonschema" ; import { warn } from "../utils" ; param { String [ ] } uiSchemaKeys param { String } parentSchemaPath return { String } const getUiSchemaKeyRecursion = ( uiSchemaKeys , parentSchemaPath ) : string => { let parentKeysWithDef = getDataKeys ( parentSchemaPath , true ) ; while ( uiSchemaKeys . length ) { const key = uiSchemaKeys . shift ( ) || "" ; parentKeysWithDef = parentKeysWithDef . concat ( key ? [ key ] : [ ] ) ; const keysStr = parentKeysWithDef . join ( "/" ) . replace ( /\/$/ , "" ) ; if ( ! schemaKeysFactory . has ( keysStr ) ) { if ( __DEV__ ) { warn ( `${ keysStr } did not found.` ) ; } return "" ; } const schema = schemaFieldFactory . get ( schemaKeysFactory . get ( keysStr ) ) ; if ( schema . $ref ) { parentKeysWithDef = getDataKeys ( schema . $ref , true ) ; } } return parentKeysWithDef . join ( "/" ) ; } ; param { UiSchema } parent return { Array < string | number > } const getParentSchemaKeys = ( parent ) : Array < string | number > => { if ( parent && parent . keys ) { return parent . keys ; } return [ ] ; } ; param { UiSchema } parent param { string } schemaPath param { UiSchema } uiSchema return { String } const getCurrentSchemaKey = ( parent , schemaPath , uiSchema ) : string => { const $id = getSchemaId ( schemaPath ) ; let uiSchemaKeys = uiSchema . key . split ( "/" ) ; if ( parent && getSchemaId ( parent . key ) === $id ) { return getUiSchemaKeyRecursion ( uiSchemaKeys , parent . schemaPath || "" ) ; } return getUiSchemaKeyRecursion ( uiSchemaKeys , schemaPath ) ; } ; param { UiSchema } uiSchema return { UiSchema } const mergeUiSchemaToArray = ( uiSchema ) : UiSchema => { if ( ! schemaKeysFactory . has ( uiSchema . key ) ) { if ( __DEV__ ) { console . log ( schemaKeysFactory ) ; warn ( `${ uiSchema . key } did not found. do you forget to resolve schema first.` ) ; } return uiSchema ; } const schemaKey = schemaKeysFactory . get ( uiSchema . key ) ; const schema = schemaFieldFactory . get ( schemaKey ) ; return Object . assign ( { } , schema , uiSchema ) ; } ; param { UiSchema } parent param { string } schemaPath param { UiSchema } uiSchema return { UiSchema } const initUiSchema = ( parent , schemaPath , uiSchema ) : UiSchema => { let parentKeys = getParentSchemaKeys ( parent ) , key = getCurrentSchemaKey ( parent , schemaPath , uiSchema ) , keys , isRequired = false , originSchema = { } , schemaKey ; keys = parentKeys . concat ( uiSchema . key ? uiSchema . key . split ( "/" ) : [ ] ) ; if ( schemaKeysFactory . has ( key ) ) { schemaKey = schemaKeysFactory . get ( key ) ; if ( schemaFieldFactory . has ( schemaKey ) ) { originSchema = schemaFieldFactory . get ( schemaKey ) ; } } return Object . assign ( { isRequired } , originSchema , uiSchema , { key , keys } ) ; } ; param { UiSchema [ ] } uiSchemasFirst param { UiSchema [ ] } uiSchemasLast param { UiSchema } uiSchema return { Void } const pushMergeResult = ( uiSchemasFirst , uiSchemasLast , uiSchema ) : void => { if ( ! uiSchemasFirst . concat ( uiSchemasLast ) . filter ( ( val ) => { return val . key === uiSchema . key ; } ) . length ) { uiSchema = mergeUiSchemaToArray ( uiSchema ) ; uiSchemasFirst . push ( uiSchema ) ; } } ; param { UiSchema } parent param { string } schemaPath param { Array < UiSchema | string > } uiSchemas param { FxJsonSchema } curSchema return { UiSchema [ ] } const initMergeSchema = ( parent , schemaPath , uiSchemas , curSchema ) : UiSchema [ ] => { let idx = uiSchemas . indexOf ( "*" ) , uiSchemasFirst = [ ] , uiSchemasLast = [ ] , types = [ "object" , "array" ] ; if ( uiSchemas . lastIndexOf ( "*" ) !== idx ) { if ( __DEV__ ) { warn ( "uiSchema can only has one *." ) ; } return [ ] ; } if ( idx < 0 ) { uiSchemas . slice ( idx + 1 ) . map ( ( us ) => { let uiSchema = initUiSchema ( parent , schemaPath , us . constructor === String ? { key : us } as UiSchema : ( us as UiSchema ) ) ; uiSchemasFirst . push ( mergeUiSchemaToArray ( uiSchema ) ) ; } ) ; return uiSchemasFirst ; } uiSchemas . slice ( 0 , idx ) . forEach ( ( us ) => { let uiSchema = initUiSchema ( parent , curSchema . schemaPath || schemaPath , us . constructor === String ? { key : us } as UiSchema : ( us as UiSchema ) ) ; uiSchemasFirst . push ( mergeUiSchemaToArray ( uiSchema ) ) ; } ) ; uiSchemas . slice ( idx + 1 ) . forEach ( ( us ) => { let uiSchema = initUiSchema ( parent , curSchema . schemaPath || schemaPath , us . constructor === String ? { key : us } as UiSchema : ( us as UiSchema ) ) ; uiSchemasLast . push ( mergeUiSchemaToArray ( uiSchema ) ) ; } ) ; if ( curSchema . type === types [ 0 ] && curSchema . properties ) { Object . keys ( curSchema . properties ) . forEach ( ( us ) => { const uiSchema = initUiSchema ( parent , curSchema . schemaPath || schemaPath , { key : us , isRequired : curSchema . required ? curSchema . required . indexOf ( us ) >= 0 : false } as UiSchema ) ; pushMergeResult ( uiSchemasFirst , uiSchemasLast , uiSchema ) ; } ) ; } if ( curSchema . type === types [ 1 ] && curSchema . items ) { const uiSchema = initUiSchema ( parent , curSchema . schemaPath || schemaPath , { key : "-" } ) ; pushMergeResult ( uiSchemasFirst , uiSchemasLast , uiSchema ) ; } if ( types . indexOf ( curSchema . type as string ) < 0 ) { let uiSchema = initUiSchema ( parent , schemaPath , { key : getDataKeys ( curSchema . schemaPath || "" , false ) . join ( "/" ) } ) ; pushMergeResult ( uiSchemasFirst , uiSchemasLast , uiSchema ) ; } return uiSchemasFirst . concat ( uiSchemasLast ) ; } ; /**
 * 用来转换uiSchema的类
 * 如果有$ref，则直接使用
 */ export default class MergeLib { /**
     * 合并过后的数据
     */ public mergeUiSchemaList : UiSchema [ ] = [ ] ; param { Ajv } ajv param { string } $id param { UiSchema } parent param { Array < UiSchema | string > } uiSchemas constructor ( ajv , schemaPath , parent , uiSchemas ? ) { uiSchemas = uiSchemas || [ "*" ] ; let keyPath = getDataKeys ( schemaPath , true ) . join ( "/" ) ; if ( ! schemaKeysFactory . has ( keyPath ) ) { if ( __DEV__ ) { warn ( `${ keyPath } not exist or ${ keyPath } did not resolve yet.` ) ; } return ; } const curSchema = schemaFieldFactory . get ( schemaKeysFactory . get ( keyPath ) ) ; if ( curSchema . $id ) { if ( ! curSchema . $ref ) { curSchema . $ref = curSchema . $id ; } curSchema . $id = undefined ; delete curSchema . $id ; } this . mergeUiSchemaList = initMergeSchema ( parent , schemaPath , uiSchemas , curSchema ) ; } }