cfn-forge
Version:
CloudFormation deployment automation tool with git-based workflows
208 lines (173 loc) • 5.9 kB
JavaScript
/**
* CFN-Forge Templates Command
* Lists and manages available project templates
*/
const chalk = require('chalk');
const { logger } = require('../utils/logger');
const { listTemplates } = require('../../lib/templates/engine');
/**
* Format template information for display
*/
function formatTemplateInfo(template) {
const sourceIcon = template.source === 'built-in' ? '🏗️' : '👤';
const sourceBadge = template.source === 'built-in'
? chalk.white('built-in')
: chalk.green('user');
return {
name: template.name,
description: template.description || 'No description available',
version: template.version || 'unknown',
author: template.author || 'unknown',
source: template.source,
sourceIcon,
sourceBadge,
cfnForgeVersion: template.cfnForgeVersion || 'any',
};
}
/**
* Display templates in table format
*/
function displayTemplatesTable(templates) {
if (templates.length === 0) {
logger.warn('No templates found');
logger.info('');
logger.info('💡 You can create custom templates using:');
logger.info(' cfn-forge templates --create');
return;
}
logger.info('📋 Available Templates');
logger.info('');
// Calculate column widths
const maxNameLength = Math.max(8, ...templates.map((t) => t.name.length));
const maxDescLength = Math.max(15, ...templates.map((t) => (t.description || '').length));
// Header
console.log(
` ${
'NAME'.padEnd(maxNameLength + 2)
}${'DESCRIPTION'.padEnd(maxDescLength + 2)
}${'VERSION'.padEnd(10)
}SOURCE`,
);
console.log(` ${'─'.repeat(maxNameLength + maxDescLength + 25)}`);
// Template rows
templates.forEach((template) => {
const info = formatTemplateInfo(template);
console.log(
` ${
`${info.sourceIcon} ${chalk.cyan(info.name)}`.padEnd(maxNameLength + 4)
}${(info.description || 'No description').padEnd(maxDescLength + 2)
}${(info.version || 'N/A').padEnd(10)
}${info.sourceBadge}`,
);
});
logger.info('');
logger.info(`📊 Total: ${templates.length} template${templates.length === 1 ? '' : 's'}`);
}
/**
* Display templates in JSON format
*/
function displayTemplatesJSON(templates) {
const output = {
templates: templates.map((template) => ({
name: template.name,
description: template.description,
version: template.version,
author: template.author,
source: template.source,
cfnForgeVersion: template.cfnForgeVersion,
path: template.path,
})),
total: templates.length,
};
console.log(JSON.stringify(output, null, 2));
}
/**
* Display detailed template information
*/
function displayTemplatesDetailed(templates) {
if (templates.length === 0) {
logger.warn('No templates found');
return;
}
logger.info('📋 Available Templates (Detailed)');
logger.info('');
templates.forEach((template, index) => {
const info = formatTemplateInfo(template);
console.log(`${info.sourceIcon} ${chalk.cyan.bold(info.name)}`);
console.log(` Description: ${info.description}`);
console.log(` Version: ${info.version}`);
console.log(` Author: ${info.author}`);
console.log(` Source: ${info.sourceBadge}`);
console.log(` CFN-Forge Version: ${info.cfnForgeVersion}`);
if (template.variables && Object.keys(template.variables).length > 0) {
console.log(' Variables:');
Object.entries(template.variables).forEach(([key, config]) => {
const defaultVal = config.default ? ` (default: ${config.default})` : '';
console.log(` • ${key}${defaultVal}`);
});
}
if (template.hooks && template.hooks.postInstall) {
console.log(` Post-install hooks: ${template.hooks.postInstall.length}`);
}
if (index < templates.length - 1) {
console.log('');
}
});
logger.info('');
logger.info(`📊 Total: ${templates.length} template${templates.length === 1 ? '' : 's'}`);
}
/**
* Filter templates based on options
*/
function filterTemplates(templates, options) {
let filtered = [...templates];
if (options.installed) {
// Show only built-in templates that are "installed" with CFN-Forge
filtered = filtered.filter((t) => t.source === 'built-in');
}
return filtered;
}
/**
* Main templates command handler
*/
async function templatesCommand(options) {
try {
logger.info('🔍 Loading templates...');
// Get all available templates
const allTemplates = await listTemplates();
// Filter based on options
const templates = filterTemplates(allTemplates, options);
// Clear the loading message
process.stdout.write('\r\x1b[K');
// Display templates based on output format
if (options.json) {
displayTemplatesJSON(templates);
} else if (options.detailed) {
displayTemplatesDetailed(templates);
} else {
displayTemplatesTable(templates);
}
// Additional usage information
if (!options.json && templates.length > 0) {
logger.info('');
logger.info('💡 Usage:');
logger.info(' cfn-forge init <template-name> # Initialize project with template');
logger.info(' cfn-forge init --list # List templates during init');
if (templates.some((t) => t.source === 'user')) {
logger.info(' cfn-forge templates --installed # Show only built-in templates');
}
}
} catch (error) {
logger.error(`Failed to load templates: ${error.message}`);
if (process.env.DEBUG) {
console.error(error.stack);
}
logger.info('');
logger.info('💡 Troubleshooting:');
logger.info(' • Check that CFN-Forge is properly installed');
logger.info(' • Verify templates directory exists');
logger.info(' • Run with DEBUG=cfn-forge:* for more details');
process.exit(1);
}
}
module.exports = templatesCommand;