UNPKG

@simonecoelhosfo/optimizely-mcp-server

Version:

Optimizely MCP Server for AI assistants with integrated CLI tools

142 lines (133 loc) 5.3 kB
/** * Project Entity Validator * @description Validates entity operations against project capabilities * * Prevents common errors like: * - Creating flags in Web Experimentation projects * - Creating experiments in Feature Experimentation projects * - Missing project type specification * * @author Optimizely MCP Server * @version 1.0.0 */ import { HardStopError, HardStopErrorType } from '../errors/HardStopError.js'; import { getLogger } from '../logging/Logger.js'; export class ProjectEntityValidator { /** * Feature Experimentation entities */ static FEATURE_ENTITIES = new Set([ 'flag', 'ruleset', 'rule', 'environment' // Feature environments ]); /** * Web Experimentation entities */ static WEB_ENTITIES = new Set([ 'experiment', 'campaign', 'page', 'extension' ]); /** * Shared entities (available in both project types) */ static SHARED_ENTITIES = new Set([ 'audience', 'event', 'attribute', 'webhook', 'group', 'collaborator', 'project', 'variation' // Variations exist in both platforms ]); /** * Validate if an entity type is supported by the project * @throws HardStopError if entity is not supported */ static validateEntityForProject(entityType, projectInfo, operation = 'create') { const logger = getLogger(); // If no project info, we can't validate if (!projectInfo) { logger.warn({ entityType, operation }, 'No project info available for validation'); return; } // Determine project type const isFeatureProject = projectInfo.is_flags_enabled === true || projectInfo.platform === 'custom'; const isWebProject = !isFeatureProject; logger.debug({ entityType, projectId: projectInfo.id, isFeatureProject, isWebProject, is_flags_enabled: projectInfo.is_flags_enabled, platform: projectInfo.platform }, 'Validating entity for project type'); // Check if entity is supported if (this.FEATURE_ENTITIES.has(entityType) && isWebProject) { throw new HardStopError(HardStopErrorType.ENTITY_TYPE_MISMATCH, 'FEATURE_ENTITY_IN_WEB_PROJECT', `Cannot ${operation} ${entityType} in Web Experimentation project. ${entityType.charAt(0).toUpperCase() + entityType.slice(1)}s are only available in Feature Experimentation projects. This project (${projectInfo.name || projectInfo.id}) is a Web Experimentation project. To use ${entityType}s, you need a Feature Experimentation project with is_flags_enabled=true.`, 'ASK_USER', 400, ['retry', 'continue', 'auto_fix', 'ignore']); } if (this.WEB_ENTITIES.has(entityType) && isFeatureProject) { throw new HardStopError(HardStopErrorType.ENTITY_TYPE_MISMATCH, 'WEB_ENTITY_IN_FEATURE_PROJECT', `Cannot ${operation} ${entityType} in Feature Experimentation project. ${entityType.charAt(0).toUpperCase() + entityType.slice(1)}s are only available in Web Experimentation projects. This project (${projectInfo.name || projectInfo.id}) is a Feature Experimentation project. To use ${entityType}s, you need a Web Experimentation project (standard project without is_flags_enabled).`, 'ASK_USER', 400, ['retry', 'continue', 'auto_fix', 'ignore']); } // Entity is either shared or valid for this project type logger.debug({ entityType, projectId: projectInfo.id, validation: 'passed' }, 'Entity validation passed'); } /** * Get a helpful message when project type is ambiguous */ static getProjectTypeGuidance() { return `Project type not specified. Optimizely has two project types: 1. **Feature Experimentation Projects** - For feature flags, remote configuration, and server-side A/B testing - Supports: flags, rulesets, environments - Create with: { "is_flags_enabled": true } 2. **Web Experimentation Projects** - For website A/B testing, personalization, and visual editing - Supports: experiments, campaigns, pages - Create with: standard project (is_flags_enabled not set) Please specify which type of project you want to create.`; } /** * Determine if an entity type requires a specific project type */ static getRequiredProjectType(entityType) { if (this.FEATURE_ENTITIES.has(entityType)) { return 'feature'; } if (this.WEB_ENTITIES.has(entityType)) { return 'web'; } return 'any'; } /** * Get supported entities for a project */ static getSupportedEntities(projectInfo) { const isFeatureProject = projectInfo.is_flags_enabled === true || projectInfo.platform === 'custom'; const supported = [...this.SHARED_ENTITIES]; if (isFeatureProject) { this.FEATURE_ENTITIES.forEach(e => supported.push(e)); } else { this.WEB_ENTITIES.forEach(e => supported.push(e)); } return supported.sort(); } } //# sourceMappingURL=ProjectEntityValidator.js.map