diff --git a/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyAddition.test.ts b/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyAddition.test.ts index fa89080889..ae575a8b02 100644 --- a/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyAddition.test.ts +++ b/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyAddition.test.ts @@ -20,12 +20,28 @@ import { Workspace, } from '@yarnpkg/core'; import { suggestUtils } from '@yarnpkg/plugin-essentials'; +import { getPackageVersion } from '../util'; import { afterWorkspaceDependencyAddition } from './afterWorkspaceDependencyAddition'; +jest.mock('../util', () => ({ + getPackageVersion: jest.fn(), +})); + describe('afterWorkspaceDependencyAddition', () => { - const workspace = {} as Workspace; + const workspace = { + project: { + configuration: {}, + }, + } as Workspace; const target = {} as suggestUtils.Target; const strategies: Array = []; + const mockGetPackageVersion = getPackageVersion as jest.MockedFunction< + typeof getPackageVersion + >; + + beforeEach(() => { + mockGetPackageVersion.mockReset(); + }); it('should replace the range for a backstage scoped dependency', async () => { const input: Descriptor = { @@ -36,6 +52,8 @@ describe('afterWorkspaceDependencyAddition', () => { identHash: {} as IdentHash, }; + mockGetPackageVersion.mockImplementation(() => Promise.resolve('success')); + await afterWorkspaceDependencyAddition( workspace, target, @@ -44,6 +62,39 @@ describe('afterWorkspaceDependencyAddition', () => { ); expect(input.range).toBe('backstage:^'); + expect(mockGetPackageVersion).toHaveBeenCalledTimes(1); + expect(mockGetPackageVersion).toHaveBeenCalledWith( + input, + workspace.project.configuration, + ); + }); + + it('should not replace the range for a backstage scoped dependency where it cant find a version from remote', async () => { + const input: Descriptor = { + scope: 'backstage', + name: 'test-package', + range: '^1.0.0', + descriptorHash: {} as DescriptorHash, + identHash: {} as IdentHash, + }; + + mockGetPackageVersion.mockImplementation(() => + Promise.reject(new Error('test error')), + ); + + await afterWorkspaceDependencyAddition( + workspace, + target, + input, + strategies, + ); + + expect(input.range).toBe('^1.0.0'); + expect(mockGetPackageVersion).toHaveBeenCalledTimes(1); + expect(mockGetPackageVersion).toHaveBeenCalledWith( + input, + workspace.project.configuration, + ); }); it('should not replace the range for a non-backstage scoped dependency', async () => { @@ -63,5 +114,6 @@ describe('afterWorkspaceDependencyAddition', () => { ); expect(input.range).toBe('^1.0.0'); + expect(mockGetPackageVersion).not.toHaveBeenCalled(); }); }); diff --git a/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyAddition.ts b/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyAddition.ts index 8e39b1c759..9307790930 100644 --- a/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyAddition.ts +++ b/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyAddition.ts @@ -14,20 +14,34 @@ * limitations under the License. */ -import { Descriptor, Workspace } from '@yarnpkg/core'; +import { Descriptor, structUtils, Workspace } from '@yarnpkg/core'; import { suggestUtils } from '@yarnpkg/plugin-essentials'; +import { getPackageVersion } from '../util'; +import { PROTOCOL } from '../constants'; export const afterWorkspaceDependencyAddition = async ( - _workspace: Workspace, + workspace: Workspace, _target: suggestUtils.Target, descriptor: Descriptor, _strategies: Array, ) => { - if (descriptor.scope === 'backstage' && descriptor.range !== 'backstage:^') { - // is there a better way to log than console.log? - console.log( - `afterWorkspaceDependencyAddition hook: Setting descriptor range from ${descriptor.range} to 'backstage:^' for ${descriptor.scope}/${descriptor.name}`, - ); - descriptor.range = 'backstage:^'; + const descriptorRange = structUtils.parseRange(descriptor.range); + + if ( + descriptor.scope === 'backstage' && + descriptorRange.protocol !== PROTOCOL + ) { + try { + await getPackageVersion(descriptor, workspace.project.configuration); + // is there a better way to log than console.log? + console.log( + `afterWorkspaceDependencyAddition hook: Setting descriptor range from ${descriptor.range} to 'backstage:^' for ${descriptor.scope}/${descriptor.name}`, + ); + descriptor.range = `${PROTOCOL}^`; + } catch (_error: any) { + // if there's no found version then this is likely a deprecated package + // or otherwise the plugin won't be able to resolve the real version + // and we should leave the desired range as is + } } }; diff --git a/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyReplacement.test.ts b/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyReplacement.test.ts index eef3f25f97..7bf9c77554 100644 --- a/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyReplacement.test.ts +++ b/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyReplacement.test.ts @@ -20,11 +20,27 @@ import { Workspace, } from '@yarnpkg/core'; import { suggestUtils } from '@yarnpkg/plugin-essentials'; +import { getPackageVersion } from '../util'; import { afterWorkspaceDependencyReplacement } from './afterWorkspaceDependencyReplacement'; +jest.mock('../util', () => ({ + getPackageVersion: jest.fn(), +})); + describe('afterWorkspaceDependencyReplacement.test', () => { - const workspace = {} as Workspace; + const workspace = { + project: { + configuration: {}, + }, + } as Workspace; const target = {} as suggestUtils.Target; + const mockGetPackageVersion = getPackageVersion as jest.MockedFunction< + typeof getPackageVersion + >; + + beforeEach(() => { + mockGetPackageVersion.mockReset(); + }); it('should warn that the range is being changed for a backstage scoped dependency', async () => { const fromDescriptor: Descriptor = { @@ -41,6 +57,9 @@ describe('afterWorkspaceDependencyReplacement.test', () => { descriptorHash: {} as DescriptorHash, identHash: {} as IdentHash, }; + + mockGetPackageVersion.mockImplementation(() => Promise.resolve('success')); + await afterWorkspaceDependencyReplacement( workspace, target, @@ -49,7 +68,48 @@ describe('afterWorkspaceDependencyReplacement.test', () => { ); expect(toDescriptor.range).toBe('^1.0.0'); + expect(mockGetPackageVersion).toHaveBeenCalledTimes(1); + expect(mockGetPackageVersion).toHaveBeenCalledWith( + toDescriptor, + workspace.project.configuration, + ); }); + + it('should not warn that the range is being changed for a backstage scoped dependency where it cant find a version from remote', async () => { + const fromDescriptor: Descriptor = { + scope: 'backstage', + name: 'test-package', + range: 'backstage:^', + descriptorHash: {} as DescriptorHash, + identHash: {} as IdentHash, + }; + const toDescriptor: Descriptor = { + scope: 'backstage', + name: 'test-package', + range: '^1.0.0', + descriptorHash: {} as DescriptorHash, + identHash: {} as IdentHash, + }; + + mockGetPackageVersion.mockImplementation(() => + Promise.reject(new Error('test error')), + ); + + await afterWorkspaceDependencyReplacement( + workspace, + target, + fromDescriptor, + toDescriptor, + ); + + expect(toDescriptor.range).toBe('^1.0.0'); + expect(mockGetPackageVersion).toHaveBeenCalledTimes(1); + expect(mockGetPackageVersion).toHaveBeenCalledWith( + toDescriptor, + workspace.project.configuration, + ); + }); + it('should ignore that the range is being changed for a non-backstage scoped dependency', async () => { const fromDescriptor: Descriptor = { scope: 'backstage-community', @@ -73,5 +133,6 @@ describe('afterWorkspaceDependencyReplacement.test', () => { ); expect(toDescriptor.range).toBe('^1.0.0'); + expect(mockGetPackageVersion).not.toHaveBeenCalled(); }); }); diff --git a/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyReplacement.ts b/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyReplacement.ts index b8141c8bb3..a955191244 100644 --- a/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyReplacement.ts +++ b/packages/yarn-plugin/src/handlers/afterWorkspaceDependencyReplacement.ts @@ -14,22 +14,33 @@ * limitations under the License. */ -import { Descriptor, Workspace } from '@yarnpkg/core'; +import { Descriptor, structUtils, Workspace } from '@yarnpkg/core'; import { suggestUtils } from '@yarnpkg/plugin-essentials'; +import { getPackageVersion } from '../util'; +import { PROTOCOL } from '../constants'; export const afterWorkspaceDependencyReplacement = async ( - _workspace: Workspace, + workspace: Workspace, _target: suggestUtils.Target, fromDescriptor: Descriptor, toDescriptor: Descriptor, ) => { + const toDescriptorRange = structUtils.parseRange(toDescriptor.range); + if ( toDescriptor.scope === 'backstage' && - toDescriptor.range !== 'backstage:^' + toDescriptorRange.protocol !== PROTOCOL ) { - // is there a better way to log than console.log? - console.log( - `afterWorkspaceDependencyReplacement hook: Setting descriptor range from '${fromDescriptor.range}' to '${toDescriptor.range}' for ${fromDescriptor.scope}/${fromDescriptor.name}. Are you sure you want to be doing that?`, - ); + try { + await getPackageVersion(toDescriptor, workspace.project.configuration); + // is there a better way to log than console.log? + console.log( + `afterWorkspaceDependencyReplacement hook: Setting descriptor range from '${fromDescriptor.range}' to '${toDescriptor.range}' for ${fromDescriptor.scope}/${fromDescriptor.name}. Are you sure you want to be doing that?`, + ); + } catch (_error: any) { + // if there's no found version then this is likely a deprecated package + // or otherwise the plugin won't be able to resolve the real version + // and we should not warn them. + } } };