@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
268 lines (210 loc) • 7.81 kB
text/typescript
import { CodeConstruct } from './CodeConstruct';
import { CodeFile } from './CodeFile';
import { Entity, Property, Id, ManyToOne, Index, Timestamp, Auth , Labels } from '../core/decorators';
import { RelationshipType } from '../adapters/neo4j';
// Auto-generated from actual parser analysis of 80,480 relationships
type RelationshipTypeEnum =
// Top relationships from real parser data
| 'REFERENCES' // 24,360 (30.27%) - Property access expressions
| 'CALLS' // 18,518 (23.01%) - Function/method calls
| 'DECLARES' // 12,290 (15.27%) - Variable/function declarations
| 'TYPE_OF' // 7,217 (8.97%) - Type annotations
| 'DEFINES' // 6,225 (7.73%) - Assignments, initializers
| 'RETURNS' // 3,033 (3.77%) - Return statements
| 'AWAITS' // 1,472 (1.83%) - Await expressions
| 'IMPORTS' // 1,273 (1.58%) - Import declarations
| 'CASTS_TO' // 995 (1.24%) - Type assertions
| 'DESTRUCTURES' // 975 (1.21%) - Destructuring patterns
| 'DECORATES' // 829 (1.03%) - Decorator expressions
| 'UNION_WITH' // 657 (0.82%) - Union type members
| 'CATCHES' // 561 (0.7%) - Catch clauses
| 'BRANCHES_ON' // 479 (0.6%) - Conditional expressions
| 'EXPORTS' // 459 (0.57%) - Export declarations
| 'EXTENDS' // 445 - Inheritance relationships
| 'SPREADS' // 354 - Spread syntax
| 'THROWS' // 281 - Throw statements
| 'IMPLEMENTS' // 38 - Interface implementations
| 'INTERSECTS_WITH' // 19 - Intersection types
// Legacy/future types
| 'CHILD_OF'
| 'NEXT_SIBLING'
| 'SATISFIES'
| 'IMPORTS_SYMBOL'
| 'EXPORTS_SYMBOL'
| 'REFERENCES_SYMBOL'
| 'GENERIC_OF'
| 'HAS_TYPE_ERROR'
| 'HAS_LINT_ERROR'
| 'HAS_BUILD_ERROR';
export class CodeRelationship {
id!: string;
// The type of relationship (from TypeScript parser)
relationshipType!: RelationshipTypeEnum;
// Relationship category for easier querying
category!: 'ast' | 'semantic' | 'module' | 'type' | 'error';
// Source and target entities
fromType!: 'file' | 'construct'; // What type of entity is the source
fromId!: string; // ID of the source entity
fromName!: string; // Human-readable name of source
toType!: 'file' | 'construct'; // What type of entity is the target
toId!: string; // ID of the target entity
toName!: string; // Human-readable name of target
// Relationship quality and confidence
confidence!: 'high' | 'medium' | 'low';
evidence?: string; // How we detected this relationship
// Source location where this relationship was found
sourceLocation?: {
start: number;
end: number;
line?: number;
column?: number;
};
// Parser extraction metadata
extractionMethod?: 'ast-traversal' | 'symbol-table' | 'program-api' | 'external-tool';
extractedAt?: Date; // When this relationship was extracted
parserVersion?: string; // Version of parser that extracted this
// Context information
isDirectRelationship?: boolean; // Direct vs inferred relationship
relationshipDepth?: number; // For transitive relationships
isConditional?: boolean; // Only true under certain conditions
conditions?: string[]; // What conditions must be met
// Code-specific context
isAsyncRelationship?: boolean; // For async/await relationships
isTypeOnlyRelationship?: boolean; // TypeScript type-only imports
importSpecifier?: string; // For import relationships: named, default, namespace
accessModifier?: 'public' | 'private' | 'protected'; // For class member relationships
// Quality metrics
usageFrequency?: number; // How often this relationship is used
isDeprecated?: boolean; // Is this relationship deprecated
isCritical?: boolean; // Is this a critical dependency
hasCircularDependency?: boolean; // Part of a circular dependency
// Error information (for error relationships)
errorSeverity?: 'error' | 'warning' | 'info';
errorCode?: string | number;
errorMessage?: string;
errorSource?: string; // tsc, eslint, etc.
// Relationships to entities
// Source file (for file-level relationships)
fromFile?: CodeFile;
// Target file (for file-level relationships)
toFile?: CodeFile;
// Source construct (for construct-level relationships)
fromConstruct?: CodeConstruct;
// Target construct (for construct-level relationships)
toConstruct?: CodeConstruct;
// Flexible metadata for relationship-specific data
metadata: Record<string, any> = {};
createdAt!: Date;
updatedAt!: Date;
// Helper methods
getRelationshipDescription(): string {
return `${this.fromName} ${this.relationshipType} ${this.toName}`;
}
isFileToFileRelationship(): boolean {
return this.fromType === 'file' && this.toType === 'file';
}
isConstructToConstructRelationship(): boolean {
return this.fromType === 'construct' && this.toType === 'construct';
}
isFileToConstructRelationship(): boolean {
return this.fromType === 'file' && this.toType === 'construct';
}
isConstructToFileRelationship(): boolean {
return this.fromType === 'construct' && this.toType === 'file';
}
isModuleRelationship(): boolean {
return this.category === 'module';
}
isSemanticRelationship(): boolean {
return this.category === 'semantic';
}
isTypeRelationship(): boolean {
return this.category === 'type';
}
isErrorRelationship(): boolean {
return this.category === 'error';
}
isImportRelationship(): boolean {
return ['IMPORTS', 'IMPORTS_SYMBOL'].includes(this.relationshipType);
}
isExportRelationship(): boolean {
return ['EXPORTS', 'EXPORTS_SYMBOL'].includes(this.relationshipType);
}
isCallRelationship(): boolean {
return this.relationshipType === 'CALLS';
}
isInheritanceRelationship(): boolean {
return ['EXTENDS', 'IMPLEMENTS'].includes(this.relationshipType);
}
getSourceEntity(): { type: string; id: string; name: string } {
return {
type: this.fromType,
id: this.fromId,
name: this.fromName
};
}
getTargetEntity(): { type: string; id: string; name: string } {
return {
type: this.toType,
id: this.toId,
name: this.toName
};
}
getLocationString(): string {
if (this.sourceLocation) {
return `line ${this.sourceLocation.line}, column ${this.sourceLocation.column}`;
}
return 'unknown location';
}
isHighConfidence(): boolean {
return this.confidence === 'high';
}
}