|
1 | | -export default () => Promise.resolve(); |
| 1 | +import bluebird from 'bluebird'; |
| 2 | +import chalk from 'chalk'; |
| 3 | +import path from 'path'; |
| 4 | +import semver from 'semver'; |
| 5 | +import * as log from './lib/log'; |
| 6 | +import getFiles from './lib/get-files'; |
| 7 | +import writeJson from './lib/write-json'; |
| 8 | + |
| 9 | +const keys = (object = {}) => Object.keys(object); |
| 10 | +const clone = object => JSON.parse(JSON.stringify(object)); |
| 11 | +const concatAll = arrayOfArrays => [].concat.apply([], arrayOfArrays); |
| 12 | +const entries = object => keys(object).map(key => [key, object[key]]); |
| 13 | +const isEmptyObject = object => keys(object).length === 0; |
| 14 | +const pluck = key => object => object[key]; |
| 15 | + |
| 16 | +const stripWildCards = version => version.replace(/[*^=><]/g, ''); |
| 17 | +const getPackage = location => ({ location: location, json: require(location) }); |
| 18 | +const takeNewest = (max, next) => |
| 19 | + !semver.valid(stripWildCards(next)) || semver.gt(stripWildCards(next), stripWildCards(max)) |
| 20 | + ? next |
| 21 | + : max; |
| 22 | + |
| 23 | +const indexEntries = array => |
| 24 | + array.reduce((index, [key, value]) => { |
| 25 | + index[key] = index[key] || []; |
| 26 | + index[key] = index[key].indexOf(value) === -1 ? index[key].concat(value) : index[key]; |
| 27 | + return index; |
| 28 | + }, {}); |
| 29 | + |
| 30 | +const getNewestDeps = (key, packages) => { |
| 31 | + const dependencies = concatAll(packages.map(pluck('json')).map(pluck(key)).map(entries)); |
| 32 | + const versionsByDependencyName = indexEntries(dependencies); |
| 33 | + return entries(versionsByDependencyName).map(([name, versions]) => { |
| 34 | + const newest = versions.reduce(takeNewest, '0.0.0'); |
| 35 | + return [name, newest]; |
| 36 | + }); |
| 37 | +}; |
| 38 | + |
| 39 | +const getChangedDeps = (key, packages) => |
| 40 | + packages.map(pkg => |
| 41 | + getNewestDeps(key, packages).reduce((changes, [name, version]) => { |
| 42 | + if (pkg.json[key] && name in pkg.json[key] && pkg.json[key][name] !== version) { |
| 43 | + changes[name] = version; |
| 44 | + } |
| 45 | + return changes; |
| 46 | + }, {}) |
| 47 | + ); |
| 48 | + |
| 49 | +const reportChanges = (key, pkg, changes) => { |
| 50 | + const changedEntries = entries(changes); |
| 51 | + if (changedEntries.length) { |
| 52 | + changedEntries.forEach(([name, version]) => { |
| 53 | + console.log(`${key} ${name} ${chalk.red(pkg.json[key][name])} → ${chalk.green(version)}`); |
| 54 | + }); |
| 55 | + } else { |
| 56 | + console.log(`${key} ${chalk.green('✓ unchanged')}`); |
| 57 | + } |
| 58 | +}; |
| 59 | + |
| 60 | +export default async ({ pattern = './packages/*/package.json' }) => { |
| 61 | + const packages = (await getFiles(pattern)).map(getPackage); |
| 62 | + const changedDeps = getChangedDeps('dependencies', packages); |
| 63 | + const changedDevDeps = getChangedDeps('devDependencies', packages); |
| 64 | + const changedPeerDeps = getChangedDeps('peerDependencies', packages); |
| 65 | + |
| 66 | + const nextPackages = packages.map(({ location, json }, i) => { |
| 67 | + const nextPkg = { |
| 68 | + location, |
| 69 | + json: { |
| 70 | + ...json, |
| 71 | + dependencies: { ...json.dependencies, ...changedDeps[i] }, |
| 72 | + devDependencies: { ...json.devDependencies, ...changedDevDeps[i] }, |
| 73 | + peerDependencies: { ...json.peerDependencies, ...changedPeerDeps[i] } |
| 74 | + } |
| 75 | + }; |
| 76 | + if (isEmptyObject(nextPkg.json.dependencies)) { |
| 77 | + delete nextPkg.json.dependencies; |
| 78 | + } |
| 79 | + if (isEmptyObject(nextPkg.json.devDependencies)) { |
| 80 | + delete nextPkg.json.devDependencies; |
| 81 | + } |
| 82 | + if (isEmptyObject(nextPkg.json.peerDependencies)) { |
| 83 | + delete nextPkg.json.peerDependencies; |
| 84 | + } |
| 85 | + return nextPkg; |
| 86 | + }); |
| 87 | + |
| 88 | + packages.forEach((pkg, i) => { |
| 89 | + console.log(chalk.grey.underline(path.relative(process.cwd(), pkg.location))); |
| 90 | + reportChanges('dependencies', pkg, changedDeps[i]); |
| 91 | + reportChanges('devDependencies', pkg, changedDevDeps[i]); |
| 92 | + reportChanges('peerDependencies', pkg, changedPeerDeps[i]); |
| 93 | + }); |
| 94 | + |
| 95 | + await bluebird.all(nextPackages.map(pkg => writeJson(pkg.location, pkg.json))); |
| 96 | +}; |
0 commit comments