import pMap from 'p-map' ; import { SavedObjectsClientContract } from '../../types' ; import { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry' ; import type { ImportStateMap , ImportStateValue } from './types' ; import { getObjectKey , parseObjectKey } from '../../service/lib/internal_utils' ; import { createOriginQuery } from './utils' ; export interface CheckReferenceOriginsParams { savedObjectsClient : SavedObjectsClientContract ; typeRegistry : ISavedObjectTypeRegistry ; namespace ? : string ; importStateMap : ImportStateMap ; } interface Reference { type : string ; id : string ; } const MAX_CONCURRENT_SEARCHES = 10 ; /**
 * Searches for any existing object(s) for the given reference; if there is exactly one object with a matching origin *and* its ID is
 * different than this reference ID, then this returns the different ID. Otherwise, it returns null.
 */ async function checkOrigin ( type , id , savedObjectsClient , namespace ) { const findOptions = { type , search : createOriginQuery ( type , id ) , rootSearchFields : [ '_id' , 'originId' ] , page : 1 , perPage : 1 , fields : [ 'title' ] , sortField : 'updated_at' , sortOrder : 'desc' as const , ... ( namespace && { namespaces : [ namespace ] } ) , } ; const findResult = await savedObjectsClient . find < { title ? : string ; } > ( findOptions ) ; const { total , saved_objects : savedObjects } = findResult ; if ( total === 1 ) { const [ object ] = savedObjects ; if ( id !== object . id ) { return { key : getObjectKey ( { type , id } ) , value : { isOnlyReference : true , destinationId : object . id } as ImportStateValue , } ; } } return null ; } export async function checkReferenceOrigins ( params ) { const { savedObjectsClient , namespace } = params ; const referencesToCheck = [ ] ; for ( const [ key , { isOnlyReference } ] of params . importStateMap . entries ( ) ) { const { type , id } = parseObjectKey ( key ) ; if ( params . typeRegistry . isMultiNamespace ( type ) && isOnlyReference ) { referencesToCheck . push ( { type , id } ) ; } } const mapper = async ( { type , id } ) => checkOrigin ( type , id , savedObjectsClient , namespace ) ; const checkOriginResults = await pMap ( referencesToCheck , mapper , { concurrency : MAX_CONCURRENT_SEARCHES , } ) ; const importStateMap = new Map ( ) ; for ( const result of checkOriginResults ) { if ( result ) { const { key , value } = result ; importStateMap . set ( key , value ) ; } } return { importStateMap } ; }