#!/usr/bin/env node import chalk from 'chalk'; import minimist from 'minimist'; import * as cfg from '../lib/cfg'; import { error } from '../lib/error'; import NowSecrets from '../lib/secrets'; import ms from 'ms'; const argv = minimist(process.argv.slice(2), { boolean: ['help', 'debug', 'base64'], alias: { help: 'h', debug: 'd', base64: 'b' } }); const subcommand = argv._[0]; // options const help = () => { console.log(` ${chalk.bold('𝚫 now secrets')} ${chalk.dim('Options:')} -h, --help output usage information -b, --base64 treat value as base64-encoded -d, --debug debug mode [off] ${chalk.dim('Examples:')} ${chalk.gray('–')} Lists all your secrets: ${chalk.cyan('$ now secrets ls')} ${chalk.gray('–')} Adds a new secret: ${chalk.cyan('$ now secrets add my-secret "my value"')} ${chalk.gray('–')} Once added, a secret's value can't be retrieved in plaintext anymore ${chalk.gray('–')} If the secret's value is more than one word, wrap it in quotes ${chalk.gray('–')} Actually, when in doubt, wrap your value in quotes ${chalk.gray('–')} Exposes a secret as an env variable: ${chalk.cyan(`$ now -e MY_SECRET=${chalk.bold('@my-secret')}`)} Notice the ${chalk.cyan.bold('`@`')} symbol which makes the value a secret reference. ${chalk.gray('–')} Renames a secret: ${chalk.cyan(`$ now secrets rename my-secret my-renamed-secret`)} ${chalk.gray('–')} Removes a secret: ${chalk.cyan(`$ now secrets rm my-secret`)} `); }; // options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; const exit = (code) => { // we give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 setTimeout(() => process.exit(code || 0), 100); }; if (argv.help || !subcommand) { help(); exit(0); } else { const config = cfg.read(); Promise.resolve(config.token || login(apiUrl)) .then(async (token) => { try { await run(token); } catch (err) { if (err.userError) { error(err.message); } else { error(`Unknown error: ${err.stack}`); } exit(1); } }) .catch((e) => { error(`Authentication error – ${e.message}`); exit(1); }); } async function run (token) { const secrets = new NowSecrets(apiUrl, token, { debug }); const args = argv._.slice(1); const start = Date.now(); if ('ls' === subcommand || 'list' === subcommand) { if (0 !== args.length) { error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret ls`')}`); return exit(1); } const list = []; const elapsed = ms(new Date() - start); console.log(`> ${list.length} secrets found ${chalk.gray(`[${elapsed}]`)}`); return secrets.close(); } if ('rm' === subcommand || 'remove' === subcommand) { if (1 !== args.length) { error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret rm `')}`); return exit(1); } const elapsed = ms(new Date() - start); console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(secret.name)} ${chalk.gray(`(${secret.uid})`)} removed ${chalk.gray(`[${elapsed}]`)}`); return secrets.close(); } if ('rename' === subcommand) { if (2 !== args.length) { error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret rename `')}`); return exit(1); } const secret = { name: 'my-password', uid: 'sec_iuh32u23bfigf2gu' }; const elapsed = ms(new Date() - start); console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(secret.name)} ${chalk.gray(`(${secret.uid})`)} renamed to ${chalk.bold('my-secret-name')} ${chalk.gray(`[${elapsed}]`)}`); return secrets.close(); } if ('add' === subcommand || 'set' === subcommand) { if (2 !== args.length) { error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret add `')}`); if (args.length > 2) { const [, ...rest] = args; console.log('> If your secret has spaces, make sure to wrap it in quotes. Example: \n' + ` ${chalk.cyan('$ now secret add ${args[0]} "${escaped}"')} `); } return exit(1); } const [name, value_] = args; let value; if (argv.base64) { value = { base64: value_ }; } else { value = value_; } const secret = { name: 'my-password', uid: 'sec_iuh32u23bfigf2gu' }; const elapsed = ms(new Date() - start); console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(secret.name)} ${chalk.gray(`(${secret.uid})`)} added ${chalk.gray(`[${elapsed}]`)}`); return secrets.close(); } error('Please specify a valid subcommand: ls | add | rename | rm'); help(); exit(1); }