diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 042dc89b930e5358d8d155db8cad79becbcb33bf..987fdfa0293f1fc5ea64cb401eab4338818f9750 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -3849,6 +3849,16 @@ The field supports multiple URLs but it is datasource-dependent on whether only Add to this object if you wish to define rules that apply only to PRs that replace dependencies. +## replacementApproach + +For `npm` manager when `replacementApproach=alias` then instead of replacing `"foo": "1.2.3"` with `"@my/foo": "1.2.4"` we would instead replace it with `"foo": "npm:@my/foo@1.2.4"`. + +```json +{ + "replacementApproach": "alias" +} +``` + ## respectLatest Similar to `ignoreUnstable`, this option controls whether to update to versions that are greater than the version tagged as `latest` in the repository. diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index c5ad124c28110cd7f76ffe3f609b444b9a0ace06..6f20b33e45becb611e46bb82b844e9e609aa7522 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -1465,6 +1465,16 @@ const options: RenovateOptions[] = [ cli: false, env: false, }, + { + name: 'replacementApproach', + description: + 'Select whether to perform a direct replacement or alias replacement.', + type: 'string', + stage: 'branch', + allowedValues: ['replace', 'alias'], + supportedManagers: ['npm'], + default: 'replace', + }, { name: 'matchConfidence', description: diff --git a/lib/modules/manager/npm/update/dependency/index.spec.ts b/lib/modules/manager/npm/update/dependency/index.spec.ts index e02760aadc42e49db2a8803dab1a02ee46f1677f..18d871756e6d89e8530b8f00cb3b88cdbac6cc89 100644 --- a/lib/modules/manager/npm/update/dependency/index.spec.ts +++ b/lib/modules/manager/npm/update/dependency/index.spec.ts @@ -1,5 +1,6 @@ import * as npmUpdater from '../..'; import { Fixtures } from '../../../../../../test/fixtures'; +import { type Upgrade } from '../../../types'; const readFixture = (x: string): string => Fixtures.get(x, '../..'); @@ -254,6 +255,23 @@ describe('modules/manager/npm/update/dependency/index', () => { expect(JSON.parse(testContent!).dependencies.abc).toBe('2.0.0'); }); + it('supports alias-based replacement', () => { + const upgrade: Upgrade = { + depType: 'dependencies', + depName: 'config', + newName: 'abc', + replacementApproach: 'alias', + newValue: '2.0.0', + }; + const testContent = npmUpdater.updateDependency({ + fileContent: input01Content, + upgrade, + }); + expect(JSON.parse(testContent!).dependencies.config).toBe( + 'npm:abc@2.0.0', + ); + }); + it('replaces glob package resolutions', () => { const upgrade = { depType: 'dependencies', diff --git a/lib/modules/manager/npm/update/dependency/index.ts b/lib/modules/manager/npm/update/dependency/index.ts index 0d4bb218f0205e6d8be3a6e6dc3b8db16c11a2c8..c86ed856b207616680951597ef61790d954cbee4 100644 --- a/lib/modules/manager/npm/update/dependency/index.ts +++ b/lib/modules/manager/npm/update/dependency/index.ts @@ -161,25 +161,38 @@ export function updateDependency({ } // TODO #22198 - let newFileContent = replaceAsString( - parsedContents, - fileContent, - depType as NpmDepType, - depName, - oldVersion!, - newValue!, - overrideDepParents, - ); - if (upgrade.newName) { + let newFileContent: string; + if (upgrade.newName && upgrade.replacementApproach === 'alias') { newFileContent = replaceAsString( parsedContents, - newFileContent, + fileContent, depType as NpmDepType, depName, + oldVersion!, + `npm:${upgrade.newName}@${newValue}`, + overrideDepParents, + ); + } else { + newFileContent = replaceAsString( + parsedContents, + fileContent, + depType as NpmDepType, depName, - upgrade.newName, + oldVersion!, + newValue!, overrideDepParents, ); + if (upgrade.newName) { + newFileContent = replaceAsString( + parsedContents, + newFileContent, + depType as NpmDepType, + depName, + depName, + upgrade.newName, + overrideDepParents, + ); + } } // istanbul ignore if if (!newFileContent) { diff --git a/lib/modules/manager/types.ts b/lib/modules/manager/types.ts index 28ede22bda95183b199bf07cf8246af0ebf73a17..3ce881369af1e5fd745f2c436b090e668091913c 100644 --- a/lib/modules/manager/types.ts +++ b/lib/modules/manager/types.ts @@ -192,6 +192,7 @@ export interface Upgrade<T = Record<string, any>> extends PackageDependency<T> { registryUrls?: string[] | null; currentVersion?: string; replaceString?: string; + replacementApproach?: 'replace' | 'alias'; } export interface ArtifactNotice {