UNPKG

@simonecoelhosfo/optimizely-mcp-server

Version:

Optimizely MCP Server for AI assistants with integrated CLI tools

152 lines 5.29 kB
/** * Entity Table Mapper * * Handles conversion between entity names (singular) and table names (plural). * This solves the mismatch between internal entity references and SQL table names. * * Examples: * - Entity: 'flag' -> Table: 'flags' * - Entity: 'audience' -> Table: 'audiences' * - Entity: 'flag_environment' -> Table: 'flag_environments' */ import { getLogger } from '../../logging/Logger.js'; const logger = getLogger(); export class EntityTableMapper { // Explicit mappings for irregular plurals and special cases entityToTableMap = { 'flag': 'flags', 'event': 'events', 'audience': 'audiences', 'attribute': 'attributes', 'variation': 'variations', 'rule': 'rules', 'ruleset': 'rulesets', 'experiment': 'experiments', 'campaign': 'campaigns', 'page': 'pages', 'extension': 'extensions', 'webhook': 'webhooks', 'collaborator': 'collaborators', 'environment': 'environments', 'flag_environment': 'flag_environments', 'project': 'projects', 'group': 'groups', 'list_attribute': 'list_attributes', 'variable_definition': 'variable_definitions', 'change_history': 'change_history', // Already plural 'experiment_results': 'experiment_results', // Already plural 'results': 'experiment_results', // Map 'results' entity to experiment_results table 'fx_environment': 'fx_environments', 'report': 'reports', 'feature': 'features' }; // Reverse mapping for table to entity tableToEntityMap; constructor() { // Build reverse mapping this.tableToEntityMap = {}; for (const [entity, table] of Object.entries(this.entityToTableMap)) { this.tableToEntityMap[table] = entity; } logger.debug(`EntityTableMapper initialized with ${Object.keys(this.entityToTableMap).length} mappings`); } /** * Convert entity name (singular) to table name (plural) */ getTableName(entity) { if (!entity) { throw new Error('Entity name cannot be empty'); } // Check explicit mapping first if (this.entityToTableMap[entity]) { return this.entityToTableMap[entity]; } // Handle already plural cases if (entity.endsWith('s') && this.tableToEntityMap[entity]) { return entity; // It's already a table name } // Default pluralization rules if (entity.endsWith('y') && !entity.endsWith('ey')) { // entity -> entities, activity -> activities return entity.slice(0, -1) + 'ies'; } else if (entity.endsWith('s') || entity.endsWith('x') || entity.endsWith('ch') || entity.endsWith('sh')) { // status -> statuses, box -> boxes, match -> matches return entity + 'es'; } else { // Default: just add 's' return entity + 's'; } } /** * Convert table name (plural) to entity name (singular) */ getEntityName(table) { if (!table) { throw new Error('Table name cannot be empty'); } // Check explicit mapping first if (this.tableToEntityMap[table]) { return this.tableToEntityMap[table]; } // Handle already singular cases if (this.entityToTableMap[table]) { return table; // It's already an entity name } // Reverse pluralization rules if (table.endsWith('ies') && table.length > 3) { // entities -> entity, activities -> activity return table.slice(0, -3) + 'y'; } else if (table.endsWith('es') && (table.endsWith('ses') || table.endsWith('xes') || table.endsWith('ches') || table.endsWith('shes'))) { // statuses -> status, boxes -> box, matches -> match return table.slice(0, -2); } else if (table.endsWith('s') && table.length > 1) { // Default: remove 's' return table.slice(0, -1); } else { // Can't determine singular form return table; } } /** * Check if a name is an entity name (singular) */ isEntityName(name) { return this.entityToTableMap.hasOwnProperty(name) || (!this.tableToEntityMap.hasOwnProperty(name) && !name.endsWith('s')); } /** * Check if a name is a table name (plural) */ isTableName(name) { return this.tableToEntityMap.hasOwnProperty(name) || (!this.entityToTableMap.hasOwnProperty(name) && name.endsWith('s')); } /** * Normalize a name to entity form (singular) */ toEntityName(name) { if (this.isEntityName(name)) { return name; } return this.getEntityName(name); } /** * Normalize a name to table form (plural) */ toTableName(name) { if (this.isTableName(name)) { return name; } return this.getTableName(name); } } // Export singleton instance export const entityTableMapper = new EntityTableMapper(); //# sourceMappingURL=EntityTableMapper.js.map