diff --git a/bin/rebuild-package-locks.js b/bin/rebuild-package-locks.js index c13942da9528..8a986c5d473b 100755 --- a/bin/rebuild-package-locks.js +++ b/bin/rebuild-package-locks.js @@ -13,47 +13,69 @@ const path = require('path'); const fs = require('fs-extra'); const Project = require('@lerna/project'); +const filterPackages = require('@lerna/filter-packages'); const build = require('../packages/build'); /** * Remove all package-lock.json and node_modules for all packages * @param {Project} project The lerna project + * @param {string[]} scopes A list of package names to be included */ -async function removePackageLocks(project) { +async function removePackageLocks(project, ...scopes) { const packages = await project.getPackages(); const rootPath = project.rootPath; const pkgRoots = []; - for (const pkg of packages) { + const matchedPackages = filterPackages(packages, scopes, [], true, true); + if (matchedPackages.length === 0) return; + for (const pkg of matchedPackages) { pkgRoots.push(pkg.location); } - pkgRoots.push(rootPath); + // Only clean the monorepo root package if no scopes is provided + if (scopes.length === 0) pkgRoots.push(rootPath); console.log('Cleaning package-lock.json and node_modules...'); await Promise.all( pkgRoots.map(async root => { + console.log(' - %s', path.relative(rootPath, root)); await fs.remove(path.join(root, 'package-lock.json')); await fs.remove(path.join(root, 'node_modules')); }), ); + return pkgRoots; } /** * Rebuild package-lock.json files: * - * 1. Remove node_modules and package-lock.json for all packages, including the - * root one - * 2. Run `npm install` to regenerate package-lock.json files + * 1. Remove node_modules and package-lock.json for matching packages, + * including the root one if no scopes is specified + * 2. Run `npx lerna bootstrap or npm install` to regenerate package-lock.json + * files + * + * @param {string[]} scopes - Optional lerna scopes to filter packages */ -async function rebuildPackageLocks() { +async function rebuildPackageLocks(...scopes) { const project = new Project(process.cwd()); - await removePackageLocks(project); - console.log('Running npm install...'); - build.runShell('npm', ['install'], {cwd: project.rootPth}); + const removed = await removePackageLocks(project, ...scopes); + if (removed.length === 0) return; + if (scopes.length) { + const args = []; + scopes.forEach(s => args.push('--scope', s)); + + console.log(`Running lerna bootstrap ${args.join(' ')}...`); + build.runShell('npx', ['lerna', 'bootstrap', ...args], { + cwd: project.rootPth, + }); + } else { + console.log('Running npm install...'); + build.runShell('npm', ['install'], {cwd: project.rootPth}); + } } if (require.main === module) { - rebuildPackageLocks().catch(err => { + const args = process.argv.slice(2); + rebuildPackageLocks(...args).catch(err => { console.error(err); process.exit(1); }); diff --git a/bin/update-peer-deps.js b/bin/update-peer-deps.js new file mode 100755 index 000000000000..09bbe97c7480 --- /dev/null +++ b/bin/update-peer-deps.js @@ -0,0 +1,66 @@ +#!/usr/bin/env node +// Copyright IBM Corp. 2017,2018. All Rights Reserved. +// Node module: loopback-next +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +/** + * This is an internal script to update peer dependencies based on released + * LoopBack package versions. + */ +'use strict'; + +const fs = require('fs'); + +const Project = require('@lerna/project'); + +async function updatePeerDeps() { + // List all packages within the monorepo + const project = new Project(process.cwd()); + const packages = await project.getPackages(); + + // Build a map of module name/version pairs + const lbModuleVersions = {}; + for (const p of packages) { + lbModuleVersions[p.name] = p.version; + } + + for (const p of packages) { + // Load package.json + const pkgJsonFile = p.manifestLocation; + const pkgJson = require(pkgJsonFile); + let updated = false; + if (pkgJson.peerDependencies) { + // Check all entries in peerDependencies + for (const d in pkgJson.peerDependencies) { + const pkgVersion = lbModuleVersions[d]; + if (pkgVersion) { + // Update the version range to be `^` + // We choose to be conservative as only this version has been verified + // by CI + pkgJson.peerDependencies[d] = `^${pkgVersion}`; + updated = true; + } + } + } + if (!updated) continue; + + // Convert to JSON + const json = JSON.stringify(pkgJson, null, 2); + if (process.argv[2] === '-f') { + // Using `-f` to overwrite package.json + fs.writeFileSync(pkgJsonFile, json + '\n', {encoding: 'utf-8'}); + console.log('%s has been updated.', pkgJsonFile); + } else { + // Otherwise write to console + console.log('%s\n', pkgJsonFile, json); + } + } +} + +if (require.main === module) { + updatePeerDeps().catch(err => { + console.error(err); + process.exit(1); + }); +} diff --git a/package.json b/package.json index d79abd3ddab4..647599f84397 100644 --- a/package.json +++ b/package.json @@ -36,9 +36,10 @@ "release": "lerna version && lerna publish from-git --yes", "update-package-locks": "node bin/rebuild-package-locks", "update-template-deps": "node bin/update-template-deps -f", + "update-peer-deps": "node bin/update-peer-deps -f", "update-all-deps": "npm update && lerna exec -- npm update && npm run update-package-locks", "sync-dev-deps": "node bin/sync-dev-deps", - "version": "npm run update-template-deps && npm run update-package-locks && git add \"**/package-lock.json\" package-lock.json", + "version": "npm run update-template-deps && npm run update-peer-deps", "outdated": "npm outdated --depth 0 && lerna exec --no-bail \"npm outdated --depth 0\"", "tsdocs": "lerna run --scope @loopback/tsdocs build:tsdocs", "coverage:ci": "node packages/build/bin/run-nyc report --reporter=text-lcov | coveralls", @@ -54,7 +55,7 @@ "clean": "lerna run clean && node packages/build/bin/run-clean \"packages/*/dist\" \"extensions/*/dist\" \"examples/*/dist\" \"benchmark/dist\"", "clean:lerna": "lerna clean", "build": "node bin/run-lerna run build --sort", - "build:full": "lerna clean && node packages/build/bin/run-clean \"node_modules\" && npm install && npm run clean && npm run build", + "build:full": "npm ci --ignore-scripts && lerna bootstrap --ci && npm run clean && npm run build", "pretest": "npm run clean && npm run build", "test": "node packages/build/bin/run-nyc npm run mocha --scripts-prepend-node-path", "test:ci": "node packages/build/bin/run-nyc npm run mocha --scripts-prepend-node-path",