envx-cli
Version:
Environment file encryption and management tool
282 lines • 13.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCreateCommand = void 0;
const chalk_1 = __importDefault(require("chalk"));
const commander_1 = require("commander");
const path_1 = __importDefault(require("path"));
const schemas_1 = require("../schemas");
const exec_1 = require("../utils/exec");
const file_1 = require("../utils/file");
const interactive_1 = require("../utils/interactive");
const createCreateCommand = () => {
const command = new commander_1.Command('create');
command
.description('Create new environment files')
.option('-e, --environment <env>', 'Environment name (e.g., development, staging, production)')
.option('-t, --template <path>', 'Template file path to use as base')
.option('-c, --cwd <path>', 'Working directory path')
.option('-i, --interactive', 'Interactive mode for creating multiple environments')
.option('--overwrite', 'Overwrite existing files without confirmation')
.action(async (options) => {
try {
await executeCreate(options);
}
catch (error) {
exec_1.CliUtils.error(`File creation failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
return command;
};
exports.createCreateCommand = createCreateCommand;
async function executeCreate(rawOptions) {
exec_1.CliUtils.header('Environment File Creation');
const cwd = rawOptions.cwd || exec_1.ExecUtils.getCurrentDir();
const existingEnvironments = await file_1.FileUtils.findAllEnvironments(cwd);
if (existingEnvironments.length > 0) {
exec_1.CliUtils.info(`Existing environments: ${existingEnvironments.map(env => exec_1.CliUtils.formatEnvironment(env)).join(', ')}`);
}
let environment = rawOptions.environment;
let template = rawOptions.template;
if (rawOptions.interactive) {
await executeInteractiveCreate(cwd, existingEnvironments, template, rawOptions.overwrite);
return;
}
if (!environment) {
environment = await interactive_1.InteractiveUtils.promptEnvironmentName('Enter environment name:');
}
if (!file_1.FileUtils.isValidEnvironmentName(environment)) {
throw new Error('Environment name can only contain letters, numbers, hyphens, and underscores');
}
(0, schemas_1.validateCreateOptions)({
environment,
template,
cwd,
overwrite: rawOptions.overwrite,
});
if (existingEnvironments.includes(environment)) {
exec_1.CliUtils.warning(`Environment '${environment}' already exists`);
const envFiles = await file_1.FileUtils.findEnvFiles(environment, cwd);
if (envFiles.length > 0) {
console.log('Existing files:');
envFiles.forEach(file => {
const displayPath = file.encrypted
? file_1.FileUtils.getEncryptedPath(file.path)
: file.path;
console.log(` • ${exec_1.CliUtils.formatPath(displayPath, cwd)}`);
});
if (!rawOptions.overwrite) {
const confirm = await interactive_1.InteractiveUtils.confirmOperation('Do you want to create additional files for this environment?', false);
if (!confirm) {
exec_1.CliUtils.info('Operation cancelled.');
return;
}
}
}
}
if (template) {
const templatePath = path_1.default.isAbsolute(template)
? template
: path_1.default.join(cwd, template);
if (!(await file_1.FileUtils.fileExists(templatePath))) {
throw new Error(`Template file not found: ${template}`);
}
template = templatePath;
}
const envFilePath = path_1.default.join(cwd, `.env.${environment}`);
const relativePath = file_1.FileUtils.getRelativePath(envFilePath, cwd);
if ((await file_1.FileUtils.fileExists(envFilePath)) && !rawOptions.overwrite) {
const confirm = await interactive_1.InteractiveUtils.confirmOperation(`File ${chalk_1.default.cyan(relativePath)} already exists. Overwrite?`, false);
if (!confirm) {
exec_1.CliUtils.info('Operation cancelled.');
return;
}
}
exec_1.CliUtils.info(`Creating environment file: ${chalk_1.default.cyan(relativePath)}`);
try {
const result = await file_1.FileUtils.createEnvTemplate(envFilePath, template);
if (result.success) {
exec_1.CliUtils.success(`Created: ${chalk_1.default.cyan(relativePath)}`);
console.log();
exec_1.CliUtils.info('Next steps:');
console.log(chalk_1.default.gray(`• Edit ${relativePath} and add your environment variables`));
console.log(chalk_1.default.gray(`• Use "envx encrypt -e ${environment}" to encrypt the file`));
console.log(chalk_1.default.gray('• Add the encrypted .gpg file to version control'));
}
else {
exec_1.CliUtils.error(result.message);
if (result.error) {
console.log(chalk_1.default.red(` • ${result.error.message}`));
}
}
}
catch (error) {
exec_1.CliUtils.error(`Failed to create file: ${error instanceof Error ? error.message : String(error)}`);
}
}
async function executeInteractiveCreate(cwd, existingEnvironments, template, overwrite) {
exec_1.CliUtils.subheader('Interactive Environment Creation');
const commonEnvironments = [
'development',
'staging',
'production',
'local',
'test',
];
const suggestedEnvironments = commonEnvironments.filter(env => !existingEnvironments.includes(env));
if (suggestedEnvironments.length > 0) {
exec_1.CliUtils.info('Suggested environments:');
suggestedEnvironments.forEach(env => {
console.log(` • ${exec_1.CliUtils.formatEnvironment(env)}`);
});
console.log();
}
const { createMode } = (await interactive_1.InteractiveUtils.confirmOperation('Do you want to select from suggested environments?'))
? { createMode: 'suggested' }
: { createMode: 'custom' };
let environmentsToCreate = [];
if (createMode === 'suggested' && suggestedEnvironments.length > 0) {
environmentsToCreate = await interactive_1.InteractiveUtils.selectMultipleEnvironments(suggestedEnvironments, 'Select environments to create:');
}
const { addCustom } = (await interactive_1.InteractiveUtils.confirmOperation('Do you want to add custom environments?', createMode === 'custom'))
? { addCustom: true }
: { addCustom: false };
if (addCustom) {
let addingMore = true;
while (addingMore) {
const newEnv = await interactive_1.InteractiveUtils.promptEnvironmentName('Enter environment name:');
if (!environmentsToCreate.includes(newEnv) &&
!existingEnvironments.includes(newEnv)) {
environmentsToCreate.push(newEnv);
exec_1.CliUtils.success(`Added ${exec_1.CliUtils.formatEnvironment(newEnv)} to creation list`);
}
else if (existingEnvironments.includes(newEnv)) {
exec_1.CliUtils.warning(`Environment ${exec_1.CliUtils.formatEnvironment(newEnv)} already exists`);
const confirm = await interactive_1.InteractiveUtils.confirmOperation('Do you want to create files for this environment anyway?');
if (confirm) {
environmentsToCreate.push(newEnv);
}
}
else {
exec_1.CliUtils.warning(`Environment ${exec_1.CliUtils.formatEnvironment(newEnv)} already in creation list`);
}
const { continueAdding } = (await interactive_1.InteractiveUtils.confirmOperation('Do you want to add another environment?', false))
? { continueAdding: true }
: { continueAdding: false };
addingMore = continueAdding;
}
}
if (environmentsToCreate.length === 0) {
exec_1.CliUtils.warning('No environments selected for creation.');
return;
}
if (!template) {
const { useTemplate } = (await interactive_1.InteractiveUtils.confirmOperation('Do you want to use a template file?', false))
? { useTemplate: true }
: { useTemplate: false };
if (useTemplate) {
const commonTemplates = ['.env.example', '.env.template', '.env.sample'];
const foundTemplates = [];
for (const templateName of commonTemplates) {
const templatePath = path_1.default.join(cwd, templateName);
if (await file_1.FileUtils.fileExists(templatePath)) {
foundTemplates.push(templateName);
}
}
if (foundTemplates.length > 0) {
const { templateChoice } = (await interactive_1.InteractiveUtils.selectFiles([...foundTemplates, 'Enter custom path'], 'Select template file:'));
if (templateChoice === 'Enter custom path') {
const { customTemplate } = (await interactive_1.InteractiveUtils.promptEnvironmentName('Enter template file path:'));
template = customTemplate;
}
else {
template = path_1.default.join(cwd, templateChoice[0]);
}
}
else {
const { customTemplate } = (await interactive_1.InteractiveUtils.promptEnvironmentName('Enter template file path:'));
template = customTemplate;
}
if (template) {
const templatePath = path_1.default.isAbsolute(template)
? template
: path_1.default.join(cwd, template);
if (!(await file_1.FileUtils.fileExists(templatePath))) {
exec_1.CliUtils.warning(`Template file not found: ${template}`);
template = undefined;
}
else {
template = templatePath;
exec_1.CliUtils.success(`Using template: ${exec_1.CliUtils.formatPath(template, cwd)}`);
}
}
}
}
console.log();
exec_1.CliUtils.subheader('Creation Summary');
console.log(`Will create ${environmentsToCreate.length} environment file(s):`);
environmentsToCreate.forEach(env => {
console.log(` • .env.${exec_1.CliUtils.formatEnvironment(env)}`);
});
if (template) {
console.log(`Using template: ${exec_1.CliUtils.formatPath(template, cwd)}`);
}
const confirm = await interactive_1.InteractiveUtils.confirmOperation('Create these environment files?');
if (!confirm) {
exec_1.CliUtils.info('Operation cancelled.');
return;
}
exec_1.CliUtils.subheader('Creating Files');
let successCount = 0;
let errorCount = 0;
for (const environment of environmentsToCreate.sort()) {
const envFilePath = path_1.default.join(cwd, `.env.${environment}`);
const relativePath = file_1.FileUtils.getRelativePath(envFilePath, cwd);
console.log();
exec_1.CliUtils.info(`Creating: ${chalk_1.default.cyan(relativePath)}`);
try {
if ((await file_1.FileUtils.fileExists(envFilePath)) && !overwrite) {
const fileConfirm = await interactive_1.InteractiveUtils.confirmOperation(`File already exists. Overwrite ${relativePath}?`, false);
if (!fileConfirm) {
exec_1.CliUtils.warning('Skipped existing file');
continue;
}
}
const result = await file_1.FileUtils.createEnvTemplate(envFilePath, template);
if (result.success) {
exec_1.CliUtils.success(`Created: ${chalk_1.default.cyan(relativePath)}`);
successCount++;
}
else {
exec_1.CliUtils.error(`Failed: ${result.message}`);
errorCount++;
}
}
catch (error) {
exec_1.CliUtils.error(`Error creating ${relativePath}: ${error instanceof Error ? error.message : String(error)}`);
errorCount++;
}
}
console.log();
exec_1.CliUtils.subheader('Creation Results');
if (successCount > 0) {
exec_1.CliUtils.success(`Successfully created ${successCount} file(s)`);
}
if (errorCount > 0) {
exec_1.CliUtils.error(`Failed to create ${errorCount} file(s)`);
}
if (successCount > 0) {
console.log();
exec_1.CliUtils.info('Next steps:');
console.log(chalk_1.default.gray('• Edit the created files and add your environment variables'));
console.log(chalk_1.default.gray('• Use "envx encrypt" to encrypt sensitive files'));
console.log(chalk_1.default.gray('• Use "envx interactive" to set up .envrc with secrets'));
}
if (errorCount > 0) {
process.exit(1);
}
}
//# sourceMappingURL=create.js.map