/**
* AegisX CRUD Generator Tools
*/
import type { ToolDefinition } from './index.js';
import {
getTroubleshooting,
buildCommand,
generatedFiles,
} from '../data/crud-commands.js';
export const crudTools: ToolDefinition[] = [
{
name: 'aegisx_crud_build_command',
description:
'Build a CRUD generator command with the specified options. Returns the exact command to run.',
inputSchema: {
type: 'object',
properties: {
tableName: {
type: 'string',
description:
'Database table name in snake_case (e.g., "products", "user_profiles")',
},
target: {
type: 'string',
enum: ['backend', 'frontend'],
description: 'Generation target (default: backend)',
},
// === App & Shell Options (Frontend) ===
app: {
type: 'string',
enum: ['api', 'web', 'admin'],
description:
'Target app - api (backend default), web (frontend default), admin',
},
shell: {
type: 'string',
description:
'Target shell for frontend (e.g., "system", "inventory"). Routes registered in shell routes file.',
},
section: {
type: 'string',
description:
'Section within shell (e.g., "master-data"). Module registered in section config.',
},
// === Feature Options ===
withImport: {
type: 'boolean',
description: 'Include Excel/CSV import functionality',
},
withEvents: {
type: 'boolean',
description: 'Include WebSocket events for real-time updates',
},
withExport: {
type: 'boolean',
description: 'Include export functionality (CSV/Excel/PDF)',
},
// === Frontend Options ===
smartStats: {
type: 'boolean',
description: 'Auto-detect statistics fields in table (frontend only)',
},
includeAuditFields: {
type: 'boolean',
description:
'Include audit fields (created_at, updated_at, etc.) in forms (frontend only)',
},
// === Backend Options ===
package: {
type: 'string',
enum: ['standard', 'enterprise', 'full'],
description:
'Feature package to generate - standard (basic CRUD), enterprise (+ bulk ops), full (+ validation)',
},
multipleRoles: {
type: 'boolean',
description:
'Generate 3 roles (admin/editor/viewer) instead of single role (backend only)',
},
noRoles: {
type: 'boolean',
description: 'Skip role generation entirely (backend only)',
},
directDb: {
type: 'boolean',
description:
'Write roles directly to database - development only (backend only)',
},
migrationOnly: {
type: 'boolean',
description:
'Generate migration file only, no CRUD files (backend only)',
},
// === General Options ===
output: {
type: 'string',
description: 'Custom output directory (overrides --app)',
},
config: {
type: 'string',
description: 'Configuration file path',
},
noRegister: {
type: 'boolean',
description:
'Skip auto-registration in plugin.loader.ts / app.routes.ts',
},
noFormat: {
type: 'boolean',
description: 'Skip auto-formatting generated files with prettier',
},
layer: {
type: 'string',
description: 'Architectural layer: core, platform, or domains',
},
type: {
type: 'string',
description:
'Module type within domain (e.g., "master-data", "operations")',
},
// === Domain & Schema ===
domain: {
type: 'string',
description:
'Domain path for module organization (e.g., "inventory", "hr", "inventory/master-data")',
},
schema: {
type: 'string',
description:
'PostgreSQL schema to read table from (default: "public")',
},
// === Control Options ===
force: {
type: 'boolean',
description: 'Overwrite existing files without prompt',
},
dryRun: {
type: 'boolean',
description: 'Preview files without creating them',
},
},
required: ['tableName'],
},
},
// REMOVED: aegisx_crud_packages - Package system replaced with option-based system
{
name: 'aegisx_crud_files',
description: 'Show what files will be generated for a CRUD module.',
inputSchema: {
type: 'object',
properties: {
target: {
type: 'string',
enum: ['backend', 'frontend', 'both'],
description: 'Which target to show files for',
},
tableName: {
type: 'string',
description: 'Table name to show file paths for (optional)',
},
},
},
},
{
name: 'aegisx_crud_troubleshoot',
description: 'Get troubleshooting help for common CRUD generator issues.',
inputSchema: {
type: 'object',
properties: {
problem: {
type: 'string',
description: 'Describe the problem you are experiencing',
},
},
},
},
{
name: 'aegisx_crud_workflow',
description:
'Get the recommended workflow for generating a complete CRUD feature (backend + frontend).',
inputSchema: {
type: 'object',
properties: {
tableName: {
type: 'string',
description: 'Table name for the feature',
},
// Feature Options
withImport: {
type: 'boolean',
description: 'Include import functionality',
},
withEvents: {
type: 'boolean',
description: 'Include real-time events',
},
withExport: {
type: 'boolean',
description: 'Include export functionality',
},
// App & Shell (Frontend)
app: {
type: 'string',
enum: ['web', 'admin'],
description: 'Target frontend app (default: web)',
},
shell: {
type: 'string',
description:
'Target shell for frontend (e.g., "system", "inventory")',
},
section: {
type: 'string',
description: 'Section within shell (e.g., "master-data")',
},
// Domain & Schema
domain: {
type: 'string',
description:
'Domain path for module organization (e.g., "inventory", "hr")',
},
schema: {
type: 'string',
description: 'PostgreSQL schema to read table from',
},
},
required: ['tableName'],
},
},
// === Shell Generator Tools ===
{
name: 'aegisx_shell_generate',
description:
'Generate App Shell (layout component with navigation, routes, and pages). Use this to create a new shell before generating CRUD modules.',
inputSchema: {
type: 'object',
properties: {
shellName: {
type: 'string',
description:
'Shell name in kebab-case (e.g., "inventory", "system")',
},
type: {
type: 'string',
enum: ['simple', 'enterprise', 'multi-app'],
description:
'Shell type - simple (minimal), enterprise (full nav), multi-app (with sub-app tabs)',
},
app: {
type: 'string',
enum: ['web', 'admin'],
description: 'Target app (default: web)',
},
name: {
type: 'string',
description: 'Display name for the shell (e.g., "Inventory System")',
},
theme: {
type: 'string',
enum: ['default', 'indigo', 'teal', 'rose'],
description: 'Theme preset',
},
order: {
type: 'number',
description: 'App order in launcher (default: 0)',
},
withDashboard: {
type: 'boolean',
description: 'Include dashboard page (default: true)',
},
withMasterData: {
type: 'boolean',
description:
'Include Master Data page with ax-launcher (default: true)',
},
withSettings: {
type: 'boolean',
description: 'Include settings page',
},
withAuth: {
type: 'boolean',
description: 'Include AuthGuard and AuthService (default: true)',
},
withThemeSwitcher: {
type: 'boolean',
description: 'Include theme switcher component',
},
force: {
type: 'boolean',
description: 'Force overwrite existing files',
},
dryRun: {
type: 'boolean',
description: 'Preview files without creating them',
},
},
required: ['shellName'],
},
},
{
name: 'aegisx_shell_types',
description:
'Show available shell types (simple, enterprise, multi-app) and their features.',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'aegisx_section_generate',
description:
'Generate a section within a shell (sub-page with ax-launcher for grouping CRUD modules). Use this to organize CRUD modules into categories like "master-data", "reports", etc.',
inputSchema: {
type: 'object',
properties: {
shellName: {
type: 'string',
description: 'Parent shell name (e.g., "inventory")',
},
sectionName: {
type: 'string',
description:
'Section name in kebab-case (e.g., "master-data", "reports")',
},
app: {
type: 'string',
enum: ['web', 'admin'],
description: 'Target app (default: web)',
},
name: {
type: 'string',
description:
'Display name for the section (e.g., "Master Data Management")',
},
force: {
type: 'boolean',
description: 'Force overwrite existing files',
},
dryRun: {
type: 'boolean',
description: 'Preview files without creating them',
},
},
required: ['shellName', 'sectionName'],
},
},
];
// REMOVED: PackageInfo interface and formatPackage function
// Package system replaced with option-based system
export function handleCrudTool(
name: string,
args: Record<string, unknown>,
): { content: Array<{ type: string; text: string }> } {
switch (name) {
case 'aegisx_crud_build_command': {
const tableName = args.tableName as string;
const domain = args.domain as string | undefined;
const schema = args.schema as string | undefined;
const command = buildCommand(tableName, {
// Target & App
target: args.target as 'backend' | 'frontend',
app: args.app as 'api' | 'web' | 'admin' | undefined,
output: args.output as string | undefined,
config: args.config as string | undefined,
// Shell & Section (Frontend)
shell: args.shell as string | undefined,
section: args.section as string | undefined,
// Feature Options
withImport: args.withImport as boolean,
withEvents: args.withEvents as boolean,
withExport: args.withExport as boolean,
// Frontend Options
smartStats: args.smartStats as boolean,
includeAuditFields: args.includeAuditFields as boolean,
// Backend Options
package: args.package as 'standard' | 'enterprise' | 'full' | undefined,
multipleRoles: args.multipleRoles as boolean,
noRoles: args.noRoles as boolean,
directDb: args.directDb as boolean,
migrationOnly: args.migrationOnly as boolean,
// General Options
noRegister: args.noRegister as boolean,
noFormat: args.noFormat as boolean,
layer: args.layer as string | undefined,
type: args.type as string | undefined,
// Domain & Schema
domain,
schema,
// Control
force: args.force as boolean,
dryRun: args.dryRun as boolean,
});
const lines: string[] = [];
lines.push('# CRUD Generator Command');
lines.push('');
lines.push('```bash');
lines.push(command);
lines.push('```');
lines.push('');
// Add domain initialization note
if (domain) {
const domainRoot = domain.split('/')[0];
lines.push(`> **Note:** Initialize domain first if not already done:`);
lines.push('> ```bash');
lines.push(`> pnpm run domain:init -- ${domainRoot}`);
lines.push(
`> npx knex migrate:latest --knexfile knexfile-${domainRoot}.ts`,
);
lines.push('> ```');
lines.push('');
}
// Add helpful notes based on options
if (args.target === 'frontend') {
lines.push('> **Note:** Generate backend first before frontend.');
lines.push('> ```bash');
let backendCmd = `> ./bin/cli.js generate ${tableName}`;
if (domain) backendCmd += ` --domain ${domain}`;
if (schema) backendCmd += ` --schema ${schema}`;
if (args.withImport) backendCmd += ' --with-import';
if (args.withEvents) backendCmd += ' --with-events';
backendCmd += ' --force';
lines.push(backendCmd);
lines.push('> ```');
}
if (args.dryRun) {
lines.push('');
lines.push(
'> This is a dry run. Remove `--dry-run` to actually generate files.',
);
}
return {
content: [{ type: 'text', text: lines.join('\n') }],
};
}
// REMOVED: aegisx_crud_packages handler - Package system replaced with option-based system
case 'aegisx_crud_files': {
const target = (args.target as string) || 'both';
const tableName = (args.tableName as string) || '{name}';
// Convert snake_case to kebab-case
const kebabName = tableName.replace(/_/g, '-');
const lines: string[] = [];
lines.push('# Generated Files');
lines.push('');
if (target === 'backend' || target === 'both') {
lines.push('## Backend Files');
lines.push('```');
for (const file of generatedFiles.backend) {
const path = file.path.replace(/{name}/g, kebabName);
lines.push(`apps/api/src/${path}`);
lines.push(` └─ ${file.description}`);
}
lines.push('```');
lines.push('');
}
if (target === 'frontend' || target === 'both') {
lines.push('## Frontend Files');
lines.push('```');
for (const file of generatedFiles.frontend) {
const path = file.path.replace(/{name}/g, kebabName);
lines.push(`apps/admin/src/app/${path}`);
lines.push(` └─ ${file.description}`);
}
lines.push('```');
}
return {
content: [{ type: 'text', text: lines.join('\n') }],
};
}
case 'aegisx_crud_troubleshoot': {
const problem = (args.problem as string) || '';
const tips = getTroubleshooting();
const lines: string[] = [];
lines.push('# CRUD Generator Troubleshooting');
lines.push('');
// Find relevant tips
const q = problem.toLowerCase();
const relevant = tips.filter(
(t) =>
t.problem.toLowerCase().includes(q) ||
t.solution.toLowerCase().includes(q),
);
if (relevant.length > 0 && problem) {
lines.push(`## Solutions for: "${problem}"`);
lines.push('');
for (const tip of relevant) {
lines.push(`### ${tip.problem}`);
lines.push(tip.solution);
if (tip.example) {
lines.push('```bash');
lines.push(tip.example);
lines.push('```');
}
lines.push('');
}
} else {
lines.push('## Common Issues & Solutions');
lines.push('');
for (const tip of tips) {
lines.push(`### ${tip.problem}`);
lines.push(tip.solution);
if (tip.example) {
lines.push('```bash');
lines.push(tip.example);
lines.push('```');
}
lines.push('');
}
}
return {
content: [{ type: 'text', text: lines.join('\n') }],
};
}
case 'aegisx_crud_workflow': {
const tableName = args.tableName as string;
const withImport = args.withImport as boolean;
const withEvents = args.withEvents as boolean;
const withExport = args.withExport as boolean;
const app = args.app as 'web' | 'admin' | undefined;
const shell = args.shell as string | undefined;
const section = args.section as string | undefined;
const domain = args.domain as string | undefined;
const schema = args.schema as string | undefined;
const kebabName = tableName.replace(/_/g, '-');
const domainRoot = domain ? domain.split('/')[0] : null;
const kebabDomain = domainRoot ? domainRoot.replace(/_/g, '-') : null;
const lines: string[] = [];
lines.push(`# Complete CRUD Workflow for \`${tableName}\``);
if (domain) {
lines.push(
`**Domain:** ${domain} | **Schema:** ${schema || domainRoot}`,
);
}
lines.push('');
lines.push('## Prerequisites');
lines.push('');
lines.push('1. Ensure database is running:');
lines.push('```bash');
lines.push('docker ps | grep postgres');
lines.push('```');
lines.push('');
// Add domain initialization step if domain is specified
if (domain && domainRoot) {
lines.push('2. Initialize domain (if not already done):');
lines.push('```bash');
lines.push(`pnpm run domain:init -- ${domainRoot}`);
lines.push('```');
lines.push('');
lines.push('3. Run domain migrations:');
lines.push('```bash');
lines.push(
`npx knex migrate:latest --knexfile knexfile-${kebabDomain}.ts`,
);
lines.push('```');
lines.push('');
lines.push('4. Check table exists in schema:');
lines.push('```bash');
lines.push(
`psql -c "SELECT table_name FROM information_schema.tables WHERE table_schema = '${schema || domainRoot}'"`,
);
lines.push('```');
} else {
lines.push('2. Check table exists:');
lines.push('```bash');
lines.push('pnpm run crud:list');
lines.push('```');
}
lines.push('');
lines.push('## Step 1: Generate Backend');
lines.push('');
lines.push('```bash');
let backendFullCmd = `./bin/cli.js generate ${tableName}`;
if (domain) {
backendFullCmd += ` --domain ${domain}`;
}
if (schema) {
backendFullCmd += ` --schema ${schema}`;
}
if (withImport) {
backendFullCmd += ' --with-import';
}
if (withEvents) {
backendFullCmd += ' --with-events';
}
backendFullCmd += ' --force';
lines.push(backendFullCmd);
lines.push('```');
lines.push('');
// Module path depends on domain
const modulePath = domain
? `apps/api/src/modules/${kebabDomain}/${domain.includes('/') ? domain.split('/').slice(1).join('/') + '/' : ''}${kebabName}`
: `apps/api/src/modules/${kebabName}`;
lines.push('Generated files:');
lines.push(`- \`${modulePath}/${kebabName}.routes.ts\``);
lines.push(`- \`${modulePath}/${kebabName}.controller.ts\``);
lines.push(`- \`${modulePath}/${kebabName}.service.ts\``);
lines.push(`- \`${modulePath}/${kebabName}.repository.ts\``);
lines.push(`- \`${modulePath}/${kebabName}.schemas.ts\``);
lines.push(`- \`${modulePath}/${kebabName}.types.ts\``);
lines.push('');
lines.push('## Step 2: Verify Backend');
lines.push('');
lines.push('```bash');
lines.push('# Build to check for errors');
lines.push('pnpm run build');
lines.push('');
lines.push('# Start API server');
lines.push('pnpm run dev:api');
lines.push('');
lines.push('# Test endpoint (in another terminal)');
const apiPath = domain
? `/api/${kebabDomain}/${domain.includes('/') ? domain.split('/').slice(1).join('/') + '/' : ''}${kebabName}`
: `/api/${kebabName}`;
lines.push(`curl http://localhost:3333${apiPath}`);
lines.push('```');
lines.push('');
lines.push('## Step 3: Generate Frontend');
lines.push('');
lines.push('```bash');
let frontendCmd = `./bin/cli.js generate ${tableName} --target frontend`;
if (domain) {
frontendCmd += ` --domain ${domain}`;
}
if (app) {
frontendCmd += ` --app ${app}`;
}
if (shell) {
frontendCmd += ` --shell ${shell}`;
}
if (section) {
frontendCmd += ` --section ${section}`;
}
if (withImport) {
frontendCmd += ' --with-import';
}
if (withEvents) {
frontendCmd += ' --with-events';
}
if (withExport) {
frontendCmd += ' --with-export';
}
frontendCmd += ' --force';
lines.push(frontendCmd);
lines.push('```');
lines.push('');
const frontendPath = domain
? `apps/admin/src/app/features/${kebabDomain}/${domain.includes('/') ? domain.split('/').slice(1).join('/') + '/' : ''}${kebabName}`
: `apps/admin/src/app/features/${kebabName}`;
lines.push('Generated files:');
lines.push(`- \`${frontendPath}/\``);
lines.push(` - \`${kebabName}.component.ts\``);
lines.push(` - \`${kebabName}.service.ts\``);
lines.push(` - \`${kebabName}.types.ts\``);
lines.push(` - \`${kebabName}.routes.ts\``);
lines.push(` - \`components/\` (list, form, dialog)`);
lines.push('');
lines.push('## Step 4: Add Navigation');
lines.push('');
const navLink = domain
? `/${kebabDomain}/${domain.includes('/') ? domain.split('/').slice(1).join('/') + '/' : ''}${kebabName}`
: `/${kebabName}`;
lines.push('Add to your navigation config:');
lines.push('```typescript');
lines.push('// apps/admin/src/app/config/navigation.config.ts');
lines.push(`{`);
lines.push(` id: '${kebabName}',`);
lines.push(
` title: '${tableName.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase())}',`,
);
lines.push(` type: 'basic',`);
lines.push(` icon: 'heroicons_outline:folder',`);
lines.push(` link: '${navLink}',`);
lines.push(`}`);
lines.push('```');
lines.push('');
lines.push('## Step 5: Test Feature');
lines.push('');
lines.push('```bash');
lines.push('# Start both servers');
lines.push('pnpm run dev');
lines.push('');
lines.push('# Open admin app');
lines.push('open http://localhost:4200');
lines.push('```');
lines.push('');
lines.push('## Validation');
lines.push('');
lines.push('```bash');
lines.push(`pnpm run crud:validate -- ${tableName}`);
lines.push('```');
return {
content: [{ type: 'text', text: lines.join('\n') }],
};
}
case 'aegisx_shell_generate': {
const shellName = args.shellName as string;
const shellType = (args.type as string) || 'enterprise';
const app = (args.app as string) || 'web';
const lines: string[] = [];
lines.push(`# Generate App Shell: ${shellName}`);
lines.push('');
lines.push('```bash');
let cmd = `./bin/cli.js shell ${shellName}`;
if (shellType !== 'enterprise') {
cmd += ` --type ${shellType}`;
}
if (app !== 'web') {
cmd += ` --app ${app}`;
}
if (args.name) {
cmd += ` --name "${args.name}"`;
}
if (args.theme && args.theme !== 'default') {
cmd += ` --theme ${args.theme}`;
}
if (args.order) {
cmd += ` --order ${args.order}`;
}
if (args.withSettings) {
cmd += ' --with-settings';
}
if (args.withThemeSwitcher) {
cmd += ' --with-theme-switcher';
}
if (args.force) {
cmd += ' --force';
}
if (args.dryRun) {
cmd += ' --dry-run';
}
lines.push(cmd);
lines.push('```');
lines.push('');
lines.push('## Generated Files');
lines.push('');
const shellPath = `apps/${app}/src/app/features/${shellName}`;
lines.push(`\`\`\`\n${shellPath}/`);
lines.push(`├── ${shellName}-shell.component.ts`);
lines.push(`├── ${shellName}.config.ts`);
lines.push(`├── ${shellName}.routes.ts`);
lines.push(`├── index.ts`);
lines.push(`└── pages/`);
if (shellType !== 'simple') {
lines.push(` ├── dashboard/dashboard.page.ts`);
lines.push(` ├── master-data/master-data.page.ts`);
if (args.withSettings) {
lines.push(` └── settings/settings.page.ts`);
}
} else {
lines.push(` └── main/main.page.ts`);
}
lines.push('```');
lines.push('');
lines.push('## Next Steps');
lines.push('');
lines.push('1. Add route to `app.routes.ts`:');
lines.push('```typescript');
lines.push(`// ${shellName.charAt(0).toUpperCase() + shellName.slice(1)}`);
lines.push(`{`);
lines.push(` path: '${shellName}',`);
lines.push(
` loadChildren: () => import('./features/${shellName}/${shellName}.routes').then(m => m.${shellName.toUpperCase().replace(/-/g, '_')}_ROUTES)`,
);
lines.push(`}`);
lines.push('```');
lines.push('');
lines.push('2. Generate sections if needed:');
lines.push(
`\`\`\`bash\n./bin/cli.js section ${shellName} master-data --force\n\`\`\``,
);
lines.push('');
lines.push('3. Generate CRUD modules:');
lines.push(
`\`\`\`bash\n./bin/cli.js generate products --target frontend --shell ${shellName} --force\n\`\`\``,
);
return {
content: [{ type: 'text', text: lines.join('\n') }],
};
}
case 'aegisx_shell_types': {
const lines: string[] = [];
lines.push('# Available Shell Types');
lines.push('');
lines.push('## 🟢 SIMPLE');
lines.push('Uses `AxEmptyLayoutComponent`');
lines.push('');
lines.push('**Features:**');
lines.push('- Minimal layout without navigation');
lines.push('- Suitable for: Auth pages, landing pages, error pages');
lines.push('');
lines.push('**Example:**');
lines.push('```bash');
lines.push('./bin/cli.js shell auth --type simple --force');
lines.push('```');
lines.push('');
lines.push('## 🟡 ENTERPRISE (default)');
lines.push('Uses `AxEnterpriseLayoutComponent`');
lines.push('');
lines.push('**Features:**');
lines.push('- Full navigation sidebar');
lines.push('- Header with actions');
lines.push('- Footer with version');
lines.push('- Dashboard and Master Data pages');
lines.push('- Single sub-app navigation');
lines.push('');
lines.push('**Example:**');
lines.push('```bash');
lines.push('./bin/cli.js shell inventory --force');
lines.push('```');
lines.push('');
lines.push('## 🔴 MULTI-APP');
lines.push('Uses `AxEnterpriseLayoutComponent` with sub-app tabs');
lines.push('');
lines.push('**Features:**');
lines.push('- All enterprise features, plus:');
lines.push('- Sub-app tabs in header');
lines.push('- Suitable for: Large enterprise applications');
lines.push('');
lines.push('**Example:**');
lines.push('```bash');
lines.push('./bin/cli.js shell erp --type multi-app --force');
lines.push('```');
return {
content: [{ type: 'text', text: lines.join('\n') }],
};
}
case 'aegisx_section_generate': {
const shellName = args.shellName as string;
const sectionName = args.sectionName as string;
const app = (args.app as string) || 'web';
const lines: string[] = [];
lines.push(`# Generate Section: ${sectionName} in ${shellName}`);
lines.push('');
lines.push('```bash');
let cmd = `./bin/cli.js section ${shellName} ${sectionName}`;
if (app !== 'web') {
cmd += ` --app ${app}`;
}
if (args.name) {
cmd += ` --name "${args.name}"`;
}
if (args.force) {
cmd += ' --force';
}
if (args.dryRun) {
cmd += ' --dry-run';
}
lines.push(cmd);
lines.push('```');
lines.push('');
lines.push('## Generated Files');
lines.push('');
const sectionPath = `apps/${app}/src/app/features/${shellName}/pages/${sectionName}`;
lines.push(`\`\`\`\n${sectionPath}/`);
lines.push(`├── ${sectionName}.page.ts`);
lines.push(`└── ${sectionName}.config.ts`);
lines.push('```');
lines.push('');
lines.push('## What This Does');
lines.push('');
lines.push(
`1. Creates a new page in \`${shellName}\` shell with ax-launcher`,
);
lines.push(
`2. Adds route to \`${shellName}.routes.ts\`: \`/${shellName}/${sectionName}\``,
);
lines.push(
`3. CRUD modules can now be registered to this section using \`--section ${sectionName}\``,
);
lines.push('');
lines.push('## Next Steps');
lines.push('');
lines.push('Generate CRUD modules into this section:');
lines.push('```bash');
lines.push(
`./bin/cli.js generate products --target frontend --shell ${shellName} --section ${sectionName} --force`,
);
lines.push('```');
lines.push('');
lines.push('Result:');
lines.push(`- Route: \`/${shellName}/${sectionName}/products\``);
lines.push(
`- Module registered in: \`${sectionPath}/${sectionName}.config.ts\``,
);
return {
content: [{ type: 'text', text: lines.join('\n') }],
};
}
default:
return {
content: [{ type: 'text', text: `Unknown CRUD tool: ${name}` }],
};
}
}