'use strict'
const path = require('path')
const nopt = require('nopt')
const log = require('./log')
const childProcess = require('child_process')
const { EventEmitter } = require('events')
const commands = [
'build',
'clean',
'configure',
'rebuild',
'install',
'list',
'remove'
]
class Gyp extends EventEmitter {
* Export the contents of the package.json.
*/
package = require('../package.json')
* nopt configuration definitions
*/
configDefs = {
help: Boolean,
arch: String,
cafile: String,
debug: Boolean,
directory: String,
make: String,
'msvs-version': String,
ensure: Boolean,
solution: String,
proxy: String,
noproxy: String,
devdir: String,
nodedir: String,
loglevel: String,
python: String,
'dist-url': String,
tarball: String,
jobs: String,
thin: String,
'force-process-config': Boolean
}
* nopt shorthands
*/
shorthands = {
release: '--no-debug',
C: '--directory',
debug: '--debug',
j: '--jobs',
silly: '--loglevel=silly',
verbose: '--loglevel=verbose',
silent: '--loglevel=silent'
}
* expose the command aliases for the bin file to use.
*/
aliases = {
ls: 'list',
rm: 'remove'
}
constructor (...args) {
super(...args)
this.devDir = ''
this.commands = commands.reduce((acc, command) => {
acc[command] = (argv) => require('./' + command)(this, argv)
return acc
}, {})
Object.defineProperty(this, 'version', {
enumerable: true,
get: function () { return this.package.version }
})
}
* Parses the given argv array and sets the 'opts',
* 'argv' and 'command' properties.
*/
parseArgv (argv) {
this.opts = nopt(this.configDefs, this.shorthands, argv)
this.argv = this.opts.argv.remain.slice()
const commands = this.todo = []
argv = this.argv.map((arg) => {
if (arg in this.aliases) {
arg = this.aliases[arg]
}
return arg
})
argv.slice().forEach((arg) => {
if (arg in this.commands) {
const args = argv.splice(0, argv.indexOf(arg))
argv.shift()
if (commands.length > 0) {
commands[commands.length - 1].args = args
}
commands.push({ name: arg, args: [] })
}
})
if (commands.length > 0) {
commands[commands.length - 1].args = argv.splice(0)
}
const npmConfigPrefix = 'npm_config_'
Object.keys(process.env).forEach((name) => {
if (name.indexOf(npmConfigPrefix) !== 0) {
return
}
const val = process.env[name]
if (name === npmConfigPrefix + 'loglevel') {
log.logger.level = val
} else {
name = name.substring(npmConfigPrefix.length)
if (name) {
if (name.includes('_')) {
name = name.replace(/_/g, '-')
}
this.opts[name] = val
}
}
})
if (this.opts.loglevel) {
log.logger.level = this.opts.loglevel
}
log.resume()
}
* Spawns a child process and emits a 'spawn' event.
*/
spawn (command, args, opts) {
if (!opts) {
opts = {}
}
if (!opts.silent && !opts.stdio) {
opts.stdio = [0, 1, 2]
}
const cp = childProcess.spawn(command, args, opts)
log.info('spawn', command)
log.info('spawn args', args)
return cp
}
* Returns the usage instructions for node-gyp.
*/
usage () {
return [
'',
' Usage: node-gyp <command> [options]',
'',
' where <command> is one of:',
commands.map((c) => ' - ' + c + ' - ' + require('./' + c).usage).join('\n'),
'',
'node-gyp@' + this.version + ' ' + path.resolve(__dirname, '..'),
'node@' + process.versions.node
].join('\n')
}
}
module.exports = () => new Gyp()
module.exports.Gyp = Gyp