Skip to content

Commit b51a2c9

Browse files
committed
feat(cli): add copy-values command
1 parent cebae99 commit b51a2c9

9 files changed

Lines changed: 184 additions & 34 deletions

File tree

README.md

Lines changed: 98 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,57 @@
44
[![NPM downloads](http://img.shields.io/npm/dm/syncpack.svg?style=flat-square)](https://www.npmjs.com/package/syncpack)
55
[![Build Status](http://img.shields.io/travis/JamieMason/syncpack/master.svg?style=flat-square)](https://travis-ci.org/JamieMason/syncpack)
66
[![Dependency Status](http://img.shields.io/david/JamieMason/syncpack.svg?style=flat-square)](https://david-dm.org/JamieMason/syncpack)
7+
[![Code Climate](https://img.shields.io/codeclimate/github/JamieMason/syncpack.svg?style=flat-square)](https://codeclimate.com/github/JamieMason/syncpack)
78
[![Join the chat at https://gitter.im/JamieMason/syncpack](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/JamieMason/syncpack)
89
[![Analytics](https://ga-beacon.appspot.com/UA-45466560-5/syncpack?flat&useReferer)](https://github.com/igrigorik/ga-beacon)
10+
<br>
11+
[![Donate via Gratipay](https://img.shields.io/gratipay/user/JamieMason.svg)](https://gratipay.com/~JamieMason/)
12+
[![Follow JamieMason on GitHub](https://img.shields.io/github/followers/JamieMason.svg?style=social&label=Follow)](https://github.com/JamieMason)
13+
[![Follow fold_left on Twitter](https://img.shields.io/twitter/follow/fold_left.svg?style=social&label=Follow)](https://twitter.com/fold_left)
914

10-
Synchronises the versions of dependencies used across multiple `package.json` files, such as
11-
`packages/*/package.json` in [Lerna](https://lernajs.io) Monorepos.
15+
Synchronises the contents of multiple `package.json` files, such as `packages/*/package.json` in
16+
[Lerna](https://lernajs.io) Monorepos.
1217

13-
## Overview
18+
## Contents
19+
20+
* [Installation](#installation)
21+
* [Usage](#usage)
22+
* [`sync-versions`](#sync-versions)
23+
* [`copy-values`](#copy-values)
24+
25+
## Installation
26+
27+
```
28+
npm install --global syncpack
29+
```
30+
31+
## Usage
32+
33+
```
34+
Usage: syncpack [options] [command]
35+
36+
Options:
37+
38+
-V, --version output the version number
39+
-h, --help output usage information
40+
41+
Commands:
42+
43+
sync-versions synchronise dependency versions between packages
44+
copy-values <keys...> copy values from eg. ./package.json to ./packages/*/package.json
45+
help [cmd] display help for [cmd]
46+
```
47+
48+
### `sync-versions`
49+
50+
```
51+
Usage: syncpack sync-versions [options]
52+
53+
Options:
54+
55+
-p, --packages <glob> location of packages. defaults to ./packages/*/package.json
56+
-h, --help output usage information
57+
```
1458

1559
Imagine the packages `guybrush`, `herman`, and `elaine` all have `react` as a dependency, but
1660
versions `'15.4.0'`, `'15.5.4'`, and `'15.6.1'` respectively.
@@ -25,27 +69,66 @@ versions `'15.4.0'`, `'15.5.4'`, and `'15.6.1'` respectively.
2569
└── package.json
2670
```
2771

28-
Running `syncpack` will update each `package.json` to use version `'15.6.1'` of `react` in
29-
`dependencies`, `devDependencies`, and `peerDependencies` as needed.
72+
To update each `package.json` to use version `'15.6.1'` of `react` in `dependencies`,
73+
`devDependencies`, and `peerDependencies` (as needed) you can run
3074

31-
## Installation
75+
```
76+
syncpack sync-versions
77+
```
78+
79+
### `copy-values`
3280

3381
```
34-
npm install --global syncpack
82+
Usage: syncpack copy-values [options] <keys...>
83+
84+
Options:
85+
86+
-p, --packages <glob> location of packages. defaults to ./packages/*/package.json
87+
-s, --source <glob> location of source. defaults to ./package.json
88+
-h, --help output usage information
3589
```
3690

37-
## Usage
91+
Imagine the packages `carla` and `murray` were previously hosted at their own repositories, but are
92+
now part of your new Monorepo.
93+
94+
```
95+
/Users/foldleft/Dev/monorepo/packages/
96+
├── carla
97+
│   └── package.json
98+
└── murray
99+
└── package.json
100+
```
101+
102+
With the following contents
38103

39-
### Command Line
104+
```
105+
"bugs": "https://github.com/Scumm/carla/issues",
106+
"homepage": "https://github.com/Scumm/carla#readme",
107+
"repository": "Scumm/carla",
108+
```
40109

41110
```
42-
Usage: syncpack [options] [pattern]
111+
"bugs": "https://github.com/Scumm/murray/issues",
112+
"homepage": "https://github.com/Scumm/murray#readme",
113+
"repository": "Scumm/murray",
114+
```
43115

44-
Options:
116+
To copy these fields from your Monorepo's `package.json` to each of its packages, you can run
45117

46-
-h, --help output usage information
47-
-V, --version output the version number
118+
```
119+
syncpack copy-values bugs homepage repository
48120
```
49121

50-
The default pattern of `'./packages/*/package.json'` can be overridden as follows
51-
`syncpack './**/package.json'`
122+
to copy the value of those properties, leaving them like so
123+
124+
```
125+
"bugs": "https://github.com/Scumm/monorepo/issues",
126+
"homepage": "https://github.com/Scumm/monorepo#readme",
127+
"repository": "Scumm/monorepo",
128+
```
129+
130+
to copy deeply nested values, pass the path to the key as follows
131+
132+
```
133+
syncpack copy-values scripts.test
134+
```

package-lock.json

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
"version": "0.2.1",
55
"author": "Jamie Mason <jamie@foldleft.io> (https://github.com/JamieMason)",
66
"bin": {
7-
"syncpack": "dist/bin.js"
7+
"syncpack": "dist/bin.js",
8+
"syncpack-sync-versions": "dist/bin-sync-versions.js",
9+
"syncpack-copy-values": "dist/bin-copy-values.js"
810
},
911
"bugs": "https://github.com/JamieMason/syncpack/issues",
1012
"dependencies": {
1113
"bluebird": "3.5.0",
1214
"chalk": "2.1.0",
1315
"commander": "2.11.0",
1416
"glob": "7.1.2",
17+
"lodash": "4.17.4",
1518
"nodent-runtime": "3.0.4",
1619
"semver": "5.4.1"
1720
},

src/bin-copy-values.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env node
2+
3+
import 'nodent-runtime';
4+
import program from 'commander';
5+
import * as log from './lib/log';
6+
import copyValues from './copy-values';
7+
import { DEFAULT_PACKAGES, DEFAULT_SOURCE } from './constants';
8+
9+
program
10+
.option('-p, --packages <glob>', `location of packages. defaults to ${DEFAULT_PACKAGES}`)
11+
.option('-s, --source <glob>', `location of source. defaults to ${DEFAULT_SOURCE}`)
12+
.parse(process.argv);
13+
14+
const { args = [], packages = DEFAULT_PACKAGES, source = DEFAULT_SOURCE } = program;
15+
16+
copyValues({
17+
keys: args,
18+
packagesPattern: packages,
19+
sourcePattern: source
20+
}).catch(err => {
21+
log.bug('uncaught error in copyValues', err);
22+
process.exit(1);
23+
});

src/bin-sync-versions.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env node
2+
3+
import 'nodent-runtime';
4+
import program from 'commander';
5+
import * as log from './lib/log';
6+
import syncVersions from './sync-versions';
7+
import { DEFAULT_PACKAGES } from './constants';
8+
9+
program
10+
.option('-p, --packages <glob>', `location of packages. defaults to ${DEFAULT_PACKAGES}`)
11+
.parse(process.argv);
12+
13+
const { packages = DEFAULT_PACKAGES } = program;
14+
15+
syncVersions({
16+
packagesPattern: packages
17+
}).catch(err => {
18+
log.bug('uncaught error in syncVersions', err);
19+
process.exit(1);
20+
});

src/bin.js

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,13 @@
33
import 'nodent-runtime';
44
import program from 'commander';
55
import { version } from '../package.json';
6-
import * as log from './lib/log';
7-
import syncpack from './index';
6+
import { DEFAULT_PACKAGES, DEFAULT_SOURCE } from './constants';
87

9-
let patternValue;
10-
11-
program.version(version).arguments('[pattern]').action(pattern => {
12-
patternValue = pattern;
13-
});
8+
program
9+
.version(version)
10+
.command('sync-versions', 'synchronise dependency versions between packages', {
11+
isDefault: true
12+
})
13+
.command('copy-values <keys...>', `copy values from eg. ${DEFAULT_SOURCE} to ${DEFAULT_PACKAGES}`);
1414

1515
program.parse(process.argv);
16-
17-
syncpack({
18-
pattern: patternValue
19-
}).catch(err => {
20-
log.bug('uncaught error in syncpack', err);
21-
process.exit(1);
22-
});

src/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const DEFAULT_PACKAGES = './packages/*/package.json';
2+
export const DEFAULT_SOURCE = './package.json';

src/copy-values.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import path from 'path';
2+
import chalk from 'chalk';
3+
import { get, set } from 'lodash';
4+
import getFiles from './lib/get-files';
5+
6+
const getPackage = location => ({ location, json: require(location) });
7+
const formatValue = value => JSON.stringify(value);
8+
9+
export default async ({ keys, packagesPattern, sourcePattern }) => {
10+
const [source] = (await getFiles(sourcePattern)).map(getPackage);
11+
const packages = (await getFiles(packagesPattern)).map(getPackage);
12+
13+
packages.forEach(pkg => {
14+
console.log(chalk.grey.underline(path.relative(process.cwd(), pkg.location)));
15+
keys.forEach(key => {
16+
const value = get(source.json, key);
17+
const previousValue = formatValue(get(pkg.json, key));
18+
set(pkg.json, key, value);
19+
const nextValue = formatValue(value);
20+
if (previousValue === nextValue) {
21+
console.log(`${key}: ${chalk.green('✓ unchanged')}`);
22+
} else {
23+
console.log(`${key}: ${chalk.red(previousValue)}${chalk.green(nextValue)}`);
24+
}
25+
});
26+
});
27+
};

src/index.js renamed to src/sync-versions.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ const reportChanges = (key, pkg, changes) => {
5555
}
5656
};
5757

58-
export default async ({ pattern = './packages/*/package.json' }) => {
59-
const packages = (await getFiles(pattern)).map(getPackage);
58+
export default async ({ packagesPattern }) => {
59+
const packages = (await getFiles(packagesPattern)).map(getPackage);
6060
const changedDeps = getChangedDeps('dependencies', packages);
6161
const changedDevDeps = getChangedDeps('devDependencies', packages);
6262
const changedPeerDeps = getChangedDeps('peerDependencies', packages);

0 commit comments

Comments
 (0)