import { dequal } from 'dequal' ; import type { PackageJson } from 'type-fest' ; import { logger } from '../../../../logger' ; import { matchAt , replaceAt } from '../../../../util/string' ; import type { UpdateDependencyConfig } from '../../../types' ; function replaceAsString ( parsedContents , fileContent , depType , depName , oldValue , newValue ) { if ( depType === 'packageManager' ) { parsedContents [ depType ] = newValue ; } else if ( depName === oldValue ) { delete Object . assign ( parsedContents [ depType ] , { [ newValue ] : parsedContents [ depType ] [ oldValue ] , } ) [ oldValue ] ; } else { parsedContents [ depType ] [ depName ] = newValue ; } const searchString = `"${ oldValue }"` ; const newString = `"${ newValue }"` ; let searchIndex = fileContent . indexOf ( `"${ depType }"` ) + depType . length ; logger . trace ( `Starting search at index ${ searchIndex }` ) ; for ( ; searchIndex < fileContent . length ; searchIndex += 1 ) { if ( matchAt ( fileContent , searchIndex , searchString ) ) { logger . trace ( `Found match at index ${ searchIndex }` ) ; const testContent = replaceAt ( fileContent , searchIndex , searchString , newString ) ; if ( dequal ( parsedContents , JSON . parse ( testContent ) ) ) { return testContent ; } } } throw new Error ( ) ; } export function updateDependency ( { fileContent , upgrade , } ) { const { depType , managerData } = upgrade ; const depName = managerData ?. key || upgrade . depName ; let { newValue } = upgrade ; if ( upgrade . currentRawValue ) { if ( upgrade . currentDigest ) { logger . debug ( 'Updating package.json git digest' ) ; newValue = upgrade . currentRawValue . replace ( upgrade . currentDigest , upgrade . newDigest . substring ( 0 , upgrade . currentDigest . length ) ) ; } else { logger . debug ( 'Updating package.json git version tag' ) ; newValue = upgrade . currentRawValue . replace ( upgrade . currentValue , upgrade . newValue ) ; } } if ( upgrade . npmPackageAlias ) { newValue = `npm:${ upgrade . lookupName }@${ newValue }` ; } logger . debug ( `npm.updateDependency(): ${ depType }.${ depName } = ${ newValue }` ) ; try { const parsedContents = JSON . parse ( fileContent ) ; let oldVersion ; if ( depType === 'packageManager' ) { oldVersion = parsedContents [ depType ] ; newValue = `${ depName }@${ newValue }` ; } else { oldVersion = parsedContents [ depType ] [ depName ] ; } if ( oldVersion === newValue ) { logger . trace ( 'Version is already updated' ) ; return fileContent ; } let newFileContent = replaceAsString ( parsedContents , fileContent , depType , depName , oldVersion , newValue ) ; if ( upgrade . newName ) { newFileContent = replaceAsString ( parsedContents , newFileContent , depType , depName , depName , upgrade . newName ) ; } if ( ! newFileContent ) { logger . debug ( { fileContent , parsedContents , depType , depName , newValue } , 'Warning: updateDependency error' ) ; return fileContent ; } if ( parsedContents ?. resolutions ) { let depKey ; if ( parsedContents . resolutions [ depName ] ) { depKey = depName ; } else if ( parsedContents . resolutions [ `**/${ depName }` ] ) { depKey = `**/${ depName }` ; } if ( depKey ) { if ( parsedContents . resolutions [ depKey ] !== oldVersion ) { logger . debug ( { depName , depKey , oldVersion , resolutionsVersion : parsedContents . resolutions [ depKey ] , } , 'Upgraded dependency exists in yarn resolutions but is different version' ) ; } newFileContent = replaceAsString ( parsedContents , newFileContent , 'resolutions' , depKey , parsedContents . resolutions [ depKey ] , newValue ) ; if ( upgrade . newName ) { if ( depKey === `**/${ depName }` ) { upgrade . newName = `**/${ upgrade . newName }` ; } newFileContent = replaceAsString ( parsedContents , newFileContent , 'resolutions' , depKey , depKey , upgrade . newName ) ; } } } return newFileContent ; } catch ( err ) { logger . debug ( { err } , 'updateDependency error' ) ; return null ; } }