diff --git a/lib/manager/npm/update/dependency/index.ts b/lib/manager/npm/update/dependency/index.ts index ed939783d971a3f6bac9e8810ce437b1a972385d..9c94b58d7fd35ffa236c4d7c551047f2b3b77931 100644 --- a/lib/manager/npm/update/dependency/index.ts +++ b/lib/manager/npm/update/dependency/index.ts @@ -1,8 +1,48 @@ 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: PackageJson, + fileContent: string, + depType: string, + depName: string, + oldVersion: string, + newValue: string +): string | null { + // Update the file = this is what we want + // eslint-disable-next-line no-param-reassign + parsedContents[depType][depName] = newValue; + // Look for the old version number + const searchString = `"${oldVersion}"`; + const newString = `"${newValue}"`; + // Skip ahead to depType section + let searchIndex = fileContent.indexOf(`"${depType}"`) + depType.length; + logger.trace(`Starting search at index ${searchIndex}`); + // Iterate through the rest of the file + for (; searchIndex < fileContent.length; searchIndex += 1) { + // First check if we have a hit for the old version + if (matchAt(fileContent, searchIndex, searchString)) { + logger.trace(`Found match at index ${searchIndex}`); + // Now test if the result matches + const testContent = replaceAt( + fileContent, + searchIndex, + searchString, + newString + ); + // Compare the parsed JSON structure of old and new + if (dequal(parsedContents, JSON.parse(testContent))) { + return testContent; + } + } + } + // istanbul ignore next + throw new Error(); +} + export function updateDependency({ fileContent, upgrade, @@ -30,41 +70,21 @@ export function updateDependency({ } logger.debug(`npm.updateDependency(): ${depType}.${depName} = ${newValue}`); try { - const parsedContents = JSON.parse(fileContent); + const parsedContents: PackageJson = JSON.parse(fileContent); // Save the old version const oldVersion: string = parsedContents[depType][depName]; if (oldVersion === newValue) { logger.trace('Version is already updated'); return fileContent; } - // Update the file = this is what we want - parsedContents[depType][depName] = newValue; - // Look for the old version number - const searchString = `"${oldVersion}"`; - const newString = `"${newValue}"`; - let newFileContent = null; - // Skip ahead to depType section - let searchIndex = fileContent.indexOf(`"${depType}"`) + depType.length; - logger.trace(`Starting search at index ${searchIndex}`); - // Iterate through the rest of the file - for (; searchIndex < fileContent.length; searchIndex += 1) { - // First check if we have a hit for the old version - if (matchAt(fileContent, searchIndex, searchString)) { - logger.trace(`Found match at index ${searchIndex}`); - // Now test if the result matches - const testContent = replaceAt( - fileContent, - searchIndex, - searchString, - newString - ); - // Compare the parsed JSON structure of old and new - if (dequal(parsedContents, JSON.parse(testContent))) { - newFileContent = testContent; - break; - } - } - } + let newFileContent = replaceAsString( + parsedContents, + fileContent, + depType, + depName, + oldVersion, + newValue + ); // istanbul ignore if if (!newFileContent) { logger.debug( @@ -93,33 +113,14 @@ export function updateDependency({ 'Upgraded dependency exists in yarn resolutions but is different version' ); } - // Look for the old version number - const oldResolution = `"${String(parsedContents.resolutions[depKey])}"`; - const newResolution = `"${newValue}"`; - // Update the file = this is what we want - parsedContents.resolutions[depKey] = newValue; - // Skip ahead to depType section - searchIndex = newFileContent.indexOf(`"resolutions"`); - logger.trace(`Starting search at index ${searchIndex}`); - // Iterate through the rest of the file - for (; searchIndex < newFileContent.length; searchIndex += 1) { - // First check if we have a hit for the old version - if (matchAt(newFileContent, searchIndex, oldResolution)) { - logger.trace(`Found match at index ${searchIndex}`); - // Now test if the result matches - const testContent = replaceAt( - newFileContent, - searchIndex, - oldResolution, - newResolution - ); - // Compare the parsed JSON structure of old and new - if (dequal(parsedContents, JSON.parse(testContent))) { - newFileContent = testContent; - break; - } - } - } + newFileContent = replaceAsString( + parsedContents, + newFileContent, + 'resolutions', + depKey, + parsedContents.resolutions[depKey], + newValue + ); } } return newFileContent;