fix(ngcc): allow ngcc configuration to match pre-release versions of packages (#36370)
Ngcc supports providing a project-level configuration to affect how certain dependencies are processed and also has a built-in fallback configuration for some unmaintained packages. Each entry in these configurations could be scoped to specific versions of a package by providing a version range. If no version range is provided for a package, it defaults to `*` (with the intention of matching any version). Previously, the installed version of a package was tested against the version range using the [semver][1] package's `satisfies()` function with the default options. By default, `satisfies()` does not match pre-releases (see [here][2] for more details on reasoning). While this makes sense when determining what version of a dependency to install (trying to avoid unexpected breaking changes), it is not desired in the case of ngcc. This commit fixes it by explicitly specifying that pre-release versions should be matched normally. [1]: https://www.npmjs.com/package/semver [2]: https://github.com/npm/node-semver#prerelease-tags PR Close #36370
This commit is contained in:
parent
b59bc0e38c
commit
326240eb91
|
@ -304,5 +304,7 @@ function findSatisfactoryVersion(
|
||||||
// So just return the first config that matches the package name.
|
// So just return the first config that matches the package name.
|
||||||
return configs[0];
|
return configs[0];
|
||||||
}
|
}
|
||||||
return configs.find(config => satisfies(version, config.versionRange)) || null;
|
return configs.find(
|
||||||
|
config => satisfies(version, config.versionRange, {includePrerelease: true})) ||
|
||||||
|
null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,114 @@ runInEachFileSystem(() => {
|
||||||
.toEqual({versionRange: '*', entryPoints: {}});
|
.toEqual({versionRange: '*', entryPoints: {}});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should correctly handle pre-release versions and version ranges', () => {
|
||||||
|
loadTestFiles([
|
||||||
|
{
|
||||||
|
name: _Abs('/project-1/ngcc.config.js'),
|
||||||
|
contents: `
|
||||||
|
module.exports = {
|
||||||
|
packages: {
|
||||||
|
'package-1': {
|
||||||
|
entryPoints: {
|
||||||
|
'./entry-point-1': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'package-2@1.0.0-beta.2': {
|
||||||
|
entryPoints: {
|
||||||
|
'./entry-point-2': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'package-3@>=1.0.0-beta.2': {
|
||||||
|
entryPoints: {
|
||||||
|
'./entry-point-3': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const configuration = new NgccConfiguration(fs, _Abs('/project-1'));
|
||||||
|
const getConfig = (packageName: string, version: string | null) =>
|
||||||
|
configuration.getConfig(_Abs(`/project-1/node_modules/${packageName}`), version);
|
||||||
|
|
||||||
|
// Default version range: *
|
||||||
|
expect(getConfig('package-1', '1.0.0-beta.2'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '*',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-1/entry-point-1')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-1@1.0.0-beta.2');
|
||||||
|
|
||||||
|
// Version range: 1.0.0-beta.2
|
||||||
|
expect(getConfig('package-2', '1.0.0-beta.2'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-2/entry-point-2')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-2@1.0.0-beta.2');
|
||||||
|
|
||||||
|
expect(getConfig('package-2', '1.0.0'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '*',
|
||||||
|
entryPoints: {},
|
||||||
|
},
|
||||||
|
'Config for package-2@1.0.0');
|
||||||
|
|
||||||
|
expect(getConfig('package-2', null))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-2/entry-point-2')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-2@null');
|
||||||
|
|
||||||
|
// Version range: >=1.0.0-beta.2
|
||||||
|
expect(getConfig('package-3', '1.0.0-beta.2'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '>=1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-3/entry-point-3')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-3@1.0.0-beta.2');
|
||||||
|
|
||||||
|
expect(getConfig('package-3', '1.0.0'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '>=1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-3/entry-point-3')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-3@1.0.0');
|
||||||
|
|
||||||
|
expect(getConfig('package-3', '2.0.0'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '>=1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-3/entry-point-3')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-3@2.0.0');
|
||||||
|
|
||||||
|
expect(getConfig('package-3', '1.0.0-beta.1'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '*',
|
||||||
|
entryPoints: {},
|
||||||
|
},
|
||||||
|
'Config for package-3@1.0.0-beta.1');
|
||||||
|
|
||||||
|
expect(getConfig('package-3', '0.9.99'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '*',
|
||||||
|
entryPoints: {},
|
||||||
|
},
|
||||||
|
'Config for package-3@0.9.99');
|
||||||
|
});
|
||||||
|
|
||||||
it('should not get confused by the @ in namespaced packages', () => {
|
it('should not get confused by the @ in namespaced packages', () => {
|
||||||
loadTestFiles([{
|
loadTestFiles([{
|
||||||
name: _Abs('/project-1/ngcc.config.js'),
|
name: _Abs('/project-1/ngcc.config.js'),
|
||||||
|
@ -287,13 +395,13 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('at the default level', () => {
|
describe('at the default level', () => {
|
||||||
const originalDefaultConfig = DEFAULT_NGCC_CONFIG.packages['package-1'];
|
const originalDefaultConfig = JSON.stringify(DEFAULT_NGCC_CONFIG.packages);
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
DEFAULT_NGCC_CONFIG.packages['package-1'] = {
|
DEFAULT_NGCC_CONFIG.packages['package-1'] = {
|
||||||
entryPoints: {'./default-level-entry-point': {}},
|
entryPoints: {'./default-level-entry-point': {}},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
afterEach(() => { DEFAULT_NGCC_CONFIG.packages['package-1'] = originalDefaultConfig; });
|
afterEach(() => DEFAULT_NGCC_CONFIG.packages = JSON.parse(originalDefaultConfig));
|
||||||
|
|
||||||
it('should return configuration for a package found in the default config', () => {
|
it('should return configuration for a package found in the default config', () => {
|
||||||
const readFileSpy = spyOn(fs, 'readFile').and.callThrough();
|
const readFileSpy = spyOn(fs, 'readFile').and.callThrough();
|
||||||
|
@ -361,6 +469,105 @@ runInEachFileSystem(() => {
|
||||||
{[_Abs('/project-1/node_modules/package-1/project-level-entry-point')]: {}}
|
{[_Abs('/project-1/node_modules/package-1/project-level-entry-point')]: {}}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should correctly handle pre-release versions and version ranges', () => {
|
||||||
|
Object.assign(DEFAULT_NGCC_CONFIG.packages, {
|
||||||
|
'package-1': {
|
||||||
|
entryPoints: {
|
||||||
|
'./entry-point-1': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'package-2@1.0.0-beta.2': {
|
||||||
|
entryPoints: {
|
||||||
|
'./entry-point-2': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'package-3@>=1.0.0-beta.2': {
|
||||||
|
entryPoints: {
|
||||||
|
'./entry-point-3': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const configuration = new NgccConfiguration(fs, _Abs('/project-1'));
|
||||||
|
const getConfig = (packageName: string, version: string | null) =>
|
||||||
|
configuration.getConfig(_Abs(`/project-1/node_modules/${packageName}`), version);
|
||||||
|
|
||||||
|
// Default version range: *
|
||||||
|
expect(getConfig('package-1', '1.0.0-beta.2'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '*',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-1/entry-point-1')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-1@1.0.0-beta.2');
|
||||||
|
|
||||||
|
// Version range: 1.0.0-beta.2
|
||||||
|
expect(getConfig('package-2', '1.0.0-beta.2'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-2/entry-point-2')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-2@1.0.0-beta.2');
|
||||||
|
|
||||||
|
expect(getConfig('package-2', '1.0.0'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '*',
|
||||||
|
entryPoints: {},
|
||||||
|
},
|
||||||
|
'Config for package-2@1.0.0');
|
||||||
|
|
||||||
|
expect(getConfig('package-2', null))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-2/entry-point-2')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-2@null');
|
||||||
|
|
||||||
|
// Version range: >=1.0.0-beta.2
|
||||||
|
expect(getConfig('package-3', '1.0.0-beta.2'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '>=1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-3/entry-point-3')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-3@1.0.0-beta.2');
|
||||||
|
|
||||||
|
expect(getConfig('package-3', '1.0.0'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '>=1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-3/entry-point-3')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-3@1.0.0');
|
||||||
|
|
||||||
|
expect(getConfig('package-3', '2.0.0'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '>=1.0.0-beta.2',
|
||||||
|
entryPoints: {[_Abs('/project-1/node_modules/package-3/entry-point-3')]: {}},
|
||||||
|
},
|
||||||
|
'Config for package-3@2.0.0');
|
||||||
|
|
||||||
|
expect(getConfig('package-3', '1.0.0-beta.1'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '*',
|
||||||
|
entryPoints: {},
|
||||||
|
},
|
||||||
|
'Config for package-3@1.0.0-beta.1');
|
||||||
|
|
||||||
|
expect(getConfig('package-3', '0.9.99'))
|
||||||
|
.toEqual(
|
||||||
|
{
|
||||||
|
versionRange: '*',
|
||||||
|
entryPoints: {},
|
||||||
|
},
|
||||||
|
'Config for package-3@0.9.99');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue