import { Command } from 'commander'; import path from 'path'; import fs from 'fs'; import { v4 } from 'uuid'; import { getProjectPath } from '../../../../helpers/cluserHelper'; import { schemaYaml } from '../../../../components/schemaTemplate'; import { tableYaml } from '../../../../components/tableTemplate'; import { normalizeName } from '../../../../helpers/profileGeneratorHelper'; import inquirer from 'inquirer'; import { parse, stringify } from 'yaml'; import { mergeVariables } from '../../../../helpers/variablesHelper'; import { setEntityColumnsSourceId, setEntityColumnsKeys, setEntityColumnsTrackForChanges, setEntityColumnsVisibility, } from '../../../../helpers/entityHelper'; import { composeProfile } from '../../../compose/composeCommand'; import { switchProfile } from '../../switchProfileCommand'; export function GenerateSchemaCommand(): Command { const cmd = new Command('generate') .alias('g') .description('Generate a schema and its table from input.') .option( '-n, --schema-name ', "Search for related schema, e.g.: 'warehouse mapping', 'shipping method mapping', etc.", ) .action(async ({ schemaName }) => { const componentPath = getProjectPath(); if (!fs.existsSync(path.join(componentPath, 'schemas'))) { fs.mkdirSync(path.join(componentPath, 'schemas'), { recursive: true, }); } const schemaPath = path.join(componentPath, 'schemas'); if (!fs.existsSync(schemaPath)) { fs.mkdirSync(schemaPath, { recursive: true }); } const normalizedSchemaName = normalizeName(schemaName); const schemaVariableKey = `${normalizedSchemaName.camelCaseName}_Schema`; let schemaYml = schemaYaml(); const schemaId = v4(); const tableId = v4(); const schemaVariables = [ { field: 'id', key: `**${schemaVariableKey}_Id**`, value: schemaId, }, { field: 'name', key: `**${schemaVariableKey}_Name**`, value: `[Mapping] ${normalizedSchemaName.displayName}`, }, { field: 'tableName', key: `**${schemaVariableKey}_Table_Name**`, value: `schema_${normalizedSchemaName.underscoreSlug}`, }, { field: 'tableId', key: `**${schemaVariableKey}_Table_Id**`, value: tableId, }, ]; for (const variable of schemaVariables) { schemaYml = schemaYml.replaceAll( `||VARIABLE_KEY_${variable.field}||`, variable.key, ); } const { columns } = await inquirer.prompt([ { type: 'input', name: 'columns', message: 'Please provide table columns (comma-separated):', }, ]); const columnsArray = columns.split(',').map((col) => col.trim()); let tableYml = tableYaml(); const tableVariables = [ { field: 'id', key: `**${schemaVariableKey}_Table_Id**`, value: tableId, }, ]; for (const variable of tableVariables) { tableYml = tableYml.replaceAll( `||VARIABLE_KEY_${variable.field}||`, variable.key, ); } const tableContent = parse(tableYml); tableContent.tables[0].columns = columnsArray.reduce((acc, col) => { acc[col.replace(/[^a-zA-Z0-9]+/g, '_').toLowerCase()] = { name: col, indexGroups: [], }; return acc; }, {}); tableYml = stringify(tableContent, { keepSourceTokens: true, lineWidth: 0, }); mergeVariables(schemaVariables); const schemaFilePath = path.join(schemaPath, `${schemaVariableKey}.yaml`); const schemaTableFilePath = path.join( schemaPath, `${schemaVariableKey}_Table.yaml`, ); if (fs.existsSync(schemaFilePath)) { console.error(`Schema file already exists at ${schemaFilePath}`); return; } if (fs.existsSync(schemaTableFilePath)) { console.error(`Table file already exists at ${schemaTableFilePath}`); return; } fs.writeFileSync(schemaFilePath, schemaYml); fs.writeFileSync(schemaTableFilePath, tableYml); console.log(`Schema and table generated successfully: Columns: ${columnsArray.join(', ')}`); await switchProfile(componentPath, {}); await setEntityColumnsSourceId(tableId, '', 'table'); await setEntityColumnsKeys(tableId, '', 'table'); await setEntityColumnsTrackForChanges(tableId, '', 'table'); await setEntityColumnsVisibility(tableId, '', 'table'); await composeProfile(); }); return cmd; }