///
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 || [] },
};
};