Skip to main content
Glama

WhaTap MXQL CLI

by devload
interactive.ts6.44 kB
/** * Interactive REPL mode */ import inquirer from 'inquirer'; import chalk from 'chalk'; import { WhatapClient } from '../../core/client/WhatapClient'; import { MxqlExecutor, TimeRanges } from '../../core/executor/MxqlExecutor'; import { requireAuth } from '../utils/session'; import { formatOutput, formatQuerySummary, printSuccess, printError, printInfo, printWarning } from '../utils/formatters'; import type { Project } from '../../core/types'; interface InteractiveOptions { project?: string; } /** * Interactive command handler */ export async function interactiveCommand(options: InteractiveOptions): Promise<void> { try { console.log(''); console.log(chalk.cyan.bold('WhaTap MXQL Interactive Mode')); console.log(chalk.gray('Type "help" for available commands, "exit" to quit')); console.log(''); // Require authentication const authManager = await requireAuth(); // Create client and executor const client = new WhatapClient(authManager); const executor = new MxqlExecutor(client); // Get projects printInfo('Loading projects...'); const projects = await client.getProjects(); console.log(''); printSuccess(`Loaded ${projects.length} projects`); console.log(''); // Select default project let currentProject: Project | undefined; if (options.project) { const pcode = parseInt(options.project, 10); currentProject = projects.find(p => p.projectCode === pcode); if (!currentProject) { printWarning(`Project ${options.project} not found`); } else { console.log(chalk.gray('Default project:'), chalk.cyan(currentProject.projectName), chalk.gray(`(${currentProject.projectCode})`)); console.log(''); } } // REPL loop let running = true; while (running) { const { command } = await inquirer.prompt([ { type: 'input', name: 'command', message: currentProject ? chalk.cyan(`[${currentProject.projectCode}]`) + chalk.gray('>') : chalk.gray('>'), prefix: '', }, ]); const trimmed = command.trim(); if (!trimmed) { continue; } // Parse command const parts = trimmed.split(/\s+/); const cmd = parts[0].toLowerCase(); try { switch (cmd) { case 'help': showHelp(); break; case 'exit': case 'quit': console.log(''); printInfo('Goodbye!'); console.log(''); running = false; break; case 'projects': case 'list': listProjects(projects); break; case 'use': case 'select': if (parts.length < 2) { printError('Usage: use <project_code>'); break; } const pcode = parseInt(parts[1], 10); const project = projects.find(p => p.projectCode === pcode); if (!project) { printError(`Project ${parts[1]} not found. Use "projects" to list all projects`); } else { currentProject = project; printSuccess(`Selected project: ${project.projectName} (${project.projectCode})`); } break; case 'query': case 'exec': if (!currentProject) { printError('No project selected. Use "use <project_code>" to select a project'); break; } const mxql = parts.slice(1).join(' '); if (!mxql) { printError('Usage: query <mxql>'); printInfo('Or enter multi-line MXQL directly'); break; } await executeQuery(executor, currentProject.projectCode, mxql); break; default: // Treat as MXQL query if project is selected if (currentProject) { await executeQuery(executor, currentProject.projectCode, trimmed); } else { printError(`Unknown command: ${cmd}. Type "help" for available commands`); } break; } } catch (error: any) { printError('Command failed', error); } console.log(''); } } catch (error: any) { console.log(''); printError('Interactive mode failed', error); process.exit(1); } } /** * Show help message */ function showHelp(): void { console.log(''); console.log(chalk.cyan.bold('Available Commands:')); console.log(''); console.log(chalk.white(' help'), chalk.gray('- Show this help message')); console.log(chalk.white(' projects'), chalk.gray('or'), chalk.white('list'), chalk.gray('- List all projects')); console.log(chalk.white(' use <pcode>'), chalk.gray('- Select a project')); console.log(chalk.white(' query <mxql>'), chalk.gray('- Execute MXQL query')); console.log(chalk.white(' exit'), chalk.gray('or'), chalk.white('quit'), chalk.gray('- Exit interactive mode')); console.log(''); console.log(chalk.cyan.bold('MXQL Shortcuts:')); console.log(''); console.log(chalk.gray(' When a project is selected, you can type MXQL directly:')); console.log(chalk.white(' > CATEGORY app_counter')); console.log(chalk.white(' > TAGLOAD')); console.log(''); } /** * List projects */ function listProjects(projects: Project[]): void { console.log(''); console.log(chalk.cyan.bold(`Projects (${projects.length}):`)); console.log(''); projects.forEach((p, i) => { const typeColor = p.productType === 'MOBILE' ? chalk.blue : p.productType === 'BROWSER' ? chalk.magenta : chalk.green; console.log( chalk.gray(` ${i + 1}.`), chalk.white(p.projectCode), chalk.gray('-'), chalk.cyan(p.projectName), typeColor(`[${p.productType}]`) ); }); console.log(''); } /** * Execute MXQL query */ async function executeQuery(executor: MxqlExecutor, pcode: number, mxql: string): Promise<void> { printInfo('Executing...'); const result = await executor.execute( pcode, mxql, TimeRanges.lastHour(), 50 ); console.log(''); printSuccess('Query executed'); console.log(''); console.log(formatQuerySummary(result)); console.log(''); if (result.rowCount === 0) { printWarning('No data returned'); } else { console.log(formatOutput(result.data, 'table')); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/devload/whatap-mxql-cli'

If you have feedback or need assistance with the MCP directory API, please join our Discord server