hidenv
Version:
Beautiful CLI tool to encrypt and decrypt .env files with AES-256-GCM
140 lines (119 loc) • 3.84 kB
JavaScript
import { encryptEnv, decryptEnv } from '../src/cryptoUtils.js';
import chalk from 'chalk';
import ora from 'ora';
import inquirer from 'inquirer';
import figlet from 'figlet';
import fs from 'fs';
function showHelp() {
console.log(`
${chalk.cyanBright('hidenv - Secure Environment Tool')}
${chalk.yellow('Usage:')}
hidenv Interactive mode
hidenv --e [password] Encrypt .env
hidenv --d [password] Decrypt .env.enc
hidenv --help Show this help
${chalk.yellow('Options:')}
--e, --encrypt Encrypt .env file
--d, --decrypt Decrypt .env.enc file
--help Show help
${chalk.yellow('Examples:')}
hidenv --e Encrypt (will prompt for password)
hidenv --e mypassword Encrypt with password
hidenv --d Decrypt (will prompt for password)
hidenv --d mypassword Decrypt with password
`);
}
function parseArgs() {
const args = process.argv.slice(2);
if (args.includes('--help') || args.includes('-h')) {
showHelp();
process.exit(0);
}
const encryptIndex = args.findIndex(arg => arg === '--e' || arg === '--encrypt');
const decryptIndex = args.findIndex(arg => arg === '--d' || arg === '--decrypt');
if (encryptIndex !== -1) {
const password = args[encryptIndex + 1];
return { action: 'encrypt', password: password && !password.startsWith('--') ? password : null };
}
if (decryptIndex !== -1) {
const password = args[decryptIndex + 1];
return { action: 'decrypt', password: password && !password.startsWith('--') ? password : null };
}
return { action: null, password: null };
}
try {
console.log(
chalk.cyanBright(
figlet.textSync('HidENV', { horizontalLayout: 'default' })
)
);
} catch (e) {
console.log(chalk.cyanBright('=== Hidden ENV ==='));
}
async function main() {
const { action: cliAction, password: cliPassword } = parseArgs();
let action, password;
if (cliAction) {
action = cliAction;
if (!cliPassword) {
const result = await inquirer.prompt([
{
type: 'password',
name: 'password',
message: 'Enter your secret key:',
mask: '*',
validate: (input) => input.length > 0 || 'Password cannot be empty'
}
]);
password = result.password;
} else {
password = cliPassword;
}
} else {
const actionResult = await inquirer.prompt([
{
type: 'list',
name: 'action',
message: 'What do you want to do?',
choices: [
{ name: '🔒 Encrypt .env', value: 'encrypt' },
{ name: '🔓 Decrypt .env', value: 'decrypt' }
]
}
]);
const passwordResult = await inquirer.prompt([
{
type: 'password',
name: 'password',
message: 'Enter your secret key:',
mask: '*',
validate: (input) => input.length > 0 || 'Password cannot be empty'
}
]);
action = actionResult.action;
password = passwordResult.password;
}
const spinner = ora(action === 'encrypt' ? 'Encrypting...' : 'Decrypting...').start();
try {
if (action === 'encrypt') {
if (!fs.existsSync('.env')) {
spinner.fail(chalk.red('.env file not found in current directory.'));
process.exit(1);
}
encryptEnv('.env', password, '.env.enc');
spinner.succeed(chalk.green('File encrypted as .env.enc'));
} else {
if (!fs.existsSync('.env.enc')) {
spinner.fail(chalk.red('.env.enc file not found.'));
process.exit(1);
}
decryptEnv('.env.enc', password, '.env');
spinner.succeed(chalk.green('File decrypted as .env'));
}
} catch (err) {
spinner.fail(chalk.red(`Error: ${err.message}`));
process.exit(1);
}
}
main();