diff --git a/aio/tools/examples/UPDATING.md b/aio/tools/examples/UPDATING.md index 773d59f230..65c7f1d6e8 100644 --- a/aio/tools/examples/UPDATING.md +++ b/aio/tools/examples/UPDATING.md @@ -9,7 +9,7 @@ Follow these steps to update the examples to the latest versions of Angular (and - In the [shared/](./shared) folder, run `yarn` to update the dependencies in the [shared/node_modules/](./shared/node_modules) folder and the [shared/yarn.lock](./shared/yarn.lock) file. -- In the [shared/boilerplate/](./shared/boilerplate) folder, go through each sub-folder and update the dependency versions in all `package.json` files to match the ones in [shared/package.json](./shared/package.json). +- In the [shared/](./shared) folder, run `yarn sync-deps` to update the dependency versions of the `package.json` files in each sub-folder of [shared/boilerplate/](./shared/boilerplate) to match the ones in [shared/package.json](./shared/package.json). - Follow the steps in the following section to update the rest of the boilerplate files. diff --git a/aio/tools/examples/shared/package.json b/aio/tools/examples/shared/package.json index a10fba42c3..ddc2cf3672 100644 --- a/aio/tools/examples/shared/package.json +++ b/aio/tools/examples/shared/package.json @@ -8,7 +8,8 @@ "protractor": "protractor", "webdriver:update": "node ../../../../scripts/webdriver-manager-update.js", "preinstall": "node ../../../../tools/yarn/check-yarn.js", - "postinstall": "yarn webdriver:update" + "postinstall": "yarn webdriver:update", + "sync-deps": "node sync-boilerplate-dependencies" }, "//engines-comment": "Keep this in sync with /package.json and /aio/package.json", "engines": { diff --git a/aio/tools/examples/shared/sync-boilerplate-dependencies.js b/aio/tools/examples/shared/sync-boilerplate-dependencies.js new file mode 100644 index 0000000000..439c627fe9 --- /dev/null +++ b/aio/tools/examples/shared/sync-boilerplate-dependencies.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node + +/** + * Usage: + * ```sh + * node sync-boilerplate-dependencies + * ``` + * + * Updates the dependency versions of the top-level `package.json` files in each sub-folder of + * `./boilerplate/` and `./boilerplate/viewengine/` to match the ones in `./package.json`. + */ +const fs = require('fs'); +const path = require('path'); + + +const BOILERPLATE_DIR = `${__dirname}/boilerplate`; +const VIEWENGINE_DIR = `${BOILERPLATE_DIR}/viewengine`; +const SHARED_PACKAGE_JSON_PATH = `${__dirname}/package.json`; + +const sharedPkgJson = loadJsonFile(SHARED_PACKAGE_JSON_PATH); +const boilerplatePkgJsonPaths = [ + ...collectPackageJsonFiles(BOILERPLATE_DIR), + ...collectPackageJsonFiles(VIEWENGINE_DIR), +]; + +boilerplatePkgJsonPaths.forEach(syncDependencies); + +// Helpers +function collectPackageJsonFiles(dirPath) { + return fs.readdirSync(dirPath) + .map(childName => `${dirPath}/${childName}`) + .filter(childPath => fs.statSync(childPath).isDirectory()) + .map(subDirPath => `${subDirPath}/package.json`) + .filter(pkgJsonPath => fs.existsSync(pkgJsonPath)); +} + +function loadJsonFile(filePath) { + return JSON.parse(fs.readFileSync(filePath, 'utf8')); +} + +function syncDependencies(boilerplatePkgJsonPath) { + console.log(`Syncing '${path.relative(__dirname, boilerplatePkgJsonPath)}'...`); + + const boilerplatePkgJson = loadJsonFile(boilerplatePkgJsonPath); + + ['dependencies', 'devDependencies', 'peerDependencies'] + .filter(depsProp => boilerplatePkgJson.hasOwnProperty(depsProp)) + .forEach(depsProp => { + const srcDeps = sharedPkgJson[depsProp]; + const dstDeps = boilerplatePkgJson[depsProp]; + + for (const dep of Object.keys(dstDeps)) { + if (!srcDeps.hasOwnProperty(dep)) { + throw new Error( + `Unable to update dependency '${dep}' in '${boilerplatePkgJsonPath} > ${depsProp}'. ` + + `The dependency is missing from '${SHARED_PACKAGE_JSON_PATH}'.`); + } + + dstDeps[dep] = srcDeps[dep]; + } + }); + + fs.writeFileSync(boilerplatePkgJsonPath, `${JSON.stringify(boilerplatePkgJson, null, 2)}\n`); +}