import { uniq } from 'lodash' ; import { castOpenSearchToOsdFieldTypeName } from '../../../../../common' ; import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values' ; import { FieldDescriptor } from '../../../fetcher' ; interface FieldCapObject { type : string ; searchable : boolean ; aggregatable : boolean ; indices ? : string [ ] ; non_searchable_indices ? : string [ ] ; non_aggregatable_indices ? : string [ ] ; } export interface FieldCapsResponse { fields : Record < string , Record < string , FieldCapObject > > ; } param { FieldCapsResponse } fieldCapsResponse return { Array < FieldDescriptor > } export function readFieldCapsResponse ( fieldCapsResponse ) { const capsByNameThenType = fieldCapsResponse . fields ; const opensearchDashboardsFormattedCaps = Object . keys ( capsByNameThenType ) . reduce < { array : FieldDescriptor [ ] ; hash : Record < string , FieldDescriptor > ; } > ( ( agg , fieldName ) => { const capsByType = capsByNameThenType [ fieldName ] ; const types = Object . keys ( capsByType ) ; const isSearchable = types . some ( ( type ) => { return ( ! ! capsByType [ type ] . searchable || ( ! ! capsByType [ type ] . non_searchable_indices && capsByType [ type ] . non_searchable_indices ! . length > 0 ) ) ; } ) ; const isAggregatable = types . some ( ( type ) => { return ( ! ! capsByType [ type ] . aggregatable || ( ! ! capsByType [ type ] . non_aggregatable_indices && capsByType [ type ] . non_aggregatable_indices ! . length > 0 ) ) ; } ) ; const uniqueOpenSearchDashboardsTypes = uniq ( types . map ( castOpenSearchToOsdFieldTypeName ) ) ; if ( uniqueOpenSearchDashboardsTypes . length > 1 ) { const field = { name : fieldName , type : 'conflict' , esTypes : types , searchable : isSearchable , aggregatable : isAggregatable , readFromDocValues : false , conflictDescriptions : types . reduce ( ( acc , opensearchType ) => ( { ... acc , [ opensearchType ] : capsByType [ opensearchType ] . indices , } ) , { } ) , } ; agg . array . push ( field ) ; agg . hash [ fieldName ] = field ; return agg ; } const opensearchType = types [ 0 ] ; const field = { name : fieldName , type : castOpenSearchToOsdFieldTypeName ( opensearchType ) , esTypes : types , searchable : isSearchable , aggregatable : isAggregatable , readFromDocValues : shouldReadFieldFromDocValues ( isAggregatable , opensearchType ) , } ; agg . array . push ( field ) ; agg . hash [ fieldName ] = field ; return agg ; } , { array : [ ] , hash : { } , } ) ; const subFields = opensearchDashboardsFormattedCaps . array . filter ( ( field ) => { return field . name . includes ( '.' ) ; } ) ; subFields . forEach ( ( field ) => { const parentFieldNames = field . name . split ( '.' ) . slice ( 0 , - 1 ) . map ( ( _ , index , parentFieldNameParts ) => { return parentFieldNameParts . slice ( 0 , index + 1 ) . join ( '.' ) ; } ) ; const parentFieldCaps = parentFieldNames . map ( ( parentFieldName ) => opensearchDashboardsFormattedCaps . hash [ parentFieldName ] ) ; const parentFieldCapsAscending = parentFieldCaps . reverse ( ) ; if ( parentFieldCaps && parentFieldCaps . length > 0 ) { let subType = { } ; const firstParent = parentFieldCapsAscending [ 0 ] ; if ( firstParent && ! [ 'object' , 'nested' ] . includes ( firstParent . type ) ) { subType = { ... subType , multi : { parent : firstParent . name } } ; } const nestedParentCaps = parentFieldCapsAscending . find ( ( parentCaps ) => parentCaps && parentCaps . type === 'nested' ) ; if ( nestedParentCaps ) { subType = { ... subType , nested : { path : nestedParentCaps . name } } ; } if ( Object . keys ( subType ) . length > 0 ) { field . subType = subType ; } } } ) ; return opensearchDashboardsFormattedCaps . array . filter ( ( field ) => { return ! [ 'object' , 'nested' ] . includes ( field . type ) ; } ) ; }