UNPKG

@prolaxu/galaxy-api-tool

Version:

CLI tool for generating Galaxy API files (Controllers, Resources, Vue components)

173 lines (141 loc) 6.23 kB
const fs = require('fs-extra'); const path = require('path'); const Handlebars = require('handlebars'); const pluralize = require('pluralize'); class Generator { constructor(basePath = process.cwd()) { this.basePath = basePath; this.templatesPath = path.join(__dirname, '..', 'templates'); // Register Handlebars helpers this.registerHelpers(); } registerHelpers() { Handlebars.registerHelper('capitalize', (text) => { return text.charAt(0).toUpperCase() + text.slice(1); }); Handlebars.registerHelper('toLowerCase', (text) => { return text.toLowerCase(); }); Handlebars.registerHelper('pluralize', (text) => { return pluralize(text); }); Handlebars.registerHelper('singularize', (text) => { return pluralize.singular(text); }); } async loadTemplate(templateName) { const templatePath = path.join(this.templatesPath, templateName); const templateContent = await fs.readFile(templatePath, 'utf8'); return Handlebars.compile(templateContent); } async ensureDirectory(dirPath) { await fs.ensureDir(dirPath); } async writeFile(filePath, content) { await this.ensureDirectory(path.dirname(filePath)); await fs.writeFile(filePath, content, 'utf8'); } validateModelName(modelName) { if (!modelName || modelName.trim() === '') { throw new Error('Model name is required'); } if (!/^[a-zA-Z][a-zA-Z0-9_/]*$/.test(modelName)) { throw new Error('Model name must start with a letter and contain only letters, numbers, underscores, and slashes'); } } parseModelInput(modelInput) { this.validateModelName(modelInput); let modelName, groupFolder, importPath, fullLowerPath; if (modelInput.includes('/')) { groupFolder = path.dirname(modelInput); modelName = path.basename(modelInput); const lowerGroup = groupFolder.toLowerCase(); const lowerName = modelName.toLowerCase(); fullLowerPath = `${lowerGroup}/${lowerName}`; importPath = `${lowerGroup}/${lowerName}`; } else { groupFolder = ''; modelName = modelInput; const lowerName = modelName.toLowerCase(); fullLowerPath = lowerName; importPath = lowerName; } return { modelName, groupFolder, importPath, fullLowerPath }; } async generateApi(modelName) { this.validateModelName(modelName); const data = { modelName }; // Generate Controller const controllerTemplate = await this.loadTemplate('controller.hbs'); const controllerContent = controllerTemplate(data); const controllerPath = path.join(this.basePath, 'src', 'GalaxyAPI', 'Controllers', `${modelName}Controller.php`); await this.writeFile(controllerPath, controllerContent); // Generate Request const requestTemplate = await this.loadTemplate('request.hbs'); const requestContent = requestTemplate(data); const requestPath = path.join(this.basePath, 'src', 'GalaxyAPI', 'Requests', `${modelName}Request.php`); await this.writeFile(requestPath, requestContent); // Generate Resource const resourceTemplate = await this.loadTemplate('resource.hbs'); const resourceContent = resourceTemplate(data); const resourcePath = path.join(this.basePath, 'src', 'GalaxyAPI', 'Resources', `${modelName}Resource.php`); await this.writeFile(resourcePath, resourceContent); } async generateApiEmpty(modelName) { this.validateModelName(modelName); const data = { modelName }; // Generate Controller (empty version) const controllerTemplate = await this.loadTemplate('controller-empty.hbs'); const controllerContent = controllerTemplate(data); const controllerPath = path.join(this.basePath, 'src', 'GalaxyAPI', 'Controllers', `${modelName}Controller.php`); await this.writeFile(controllerPath, controllerContent); // Generate Resource const resourceTemplate = await this.loadTemplate('resource.hbs'); const resourceContent = resourceTemplate(data); const resourcePath = path.join(this.basePath, 'src', 'GalaxyAPI', 'Resources', `${modelName}Resource.php`); await this.writeFile(resourcePath, resourceContent); } async generateViews(modelInput) { const parsed = this.parseModelInput(modelInput); const { modelName, groupFolder, importPath, fullLowerPath } = parsed; const data = { modelName, groupFolder, importPath, fullLowerPath }; // Generate Store const storeTemplate = await this.loadTemplate('store.hbs'); const storeContent = storeTemplate(data); const storePath = path.join(this.basePath, 'resources', 'assets', 'spa', 'stores', 'modules', fullLowerPath, `use${modelName}Store.js`); await this.writeFile(storePath, storeContent); // Generate Form const formTemplate = await this.loadTemplate('form.hbs'); const formContent = formTemplate(data); const formPath = path.join(this.basePath, 'resources', 'assets', 'spa', 'modules', fullLowerPath, `${modelName}Form.vue`); await this.writeFile(formPath, formContent); // Generate List const listTemplate = await this.loadTemplate('list.hbs'); const listContent = listTemplate(data); const listPath = path.join(this.basePath, 'resources', 'assets', 'spa', 'modules', fullLowerPath, `${modelName}ListComponent.vue`); await this.writeFile(listPath, listContent); // Generate Select const selectTemplate = await this.loadTemplate('select.hbs'); const selectContent = selectTemplate(data); const selectPath = path.join(this.basePath, 'resources', 'assets', 'spa', 'modules', fullLowerPath, `${modelName}Select.vue`); await this.writeFile(selectPath, selectContent); return { ...parsed, storePath: `resources/assets/spa/stores/modules/${fullLowerPath}/use${modelName}Store.js`, formPath: `resources/assets/spa/modules/${fullLowerPath}/${modelName}Form.vue`, listPath: `resources/assets/spa/modules/${fullLowerPath}/${modelName}ListComponent.vue`, selectPath: `resources/assets/spa/modules/${fullLowerPath}/${modelName}Select.vue` }; } } module.exports = Generator;