UNPKG

@typescript-eda/domain

Version:

Core domain primitives for event-driven architecture

391 lines 12.5 kB
"use strict"; // Copyright 2025-today Semantest Team // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. Object.defineProperty(exports, "__esModule", { value: true }); exports.SemanTestCapability = void 0; /** * @fileoverview SemanTestCapability entity representing automation capabilities * @author Semantest Team * @module domain/semantic-automation/semantest-capability */ const entity_1 = require("../entity"); /** * SemanTestCapability entity representing individual automation capabilities * Extends Entity from typescript-eda-domain for consistent domain modeling */ class SemanTestCapability extends entity_1.Entity { constructor(props) { super(props); } /** * Factory method to create a new capability */ static create(id, name, type, description, selector, options) { const now = new Date(); return new SemanTestCapability({ id, name, type, description, selector, parameters: options?.parameters, returnType: options?.returnType, validation: options?.validation, timeout: options?.timeout, retries: options?.retries, conditions: options?.conditions, examples: options?.examples, createdAt: now, updatedAt: now }); } /** * Get capability ID */ getId() { return this.get('id'); } /** * Get capability name */ getName() { return this.get('name'); } /** * Get capability type */ getType() { return this.get('type'); } /** * Get capability description */ getDescription() { return this.get('description'); } /** * Get element selector */ getSelector() { return this.get('selector'); } /** * Get primary selector string */ getPrimarySelector() { const selector = this.getSelector(); return typeof selector === 'string' ? selector : selector.primary; } /** * Get fallback selectors */ getFallbackSelectors() { const selector = this.getSelector(); return typeof selector === 'string' ? [] : (selector.fallback || []); } /** * Get all selectors (primary + fallbacks) */ getAllSelectors() { return [this.getPrimarySelector(), ...this.getFallbackSelectors()]; } /** * Get capability parameters */ getParameters() { return this.get('parameters') || []; } /** * Get required parameters */ getRequiredParameters() { return this.getParameters().filter(param => param.required); } /** * Get optional parameters */ getOptionalParameters() { return this.getParameters().filter(param => !param.required); } /** * Get parameter by name */ getParameter(name) { return this.getParameters().find(param => param.name === name); } /** * Check if capability has parameter */ hasParameter(name) { return this.getParameters().some(param => param.name === name); } /** * Get return type definition */ getReturnType() { return this.get('returnType'); } /** * Get validation rules */ getValidation() { return this.get('validation'); } /** * Get execution timeout */ getTimeout() { return this.get('timeout'); } /** * Get retry attempts */ getRetries() { return this.get('retries'); } /** * Get execution conditions */ getConditions() { return this.get('conditions') || []; } /** * Get capability examples */ getExamples() { return this.get('examples') || []; } /** * Get creation timestamp */ getCreatedAt() { return this.get('createdAt'); } /** * Get last update timestamp */ getUpdatedAt() { return this.get('updatedAt'); } /** * Check if capability is an action type */ isAction() { return this.getType() === 'action'; } /** * Check if capability is a query type */ isQuery() { return this.getType() === 'query'; } /** * Check if capability is a form type */ isForm() { return this.getType() === 'form'; } /** * Check if capability requires parameters */ requiresParameters() { return this.getRequiredParameters().length > 0; } /** * Validate parameter values against capability definition */ validateParameters(parameters) { const errors = []; const warnings = []; // Check required parameters for (const requiredParam of this.getRequiredParameters()) { if (!(requiredParam.name in parameters)) { errors.push(`Required parameter '${requiredParam.name}' is missing`); } } // Validate provided parameters for (const [paramName, paramValue] of Object.entries(parameters)) { const paramDef = this.getParameter(paramName); if (!paramDef) { warnings.push(`Unknown parameter '${paramName}' provided`); continue; } // Type validation const expectedType = paramDef.type; const actualType = typeof paramValue; if (expectedType === 'array' && !Array.isArray(paramValue)) { errors.push(`Parameter '${paramName}' expected array, got ${actualType}`); } else if (expectedType !== 'array' && actualType !== expectedType) { errors.push(`Parameter '${paramName}' expected ${expectedType}, got ${actualType}`); } // Validation rules if (paramDef.validation) { const validation = paramDef.validation; if (typeof paramValue === 'string') { if (validation.minLength && paramValue.length < validation.minLength) { errors.push(`Parameter '${paramName}' must be at least ${validation.minLength} characters`); } if (validation.maxLength && paramValue.length > validation.maxLength) { errors.push(`Parameter '${paramName}' must be at most ${validation.maxLength} characters`); } if (validation.pattern && !new RegExp(validation.pattern).test(paramValue)) { errors.push(`Parameter '${paramName}' does not match required pattern`); } } if (typeof paramValue === 'number') { if (validation.minimum !== undefined && paramValue < validation.minimum) { errors.push(`Parameter '${paramName}' must be at least ${validation.minimum}`); } if (validation.maximum !== undefined && paramValue > validation.maximum) { errors.push(`Parameter '${paramName}' must be at most ${validation.maximum}`); } } if (validation.enum && !validation.enum.includes(paramValue)) { errors.push(`Parameter '${paramName}' must be one of: ${validation.enum.join(', ')}`); } } } return { valid: errors.length === 0, errors, warnings }; } /** * Validate capability structure and configuration */ validate() { const errors = []; const warnings = []; // Validate required fields if (!this.getId()) { errors.push('Capability ID is required'); } if (!this.getName()) { errors.push('Capability name is required'); } if (!this.getDescription()) { errors.push('Capability description is required'); } if (!this.getPrimarySelector()) { errors.push('Primary selector is required'); } // Validate selector syntax (basic check) try { const primarySelector = this.getPrimarySelector(); if (primarySelector && !this.isValidCSSSelector(primarySelector)) { warnings.push('Primary selector may not be valid CSS'); } const fallbackSelectors = this.getFallbackSelectors(); for (const selector of fallbackSelectors) { if (!this.isValidCSSSelector(selector)) { warnings.push(`Fallback selector '${selector}' may not be valid CSS`); } } } catch (error) { warnings.push('Could not validate selector syntax'); } // Validate parameters const paramNames = new Set(); for (const param of this.getParameters()) { if (paramNames.has(param.name)) { errors.push(`Duplicate parameter name: ${param.name}`); } paramNames.add(param.name); if (!param.name) { errors.push('Parameter name is required'); } if (!param.type) { errors.push(`Parameter '${param.name}' type is required`); } } // Validate examples for (const [index, example] of this.getExamples().entries()) { if (!example.description) { warnings.push(`Example ${index + 1} is missing description`); } // Validate example parameters against capability definition const paramValidation = this.validateParameters(example.parameters); if (!paramValidation.valid) { errors.push(`Example ${index + 1}: ${paramValidation.errors.join(', ')}`); } } return { valid: errors.length === 0, errors, warnings, timestamp: new Date() }; } /** * Basic CSS selector validation */ isValidCSSSelector(selector) { try { // Basic syntax check - this could be more comprehensive return selector.trim().length > 0 && !selector.includes('><') && !selector.includes('<<'); } catch { return false; } } /** * Convert capability to JSON for serialization */ toJSON() { return { id: this.getId(), name: this.getName(), type: this.getType(), description: this.getDescription(), selector: this.getSelector(), parameters: this.getParameters(), returnType: this.getReturnType(), validation: this.getValidation(), timeout: this.getTimeout(), retries: this.getRetries(), conditions: this.getConditions(), examples: this.getExamples(), createdAt: this.getCreatedAt().toISOString(), updatedAt: this.getUpdatedAt().toISOString() }; } /** * Create capability from JSON */ static fromJSON(json) { return new SemanTestCapability({ id: json.id, name: json.name, type: json.type, description: json.description, selector: json.selector, parameters: json.parameters, returnType: json.returnType, validation: json.validation, timeout: json.timeout, retries: json.retries, conditions: json.conditions, examples: json.examples, createdAt: new Date(json.createdAt), updatedAt: new Date(json.updatedAt) }); } } exports.SemanTestCapability = SemanTestCapability; //# sourceMappingURL=semantest-capability.entity.js.map