myex-cli
Version:
Opinionated Express.js framework with CLI tools
88 lines (77 loc) • 2.78 kB
JavaScript
import path from 'path';
import fs from 'fs-extra';
import chalk from 'chalk';
import ora from 'ora';
import { fileURLToPath } from 'url';
import ejs from 'ejs';
import { pascalCase, camelCase } from '../utils/string-utils.js';
// Convert ES Module path
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const templatesDir = path.resolve(__dirname, '../templates/model');
/**
* Generate a new model file
* @param {string} name - Model name
* @param {Object} options - Command options
*/
export async function generateModel(name, options) {
const spinner = ora(`Generating model: ${chalk.blue(name)}`).start();
try {
// Ensure proper casing
const modelName = pascalCase(name);
const modelFileName = `${camelCase(name)}.model.js`;
const destPath = path.join(process.cwd(), 'src', 'models', modelFileName);
// Check if model already exists
if (fs.existsSync(destPath)) {
spinner.warn(chalk.yellow(`Model ${modelFileName} already exists. Skipping.`));
return;
}
// Parse fields if provided
let fields = [];
if (options.fields && options.fields.length > 0) {
fields = parseFields(options.fields);
} else {
// Default fields if none provided
fields = [
{ name: 'name', type: 'String', required: true },
{ name: 'description', type: 'String', required: false },
{ name: 'isActive', type: 'Boolean', required: false, default: true },
{ name: 'createdBy', type: 'mongoose.Schema.Types.ObjectId', ref: 'User', required: false }
];
}
// Load template
const templateFile = path.join(templatesDir, 'model.template.ejs');
const template = await fs.readFile(templateFile, 'utf8');
// Render template
const content = ejs.render(template, {
modelName,
modelNameCamel: camelCase(name),
fields
});
// Create model file
await fs.ensureDir(path.dirname(destPath));
await fs.writeFile(destPath, content, 'utf8');
spinner.succeed(chalk.green(`Model generated: ${destPath}`));
} catch (error) {
spinner.fail(chalk.red(`Failed to generate model: ${error.message}`));
}
}
/**
* Parse field definitions from command options
* Format: name:type:required:default:ref
* Example: title:String:true:null:null
* @param {Array} fields - Array of field definitions
* @returns {Array} Parsed fields
*/
function parseFields(fields) {
return fields.map(field => {
const parts = field.split(':');
return {
name: parts[0],
type: parts[1] || 'String',
required: parts[2] === 'true',
default: parts[3] !== 'null' ? parts[3] : undefined,
ref: parts[4] !== 'null' ? parts[4] : undefined
};
});
}