/** * Type-safe relationship definitions for Enhanced Index * * This module provides a comprehensive type system for managing relationships * between elements in the DollhouseMCP Enhanced Index. It implements a three-tier * type hierarchy that ensures both compile-time and runtime safety. * * ## Type Hierarchy: * 1. BaseRelationship - The storage format (what's persisted to disk) * 2. ParsedRelationship - Valid runtime format with extracted metadata * 3. InvalidRelationship - Error state with detailed diagnostics * * ## Key Features: * - Strongly-typed interfaces with discriminated unions * - Runtime type guards for safe type narrowing * - Detailed error messages with position information * - Batch processing utilities with performance optimizations * - Relationship deduplication and sorting algorithms * * ## Usage Example: * ```typescript * // Parse a relationship from storage * const stored: BaseRelationship = { element: 'personas:expert-coder' }; * const parsed = parseRelationship(stored); * * if (isParsedRelationship(parsed)) { * console.log(`Type: ${parsed.targetType}, Name: ${parsed.targetName}`); * } else { * console.error(`Parse failed: ${parsed.parseError}`); * } * ``` * * FIXES IMPLEMENTED (Issue #1103): * - Type-safe relationship variants with discriminated unions * - Compile-time validation through TypeScript's type system * - Runtime type guards for safe type narrowing * - Safe parsing utilities with detailed error reporting * - Security audit logging for relationship operations */ /** * Base relationship interface - the storage format * * This is the fundamental relationship structure that gets persisted to disk. * It contains only the raw data without any parsed or computed fields. * * @example * ```typescript * const relationship: BaseRelationship = { * element: 'skills:debugging', * type: 'similar_to', * strength: 0.85, * metadata: { reason: 'Both involve code analysis' } * }; * ``` */ export interface BaseRelationship { /** Element ID in format "type:name" (e.g., "personas:expert", "skills:refactor") */ element: string; /** Semantic relationship type from RelationshipTypes enum (e.g., 'uses', 'similar_to', 'extends') */ type?: string; /** Relationship strength/confidence score between 0.0 and 1.0 (inclusive) */ strength?: number; /** Extensible metadata for custom properties (e.g., similarity scores, timestamps) */ metadata?: Record; } /** * Parsed relationship with extracted type and name components * * This is the runtime format after successfully parsing a BaseRelationship. * It includes all base fields plus extracted metadata for efficient querying. * * @example * ```typescript * const parsed: ParsedRelationship = { * element: 'personas:expert-coder', * type: 'similar_to', * strength: 0.9, * targetType: 'personas', // Extracted from element * targetName: 'expert-coder', // Extracted from element * isValid: true // Type discriminator * }; * ``` */ export interface ParsedRelationship extends BaseRelationship { /** Extracted element type (e.g., 'personas', 'skills', 'templates') */ targetType: string; /** Extracted element name (e.g., 'expert-coder', 'debugging') */ targetName: string; /** Type discriminator - always true for valid parsed relationships */ isValid: true; } /** * Invalid relationship state with diagnostic information * * This type represents a relationship that failed to parse, preserving * the original data while providing detailed error context for debugging. * * @example * ```typescript * const invalid: InvalidRelationship = { * element: 'malformed:element:id', * targetType: null, * targetName: null, * isValid: false, * parseError: 'Invalid element ID format: "malformed:element:id" - multiple separators...' * }; * ``` */ export interface InvalidRelationship extends BaseRelationship { /** Null when parsing fails */ targetType: null; /** Null when parsing fails */ targetName: null; /** Type discriminator - always false for invalid relationships */ isValid: false; /** Detailed error message with position information and expected format */ parseError: string; } /** * Union type for all relationship variants */ export type Relationship = BaseRelationship | ParsedRelationship | InvalidRelationship; /** * Type guard to check if a relationship is successfully parsed * * @param rel - The relationship to check * @returns True if the relationship is a ParsedRelationship with valid data * * @example * ```typescript * const rel = parseRelationship(baseRel); * if (isParsedRelationship(rel)) { * // TypeScript knows rel is ParsedRelationship here * console.log(rel.targetType, rel.targetName); * } * ``` */ export declare function isParsedRelationship(rel: Relationship): rel is ParsedRelationship; /** * Type guard to check if a relationship failed to parse * * @param rel - The relationship to check * @returns True if the relationship is an InvalidRelationship with error details * * @example * ```typescript * const rel = parseRelationship(baseRel); * if (isInvalidRelationship(rel)) { * console.error(`Parse failed: ${rel.parseError}`); * } * ``` */ export declare function isInvalidRelationship(rel: Relationship): rel is InvalidRelationship; /** * Type guard to check if a relationship is unparsed (base type only) * * @param rel - The relationship to check * @returns True if the relationship is a BaseRelationship without parsed fields * * @example * ```typescript * if (isBaseRelationship(rel)) { * // Need to parse this relationship before use * const parsed = parseRelationship(rel); * } * ``` */ export declare function isBaseRelationship(rel: Relationship): rel is BaseRelationship; /** * Safely parse a base relationship into a typed relationship variant * * This function attempts to parse the element ID and extract type/name components. * If parsing fails, it returns an InvalidRelationship with detailed error context * including position information and what was expected. * * @param rel - The base relationship to parse * @returns ParsedRelationship if successful, InvalidRelationship with diagnostics if failed * * @example Success case * ```typescript * const base: BaseRelationship = { element: 'skills:debugging' }; * const result = parseRelationship(base); * // result: ParsedRelationship with targetType='skills', targetName='debugging' * ``` * * @example Error cases with detailed diagnostics * ```typescript * parseRelationship({ element: 'no-separator' }); * // Error: "missing separator ':'" * * parseRelationship({ element: ':missing-type' }); * // Error: "missing type before ':'" * * parseRelationship({ element: 'too:many:colons' }); * // Error: "multiple separators ':' found at positions [3, 8]" * ``` */ export declare function parseRelationship(rel: BaseRelationship): ParsedRelationship | InvalidRelationship; /** * Batch parse relationships with type safety * Filters out invalid relationships by default */ export declare function parseRelationships(relationships: BaseRelationship[], includeInvalid?: boolean): ParsedRelationship[] | (ParsedRelationship | InvalidRelationship)[]; /** * Create a new relationship with validation */ export declare function createRelationship(targetType: string, targetName: string, relationType?: string, strength?: number, metadata?: Record): ParsedRelationship; /** * Validate a relationship has required fields */ export declare function validateRelationship(rel: any): rel is BaseRelationship; /** * Group relationships by target type for efficient processing */ export declare function groupRelationshipsByType(relationships: ParsedRelationship[]): Map; /** * Find duplicate relationships (same target element) */ export declare function findDuplicateRelationships(relationships: BaseRelationship[]): BaseRelationship[][]; /** * Merge duplicate relationships, keeping highest strength */ export declare function deduplicateRelationships(relationships: BaseRelationship[]): BaseRelationship[]; /** * Sort relationships by strength (descending) */ export declare function sortRelationshipsByStrength(relationships: BaseRelationship[]): BaseRelationship[]; /** * Filter relationships by minimum strength threshold */ export declare function filterRelationshipsByStrength(relationships: BaseRelationship[], minStrength: number): BaseRelationship[]; /** * Relationship type aliases for common patterns */ export declare const RelationshipTypes: { readonly SIMILAR_TO: "similar_to"; readonly USES: "uses"; readonly USED_BY: "used_by"; readonly EXTENDS: "extends"; readonly EXTENDED_BY: "extended_by"; readonly CONTAINS: "contains"; readonly CONTAINED_BY: "contained_by"; readonly HELPS_DEBUG: "helps_debug"; readonly DEBUGGED_BY: "debugged_by"; readonly CONTRADICTS: "contradicts"; readonly SUPPORTS: "supports"; readonly SEMANTIC_SIMILARITY: "semantic_similarity"; }; export type RelationshipType = typeof RelationshipTypes[keyof typeof RelationshipTypes]; //# sourceMappingURL=RelationshipTypes.d.ts.map