build(aio): fix overwriting with local Angular packages that depend on other local ones (#19655)
PR Close #19655
This commit is contained in:
parent
62c7b7842b
commit
43f9d917d9
@ -65,6 +65,32 @@ class NgPackagesInstaller {
|
|||||||
if (this._checkLocalMarker() !== true || this.force) {
|
if (this._checkLocalMarker() !== true || this.force) {
|
||||||
const pathToPackageConfig = path.resolve(this.projectDir, PACKAGE_JSON);
|
const pathToPackageConfig = path.resolve(this.projectDir, PACKAGE_JSON);
|
||||||
const packages = this._getDistPackages();
|
const packages = this._getDistPackages();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Overwrite local Angular packages dependencies to other Angular packages with local files.
|
||||||
|
Object.keys(packages).forEach(key => {
|
||||||
|
const pkg = packages[key];
|
||||||
|
const tmpConfig = JSON.parse(JSON.stringify(pkg.config));
|
||||||
|
|
||||||
|
// Prevent accidental publishing of the package, if something goes wrong.
|
||||||
|
tmpConfig.private = true;
|
||||||
|
|
||||||
|
// Overwrite project dependencies/devDependencies to Angular packages with local files.
|
||||||
|
['dependencies', 'devDependencies'].forEach(prop => {
|
||||||
|
const deps = tmpConfig[prop] || {};
|
||||||
|
Object.keys(deps).forEach(key2 => {
|
||||||
|
const pkg2 = packages[key2];
|
||||||
|
if (pkg2) {
|
||||||
|
// point the core Angular packages at the distributable folder
|
||||||
|
deps[key2] = `file:${pkg2.parentDir}/${key2.replace('@angular/', '')}`;
|
||||||
|
this._log(`Overriding dependency of local ${key} with local package: ${key2}: ${deps[key2]}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync(pkg.packageJsonPath, JSON.stringify(tmpConfig));
|
||||||
|
});
|
||||||
|
|
||||||
const packageConfigFile = fs.readFileSync(pathToPackageConfig);
|
const packageConfigFile = fs.readFileSync(pathToPackageConfig);
|
||||||
const packageConfig = JSON.parse(packageConfigFile);
|
const packageConfig = JSON.parse(packageConfigFile);
|
||||||
|
|
||||||
@ -87,6 +113,14 @@ class NgPackagesInstaller {
|
|||||||
this._log(`Restoring original ${PACKAGE_JSON} to ${pathToPackageConfig}`);
|
this._log(`Restoring original ${PACKAGE_JSON} to ${pathToPackageConfig}`);
|
||||||
fs.writeFileSync(pathToPackageConfig, packageConfigFile);
|
fs.writeFileSync(pathToPackageConfig, packageConfigFile);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
// Restore local Angular packages dependencies to other Angular packages.
|
||||||
|
this._log(`Restoring original ${PACKAGE_JSON} for local Angular packages.`);
|
||||||
|
Object.keys(packages).forEach(key => {
|
||||||
|
const pkg = packages[key];
|
||||||
|
fs.writeFileSync(pkg.packageJsonPath, JSON.stringify(pkg.config));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +185,11 @@ class NgPackagesInstaller {
|
|||||||
const packageName = `@angular/${packagePath.slice(0, -PACKAGE_JSON.length -1)}`;
|
const packageName = `@angular/${packagePath.slice(0, -PACKAGE_JSON.length -1)}`;
|
||||||
if (this.ignorePackages.indexOf(packageName) === -1) {
|
if (this.ignorePackages.indexOf(packageName) === -1) {
|
||||||
const packageConfig = require(path.resolve(distDir, packagePath));
|
const packageConfig = require(path.resolve(distDir, packagePath));
|
||||||
packageConfigs[packageName] = {parentDir: distDir, config: packageConfig};
|
packageConfigs[packageName] = {
|
||||||
|
parentDir: distDir,
|
||||||
|
packageJsonPath: path.resolve(distDir, packagePath),
|
||||||
|
config: packageConfig
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
this._log('Ignoring package', packageName);
|
this._log('Ignoring package', packageName);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ describe('NgPackagesInstaller', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('installLocalDependencies()', () => {
|
describe('installLocalDependencies()', () => {
|
||||||
|
const copyJsonObj = obj => JSON.parse(JSON.stringify(obj));
|
||||||
let dummyNgPackages, dummyPackage, dummyPackageJson, expectedModifiedPackage, expectedModifiedPackageJson;
|
let dummyNgPackages, dummyPackage, dummyPackageJson, expectedModifiedPackage, expectedModifiedPackageJson;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -54,12 +55,39 @@ describe('NgPackagesInstaller', () => {
|
|||||||
|
|
||||||
// These are the packages that are "found" in the dist directory
|
// These are the packages that are "found" in the dist directory
|
||||||
dummyNgPackages = {
|
dummyNgPackages = {
|
||||||
'@angular/core': { parentDir: packagesDir, config: { peerDependencies: { rxjs: '5.0.1' } } },
|
'@angular/core': {
|
||||||
'@angular/common': { parentDir: packagesDir, config: { peerDependencies: { '@angular/core': '4.4.1' } } },
|
parentDir: packagesDir,
|
||||||
'@angular/compiler': { parentDir: packagesDir, config: { } },
|
packageJsonPath: `${packagesDir}/core/package.json`,
|
||||||
'@angular/compiler-cli': { parentDir: toolsDir, config: { peerDependencies: { typescript: '^2.4.2', '@angular/compiler': '4.3.2' } } }
|
config: { peerDependencies: { rxjs: '5.0.1' } }
|
||||||
|
},
|
||||||
|
'@angular/common': {
|
||||||
|
parentDir: packagesDir,
|
||||||
|
packageJsonPath: `${packagesDir}/common/package.json`,
|
||||||
|
config: { peerDependencies: { '@angular/core': '4.4.4-1ab23cd4' } }
|
||||||
|
},
|
||||||
|
'@angular/compiler': {
|
||||||
|
parentDir: packagesDir,
|
||||||
|
packageJsonPath: `${packagesDir}/compiler/package.json`,
|
||||||
|
config: { peerDependencies: { '@angular/common': '4.4.4-1ab23cd4' } }
|
||||||
|
},
|
||||||
|
'@angular/compiler-cli': {
|
||||||
|
parentDir: toolsDir,
|
||||||
|
packageJsonPath: `${toolsDir}/compiler-cli/package.json`,
|
||||||
|
config: {
|
||||||
|
dependencies: { '@angular/tsc-wrapped': '4.4.4-1ab23cd4' },
|
||||||
|
peerDependencies: { typescript: '^2.4.2', '@angular/compiler': '4.4.4-1ab23cd4' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'@angular/tsc-wrapped': {
|
||||||
|
parentDir: toolsDir,
|
||||||
|
packageJsonPath: `${toolsDir}/tsc-wrapped/package.json`,
|
||||||
|
config: {
|
||||||
|
devDependencies: { '@angular/common': '4.4.4-1ab23cd4' },
|
||||||
|
peerDependencies: { tsickle: '^1.4.0' }
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
spyOn(installer, '_getDistPackages').and.returnValue(dummyNgPackages);
|
spyOn(installer, '_getDistPackages').and.callFake(() => copyJsonObj(dummyNgPackages));
|
||||||
|
|
||||||
// This is the package.json in the "test" folder
|
// This is the package.json in the "test" folder
|
||||||
dummyPackage = {
|
dummyPackage = {
|
||||||
@ -118,6 +146,33 @@ describe('NgPackagesInstaller', () => {
|
|||||||
expect(installer._getDistPackages).toHaveBeenCalled();
|
expect(installer._getDistPackages).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should temporarily overwrite the package.json files of local Angular packages', () => {
|
||||||
|
const pkgJsonFor = pkgName => dummyNgPackages[`@angular/${pkgName}`].packageJsonPath;
|
||||||
|
const pkgConfigFor = pkgName => copyJsonObj(dummyNgPackages[`@angular/${pkgName}`].config);
|
||||||
|
const overwriteConfigFor = (pkgName, newProps) => Object.assign(pkgConfigFor(pkgName), newProps);
|
||||||
|
|
||||||
|
const allArgs = fs.writeFileSync.calls.allArgs();
|
||||||
|
const firstFiveArgs = allArgs.slice(0, 5);
|
||||||
|
const lastFiveArgs = allArgs.slice(-5);
|
||||||
|
|
||||||
|
expect(firstFiveArgs).toEqual([
|
||||||
|
[pkgJsonFor('core'), JSON.stringify(overwriteConfigFor('core', {private: true}))],
|
||||||
|
[pkgJsonFor('common'), JSON.stringify(overwriteConfigFor('common', {private: true}))],
|
||||||
|
[pkgJsonFor('compiler'), JSON.stringify(overwriteConfigFor('compiler', {private: true}))],
|
||||||
|
[pkgJsonFor('compiler-cli'), JSON.stringify(overwriteConfigFor('compiler-cli', {
|
||||||
|
private: true,
|
||||||
|
dependencies: { '@angular/tsc-wrapped': `file:${toolsDir}/tsc-wrapped` }
|
||||||
|
}))],
|
||||||
|
[pkgJsonFor('tsc-wrapped'), JSON.stringify(overwriteConfigFor('tsc-wrapped', {
|
||||||
|
private: true,
|
||||||
|
devDependencies: { '@angular/common': `file:${packagesDir}/common` }
|
||||||
|
}))],
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(lastFiveArgs).toEqual(['core', 'common', 'compiler', 'compiler-cli', 'tsc-wrapped']
|
||||||
|
.map(pkgName => [pkgJsonFor(pkgName), JSON.stringify(pkgConfigFor(pkgName))]));
|
||||||
|
});
|
||||||
|
|
||||||
it('should load the package.json', () => {
|
it('should load the package.json', () => {
|
||||||
expect(fs.readFileSync).toHaveBeenCalledWith(packageJsonPath);
|
expect(fs.readFileSync).toHaveBeenCalledWith(packageJsonPath);
|
||||||
});
|
});
|
||||||
@ -152,11 +207,12 @@ describe('NgPackagesInstaller', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('_getDistPackages', () => {
|
describe('_getDistPackages()', () => {
|
||||||
it('should include top level Angular packages', () => {
|
it('should include top level Angular packages', () => {
|
||||||
const ngPackages = installer._getDistPackages();
|
const ngPackages = installer._getDistPackages();
|
||||||
const expectedValue = jasmine.objectContaining({
|
const expectedValue = jasmine.objectContaining({
|
||||||
parentDir: jasmine.any(String),
|
parentDir: jasmine.any(String),
|
||||||
|
packageJsonPath: jasmine.any(String),
|
||||||
config: jasmine.any(Object),
|
config: jasmine.any(Object),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -208,7 +264,7 @@ describe('NgPackagesInstaller', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('_printWarning', () => {
|
describe('_printWarning()', () => {
|
||||||
it('should mention the message passed in the warning', () => {
|
it('should mention the message passed in the warning', () => {
|
||||||
installer._printWarning();
|
installer._printWarning();
|
||||||
expect(console.warn.calls.argsFor(0)[0]).toContain('is running against the local Angular build');
|
expect(console.warn.calls.argsFor(0)[0]).toContain('is running against the local Angular build');
|
||||||
@ -231,7 +287,7 @@ describe('NgPackagesInstaller', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('_installDeps', () => {
|
describe('_installDeps()', () => {
|
||||||
it('should run yarn install with the given options', () => {
|
it('should run yarn install with the given options', () => {
|
||||||
installer._installDeps('option-1', 'option-2');
|
installer._installDeps('option-1', 'option-2');
|
||||||
expect(shelljs.exec).toHaveBeenCalledWith('yarn install option-1 option-2', { cwd: absoluteRootDir });
|
expect(shelljs.exec).toHaveBeenCalledWith('yarn install option-1 option-2', { cwd: absoluteRootDir });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user