/// import { ApiPayload, CreateEventSourceInput, DetachEventSource, DetachEventSourceInput, EventSource, EventSourcesPayload, SdkError, UpdateEventSourcesInput, } from '@atlassian/forge-graphql-types'; import { CompassRequests } from '../../compass-requests'; import { DETACH_EVENT_SOURCES_MUTATION_NAME, constructGqlSegmentFromArray, generateMutationGql, mapGqlErrors, parseCompoundMutationErrors, prefixMutation, } from '../../helpers'; declare module '../../compass-requests' { interface CompassRequests { /** * Updates the collection of event sources associated with a component. * * **Required Oauth Scopes:** `write:component:compass`, `write:event:compass` */ updateEventSources( input: UpdateEventSourcesInput, ): Promise>; } } function isEventSourceEqual( a: EventSource | CreateEventSourceInput, b: EventSource | CreateEventSourceInput, ) { return ( a.externalEventSourceId === b.externalEventSourceId && a.eventType === b.eventType ); } function transformIntoDetachEventSourceInput( item: EventSource, componentId?: string, ): DetachEventSourceInput { return { eventSourceId: item.id, componentId, }; } CompassRequests.prototype.updateEventSources = async function ( this: CompassRequests, { componentId, oldEventSources, newEventSources }, ) { let errorsAcc = [] as Array; const eventSourcesInBoth = oldEventSources.filter((existingEventSource) => newEventSources.some((newEventSource) => isEventSourceEqual(existingEventSource, newEventSource), ), ); const toBeAdded = newEventSources.filter( (newEventSource) => !eventSourcesInBoth.some((overlapEventSource) => isEventSourceEqual(newEventSource, overlapEventSource), ), ); const toBeDetached = oldEventSources.filter( (oldEventSource) => !eventSourcesInBoth.some((overlapEventSource) => isEventSourceEqual(overlapEventSource, oldEventSource), ), ); // TODO: Make these into bulk requests for (const newEventSource of toBeAdded) { // eslint-disable-next-line no-await-in-loop const { errors } = await this.addEventSource({ componentId, eventSource: newEventSource, }); errorsAcc = errorsAcc.concat(errors); } if (toBeDetached.length > 0) { const segmentAcc = { mutation: '', parameters: [] as Array, variables: {} as Record, }; const detachEventSourceGqlSegment = () => generateMutationGql(DetachEventSource, 'detachEventSource'); const { mutation, parameters, variables } = constructGqlSegmentFromArray( toBeDetached, detachEventSourceGqlSegment, transformIntoDetachEventSourceInput, segmentAcc, componentId, ); const detachEventSourcesResp = await this.api.requestGraph( prefixMutation(mutation, DETACH_EVENT_SOURCES_MUTATION_NAME, parameters), variables, 'updateEventSources', ); const { errors, data } = await detachEventSourcesResp.json(); errorsAcc = errorsAcc.concat(parseCompoundMutationErrors(data, variables)); errorsAcc = errorsAcc.concat(mapGqlErrors(errors)); } let eventSources; try { ({ data: { component: { eventSources }, }, } = await this.getComponent({ componentId, })); } catch { console.error('Error: Could not parse getComponent response'); } return { errors: errorsAcc, success: errorsAcc.length === 0, data: { eventSources: eventSources || [] }, }; };