UNPKG

@praxisui/visual-builder

Version:

Visual rule and expression builder for Praxis UI with mini-DSL support, validation and context variables.

1,574 lines (1,557 loc) 121 kB
import * as i0 from '@angular/core'; import { EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, ElementRef, ChangeDetectorRef } from '@angular/core'; import { ContextProvider, FunctionRegistry, ExportOptions as ExportOptions$1, ValidationIssue as ValidationIssue$1, ContextualSpecification } from '@praxisui/specification'; import { SpecificationMetadata, Specification } from '@praxisui/specification-core'; export { SpecificationMetadata } from '@praxisui/specification-core'; import { Observable } from 'rxjs'; import { FormBuilder, FormGroup, FormArray } from '@angular/forms'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatButtonToggleChange } from '@angular/material/button-toggle'; import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { MatSelectChange } from '@angular/material/select'; import { MatSlideToggleChange } from '@angular/material/slide-toggle'; import { MatChipInputEvent } from '@angular/material/chips'; /** * Models for the Visual Rule Builder */ /** * Value types for rule configuration */ type ValueType = 'literal' | 'field' | 'context' | 'function'; /** * Valid comparison operators (aligned with @praxisui/specification) */ type ValidComparisonOperator = 'eq' | 'neq' | 'lt' | 'lte' | 'gt' | 'gte' | 'contains' | 'startsWith' | 'endsWith' | 'in'; interface RuleNode { /** Unique identifier for this rule node */ id: string; /** Type of rule node */ type: RuleNodeType | RuleNodeTypeString; /** Human-readable label for this rule */ label?: string; /** Rule metadata */ metadata?: SpecificationMetadata; /** Whether this node is currently selected */ selected?: boolean; /** Whether this node is expanded (for groups) */ expanded?: boolean; /** Parent node ID */ parentId?: string; /** Child node IDs (for groups) */ children?: string[]; /** Rule-specific configuration */ config?: RuleNodeConfig; } declare enum RuleNodeType { FIELD_CONDITION = "fieldCondition", AND_GROUP = "andGroup", OR_GROUP = "orGroup", NOT_GROUP = "notGroup", XOR_GROUP = "xorGroup", IMPLIES_GROUP = "impliesGroup", REQUIRED_IF = "requiredIf", VISIBLE_IF = "visibleIf", DISABLED_IF = "disabledIf", READONLY_IF = "readonlyIf", FOR_EACH = "forEach", UNIQUE_BY = "uniqueBy", MIN_LENGTH = "minLength", MAX_LENGTH = "maxLength", IF_DEFINED = "ifDefined", IF_NOT_NULL = "ifNotNull", IF_EXISTS = "ifExists", WITH_DEFAULT = "withDefault", FUNCTION_CALL = "functionCall", FIELD_TO_FIELD = "fieldToField", CONTEXTUAL = "contextual", AT_LEAST = "atLeast", EXACTLY = "exactly", EXPRESSION = "expression", CONTEXTUAL_TEMPLATE = "contextualTemplate", CUSTOM = "custom" } /** * String literal type for rule node types (for flexibility) */ type RuleNodeTypeString = 'fieldCondition' | 'andGroup' | 'orGroup' | 'notGroup' | 'xorGroup' | 'impliesGroup' | 'requiredIf' | 'visibleIf' | 'disabledIf' | 'readonlyIf' | 'forEach' | 'uniqueBy' | 'minLength' | 'maxLength' | 'ifDefined' | 'ifNotNull' | 'ifExists' | 'withDefault' | 'functionCall' | 'fieldToField' | 'contextual' | 'atLeast' | 'exactly' | 'expression' | 'contextualTemplate' | 'custom'; type RuleNodeConfig = FieldConditionConfig | BooleanGroupConfig | ConditionalValidatorConfig | CollectionValidationConfig | CollectionValidatorConfig | OptionalFieldConfig | FunctionCallConfig | FieldToFieldConfig | ContextualConfig$1 | CardinalityConfig | ExpressionConfig | ContextualTemplateConfig | CustomConfig; interface FieldConditionConfig { type: 'fieldCondition'; /** Primary field name */ fieldName: string; /** Comparison operator aligned with @praxisui/specification */ operator: ValidComparisonOperator | string; /** Comparison value */ value: unknown; /** Type of value for proper handling */ valueType?: ValueType; /** Field to compare against (for field-to-field comparisons) */ compareToField?: string; /** Context variable to use as value */ contextVariable?: string; /** Optional metadata for error messages and UI hints */ metadata?: SpecificationMetadata; /** Legacy field alias for backward compatibility */ field?: string; } interface BooleanGroupConfig { type: 'booleanGroup' | 'andGroup' | 'orGroup' | 'notGroup' | 'xorGroup' | 'impliesGroup'; /** Boolean operator type */ operator: 'and' | 'or' | 'not' | 'xor' | 'implies'; /** Minimum required true conditions (for atLeast scenarios) */ minimumRequired?: number; /** Exact required true conditions (for exactly scenarios) */ exactRequired?: number; /** Optional metadata for group validation */ metadata?: SpecificationMetadata; } interface ConditionalValidatorConfig { type: 'requiredIf' | 'visibleIf' | 'disabledIf' | 'readonlyIf'; /** Specific validator type (mirrors type for backward compatibility) */ validatorType: 'requiredIf' | 'visibleIf' | 'disabledIf' | 'readonlyIf'; /** Target field to apply conditional logic */ targetField: string; /** Optional single condition (legacy support) */ condition?: RuleNode; /** Multiple conditions for advanced mode */ conditions?: RuleNode[]; /** Reference to condition rule node ID (for backward compatibility) */ conditionNodeId?: string; /** Whether to invert the condition result */ inverse?: boolean; /** Logic operator to combine multiple conditions */ logicOperator?: 'and' | 'or'; /** Custom error message */ errorMessage?: string; /** Validate on value change */ validateOnChange?: boolean; /** Validate on blur */ validateOnBlur?: boolean; /** Show error immediately */ showErrorImmediately?: boolean; /** Animation type */ animation?: string; /** Hide field label */ hideLabel?: boolean; /** Preserve space when hidden */ preserveSpace?: boolean; /** Style when disabled */ disabledStyle?: string; /** Clear value when disabled */ clearOnDisable?: boolean; /** Show disabled message */ showDisabledMessage?: boolean; /** Custom disabled message */ disabledMessage?: string; /** Readonly style */ readonlyStyle?: string; /** Show readonly indicator */ showReadonlyIndicator?: boolean; /** Metadata aligned with @praxisui/specification */ metadata?: SpecificationMetadata; } interface CollectionValidationConfig { type: 'collectionValidation'; /** Type of collection validation */ validationType: 'forEach' | 'uniqueBy' | 'minLength' | 'maxLength'; /** Array field to validate */ arrayField: string; /** Reference to rule node ID for forEach validation */ itemCondition?: string; /** Property name for uniqueBy validation */ uniqueKey?: string; /** Length value for min/max length validation */ lengthValue?: number; /** Optional metadata for validation */ metadata?: SpecificationMetadata; } /** * Enhanced collection validator configuration (Phase 2 Implementation) * Aligned with @praxisui/specification collection validation patterns */ interface CollectionValidatorConfig { type: 'forEach' | 'uniqueBy' | 'minLength' | 'maxLength'; /** Target collection field name */ targetCollection: string; /** Variable name for current item in forEach */ itemVariable?: string; /** Variable name for current index in forEach */ indexVariable?: string; /** Validation rules applied to each item */ itemValidationRules?: { ruleType: string; fieldPath: string; errorMessage?: string; }[]; /** Fields to check uniqueness by */ uniqueByFields?: string[]; /** Case-sensitive uniqueness check */ caseSensitive?: boolean; /** Ignore empty values in uniqueness check */ ignoreEmpty?: boolean; /** Custom error message for duplicates */ duplicateErrorMessage?: string; /** Minimum number of items */ minItems?: number; /** Maximum number of items */ maxItems?: number; /** Custom error message for length validation */ lengthErrorMessage?: string; /** Show current item count in UI */ showItemCount?: boolean; /** Prevent adding items beyond maxItems */ preventExcess?: boolean; /** Validate when items are added */ validateOnAdd?: boolean; /** Validate when items are removed */ validateOnRemove?: boolean; /** Validate when items are changed */ validateOnChange?: boolean; /** Validate on form submit */ validateOnSubmit?: boolean; /** Error display strategy */ errorStrategy?: 'summary' | 'inline' | 'both'; /** Stop validation on first error */ stopOnFirstError?: boolean; /** Highlight items with errors */ highlightErrorItems?: boolean; /** Batch size for large collections */ batchSize?: number; /** Debounce validation for performance */ debounceValidation?: boolean; /** Debounce delay in milliseconds */ debounceDelay?: number; /** Optional metadata for validation messages */ metadata?: SpecificationMetadata; } interface FunctionCallConfig { type: 'functionCall'; /** Name of the function to call */ functionName: string; /** Function parameters with type information */ parameters: FunctionParameter[]; /** Optional metadata for validation */ metadata?: SpecificationMetadata; } interface FunctionParameter { /** Parameter name */ name: string; /** Parameter value */ value: unknown; /** Type of parameter value */ valueType: ValueType; /** Field name if valueType is 'field' */ fieldName?: string; /** Context variable name if valueType is 'context' */ contextVariable?: string; } interface FieldToFieldConfig { type: 'fieldToField'; /** Left side field name */ leftField: string; /** Comparison operator */ operator: ValidComparisonOperator | string; /** Right side field name */ rightField: string; /** Transform functions applied to left field */ leftTransforms?: string[]; /** Transform functions applied to right field */ rightTransforms?: string[]; /** Optional metadata for validation */ metadata?: SpecificationMetadata; } interface ContextualConfig$1 { type: 'contextual'; /** Template string with context placeholders */ template: string; /** Available context variables */ contextVariables: Record<string, unknown>; /** Optional context provider for dynamic values */ contextProvider?: ContextProvider; /** Strict validation of context tokens */ strictContextValidation?: boolean; /** Optional metadata */ metadata?: SpecificationMetadata; } interface CardinalityConfig { type: 'cardinality'; /** Type of cardinality check */ cardinalityType: 'atLeast' | 'exactly'; /** Required count of true conditions */ count: number; /** References to rule node IDs to evaluate */ conditions: string[]; /** Optional metadata for validation */ metadata?: SpecificationMetadata; } interface CustomConfig { type: 'custom'; /** Custom configuration type identifier */ customType: string; /** Custom properties specific to the type */ properties: Record<string, unknown>; /** Optional metadata for validation */ metadata?: SpecificationMetadata; } /** * Validator types for conditional validation */ declare enum ConditionalValidatorType { REQUIRED_IF = "requiredIf", VISIBLE_IF = "visibleIf", DISABLED_IF = "disabledIf", READONLY_IF = "readonlyIf" } /** * Preview data for conditional validator simulation */ interface ConditionalValidatorPreview { targetField: string; currentValue: unknown; conditionResult: boolean; validatorType: ConditionalValidatorType; resultingState: { isRequired?: boolean; isVisible?: boolean; isDisabled?: boolean; isReadonly?: boolean; }; example: string; } /** * Rule building session state */ interface RuleBuilderState { /** All rule nodes in the current session */ nodes: Record<string, RuleNode>; /** Root node IDs (top-level rules) */ rootNodes: string[]; /** Currently selected node ID */ selectedNodeId?: string; /** Current DSL representation */ currentDSL?: string; /** Current JSON representation */ currentJSON?: unknown; /** Validation errors */ validationErrors: ValidationError$1[]; /** Build mode */ mode: 'visual' | 'dsl' | 'json'; /** Whether the rule is dirty (has unsaved changes) */ isDirty: boolean; /** Undo/redo history */ history: RuleBuilderSnapshot[]; /** Current history position */ historyPosition: number; } interface ValidationError$1 { /** Error ID */ id: string; /** Error message */ message: string; /** Error severity */ severity: 'error' | 'warning' | 'info'; /** Associated node ID */ nodeId?: string; /** Error code for programmatic handling */ code?: string; /** Suggested fix */ suggestion?: string; } interface RuleBuilderSnapshot { /** Timestamp of this snapshot */ timestamp: number; /** Description of the change */ description: string; /** Complete state at this point */ state: { nodes: Record<string, RuleNode>; rootNodes: string[]; selectedNodeId?: string; }; } /** * Rule template for common scenarios */ interface RuleTemplate { /** Template ID */ id: string; /** Template name */ name: string; /** Template description */ description: string; /** Template category */ category: string; /** Template tags for search */ tags: string[]; /** Rule nodes that make up this template */ nodes: RuleNode[]; /** Root node IDs */ rootNodes: string[]; /** Required field schemas for this template */ requiredFields?: string[]; /** Example usage */ example?: string; /** Template preview image/icon */ icon?: string; /** Template metadata */ metadata?: TemplateMetadata; } /** * Template metadata for tracking and management */ interface TemplateMetadata { /** Creation date */ createdAt?: Date; /** Last update date */ updatedAt?: Date; /** Last used date */ lastUsed?: Date; /** Import date (if imported) */ importedAt?: Date; /** Template version */ version?: string; /** Usage count */ usageCount?: number; /** Template complexity */ complexity?: 'simple' | 'medium' | 'complex'; /** Original template ID (for imports/copies) */ originalId?: string; /** Author information */ author?: { name?: string; email?: string; organization?: string; }; /** Template size metrics */ metrics?: { nodeCount?: number; maxDepth?: number; fieldCount?: number; }; } /** * Export options for rules */ interface ExportOptions { /** Export format */ format: 'json' | 'dsl' | 'typescript' | 'form-config'; /** Include metadata in export */ includeMetadata?: boolean; /** Pretty print JSON/DSL */ prettyPrint?: boolean; /** Include comments in DSL */ includeComments?: boolean; /** Metadata position in DSL */ metadataPosition?: 'before' | 'after' | 'inline'; /** TypeScript interface name (for TS export) */ interfaceName?: string; /** Additional export configuration */ config?: Record<string, unknown>; } /** * Import options for rules */ interface ImportOptions { /** Source format */ format: 'json' | 'dsl' | 'form-config'; /** Whether to merge with existing rules */ merge?: boolean; /** Whether to preserve existing metadata */ preserveMetadata?: boolean; /** Field schema mapping for validation */ fieldSchemas?: Record<string, unknown>; } /** * Rule builder configuration */ interface RuleBuilderConfig { /** Available field schemas */ fieldSchemas: Record<string, unknown>; /** Context variables */ contextVariables?: unknown[]; /** Custom functions */ customFunctions?: unknown[]; /** Available rule templates */ templates?: RuleTemplate[]; /** UI configuration */ ui?: { /** Theme */ theme?: 'light' | 'dark' | 'auto'; /** Show advanced features */ showAdvanced?: boolean; /** Enable drag and drop */ enableDragDrop?: boolean; /** Show DSL preview */ showDSLPreview?: boolean; /** Show validation errors inline */ showInlineErrors?: boolean; /** Auto-save interval (ms) */ autoSaveInterval?: number; }; /** Validation configuration */ validation?: { /** Enable real-time validation */ realTime?: boolean; /** Validation strictness */ strictness?: 'strict' | 'normal' | 'loose'; /** Custom validation rules */ customRules?: unknown[]; }; /** Export/import configuration */ exportImport?: { /** Default export format */ defaultExportFormat?: 'json' | 'dsl' | 'typescript'; /** Supported formats */ supportedFormats?: string[]; /** Include metadata by default */ includeMetadataByDefault?: boolean; }; } /** * Configuration for optional field handling */ interface OptionalFieldConfig { type: 'optionalField'; /** Type of optional field validation */ validationType: 'ifDefined' | 'ifNotNull' | 'ifExists' | 'withDefault'; /** Target field name */ fieldName: string; /** Default value when field is undefined/null */ defaultValue?: unknown; /** Reference to condition rule node ID */ conditionNodeId?: string; /** Optional metadata for validation */ metadata?: SpecificationMetadata; } /** * Configuration for expression specifications (aligned with @praxisui/specification) */ interface ExpressionConfig { type: 'expression'; /** DSL expression string */ expression: string; /** Function registry for validation */ functionRegistry?: FunctionRegistry<unknown>; /** Context provider for variable resolution */ contextProvider?: ContextProvider; /** Known field names for validation */ knownFields?: string[]; /** Enable performance warnings */ enablePerformanceWarnings?: boolean; /** Maximum expression complexity */ maxComplexity?: number; /** Metadata aligned with @praxisui/specification */ metadata?: SpecificationMetadata; } /** * Configuration for contextual template specifications (aligned with @praxisui/specification) */ interface ContextualTemplateConfig { type: 'contextualTemplate'; /** Template string with context tokens */ template: string; /** Available context variables */ contextVariables?: Record<string, unknown>; /** Context provider instance */ contextProvider?: ContextProvider; /** Enable strict validation of context tokens */ strictContextValidation?: boolean; /** Metadata aligned with @praxisui/specification */ metadata?: SpecificationMetadata; } declare class PraxisVisualBuilder { config: RuleBuilderConfig | null; initialRules: any; rulesChanged: EventEmitter<any>; exportRequested: EventEmitter<ExportOptions>; importRequested: EventEmitter<ImportOptions>; onRulesChanged(rules: any): void; onExportRequested(options: ExportOptions): void; onImportRequested(options: ImportOptions): void; static ɵfac: i0.ɵɵFactoryDeclaration<PraxisVisualBuilder, never>; static ɵcmp: i0.ɵɵComponentDeclaration<PraxisVisualBuilder, "praxis-visual-builder", never, { "config": { "alias": "config"; "required": false; }; "initialRules": { "alias": "initialRules"; "required": false; }; }, { "rulesChanged": "rulesChanged"; "exportRequested": "exportRequested"; "importRequested": "importRequested"; }, never, never, true, never>; } /** * Field schema model for dynamic field configuration in the Visual Builder */ interface FieldSchema { /** Unique field identifier */ name: string; /** Human-readable field label */ label: string; /** Field data type */ type: FieldType; /** Optional description or help text */ description?: string; /** Whether this field is required */ required?: boolean; /** Allowed values for enum/select fields */ allowedValues?: FieldOption[]; /** Format constraints for the field */ format?: FieldFormat; /** UI configuration for field display */ uiConfig?: FieldUIConfig; /** Nested fields for object types */ properties?: Record<string, FieldSchema>; /** Item schema for array types */ items?: FieldSchema; } interface FieldOption { /** Option value */ value: any; /** Option display label */ label: string; /** Optional description */ description?: string; /** Whether this option is disabled */ disabled?: boolean; } interface FieldFormat { /** Minimum value (for numbers) or length (for strings/arrays) */ minimum?: number; /** Maximum value (for numbers) or length (for strings/arrays) */ maximum?: number; /** Regular expression pattern for string validation */ pattern?: string; /** Date format for date fields */ dateFormat?: string; /** Number format options */ numberFormat?: { decimals?: number; currency?: string; percentage?: boolean; }; } interface FieldUIConfig { /** Icon to display with the field */ icon?: string; /** Color theme for the field */ color?: string; /** Field category for grouping */ category?: string; /** Field priority for sorting */ priority?: number; /** Whether to show this field in simple mode */ showInSimpleMode?: boolean; /** Custom CSS classes */ cssClass?: string; } declare enum FieldType { STRING = "string", NUMBER = "number", INTEGER = "integer", BOOLEAN = "boolean", DATE = "date", DATETIME = "datetime", TIME = "time", EMAIL = "email", URL = "url", PHONE = "phone", ARRAY = "array", OBJECT = "object", ENUM = "enum", UUID = "uuid", JSON = "json" } /** * Available comparison operators for each field type */ declare const FIELD_TYPE_OPERATORS: Record<FieldType, string[]>; /** * Operator display labels for UI */ declare const OPERATOR_LABELS: Record<string, string>; /** * Context for field schema interpretation */ interface FieldSchemaContext { /** Available context variables (e.g., ${user.role}, ${now}) */ contextVariables?: ContextVariable[]; /** Available custom functions */ customFunctions?: CustomFunction[]; /** Global configuration */ config?: { /** Whether to show advanced features */ showAdvanced?: boolean; /** Default locale for formatting */ locale?: string; /** Theme configuration */ theme?: 'light' | 'dark' | 'auto'; }; } interface ContextVariable { /** Variable name (without ${} wrapper) */ name: string; /** Display label */ label: string; /** Variable type */ type: FieldType; /** Example value for preview */ example?: any; /** Description */ description?: string; } interface CustomFunction { /** Function name */ name: string; /** Display label */ label: string; /** Function description */ description?: string; /** Expected parameter types */ parameters: { name: string; type: FieldType; required?: boolean; description?: string; }[]; /** Return type */ returnType: FieldType; /** Example usage */ example?: string; } /** * Array Field Schema Support for Collection Validators * Phase 2 Implementation */ /** * Extended field schema for array types */ interface ArrayFieldSchema extends FieldSchema { type: FieldType.ARRAY; /** Schema for individual items in the array */ itemSchema?: FieldSchema; /** Minimum number of items */ minItems?: number; /** Maximum number of items */ maxItems?: number; /** Whether items must be unique */ uniqueItems?: boolean; /** Fields to check for uniqueness */ uniqueBy?: string[]; /** Default value for new items */ defaultItem?: any; /** Whether to allow adding items */ allowAdd?: boolean; /** Whether to allow removing items */ allowRemove?: boolean; /** Whether to allow reordering items */ allowReorder?: boolean; /** Custom validation rules for the array */ arrayValidation?: { forEach?: { rules: any[]; stopOnFirstError?: boolean; }; uniqueBy?: { fields: string[]; caseSensitive?: boolean; ignoreEmpty?: boolean; }; length?: { min?: number; max?: number; errorMessage?: string; }; }; /** UI configuration specific to arrays */ arrayUiConfig?: { /** How to display the array */ displayMode?: 'table' | 'cards' | 'list' | 'accordion'; /** Whether to show item count */ showCount?: boolean; /** Custom add button text */ addButtonText?: string; /** Custom remove button text */ removeButtonText?: string; /** Whether to confirm before removing */ confirmRemove?: boolean; /** Message to show when array is empty */ emptyMessage?: string; /** Whether to collapse items by default */ collapsedByDefault?: boolean; /** Maximum items to show before pagination */ pageSize?: number; }; } /** * Utility to check if a field schema is an array */ declare function isArrayFieldSchema(schema: FieldSchema): schema is ArrayFieldSchema; /** * Utility to get nested field paths from an array schema */ declare function getArrayItemFieldPaths(schema: ArrayFieldSchema, prefix?: string): string[]; /** * Array validation context for runtime validation */ interface ArrayValidationContext { /** The array being validated */ array: any[]; /** Current item being validated (for forEach) */ currentItem?: any; /** Current item index (for forEach) */ currentIndex?: number; /** Parent context */ parentContext?: any; /** Field schema */ schema: ArrayFieldSchema; /** Accumulated errors */ errors: ArrayValidationError[]; } /** * Array validation error */ interface ArrayValidationError { /** Error type */ type: 'forEach' | 'uniqueBy' | 'minLength' | 'maxLength' | 'other'; /** Error message */ message: string; /** Item index (if applicable) */ itemIndex?: number; /** Field path within item (if applicable) */ fieldPath?: string; /** Duplicate indices (for uniqueBy) */ duplicateIndices?: number[]; /** Expected value */ expected?: any; /** Actual value */ actual?: any; } /** * Array field analyzer for detecting array fields in schemas */ declare class ArrayFieldAnalyzer { /** * Analyze a schema tree and find all array fields */ static findArrayFields(schemas: Record<string, FieldSchema>): Record<string, ArrayFieldSchema>; /** * Get validation rules for an array field */ static getValidationRules(schema: ArrayFieldSchema): ArrayCollectionValidationRule[]; } /** * Array collection validation rule */ interface ArrayCollectionValidationRule { type: 'forEach' | 'uniqueBy' | 'minLength' | 'maxLength'; value?: any; fields?: string[]; rules?: any[]; message: string; } declare class FieldSchemaService { private readonly _fieldSchemas; private readonly _context; readonly fieldSchemas$: Observable<Record<string, FieldSchema>>; readonly context$: Observable<FieldSchemaContext>; constructor(); /** * Set field schemas for the visual builder */ setFieldSchemas(schemas: Record<string, FieldSchema>): void; /** * Add a single field schema */ addFieldSchema(name: string, schema: FieldSchema): void; /** * Remove a field schema */ removeFieldSchema(name: string): void; /** * Get field schema by name */ getFieldSchema(name: string): FieldSchema | undefined; /** * Get all field schemas */ getAllFieldSchemas(): Record<string, FieldSchema>; /** * Get field schemas as array with enhanced info */ getFieldSchemasArray(): Observable<EnhancedFieldSchema[]>; /** * Set context for field schemas */ setContext(context: FieldSchemaContext): void; /** * Get available operators for a field type */ getAvailableOperators(fieldType: FieldType): string[]; /** * Get operator labels for a field type */ getOperatorLabels(fieldType: FieldType): Record<string, string>; /** * Validate field value against schema */ validateFieldValue(fieldName: string, value: any): ValidationResult; /** * Get field suggestions based on partial input */ getFieldSuggestions(partial: string, category?: string): FieldSchema[]; /** * Create field schema from JSON Schema */ createFromJsonSchema(jsonSchema: any): Record<string, FieldSchema>; /** * Create field schema from form metadata */ createFromFormMetadata(formFields: any[]): Record<string, FieldSchema>; /** * Get context variables */ getContextVariables(): Observable<ContextVariable[]>; /** * Get custom functions */ getCustomFunctions(): Observable<CustomFunction[]>; /** * Group field schemas by category */ getFieldSchemasByCategory(): Observable<Record<string, FieldSchema[]>>; private isValidType; private validateFormat; private convertJsonSchemaProperty; private mapJsonSchemaType; private mapFormFieldType; private extractFormatFromField; static ɵfac: i0.ɵɵFactoryDeclaration<FieldSchemaService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<FieldSchemaService>; } interface EnhancedFieldSchema extends FieldSchema { operators: string[]; operatorLabels: Record<string, string>; } interface ValidationResult { valid: boolean; errors: string[]; } interface DslContextVariable { /** Variable name */ name: string; /** Variable type */ type: 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array'; /** Variable scope */ scope: 'user' | 'session' | 'env' | 'global'; /** Description */ description?: string; /** Example value */ example?: string; } /** * Registry service for managing RuleNode instances and their relationships. * Solves the core problem of resolving string IDs to actual RuleNode objects. */ declare class RuleNodeRegistryService { private nodes; private nodesSubject; /** * Observable stream of all registered nodes */ nodes$: Observable<Map<string, RuleNode>>; /** * Register a node in the registry */ register(node: RuleNode): void; /** * Register multiple nodes at once */ registerAll(nodes: RuleNode[]): void; /** * Unregister a node from the registry */ unregister(nodeId: string): boolean; /** * Resolve a node by its ID */ resolve(nodeId: string): RuleNode | null; /** * Retrieve a node synchronously by its ID. * * Provided for backwards compatibility with code that expected a * synchronous `getNode` API. Internally this simply delegates to * {@link resolve}. */ getNode(nodeId: string): RuleNode | null; /** * Resolve multiple nodes by their IDs */ resolveMultiple(nodeIds: string[]): RuleNode[]; /** * Resolve children nodes for a given node */ resolveChildren(node: RuleNode): RuleNode[]; /** * Get all nodes that have the specified parent ID */ getChildrenOf(parentId: string): RuleNode[]; /** * Get the parent node of a given node */ getParent(node: RuleNode): RuleNode | null; /** * Get all root nodes (nodes without parents) */ getRootNodes(): RuleNode[]; /** * Check if a node exists in the registry */ exists(nodeId: string): boolean; /** * Get all registered node IDs */ getAllIds(): string[]; /** * Get all registered nodes */ getAllNodes(): RuleNode[]; /** * Clear all nodes from the registry */ clear(): void; /** * Get the size of the registry */ size(): number; /** * Remove orphaned nodes (nodes without parents and not referenced by others) */ cleanupOrphanedNodes(): string[]; /** * Detect circular references in the registry */ detectCircularReferences(): CircularReference[]; /** * Get memory usage statistics */ getMemoryStats(): MemoryStats; /** * Validate registry integrity */ validateIntegrity(): RegistryIntegrityResult; /** * Perform automatic cleanup operations */ performCleanup(): CleanupResult; /** * Build a tree structure starting from root nodes */ buildTree(): RuleNodeTree[]; /** * Build tree structure for a specific node */ buildNodeTree(node: RuleNode): RuleNodeTree; /** * Find nodes by a predicate function */ findNodes(predicate: (node: RuleNode) => boolean): RuleNode[]; /** * Find nodes by type */ findNodesByType(type: string): RuleNode[]; /** * Validate the graph structure integrity (legacy method for backward compatibility) */ validateGraphIntegrity(): RegistryValidationResult; /** * Check if a node has circular references */ private hasCircularReference; /** * Get observable for a specific node */ getNode$(nodeId: string): Observable<RuleNode | null>; /** * Get observable for children of a node */ getChildren$(nodeId: string): Observable<RuleNode[]>; private notifyChange; static ɵfac: i0.ɵɵFactoryDeclaration<RuleNodeRegistryService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<RuleNodeRegistryService>; } /** * Tree structure for representing node hierarchies */ interface RuleNodeTree { node: RuleNode; children: RuleNodeTree[]; } /** * Result of registry integrity validation */ interface RegistryValidationResult { isValid: boolean; errors: string[]; warnings: string[]; } /** * Circular reference information */ interface CircularReference { cycle: string[]; affectedNodes: string[]; } /** * Memory usage statistics */ interface MemoryStats { totalNodes: number; estimatedSizeBytes: number; breakdown: { config: number; children: number; metadata: number; other: number; }; } /** * Registry integrity validation result */ interface RegistryIntegrityResult { isValid: boolean; issues: string[]; warnings: string[]; circularReferences: CircularReference[]; memoryStats: MemoryStats; } /** * Cleanup operation result */ interface CleanupResult { orphanedNodesRemoved: string[]; circularReferencesDetected: CircularReference[]; memoryFreed: number; } /** * Context interface for rule conversion operations * Eliminates circular dependencies between converters and factory */ interface ConversionContext { /** * Convert a child node to a specification * This method is provided by the factory to avoid circular dependencies */ convertChild<T extends object = any>(node: RuleNode): Specification<T>; /** * Convert multiple child nodes to specifications */ convertChildren<T extends object = any>(nodes: RuleNode[]): Specification<T>[]; /** * Check if a node type is supported */ isSupported(nodeType: string): boolean; /** * Validate that a node can be converted */ validateNode(node: RuleNode): { isValid: boolean; errors: string[]; }; } /** * Interface for rule converters that transform RuleNodes to Specifications */ interface RuleConverter { /** * Convert a RuleNode to a Specification * @param node The node to convert * @param context Context providing access to child conversion capabilities */ convert<T extends object = any>(node: RuleNode, context?: ConversionContext): Specification<T>; /** * Check if this converter can handle the given node type */ canConvert(nodeType: string): boolean; /** * Get the supported node types */ getSupportedTypes(): string[]; /** * Set the conversion context (called by factory during initialization) */ setContext?(context: ConversionContext): void; } /** * Base abstract class for rule converters */ declare abstract class BaseRuleConverter implements RuleConverter { protected abstract supportedTypes: string[]; protected context?: ConversionContext; abstract convert<T extends object = any>(node: RuleNode, context?: ConversionContext): Specification<T>; /** * Set the conversion context */ setContext(context: ConversionContext): void; canConvert(nodeType: string): boolean; getSupportedTypes(): string[]; protected validateNode(node: RuleNode, expectedType?: string): void; } /** * Converter for field condition rules to field specifications */ declare class FieldConditionConverter extends BaseRuleConverter { protected supportedTypes: string[]; convert<T extends object>(node: RuleNode, context?: ConversionContext): Specification<T>; private mapOperator; private convertValue; private inferAndConvertValue; static ɵfac: i0.ɵɵFactoryDeclaration<FieldConditionConverter, never>; static ɵprov: i0.ɵɵInjectableDeclaration<FieldConditionConverter>; } /** * Converter for boolean group rules (AND, OR, NOT, XOR, IMPLIES) */ declare class BooleanGroupConverter extends BaseRuleConverter { private nodeRegistry; protected supportedTypes: string[]; constructor(nodeRegistry: RuleNodeRegistryService); convert<T extends object>(node: RuleNode, context?: ConversionContext): Specification<T>; static ɵfac: i0.ɵɵFactoryDeclaration<BooleanGroupConverter, never>; static ɵprov: i0.ɵɵInjectableDeclaration<BooleanGroupConverter>; } /** * Converter for cardinality rules (atLeast, exactly) */ declare class CardinalityConverter extends BaseRuleConverter { private nodeRegistry; protected supportedTypes: string[]; constructor(nodeRegistry: RuleNodeRegistryService); convert<T extends object>(node: RuleNode, context?: ConversionContext): Specification<T>; static ɵfac: i0.ɵɵFactoryDeclaration<CardinalityConverter, never>; static ɵprov: i0.ɵɵInjectableDeclaration<CardinalityConverter>; } /** * Factory service for converting RuleNodes to Specifications * Uses Strategy pattern to delegate to appropriate converters */ declare class ConverterFactoryService { private fieldConditionConverter; private booleanGroupConverter; private cardinalityConverter; private converters; private context; constructor(fieldConditionConverter: FieldConditionConverter, booleanGroupConverter: BooleanGroupConverter, cardinalityConverter: CardinalityConverter); /** * Convert a RuleNode to a Specification */ convert<T extends object = any>(node: RuleNode): Specification<T>; /** * Get converter for a specific node type */ getConverter(nodeType: string): RuleConverter | undefined; /** * Register a new converter */ registerConverter(name: string, converter: RuleConverter): void; /** * Unregister a converter */ unregisterConverter(name: string): boolean; /** * Get all supported node types */ getSupportedTypes(): string[]; /** * Check if a node type is supported */ isSupported(nodeType: string): boolean; private initializeContext; /** * Internal convert method that bypasses context to avoid recursion */ private convertInternal; private initializeConverters; /** * Convert multiple nodes to specifications */ convertMultiple<T extends object = any>(nodes: RuleNode[]): Specification<T>[]; /** * Validate that a node can be converted */ validateNode(node: RuleNode): { isValid: boolean; errors: string[]; }; /** * Get statistics about converter usage */ getStatistics(): ConverterStatistics; static ɵfac: i0.ɵɵFactoryDeclaration<ConverterFactoryService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<ConverterFactoryService>; } /** * Statistics about the converter factory */ interface ConverterStatistics { converterCount: number; supportedTypeCount: number; supportedTypes: string[]; converterNames: string[]; } /** * Configuration for parsing DSL expressions */ interface DslParsingConfig$1 { /** Available function registry */ functionRegistry?: FunctionRegistry<any>; /** Context provider for variable resolution */ contextProvider?: ContextProvider; /** Known field names for validation */ knownFields?: string[]; /** Enable performance warnings */ enablePerformanceWarnings?: boolean; /** Maximum expression complexity */ maxComplexity?: number; } /** * Result of parsing a DSL expression */ interface DslParsingResult$1<T extends object = any> { /** Whether parsing was successful */ success: boolean; /** Parsed specification (if successful) */ specification?: Specification<T>; /** Validation issues found */ issues: ValidationIssue$1[]; /** Performance metrics */ metrics?: { parseTime: number; complexity: number; }; } /** * Configuration for contextual specification support */ interface SpecificationContextualConfig { /** Context variables available for token resolution */ contextVariables?: DslContextVariable[]; /** Context provider instance */ contextProvider?: ContextProvider; /** Enable strict validation of context tokens */ strictContextValidation?: boolean; } declare class SpecificationBridgeService { private nodeRegistry; private converterFactory; private dslExporter; private dslParser; private dslValidator; private contextProvider?; constructor(nodeRegistry: RuleNodeRegistryService, converterFactory: ConverterFactoryService); /** * Converts a RuleNode tree to a Specification instance */ ruleNodeToSpecification<T extends object = any>(node: RuleNode): Specification<T>; /** * Converts a Specification instance to a RuleNode tree */ specificationToRuleNode<T extends object = any>(spec: Specification<T>): RuleNode; /** * Exports a RuleNode tree to DSL format */ exportToDsl<T extends object = any>(node: RuleNode, options?: Partial<ExportOptions$1>): string; /** * Exports a RuleNode tree to DSL format with metadata */ exportToDslWithMetadata<T extends object = any>(node: RuleNode): string; /** * Validates that a RuleNode can be successfully round-tripped */ validateRoundTrip<T extends object = any>(node: RuleNode): { success: boolean; errors: string[]; warnings: string[]; }; /** * Performs deep validation between original and reconstructed nodes */ private deepValidateRoundTrip; /** * Compares two configuration objects */ private compareConfigs; /** * Validates DSL round-trip conversion */ private validateDslRoundTrip; /** * Parses a DSL expression string into a Specification */ parseDslExpression<T extends object = any>(expression: string, config?: DslParsingConfig$1): DslParsingResult$1<T>; /** * Creates a ContextualSpecification with token resolution */ createContextualSpecification<T extends object = any>(template: string, config?: SpecificationContextualConfig): ContextualSpecification<T>; /** * Resolves context tokens in a template using provided variables */ resolveContextTokens(template: string, contextVariables: DslContextVariable[]): string; /** * Extracts all context tokens from a template */ extractContextTokens(template: string): string[]; /** * Validates that all context tokens in a template have corresponding variables */ validateContextTokens(template: string, contextVariables: DslContextVariable[]): ValidationIssue$1[]; /** * Converts a DSL expression to a ContextualSpecification */ dslToContextualSpecification<T extends object = any>(dslExpression: string, config?: SpecificationContextualConfig): ContextualSpecification<T>; /** * Converts a ContextualSpecification back to DSL template */ contextualSpecificationToDsl<T extends object = any>(spec: ContextualSpecification<T>): string; /** * Performs round-trip validation for expression specifications */ validateExpressionRoundTrip<T extends object = any>(originalExpression: string, config?: DslParsingConfig$1): { success: boolean; errors: string[]; warnings: string[]; reconstructedExpression?: string; }; /** * Updates the context provider for contextual specifications */ updateContextProvider(contextProvider: ContextProvider): void; /** * Gets the current context provider */ getContextProvider(): ContextProvider | undefined; /** * Gets expected DSL keywords for a given node type */ private getExpectedDslKeywords; private createFieldSpecification; private createBooleanGroupSpecification; private createFunctionSpecification; private createFieldToFieldSpecification; private createCardinalitySpecification; /** * Creates conditional validator specifications (Phase 1 implementation) */ private createConditionalValidatorSpecification; /** * Creates collection validator specifications (Phase 2 implementation) */ private createCollectionValidatorSpecification; /** * Creates expression specification from DSL (Phase 4 implementation) */ private createExpressionSpecification; /** * Creates contextual specification (Phase 4 implementation) */ private createContextualSpecificationFromNode; private convertToComparisonOperator; private convertValue; private jsonToRuleNode; private mapSpecificationTypeToNodeType; private mapComparisonOperator; private inferValueType; private generateNodeId; private generateNodeLabel; /** * Creates a context provider from context variables */ private createContextProviderFromVariables; /** * Calculates complexity of a DSL expression */ private calculateComplexity; /** * Finds the position of a token in a template */ private findTokenPosition; /** * Suggests similar variable names using Levenshtein distance */ private suggestSimilarVariable; /** * Calculates Levenshtein distance between two strings */ private levenshteinDistance; /** * Parses a value expression. Phase 1 shim: accepts strings starting with '=' or { expr } objects. * Returns success when the shape is acceptable; full DSL parsing will be integrated in Phase 2. */ parseDslExpressionValue(expression: string | { expr: string; } | null | undefined, _config?: DslParsingConfig$1): { success: boolean; issues: string[]; }; /** * Evaluates a value expression with a row context. Phase 1 shim: executes simple '=' expressions in a sandboxed Function. * In Phase 2, this will use the real DSL evaluator from @praxisui/specification. */ evaluateValue(expression: string | { expr: string; }, ctx: { row: any; }): any; static ɵfac: i0.ɵɵFactoryDeclaration<SpecificationBridgeService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<SpecificationBridgeService>; } interface RoundTripValidationResult { success: boolean; errors: ValidationError$1[]; warnings: ValidationError$1[]; stages: { visualToSpecification: { success: boolean; error?: string; }; specificationToDsl: { success: boolean; error?: string; dsl?: string; }; dslToSpecification: { success: boolean; error?: string; }; specificationToVisual: { success: boolean; error?: string; }; }; dataIntegrity: { nodeCountMatch: boolean; structureMatch: boolean; metadataPreserved: boolean; logicPreserved: boolean; }; performance: { totalTime: number; stageTimings: Record<string, number>; }; } interface RoundTripTestCase { id: string; name: string; description: string; visualRule: RuleNode; expectedDsl?: string; expectedValidation?: { shouldSucceed: boolean; expectedErrors?: string[]; expectedWarnings?: string[]; }; } declare class RoundTripValidatorService { private specificationBridge; private dslParser; constructor(specificationBridge: SpecificationBridgeService); /** * Validates complete round-trip conversion: Visual → DSL → Visual */ validateRoundTrip(visualRule: RuleNode): RoundTripValidationResult; /** * Validates data integrity between original and reconstructed visual rules */ private valida