@typescript-eda/domain
Version:
Core domain primitives for event-driven architecture
391 lines • 12.5 kB
JavaScript
"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