import { formatPath } from '@/cli/utilities/file/utils/file-path'; import chalk from 'chalk'; import type { Command } from 'commander'; import { AppBuildCommand } from './app/app-build'; import { AppDevCommand } from './app/app-dev'; import { AppGenerateCommand } from './app/app-generate'; import { AppSyncCommand } from './app/app-sync'; import { AppUninstallCommand } from './app/app-uninstall'; import { AuthLoginCommand } from './auth/auth-login'; import { AuthLogoutCommand } from './auth/auth-logout'; import { AuthStatusCommand } from './auth/auth-status'; import { FunctionExecuteCommand } from './function/function-execute'; import { FunctionLogsCommand } from './function/function-logs'; import { EntityAddCommand, isSyncableEntity, SyncableEntity, } from './entity/entity-add'; export const registerCommands = (program: Command): void => { // Auth commands const loginCommand = new AuthLoginCommand(); const logoutCommand = new AuthLogoutCommand(); const statusCommand = new AuthStatusCommand(); program .command('auth:login') .description('Authenticate with Twenty') .option('--api-key ', 'API key for authentication') .option('--api-url ', 'Twenty API URL') .action(async (options) => { await loginCommand.execute(options); }); program .command('auth:logout') .description('Remove authentication credentials') .action(async () => { await logoutCommand.execute(); }); program .command('auth:status') .description('Check authentication status') .action(async () => { await statusCommand.execute(); }); // App commands const devCommand = new AppDevCommand(); const syncCommand = new AppSyncCommand(); const uninstallCommand = new AppUninstallCommand(); const addCommand = new EntityAddCommand(); const generateCommand = new AppGenerateCommand(); const logsCommand = new FunctionLogsCommand(); const executeCommand = new FunctionExecuteCommand(); const buildCommand = new AppBuildCommand(); program .command('app:dev [appPath]') .description('Watch and sync local application changes') .action(async (appPath) => { await devCommand.execute({ appPath: formatPath(appPath), }); }); program .command('app:build [appPath]') .description('Build application for deployment') .option('-w, --watch', 'Watch for changes and rebuild') .option('-t, --tarball', 'Create a tarball after build') .action(async (appPath, options) => { try { const result = await buildCommand.execute({ ...options, appPath: formatPath(appPath), }); if (!result.success) { process.exit(1); } } catch { process.exit(1); } }); program .command('app:sync [appPath]') .description('Sync application to Twenty') .action(async (appPath?: string) => { try { const result = await syncCommand.execute(formatPath(appPath)); if (!result.success) { process.exit(1); } } catch { process.exit(1); } }); program .command('app:uninstall [appPath]') .description('Uninstall application from Twenty') .action(async (appPath?: string) => { try { const result = await uninstallCommand.execute({ appPath: formatPath(appPath), askForConfirmation: true, }); if (!result.success) { process.exit(1); } } catch { process.exit(1); } }); program .command('entity:add [entityType]') .option('--path ', 'Path in which the entity should be created.') .description( `Add a new entity to your application (${Object.values(SyncableEntity).join('|')})`, ) .action(async (entityType?: string, options?: { path?: string }) => { if (entityType && !isSyncableEntity(entityType)) { console.error( chalk.red( `Invalid entity type "${entityType}". Must be one of: ${Object.values(SyncableEntity).join('|')}`, ), ); process.exit(1); } await addCommand.execute(entityType as SyncableEntity, options?.path); }); program .command('app:generate [appPath]') .description('Generate Twenty client') .action(async (appPath?: string) => { await generateCommand.execute(formatPath(appPath)); }); // Function commands program .command('function:logs [appPath]') .option( '-u, --functionUniversalIdentifier ', 'Only show logs for the function with this universal ID', ) .option( '-n, --functionName ', 'Only show logs for the function with this name', ) .description('Watch application function logs') .action( async ( appPath?: string, options?: { functionUniversalIdentifier?: string; functionName?: string; }, ) => { await logsCommand.execute({ ...options, appPath: formatPath(appPath), }); }, ); program .command('function:execute [appPath]') .option( '-p, --payload ', 'JSON payload to send to the function', '{}', ) .option( '-u, --functionUniversalIdentifier ', 'Universal ID of the function to execute', ) .option( '-n, --functionName ', 'Name of the function to execute', ) .description('Execute a serverless function with a JSON payload') .action( async ( appPath?: string, options?: { payload?: string; functionUniversalIdentifier?: string; functionName?: string; }, ) => { if (!options?.functionUniversalIdentifier && !options?.functionName) { console.error( chalk.red( 'Error: Either --functionName (-n) or --functionUniversalIdentifier (-u) is required.', ), ); process.exit(1); } await executeCommand.execute({ ...options, payload: options?.payload ?? '{}', appPath: formatPath(appPath), }); }, ); };