@wkovacs64/add-icon
Version:
CLI tool to download and transform icons from Iconify
127 lines (124 loc) • 5.44 kB
JavaScript
import path from 'node:path';
import { Command } from 'commander';
import { downloadIcon } from './iconify.js';
import { loadConfig } from './config.js';
import { importModule } from './import-module.js';
import { getPackageInfo } from './package-info.js';
// Re-export other useful functions
export { downloadIcon, parseIconReference } from './iconify.js';
export { loadConfig, defaultConfig } from './config.js';
// Create CLI program
const program = new Command();
// Set up the program with package info
const setupProgram = async () => {
const { name, version, description } = await getPackageInfo();
return program
.name(name.split('/').pop() || name)
.description(description)
.option('--init', 'Generate a config file in the current directory')
.option('-o, --output-dir <dir>', 'Directory to save icons')
.option('-c, --config <path>', 'Path to config file')
.option('-t, --transform <path>', 'Path to custom transform module (.js or .ts)')
.version(version, '-v, --version', 'Output the current version')
.argument('[icons...]', 'Icon references (e.g., heroicons:arrow-up-circle mdi:home)');
};
// Initialize the program
const initializedProgram = await setupProgram();
initializedProgram.action(async (icons, options) => {
try {
// Validate that icons are provided when not using --init
if (!options.init && (!icons || icons.length === 0)) {
console.error('Error: At least one icon reference is required.');
program.help();
return;
}
// Handle --init flag to generate a config file
if (options.init) {
const fs = await import('node:fs/promises');
const configFileContent = `import type { Config } from '@wkovacs64/add-icon';
const config = {
outputDir: 'app/assets/svg-icons',
} satisfies Config;
export default config;
`;
try {
const configFilePath = path.resolve(process.cwd(), 'add-icon.config.ts');
await fs.writeFile(configFilePath, configFileContent, 'utf-8');
console.log(`✓ Configuration file created at: ${configFilePath}`);
process.exit(0);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error(`Error creating config file: ${errorMessage}`);
process.exit(1);
}
}
// Load config (first from config file, then override with CLI options)
const config = await loadConfig(options.config);
// Override output directory if specified in CLI
if (options.outputDir) {
config.outputDir = options.outputDir;
}
// Load custom transform if specified
if (options.transform) {
try {
const transformPath = path.resolve(process.cwd(), options.transform);
let customTransform;
try {
// Use unified import method for both JS and TS files
customTransform = await importModule(transformPath);
}
catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
console.error(`Error loading transform: ${errorMessage}`);
process.exit(1);
}
if (customTransform && typeof customTransform.default === 'function') {
config.transforms = [customTransform.default];
}
else {
console.error('Custom transform must export a default function');
process.exit(1);
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error(`Failed to load custom transform: ${errorMessage}`);
process.exit(1);
}
}
// Download all icons
const results = [];
for (const icon of icons) {
console.log(`Downloading icon: ${icon}...`);
try {
const savedPath = await downloadIcon(icon, config);
console.log(`✓ Icon saved to: ${savedPath}`);
results.push({ icon, path: savedPath, success: true });
}
catch (iconError) {
const errorMessage = iconError instanceof Error ? iconError.message : String(iconError);
console.error(`Error downloading ${icon}: ${errorMessage}`);
results.push({ icon, error: errorMessage, success: false });
}
}
// Report summary if multiple icons
if (icons.length > 1) {
const successful = results.filter((r) => r.success).length;
console.log(`\nSummary: Downloaded ${successful}/${icons.length} icons`);
// If any failed, exit with error
if (successful < icons.length) {
process.exit(1);
}
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error(`Error: ${errorMessage}`);
process.exit(1);
}
});
// Parse command line arguments if called directly
export function runCli() {
program.parse(process.argv);
}