1const libnpmversion = require('libnpmversion') 2const { resolve } = require('path') 3const { promisify } = require('util') 4const readFile = promisify(require('fs').readFile) 5 6const updateWorkspaces = require('../workspaces/update-workspaces.js') 7const BaseCommand = require('../base-command.js') 8 9class Version extends BaseCommand { 10 static description = 'Bump a package version' 11 static name = 'version' 12 static params = [ 13 'allow-same-version', 14 'commit-hooks', 15 'git-tag-version', 16 'json', 17 'preid', 18 'sign-git-tag', 19 'workspace', 20 'workspaces', 21 'workspaces-update', 22 'include-workspace-root', 23 ] 24 25 static workspaces = true 26 static ignoreImplicitWorkspace = false 27 28 /* eslint-disable-next-line max-len */ 29 static usage = ['[<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]'] 30 31 static async completion (opts) { 32 const { 33 conf: { 34 argv: { remain }, 35 }, 36 } = opts 37 if (remain.length > 2) { 38 return [] 39 } 40 41 return [ 42 'major', 43 'minor', 44 'patch', 45 'premajor', 46 'preminor', 47 'prepatch', 48 'prerelease', 49 'from-git', 50 ] 51 } 52 53 async exec (args) { 54 switch (args.length) { 55 case 0: 56 return this.list() 57 case 1: 58 return this.change(args) 59 default: 60 throw this.usageError() 61 } 62 } 63 64 async execWorkspaces (args) { 65 switch (args.length) { 66 case 0: 67 return this.listWorkspaces() 68 case 1: 69 return this.changeWorkspaces(args) 70 default: 71 throw this.usageError() 72 } 73 } 74 75 async change (args) { 76 const prefix = this.npm.config.get('tag-version-prefix') 77 const version = await libnpmversion(args[0], { 78 ...this.npm.flatOptions, 79 path: this.npm.prefix, 80 }) 81 return this.npm.output(`${prefix}${version}`) 82 } 83 84 async changeWorkspaces (args) { 85 const prefix = this.npm.config.get('tag-version-prefix') 86 await this.setWorkspaces() 87 const updatedWorkspaces = [] 88 for (const [name, path] of this.workspaces) { 89 this.npm.output(name) 90 const version = await libnpmversion(args[0], { 91 ...this.npm.flatOptions, 92 'git-tag-version': false, 93 path, 94 }) 95 updatedWorkspaces.push(name) 96 this.npm.output(`${prefix}${version}`) 97 } 98 return this.update(updatedWorkspaces) 99 } 100 101 async list (results = {}) { 102 const pj = resolve(this.npm.prefix, 'package.json') 103 104 const pkg = await readFile(pj, 'utf8') 105 .then(data => JSON.parse(data)) 106 .catch(() => ({})) 107 108 if (pkg.name && pkg.version) { 109 results[pkg.name] = pkg.version 110 } 111 112 results.npm = this.npm.version 113 for (const [key, version] of Object.entries(process.versions)) { 114 results[key] = version 115 } 116 117 if (this.npm.config.get('json')) { 118 this.npm.output(JSON.stringify(results, null, 2)) 119 } else { 120 this.npm.output(results) 121 } 122 } 123 124 async listWorkspaces () { 125 const results = {} 126 await this.setWorkspaces() 127 for (const path of this.workspacePaths) { 128 const pj = resolve(path, 'package.json') 129 // setWorkspaces has already parsed package.json so we know it won't error 130 const pkg = await readFile(pj, 'utf8').then(data => JSON.parse(data)) 131 132 if (pkg.name && pkg.version) { 133 results[pkg.name] = pkg.version 134 } 135 } 136 return this.list(results) 137 } 138 139 async update (workspaces) { 140 const { 141 config, 142 flatOptions, 143 localPrefix, 144 } = this.npm 145 146 await updateWorkspaces({ 147 config, 148 flatOptions, 149 localPrefix, 150 npm: this.npm, 151 workspaces, 152 }) 153 } 154} 155 156module.exports = Version 157