/
cli.js
executable file
·109 lines (96 loc) · 2.41 KB
/
cli.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env node
/* eslint-disable no-restricted-globals */
/* eslint-disable n/shebang */
// @ts-check
const { bold, magenta, gray, italic, cyan, underline } = require('kleur')
const util = require('node:util')
const { Laverna } = require('./laverna')
const { ERR } = require('./log-symbols')
const { name, bugs, version, description } = require('../package.json')
/**
* CLI for `laverna`, which wraps `npm publish` to only attempt publishing
* packages that have not yet been published.
*
* @packageDocumentation
*/
/**
* Options for {@link util.parseArgs} config (`options` property).
*
* @satisfies {import('node:util').ParseArgsConfig['options']}
*/
const options = /**
* @type {const}
*/ ({
dryRun: {
type: 'boolean',
},
'dry-run': {
type: 'boolean',
},
root: {
type: 'string',
},
help: {
type: 'boolean',
},
newPkg: {
type: 'string',
multiple: true,
default: [],
},
'new-pkg': {
type: 'string',
multiple: true,
default: [],
},
yes: {
type: 'boolean',
short: 'y',
},
})
/**
* Parses CLI args
*
* @param {string[]} [args]
*/
function parseArgs(args) {
const { values } = util.parseArgs({
args,
options,
})
return values
}
function main() {
let opts = parseArgs()
if (opts.help) {
// this should be the only place we write to stdout unless we
// want to start outputting JSON
console.log(`
${cyan(bold('laverna'))} ${cyan('[options..]')}
"${description}"
Options:
${bold('--dryRun')} - Enable dry-run mode
${bold('--root=<path>')} - Path to workspace root (default: current working dir)
${bold('--newPkg=<name>')} - Workspace <name> should be treated as a new package (repeatable)
${bold('--yes/-y')} - Skip confirmation prompt (default: false; true ${italic('in CI')})
Problems? Visit ${underline(bugs.url)}
`)
} else {
// prefer camelCase
opts.dryRun = opts.dryRun || opts['dry-run']
opts.newPkg = [
...new Set([...(opts.newPkg ?? []), ...(opts['new-pkg'] ?? [])]),
]
// must be true in CI; --yes=false is not a thing
opts.yes = Boolean(process.env.CI) || opts.yes
console.error(`📦 ${bold(magenta(name)) + gray('@') + magenta(version)}\n`)
const laverna = new Laverna(opts)
laverna.publishWorkspaces().catch((err) => {
console.error(ERR, err?.message ?? err)
process.exitCode = 1
})
}
}
if (require.main === module) {
main()
}