1 | import { constants, dependsOn, filter, inquirer, loadSettings, log, R, savePackage, semver, updatePackageRef, formatModuleName, } from '../common';
|
2 | import * as listCommand from './ls.cmd';
|
3 | export const name = 'bump';
|
4 | export const alias = 'b';
|
5 | export const description = `Bumps a module version along with it's entire dependency graph.`;
|
6 | export const args = {
|
7 | '-i': 'Include ignored modules.',
|
8 | '-d': 'Dry run where no files are saved.',
|
9 | '-l': 'Local versions only. Does not retrieve NPM details.',
|
10 | };
|
11 | export async function cmd(args) {
|
12 | const options = (args && args.options) || {};
|
13 | await bump({
|
14 | includeIgnored: options.i || false,
|
15 | local: options.l || false,
|
16 | dryRun: options.d || false,
|
17 | });
|
18 | }
|
19 | export async function bump(options = {}) {
|
20 | const { includeIgnored = false, local = false, dryRun = false } = options;
|
21 | const save = !dryRun;
|
22 | const npm = !local;
|
23 | const settings = await loadSettings({ npm, spinner: npm });
|
24 | if (!settings) {
|
25 | log.warn.yellow(constants.CONFIG_NOT_FOUND_ERROR);
|
26 | return;
|
27 | }
|
28 | const modules = settings.modules.filter((pkg) => filter.includeIgnored(pkg, includeIgnored));
|
29 | const module = await promptForModule(modules);
|
30 | if (!module) {
|
31 | return;
|
32 | }
|
33 | log.info();
|
34 | const dependants = dependsOn(module, modules);
|
35 | listCommand.printTable([module], { includeIgnored: true, dependants });
|
36 | if (dryRun) {
|
37 | log.info.gray(`Dry run...no files will be saved.\n`);
|
38 | }
|
39 | log.info();
|
40 | const release = (await promptForReleaseType(module.version));
|
41 | if (!release) {
|
42 | return;
|
43 | }
|
44 | log.info();
|
45 | const bumped = await bumpModule({
|
46 | release,
|
47 | pkg: module,
|
48 | allModules: modules,
|
49 | save,
|
50 | });
|
51 | log.info();
|
52 | log.info(bumped.log());
|
53 | log.info();
|
54 | if (dryRun) {
|
55 | log.info.gray(`\nNo files were saved.`);
|
56 | }
|
57 | else {
|
58 | log.info();
|
59 | }
|
60 | }
|
61 | async function bumpModule(options) {
|
62 | const { release, pkg, allModules, save, level = 0, ref } = options;
|
63 | const dependants = dependsOn(pkg, allModules);
|
64 | const version = semver.inc(pkg.latest, release);
|
65 | const isRoot = ref === undefined;
|
66 | if (!version) {
|
67 | throw new Error(`Failed to '${release}' the semver ${pkg.latest}.`);
|
68 | }
|
69 | const head = ['update', 'module', 'version', 'dependants'].map((title) => log.gray(title));
|
70 | const table = options.table || log.table({ head, border: false });
|
71 | const logPkgUpdate = (args) => {
|
72 | const { release, pkg, version } = args;
|
73 | let msg = '';
|
74 | msg += ` ${log.yellow(release.toUpperCase())} `;
|
75 | msg += `${formatModuleName(pkg.name)} from ${pkg.latest} → ${log.yellow(version)} `;
|
76 | return log.gray(msg);
|
77 | };
|
78 | if (ref) {
|
79 | table.add([
|
80 | log.yellow(` ${release.toUpperCase()} `),
|
81 | formatModuleName(`${pkg.name} `),
|
82 | log.gray(`${pkg.latest} → ${log.magenta(version)} `),
|
83 | log.gray(`${formatModuleName(ref.name)} ${ref.fromVersion} → ${log.magenta(ref.toVersion)}`),
|
84 | ]);
|
85 | }
|
86 | const json = R.clone(pkg.json);
|
87 | json.version = version;
|
88 | if (save) {
|
89 | await savePackage(pkg.dir, json);
|
90 | }
|
91 | if (isRoot && dependants.length > 0) {
|
92 | log.info.gray('\nchanges:');
|
93 | }
|
94 | for (const dependentPkg of dependants) {
|
95 | await updatePackageRef(dependentPkg, pkg.name, version, { save });
|
96 | await bumpModule({
|
97 | release: 'patch',
|
98 | pkg: dependentPkg,
|
99 | allModules,
|
100 | level: level + 1,
|
101 | ref: { name: pkg.name, fromVersion: pkg.latest, toVersion: version },
|
102 | save,
|
103 | table,
|
104 | });
|
105 | }
|
106 | return {
|
107 | table,
|
108 | log() {
|
109 | return `
|
110 | ${log.info(logPkgUpdate({ release, pkg, version }))}
|
111 |
|
112 | ${table.toString()}
|
113 |
|
114 | ${log.gray('complete')}
|
115 | ${log.info(logPkgUpdate({ release, pkg, version }))}
|
116 | `.substring(1);
|
117 | },
|
118 | };
|
119 | }
|
120 | async function promptForModule(modules) {
|
121 | const choices = modules.map((pkg) => ({ name: pkg.name, value: pkg.name }));
|
122 | const res = (await inquirer.prompt({
|
123 | type: 'list',
|
124 | name: 'name',
|
125 | message: 'Select a module',
|
126 | choices,
|
127 | pageSize: 30,
|
128 | }));
|
129 | const name = res.name;
|
130 | return modules.find((pkg) => pkg.name === name);
|
131 | }
|
132 | async function promptForReleaseType(version) {
|
133 | const choices = ['patch', 'minor', 'major'];
|
134 | const res = (await inquirer.prompt({
|
135 | type: 'list',
|
136 | name: 'name',
|
137 | message: 'Release',
|
138 | choices,
|
139 | }));
|
140 | return res.name;
|
141 | }
|