263 lines
11 KiB
JavaScript
Executable File
263 lines
11 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
/* c8 ignore start */
|
|
const { Command } = require('commander')
|
|
const program = new Command()
|
|
|
|
const { setLogLevel, logger } = require('../shared/logger')
|
|
const examples = require('./examples')
|
|
const packageJson = require('./../lib/helpers/packageJson')
|
|
const Errors = require('./../lib/helpers/errors')
|
|
const getCommanderVersion = require('./../lib/helpers/getCommanderVersion')
|
|
const executeDynamic = require('./../lib/helpers/executeDynamic')
|
|
const removeDynamicHelpSection = require('./../lib/helpers/removeDynamicHelpSection')
|
|
const removeOptionsHelpParts = require('./../lib/helpers/removeOptionsHelpParts')
|
|
|
|
const Session = require('./../db/session')
|
|
const sesh = new Session()
|
|
|
|
// for use with run
|
|
const envs = []
|
|
function collectEnvs (type) {
|
|
return function (value, previous) {
|
|
envs.push({ type, value })
|
|
return previous.concat([value])
|
|
}
|
|
}
|
|
|
|
// surface hoisting problems
|
|
const commanderVersion = getCommanderVersion()
|
|
if (commanderVersion && parseInt(commanderVersion.split('.')[0], 10) >= 12) {
|
|
const message = `dotenvx depends on commander@11.x.x but you are attempting to hoist commander@${commanderVersion}`
|
|
const error = new Errors({ message }).dangerousDependencyHoist()
|
|
logger.error(error.messageWithHelp)
|
|
}
|
|
|
|
// global log levels
|
|
program
|
|
.usage('run -- yourcommand')
|
|
.option('-l, --log-level <level>', 'set log level', 'info')
|
|
.option('-q, --quiet', 'sets log level to error')
|
|
.option('-v, --verbose', 'sets log level to verbose')
|
|
.option('-d, --debug', 'sets log level to debug')
|
|
.hook('preAction', (thisCommand, actionCommand) => {
|
|
const options = thisCommand.opts()
|
|
|
|
setLogLevel(options)
|
|
})
|
|
|
|
// for dynamic loading of dotenvx-ops, etc
|
|
program
|
|
.argument('[command]', 'dynamic command')
|
|
.argument('[args...]', 'dynamic command arguments')
|
|
.action((command, args, cmdObj) => {
|
|
const rawArgs = process.argv.slice(3) // adjust the index based on where actual args start
|
|
executeDynamic(program, command, rawArgs)
|
|
})
|
|
|
|
// cli
|
|
program
|
|
.name('dotenvx')
|
|
.description(packageJson.description)
|
|
.version(packageJson.version)
|
|
.allowUnknownOption()
|
|
|
|
// dotenvx run -- node index.js
|
|
const runAction = require('./actions/run')
|
|
program.command('run')
|
|
.description('inject env at runtime [dotenvx run -- yourcommand]')
|
|
.addHelpText('after', examples.run)
|
|
.option('-e, --env <strings...>', 'environment variable(s) set as string (example: "HELLO=World")', collectEnvs('env'), [])
|
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
.option('-o, --overload', 'override existing env variables (by default, existing env vars take precedence over .env files)')
|
|
.option('--strict', 'process.exit(1) on any errors', false)
|
|
.option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\', \'flow\'])')
|
|
.option('--ignore <errorCodes...>', 'error code(s) to ignore (example: --ignore=MISSING_ENV_FILE)')
|
|
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
.action(function (...args) {
|
|
this.envs = envs
|
|
runAction.apply(this, args)
|
|
})
|
|
|
|
// dotenvx get
|
|
const getAction = require('./actions/get')
|
|
program.command('get')
|
|
.usage('[KEY] [options]')
|
|
.description('return a single environment variable')
|
|
.argument('[KEY]', 'environment variable name')
|
|
.option('-e, --env <strings...>', 'environment variable(s) set as string (example: "HELLO=World")', collectEnvs('env'), [])
|
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
.option('-o, --overload', 'override existing env variables (by default, existing env vars take precedence over .env files)')
|
|
.option('--strict', 'process.exit(1) on any errors', false)
|
|
.option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\', \'flow\'])')
|
|
.option('--ignore <errorCodes...>', 'error code(s) to ignore (example: --ignore=MISSING_ENV_FILE)')
|
|
.option('-a, --all', 'include all machine envs as well')
|
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
.option('--pp', 'pretty print output (alias)')
|
|
.option('--format <type>', 'format of the output (json, shell, eval)', 'json')
|
|
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
.action(function (...args) {
|
|
this.envs = envs
|
|
getAction.apply(this, args)
|
|
})
|
|
|
|
// dotenvx set
|
|
const setAction = require('./actions/set')
|
|
program.command('set')
|
|
.usage('<KEY> <value> [options]')
|
|
.description('encrypt a single environment variable')
|
|
.addHelpText('after', examples.set)
|
|
.allowUnknownOption()
|
|
.argument('KEY', 'KEY')
|
|
.argument('value', 'value')
|
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
.option('-c, --encrypt', 'encrypt value', true)
|
|
.option('-p, --plain', 'store value as plain text', false)
|
|
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
.action(function (...args) {
|
|
this.envs = envs
|
|
setAction.apply(this, args)
|
|
})
|
|
|
|
// dotenvx encrypt
|
|
const encryptAction = require('./actions/encrypt')
|
|
program.command('encrypt')
|
|
.description('convert .env file(s) to encrypted .env file(s)')
|
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
|
|
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
.option('--stdout', 'send to stdout')
|
|
.action(function (...args) {
|
|
this.envs = envs
|
|
encryptAction.apply(this, args)
|
|
})
|
|
|
|
// dotenvx decrypt
|
|
const decryptAction = require('./actions/decrypt')
|
|
program.command('decrypt')
|
|
.description('convert encrypted .env file(s) to plain .env file(s)')
|
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
.option('-k, --key <keys...>', 'keys(s) to decrypt (default: all keys in file)')
|
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from decryption (default: none)')
|
|
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
.option('--stdout', 'send to stdout')
|
|
.action(function (...args) {
|
|
this.envs = envs
|
|
decryptAction.apply(this, args)
|
|
})
|
|
|
|
// dotenvx rotate
|
|
const rotateAction = require('./actions/rotate')
|
|
program.command('rotate')
|
|
.description('rotate keypair(s) and re-encrypt .env file(s)')
|
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
|
|
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
.option('--stdout', 'send to stdout')
|
|
.action(function (...args) {
|
|
this.envs = envs
|
|
rotateAction.apply(this, args)
|
|
})
|
|
|
|
// dotenvx keypair
|
|
const keypairAction = require('./actions/keypair')
|
|
program.command('keypair')
|
|
.usage('[KEY] [options]')
|
|
.description('print public/private keys for .env file(s)')
|
|
.argument('[KEY]', 'environment variable key name')
|
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
|
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
.option('--ops-off', 'disable dotenvx-ops features', sesh.opsOff())
|
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
.option('--pp', 'pretty print output (alias)')
|
|
.option('--format <type>', 'format of the output (json, shell)', 'json')
|
|
.action(keypairAction)
|
|
|
|
// dotenvx ls
|
|
const lsAction = require('./actions/ls')
|
|
program.command('ls')
|
|
.description('print all .env files in a tree structure')
|
|
.argument('[directory]', 'directory to list .env files from', '.')
|
|
.option('-f, --env-file <filenames...>', 'path(s) to your env file(s)', '.env*')
|
|
.option('-ef, --exclude-env-file <excludeFilenames...>', 'path(s) to exclude from your env file(s) (default: none)')
|
|
.action(lsAction)
|
|
|
|
// dotenvx help
|
|
program.command('help [command]')
|
|
.description('display help for command')
|
|
.action((command) => {
|
|
if (command) {
|
|
const subCommand = program.commands.find(c => c.name() === command)
|
|
if (subCommand) {
|
|
subCommand.outputHelp()
|
|
} else {
|
|
program.outputHelp()
|
|
}
|
|
} else {
|
|
program.outputHelp()
|
|
}
|
|
})
|
|
|
|
// dotenvx pro
|
|
program.addHelpText('after', ' ')
|
|
program.addHelpText('after', 'Advanced: ')
|
|
program.addHelpText('after', ' ops 🛡️ ops')
|
|
program.addHelpText('after', ' ext 🔌 extensions')
|
|
|
|
// dotenvx ext
|
|
program.addCommand(require('./commands/ext'))
|
|
|
|
//
|
|
// MOVED
|
|
//
|
|
const prebuildAction = require('./actions/ext/prebuild')
|
|
program.command('prebuild')
|
|
.description('DEPRECATED: moved to [dotenvx ext prebuild]')
|
|
.addHelpText('after', examples.prebuild)
|
|
.action(function (...args) {
|
|
logger.warn('DEPRECATION NOTICE: [prebuild] has moved to [dotenvx ext prebuild]')
|
|
|
|
prebuildAction.apply(this, args)
|
|
})
|
|
|
|
const precommitAction = require('./actions/ext/precommit')
|
|
program.command('precommit')
|
|
.description('DEPRECATED: moved to [dotenvx ext precommit]')
|
|
.addHelpText('after', examples.precommit)
|
|
.option('-i, --install', 'install to .git/hooks/pre-commit')
|
|
.action(function (...args) {
|
|
logger.warn('DEPRECATION NOTICE: [precommit] has moved to [dotenvx ext precommit]')
|
|
|
|
precommitAction.apply(this, args)
|
|
})
|
|
|
|
// override helpInformation to hide DEPRECATED and 'ext' commands
|
|
program.helpInformation = function () {
|
|
const originalHelp = Command.prototype.helpInformation.call(this)
|
|
const lines = originalHelp.split('\n')
|
|
|
|
removeDynamicHelpSection(lines)
|
|
removeOptionsHelpParts(lines)
|
|
|
|
// Filter out the hidden command from the help output
|
|
const filteredLines = lines.filter(line =>
|
|
!line.includes('DEPRECATED') &&
|
|
!line.includes('help [command]') &&
|
|
!line.includes('🔌 extensions') &&
|
|
!/^\s*ls\b/.test(line)
|
|
)
|
|
|
|
return filteredLines.join('\n')
|
|
}
|
|
/* c8 ignore stop */
|
|
|
|
program.parse(process.argv)
|