diff --git a/aio/tools/examples/shared/package.json b/aio/tools/examples/shared/package.json index 2a076d334c..2358b39a81 100644 --- a/aio/tools/examples/shared/package.json +++ b/aio/tools/examples/shared/package.json @@ -79,7 +79,7 @@ "rollup-plugin-uglify": "^1.0.1", "source-map-explorer": "^1.3.2", "style-loader": "^0.13.1", - "ts-node": "~3.0.4", + "ts-node": "^3.3.0", "tslint": "^3.15.1", "typescript": "~2.3.2", "webpack": "2.2.1", diff --git a/aio/tools/examples/shared/yarn.lock b/aio/tools/examples/shared/yarn.lock index a443dc2a91..9ec2a8870d 100644 --- a/aio/tools/examples/shared/yarn.lock +++ b/aio/tools/examples/shared/yarn.lock @@ -1390,6 +1390,14 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + chalk@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" @@ -2950,6 +2958,12 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" +homedir-polyfill@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" + dependencies: + parse-passwd "^1.0.0" + hosted-git-info@^2.1.4: version "2.4.2" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67" @@ -4383,6 +4397,10 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + parse5@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.2.tgz#05eff57f0ef4577fb144a79f8b9a967a6cc44510" @@ -6101,19 +6119,19 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" -ts-node@~3.0.4: - version "3.0.6" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-3.0.6.tgz#55127ff790c7eebf6ba68c1e6dde94b09aaa21e0" +ts-node@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-3.3.0.tgz#c13c6a3024e30be1180dd53038fc209289d4bf69" dependencies: arrify "^1.0.0" - chalk "^1.1.1" + chalk "^2.0.0" diff "^3.1.0" make-error "^1.1.1" minimist "^1.2.0" mkdirp "^0.5.1" source-map-support "^0.4.0" tsconfig "^6.0.0" - v8flags "^2.0.11" + v8flags "^3.0.0" yn "^2.0.0" tsconfig@^6.0.0: @@ -6341,12 +6359,18 @@ uuid@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" -v8flags@^2.0.10, v8flags@^2.0.11: +v8flags@^2.0.10: version "2.1.1" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" dependencies: user-home "^1.1.1" +v8flags@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.0.1.tgz#dce8fc379c17d9f2c9e9ed78d89ce00052b1b76b" + dependencies: + homedir-polyfill "^1.0.1" + validate-npm-package-license@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" diff --git a/aio/tools/ng-packages-installer/index.js b/aio/tools/ng-packages-installer/index.js index 454371c629..d6c5aca5cb 100644 --- a/aio/tools/ng-packages-installer/index.js +++ b/aio/tools/ng-packages-installer/index.js @@ -66,27 +66,59 @@ class NgPackagesInstaller { if (this._checkLocalMarker() !== true || this.force) { const pathToPackageConfig = path.resolve(this.projectDir, PACKAGE_JSON); const packages = this._getDistPackages(); - const packageConfigFile = fs.readFileSync(pathToPackageConfig); - const packageConfig = JSON.parse(packageConfigFile); - - const [dependencies, peers] = this._collectDependencies(packageConfig.dependencies || {}, packages); - const [devDependencies, devPeers] = this._collectDependencies(packageConfig.devDependencies || {}, packages); - - this._assignPeerDependencies(peers, dependencies, devDependencies); - this._assignPeerDependencies(devPeers, dependencies, devDependencies); - - const localPackageConfig = Object.assign(Object.create(null), packageConfig, { dependencies, devDependencies }); - localPackageConfig.__angular = { local: true }; - const localPackageConfigJson = JSON.stringify(localPackageConfig, null, 2); try { - this._log(`Writing temporary local ${PACKAGE_JSON} to ${pathToPackageConfig}`); - fs.writeFileSync(pathToPackageConfig, localPackageConfigJson); - this._installDeps('--no-lockfile', '--check-files'); - this._setLocalMarker(localPackageConfigJson); + // 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 to Angular packages with local files. + const deps = tmpConfig.dependencies || {}; + 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 packageConfig = JSON.parse(packageConfigFile); + + const [dependencies, peers] = this._collectDependencies(packageConfig.dependencies || {}, packages); + const [devDependencies, devPeers] = this._collectDependencies(packageConfig.devDependencies || {}, packages); + + this._assignPeerDependencies(peers, dependencies, devDependencies); + this._assignPeerDependencies(devPeers, dependencies, devDependencies); + + const localPackageConfig = Object.assign(Object.create(null), packageConfig, { dependencies, devDependencies }); + localPackageConfig.__angular = { local: true }; + const localPackageConfigJson = JSON.stringify(localPackageConfig, null, 2); + + try { + this._log(`Writing temporary local ${PACKAGE_JSON} to ${pathToPackageConfig}`); + fs.writeFileSync(pathToPackageConfig, localPackageConfigJson); + this._installDeps('--no-lockfile', '--check-files'); + this._setLocalMarker(localPackageConfigJson); + } finally { + this._log(`Restoring original ${PACKAGE_JSON} to ${pathToPackageConfig}`); + fs.writeFileSync(pathToPackageConfig, packageConfigFile); + } } finally { - this._log(`Restoring original ${PACKAGE_JSON} to ${pathToPackageConfig}`); - fs.writeFileSync(pathToPackageConfig, packageConfigFile); + // 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)); + }); } } } @@ -152,7 +184,11 @@ class NgPackagesInstaller { const packageName = `@angular/${packagePath.slice(0, -PACKAGE_JSON.length -1)}`; if (this.ignorePackages.indexOf(packageName) === -1) { 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 { this._log('Ignoring package', packageName); } diff --git a/aio/tools/ng-packages-installer/index.spec.js b/aio/tools/ng-packages-installer/index.spec.js index b5240f16fb..55ba1c5384 100644 --- a/aio/tools/ng-packages-installer/index.spec.js +++ b/aio/tools/ng-packages-installer/index.spec.js @@ -47,6 +47,7 @@ describe('NgPackagesInstaller', () => { }); describe('installLocalDependencies()', () => { + const copyJsonObj = obj => JSON.parse(JSON.stringify(obj)); let dummyNgPackages, dummyPackage, dummyPackageJson, expectedModifiedPackage, expectedModifiedPackageJson; beforeEach(() => { @@ -54,12 +55,36 @@ describe('NgPackagesInstaller', () => { // These are the packages that are "found" in the dist directory dummyNgPackages = { - '@angular/core': { parentDir: packagesDir, config: { peerDependencies: { rxjs: '5.0.1' } } }, - '@angular/common': { parentDir: packagesDir, config: { peerDependencies: { '@angular/core': '4.4.1' } } }, - '@angular/compiler': { parentDir: packagesDir, config: { } }, - '@angular/compiler-cli': { parentDir: toolsDir, config: { peerDependencies: { typescript: '^2.4.2', '@angular/compiler': '4.3.2' } } } + '@angular/core': { + parentDir: packagesDir, + packageJsonPath: `${packagesDir}/core/package.json`, + 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: { 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 dummyPackage = { @@ -118,6 +143,30 @@ describe('NgPackagesInstaller', () => { 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}))], + ]); + + expect(lastFiveArgs).toEqual(['core', 'common', 'compiler', 'compiler-cli', 'tsc-wrapped'] + .map(pkgName => [pkgJsonFor(pkgName), JSON.stringify(pkgConfigFor(pkgName))])); + }); + it('should load the package.json', () => { expect(fs.readFileSync).toHaveBeenCalledWith(packageJsonPath); }); @@ -157,6 +206,7 @@ describe('NgPackagesInstaller', () => { const ngPackages = installer._getDistPackages(); const expectedValue = jasmine.objectContaining({ parentDir: jasmine.any(String), + packageJsonPath: jasmine.any(String), config: jasmine.any(Object), });