import { ApiPayload, CompassExternalAliasInput, Component, ComponentPayload, ConfigFileActions, CreateLinkInput, GetComponentByExternalAliasInput, } from '@atlassian/forge-graphql-types'; import { CompassRequests } from '../../../../compass-requests'; import { ModificationNotSupportedForThatType, UnexpectedConfigFileActionError, } from './errors'; import { EXTERNAL_ALIAS_SOURCE_COMPONENT_NAME } from './constants'; import { CompassYaml } from '../../../../types'; import { generateExternalIdWithPrefix, isYamlNameValid, updateComponent, } from './helpers'; import { unlinkComponentIfRetargetedByNewId, updateActionForExistingComponentByName, updateOrCreateComponentByPath, } from './updateActionHelper'; import { createActionForComponentByPath, createActionWithExistingComponentByName, } from './createActionHelper'; import { ConfigAsCodeRequests } from '../../../../config-as-code-requests'; import { HELLO_CLOUD_ID, HELLO_RESTRICTED_TYPE, } from '../../../../helpers/constants'; type CreateOrUpdateComponentParams = { requestApi: CompassRequests; configAsCodeApi: ConfigAsCodeRequests; cloudId: string; deduplicationId?: string; configFileAction: ConfigFileActions; oldPath?: string; newPath: string; componentYaml: CompassYaml; additionalLinks?: CreateLinkInput[]; additionalExternalAliases?: CompassExternalAliasInput[]; externalSourceURL?: string; }; export const createOrUpdateComponent = async ( input: CreateOrUpdateComponentParams, ): Promise => { const { requestApi, configAsCodeApi, cloudId, deduplicationId, configFileAction, oldPath, newPath, componentYaml, additionalLinks, additionalExternalAliases, externalSourceURL, } = input; const { name: yamlName } = componentYaml; if (componentYaml.id) { if (configFileAction === ConfigFileActions.UPDATE) { await unlinkComponentIfRetargetedByNewId({ requestApi, configAsCodeApi, cloudId, deduplicationId, oldPath, componentYaml, additionalExternalAliases, }); } const componentByIdResp = await requestApi.getComponent({ componentId: componentYaml.id, options: { includeLinks: true, includeCustomFields: true, includeCustomFieldOptions: true, }, }); if ( cloudId === HELLO_CLOUD_ID && componentByIdResp?.data?.component?.typeId === HELLO_RESTRICTED_TYPE ) { console.warn( `Unable to sync ${HELLO_RESTRICTED_TYPE} on this cloudId: ${HELLO_CLOUD_ID}. Please use the UI to create or update ${HELLO_RESTRICTED_TYPE} components.`, ); throw new ModificationNotSupportedForThatType(); } return updateComponent( cloudId, requestApi, componentByIdResp.data?.component, componentYaml, additionalLinks, additionalExternalAliases, externalSourceURL, ); } let componentByNameAliasResponse: ApiPayload; if (isYamlNameValid(yamlName)) { componentByNameAliasResponse = await requestApi.getComponentByExternalAlias( { cloudId, externalSource: EXTERNAL_ALIAS_SOURCE_COMPONENT_NAME, externalId: generateExternalIdWithPrefix(deduplicationId, yamlName), options: { includeLinks: true, includeCustomFields: true, includeCustomFieldOptions: true, }, } as GetComponentByExternalAliasInput, ); } if (componentByNameAliasResponse?.data?.component) { const componentByName = componentByNameAliasResponse?.data?.component; switch (configFileAction) { case 'UPDATE': { const updatedComponent = await updateActionForExistingComponentByName({ requestApi, componentByName, oldPath, newPath, deduplicationId, componentYaml, cloudId, externalSourceURL, additionalLinks, additionalExternalAliases, }); return updatedComponent; } case 'CREATE': { const createdComponent = await createActionWithExistingComponentByName({ requestApi, newPath, deduplicationId, componentYaml, cloudId, externalSourceURL, }); return createdComponent; } default: throw new UnexpectedConfigFileActionError( 'Unexpected config action type', ); } } else { // Component with Name alias does not exist switch (configFileAction) { case 'UPDATE': { const updatedComponent = await updateOrCreateComponentByPath({ requestApi, oldPath, newPath, deduplicationId, componentYaml, cloudId, externalSourceURL, additionalLinks, additionalExternalAliases, }); return updatedComponent; } case 'CREATE': { const createdComponent = await createActionForComponentByPath({ requestApi, newPath, deduplicationId, componentYaml, cloudId, externalSourceURL, additionalLinks, additionalExternalAliases, }); return createdComponent; } default: throw new UnexpectedConfigFileActionError( 'Unexpected config action type', ); } } };