Skip to content
This repository was archived by the owner on Jul 28, 2021. It is now read-only.

Commit 0cf251f

Browse files
committed
feat(cmd): big refactor on cmd and opts stuff.
1 parent 215905c commit 0cf251f

File tree

10 files changed

+792
-135
lines changed

10 files changed

+792
-135
lines changed

bin/tink.js

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,52 @@
22

33
require('../lib/node/index.js')
44

5+
const MainOpts = require('figgy-pudding')(require('../lib/common-opts.js'))
6+
const CMDS = new Map([
7+
['sh', require('../lib/commands/shell.js')],
8+
['shell', require('../lib/commands/shell.js')],
9+
['prep', require('../lib/commands/prepare.js')],
10+
['prepare', require('../lib/commands/prepare.js')],
11+
['ping', require('../lib/commands/ping.js')]
12+
])
13+
514
if (require.main === module) {
6-
main()
15+
main(process.argv)
716
}
17+
818
module.exports = main
9-
function main () {
10-
require('npmlog').heading = 'tink'
11-
return require('yargs')
12-
.commandDir('../lib/commands')
13-
.demandCommand(1, 'Subcommand is required')
14-
.recommendCommands()
15-
.help()
16-
.alias('help', 'h')
17-
.alias('version', 'v')
18-
.completion()
19-
.argv
19+
function main (argv) {
20+
const log = require('npmlog')
21+
const npmConfig = require('../lib/config.js')
22+
log.heading = 'tink'
23+
if (needsYargs(argv)) {
24+
console.error('using yargs...', argv)
25+
let config = require('yargs')
26+
.demandCommand(1, 'Subcommand is required')
27+
.recommendCommands()
28+
.help()
29+
.alias('help', 'h')
30+
.alias('version', 'v')
31+
.completion()
32+
for (const mod of CMDS.values()) {
33+
config = config.command(mod)
34+
}
35+
const yargv = npmConfig(config.argv).concat({ log })
36+
log.level = yargv.loglevel || 'notice'
37+
} else {
38+
// This is an optimization because Yargs can be expensive to load.
39+
const opts = npmConfig({ log, _: argv.slice(2) })
40+
log.level = opts.loglevel
41+
return noYargsShortcut(argv[2], opts)
42+
}
43+
}
44+
45+
function needsYargs (argv) {
46+
return argv.length > 3 && (
47+
argv[3] !== '--' && argv[3].match(/^--?[a-z0-9]+/i)
48+
)
49+
}
50+
51+
function noYargsShortcut (cmd, opts) {
52+
return CMDS.get(cmd).handler(opts)
2053
}

lib/commands/ping.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
'use strict'
22

3-
module.exports = {
3+
const Ping = module.exports = {
44
command: 'ping',
55
describe: 'ping registry',
66
builder (y) {
77
return y.help().alias('help', 'h')
8-
.options(Object.assign(require('../common-opts.js'), module.exports.options()))
8+
.options(Ping.options)
99
},
10-
options () { return {} },
11-
// lazy-load subcommands
12-
handler: ping
10+
options: Object.assign(require('../common-opts.js', {})),
11+
handler: async argv => ping(argv)
1312
}
1413

1514
function ping (argv) {
@@ -20,27 +19,33 @@ function ping (argv) {
2019

2120
const PingConfig = figgyPudding({
2221
json: {},
22+
log: { default: () => log },
23+
loglevel: { default: 'notice' },
2324
registry: {},
2425
silent: {}
2526
})
2627

27-
const opts = PingConfig(npmConfig().concat(argv))
28+
const opts = PingConfig(npmConfig().concat(argv).concat({ log }))
2829

29-
log.notice('PING', opts.registry)
30+
if (opts.loglevel !== 'silent' && !opts.json) {
31+
process.stdout.write(`PING ${opts.registry}`)
32+
}
3033
const start = Date.now()
3134
return libnpm.fetch.json('/-/ping?write=true', opts).catch(() => ({})).then(details => {
3235
if (opts.loglevel === 'silent') {
3336
} else {
3437
const time = Date.now() - start
35-
log.notice('PONG', `${time / 1000}ms`)
3638
if (opts.json) {
3739
console.log(JSON.stringify({
3840
registry: opts.registry,
3941
time,
4042
details
4143
}, null, 2))
42-
} else if (Object.keys(details).length) {
43-
log.notice('PONG', `${JSON.stringify(details, null, 2)}`)
44+
} else {
45+
process.stdout.write(` => PONG ${time / 1000}ms\n`)
46+
if (Object.keys(details).length) {
47+
console.log(JSON.stringify(details, null, 2))
48+
}
4449
}
4550
}
4651
})

lib/commands/prepare.js

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,45 @@
11
'use strict'
22

3-
module.exports = {
3+
const Prepare = module.exports = {
44
command: 'prepare',
55
aliases: ['prep'],
66
describe: 'pre-fetch all dependencies',
77
builder (y) {
8-
return y.help().alias('help', 'h')
9-
.options(Object.assign(require('../common-opts.js'), module.exports.options()))
8+
return y.help().alias('help', 'h').options(Prepare.options)
109
},
11-
options () {
12-
return {
13-
force: {
14-
alias: 'f',
15-
describe: 'Unconditionally prepare dependencies.',
16-
type: 'boolean'
17-
}
10+
options: Object.assign(require('../common-opts.js'), {
11+
force: {
12+
alias: 'f',
13+
describe: 'Unconditionally prepare dependencies.',
14+
type: 'boolean'
1815
}
19-
},
20-
handler: prepare
16+
}),
17+
handler: async argv => prepare(argv)
2118
}
2219

23-
function prepare (argv) {
24-
const cp = require('child_process')
20+
async function prepare (argv) {
21+
const figgyPudding = require('figgy-pudding')
2522
const fs = require('graceful-fs')
2623
const log = require('npmlog')
2724
const path = require('path')
2825

29-
log.level = argv.loglevel
30-
let pkgMap = checkPkgMap()
26+
const opts = figgyPudding(Prepare.options)(argv)
27+
28+
log.level = opts.loglevel
29+
let pkgMap = await checkPkgMap()
3130
if (!pkgMap || argv.force) {
32-
log.notice('regenerating pkgmap')
33-
cp.spawnSync(process.argv[0], [
34-
require.resolve('../worker.js'), ...process.argv.slice(2)
35-
], {
36-
stdio: 'inherit'
37-
})
31+
const installer = require('../installer.js')
32+
try {
33+
await installer({
34+
log (level, ...args) {
35+
return log[level](...args)
36+
}
37+
})
38+
} catch (e) {
39+
log.error('installer', e)
40+
}
3841
}
42+
return pkgMap
3943

4044
function checkPkgMap () {
4145
try {

lib/commands/shell.js

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,73 @@
11
'use strict'
22

3-
module.exports = {
3+
const Shell = module.exports = {
44
command: 'shell',
55
aliases: ['sh'],
66
describe: 'Launch a tink shell or execute a script',
77
builder (yargs) {
8-
return yargs.help().alias('help', 'h').options({
9-
'ignore-scripts': {},
10-
'node-arg': {
11-
alias: ['n', 'nodeArg'],
12-
describe: 'Arguments to pass down directly to node',
13-
type: 'array'
14-
},
15-
prefix: {
16-
describe: 'Directory to execute package management operations in.',
17-
type: 'string'
18-
},
19-
'restore-missing': {
20-
default: true,
21-
type: 'boolean'
22-
}
23-
})
8+
return yargs.help().alias('help', 'h').options(Shell.options)
249
},
10+
options: Object.assign(require('../common-opts'), {
11+
_: { default: [] },
12+
'ignore-scripts': {},
13+
nodeArg: {
14+
alias: ['n', 'node-arg'],
15+
describe: 'Arguments to pass down directly to node',
16+
type: 'array'
17+
},
18+
prefix: {
19+
alias: 'C',
20+
describe: 'Directory to execute package management operations in.',
21+
type: 'string'
22+
},
23+
restore: {
24+
alias: 'restore-missing',
25+
default: true,
26+
type: 'boolean'
27+
},
28+
also: {
29+
hidden: true
30+
},
31+
dev: {
32+
hidden: true
33+
},
34+
development: {
35+
hidden: true
36+
},
37+
only: {
38+
hidden: true
39+
},
40+
production: {
41+
type: 'boolean',
42+
describe: 'Limit downloads to production dependencies, skipping devDependencies.'
43+
}
44+
}),
2545
// lazy-load subcommands
26-
handler: shell
46+
handler: async argv => shell(argv)
2747
}
2848

29-
function shell (argv) {
49+
async function shell (argv) {
3050
const cp = require('child_process')
51+
const figgyPudding = require('figgy-pudding')
52+
const path = require('path')
3153
const prepare = require('./prepare.js')
3254

33-
prepare.handler(argv)
34-
if (argv.nodeArg && argv.nodeArg.length) {
55+
const opts = figgyPudding(Shell.options)(argv)
56+
57+
await prepare.handler(argv)
58+
if (opts.nodeArg && opts.nodeArg.length) {
3559
cp.spawnSync(
3660
process.argv[0],
37-
['-r', require.resolve('../node'), ...(argv.nodeArg || []), ...(argv.script ? [argv.script, ...(argv.arguments || [])] : [])],
61+
['-r', require.resolve('../node/index.js'), ...(opts.nodeArg || []), ...(argv.script ? [argv.script, ...(argv.arguments || [])] : [])],
3862
{ stdio: 'inherit' }
3963
)
4064
} else if (argv._.length > 1) {
4165
const Module = require('module')
42-
require('clear-module').all()
66+
require('clear-module').match(/yargs/)
4367
process.argv = [
4468
process.argv[0],
45-
...argv._.slice(1)
69+
path.resolve(argv._[1]),
70+
...argv._.slice(2)
4671
]
4772
Module.runMain()
4873
} else {

lib/common-opts.js

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,37 @@ const path = require('path')
66
module.exports = {
77
cache: {
88
default: path.join(os.homedir(), '.tink'),
9-
describe: 'Path to the global tink cache',
10-
hidden: true
9+
describe: 'Path to the global tink cache'
1110
},
1211
json: {
1312
default: false,
1413
describe: 'Output in JSON format.',
15-
choices: [false, true],
16-
hidden: true
14+
type: 'boolean'
1715
},
1816
loglevel: {
19-
default: 'warn',
17+
default: 'notice',
2018
alias: ['log', 'l'],
2119
describe: 'Logger output level.',
22-
choices: ['silent', 'error', 'warn', 'http', 'verbose', 'info', 'notice', 'silly'],
23-
hidden: true
20+
choices: ['silent', 'error', 'warn', 'http', 'verbose', 'info', 'notice', 'silly']
2421
},
2522
registry: {
2623
alias: 'r',
2724
default: 'https://registry.npmjs.org',
28-
describe: 'Registry to ping',
29-
hidden: true
25+
describe: 'Registry to ping'
3026
},
3127
userconfig: {
3228
default: path.join(os.homedir(), '.npmrc'),
33-
describe: 'Path to user config file.',
34-
hidden: true
35-
}
29+
describe: 'Path to user config file.'
30+
},
31+
force: {
32+
type: 'boolean',
33+
describe: 'Force an action (use with care). This should be defined per-command.'
34+
},
35+
log: {},
36+
prefix: {},
37+
then: {}
3638
}
39+
40+
Object.keys(module.exports).forEach(k => {
41+
module.exports[k].hidden = true
42+
})

lib/config.js

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,9 @@
33
const fs = require('fs')
44
const figgyPudding = require('figgy-pudding')
55
const ini = require('ini')
6-
const os = require('os')
76
const path = require('path')
87

9-
const tinkConfig = module.exports = figgyPudding({
10-
also: {},
11-
cache: { default: path.join(os.homedir(), '.npm') },
12-
dev: {},
13-
development: {},
14-
force: {},
15-
global: {},
16-
'ignore-scripts': {},
17-
log: {},
18-
loglevel: { default: 'warn' },
19-
only: {},
20-
prefix: {},
21-
production: {},
22-
restore: {},
23-
then: {}, // omfg
24-
umask: {},
25-
userconfig: { default: path.join(os.homedir(), '.npmrc') }
26-
})
8+
const tinkConfig = figgyPudding(require('./common-opts.js'))
279

2810
module.exports = getNpmConfig
2911
module.exports.pudding = tinkConfig
@@ -38,7 +20,7 @@ function getNpmConfig (_opts) {
3820
path: '',
3921
configs: []
4022
}).configs.concat(
41-
maybeReadIni(opts.userconfig || path.join(os.homedir(), '.npmrc'))
23+
maybeReadIni(opts.userconfig)
4224
).filter(x => x)
4325
const env = Object.keys(process.env).reduce((acc, key) => {
4426
if (key.match(/^(?:npm|tink)_config_/i)) {

lib/installer.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,7 @@ class Installer {
281281
name: pkg.name,
282282
pkgId: pkg.name + '@' + pkg.version,
283283
prefix: this.prefix,
284-
prefixes: [this.prefix],
285-
umask: this.opts.umask
284+
prefixes: [this.prefix]
286285
})
287286
await this.runScript('install', pkg, depPath)
288287
await this.runScript('postinstall', pkg, depPath)

lib/pkgmap.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ if (require.main === module && process.argv[2] === 'ensure-pkg') {
275275
cache,
276276
integrity,
277277
log: require('npmlog'),
278-
restore: true
278+
'restore-missing': true
279279
})
280280
opts.log.level = opts.loglevel
281281
opts.log.warn('fs', 'restoring broken or missing file from package', `${pkg.name}@${pkg.version}`)

0 commit comments

Comments
 (0)