@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
281 lines (210 loc) • 6.81 kB
text/typescript
import { CodeFile } from './CodeFile';
import { Entity, Property, Id, ManyToOne, OneToMany, ManyToMany, Index, Timestamp, Auth , Labels } from '../core/decorators';
import { RelationshipType } from '../adapters/neo4j';
export class CodeConstruct {
id!: string;
// Basic construct information
name!: string; // Function name, class name, variable name, etc.
constructType!: 'function' | 'class' | 'interface' | 'type' | 'variable' | 'constant' | 'enum' | 'namespace' | 'module' | 'import' | 'export' | 'decorator' | 'unknown';
description?: string; // From JSDoc comments
visibility?: 'public' | 'private' | 'protected' | 'internal'; // TypeScript visibility
isAsync?: boolean; // For functions
isGenerator?: boolean; // For generator functions
isExported?: boolean; // Is this construct exported?
isDefault?: boolean; // Is this the default export?
isAbstract?: boolean; // For classes/methods
isStatic?: boolean; // For class members
isReadonly?: boolean; // For properties
isOptional?: boolean; // For interface properties
// Source location information
startLine!: number;
startColumn!: number;
endLine!: number;
endColumn!: number;
startPosition?: number; // Character position in file
endPosition?: number;
length?: number; // Length in characters
// Type information (for TypeScript)
typeAnnotation?: string; // The raw type annotation
returnType?: string; // For functions
parameters?: Array<{
name: string;
type?: string;
isOptional?: boolean;
isRest?: boolean;
defaultValue?: string;
}>;
genericParameters?: Array<{
name: string;
constraint?: string;
defaultType?: string;
}>;
// Function/method specific
parameterCount?: number;
complexity?: number; // Cyclomatic complexity
linesOfCode?: number;
// Class specific
memberCount?: number;
methodCount?: number;
propertyCount?: number;
// React specific
isReactComponent?: boolean;
isReactHook?: boolean;
hasProps?: boolean;
hasState?: boolean;
usesHooks?: boolean;
propTypes?: Array<{
name: string;
type: string;
required?: boolean;
}>;
// JSDoc and documentation
jsDocComment?: string;
jsDocTags?: Array<{
tag: string;
value?: string;
}>;
hasDocumentation?: boolean;
// Decorators (for classes, methods, properties)
decorators?: Array<{
name: string;
arguments?: string[];
}>;
// Code quality metrics
hasTests?: boolean;
testCoverage?: number;
isDeprecated?: boolean;
deprecationMessage?: string;
// Usage tracking
usageCount?: number; // How many times this is referenced
importCount?: number; // How many files import this
callCount?: number; // How many times this function is called
// Relationships
// The file where this construct is defined
sourceFile!: CodeFile;
// Parent construct (for nested functions, class methods, etc.)
parentConstruct?: CodeConstruct;
// Child constructs (methods in a class, nested functions, etc.)
childConstructs!: CodeConstruct[];
// Inheritance relationships (classes extending other classes)
baseClass?: CodeConstruct;
derivedClasses!: CodeConstruct[];
// Interface implementation
implementedInterfaces!: CodeConstruct[];
implementingClasses!: CodeConstruct[];
// Type relationships
typeDefinition?: CodeConstruct;
typedReferences!: CodeConstruct[];
// Function calls and references (handled by CodeRelationship entity)
// Flexible metadata for framework-specific analysis
metadata: Record<string, any> = {};
createdAt!: Date;
updatedAt!: Date;
// Helper methods
getFullyQualifiedName(): string {
if (this.parentConstruct) {
return `${this.parentConstruct.getFullyQualifiedName()}.${this.name}`;
}
return this.name;
}
isFunction(): boolean {
return this.constructType === 'function';
}
isClass(): boolean {
return this.constructType === 'class';
}
isInterface(): boolean {
return this.constructType === 'interface';
}
isType(): boolean {
return this.constructType === 'type';
}
isVariable(): boolean {
return this.constructType === 'variable' || this.constructType === 'constant';
}
getSignature(): string {
if (this.isFunction() && this.parameters) {
const params = this.parameters.map(p =>
`${p.name}${p.isOptional ? '?' : ''}${p.type ? `: ${p.type}` : ''}`
).join(', ');
return `${this.name}(${params})${this.returnType ? `: ${this.returnType}` : ''}`;
}
return this.name;
}
getLocation(): string {
return `${this.sourceFile.fileName}:${this.startLine}:${this.startColumn}`;
}
isPublicAPI(): boolean {
return this.isExported === true && this.visibility !== 'private';
}
}