Skip to main content
Glama
GetRelationshipsUseCase.ts5.03 kB
/** * GetRelationshipsUseCase.ts * * @semantic-intent Use case for extracting table relationships * Coordinates domain services to analyze foreign key relationships * * @observable-anchoring * - Relationships based on observable foreign key definitions * - Environment drives database selection * - Optional table filtering based on observable table name * * @intent-preservation * - Relationship semantics preserved from domain layer * - Referential integrity intent maintained * - Environment semantic maintained throughout * * @semantic-over-structural * - Focuses on relationship semantics, not join performance * - Cascade rules represent semantic constraints */ import { ICloudflareD1Repository } from '../../domain/repositories/ICloudflareD1Repository'; import { ICacheProvider } from '../ports/ICacheProvider'; import { RelationshipAnalyzer } from '../../domain/services/RelationshipAnalyzer'; import { DatabaseConfig } from '../../infrastructure/config/DatabaseConfig'; import { Environment } from '../../domain/value-objects/Environment'; import { DatabaseSchema } from '../../domain/entities/DatabaseSchema'; import { Relationship } from '../../domain/entities/Relationship'; /** * Request DTO for relationship analysis * * Observable properties: * - environment: Which database environment to analyze * - tableName: Optional filter for specific table's relationships */ export interface GetRelationshipsRequest { environment: Environment; tableName?: string; } /** * Response DTO for relationship analysis */ export interface RelationshipsResponse { databaseName: string; environment: Environment; relationships: RelationshipDTO[]; relationshipCount: number; } /** * Relationship DTO */ export interface RelationshipDTO { fromTable: string; fromColumn: string; toTable: string; toColumn: string; onDelete: 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | 'RESTRICT' | 'NO ACTION' | null; onUpdate: 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | 'RESTRICT' | 'NO ACTION' | null; isRequired: boolean; } /** * Use case: Get table relationships * * Semantic Intent: Extract and analyze foreign key relationships between tables * Observable Anchoring: Relationships based on observable foreign key metadata */ export class GetRelationshipsUseCase { private static readonly CACHE_TTL_SECONDS = 600; // 10 minutes constructor( private readonly repository: ICloudflareD1Repository, private readonly relationshipAnalyzer: RelationshipAnalyzer, private readonly databaseConfig: DatabaseConfig, private readonly cache: ICacheProvider, ) { Object.freeze(this); } /** * Execute relationship extraction * * Semantic: Environment drives database selection, optional table filter */ async execute(request: GetRelationshipsRequest): Promise<RelationshipsResponse> { const environment = request.environment; // Get or fetch schema (with caching) const schema = await this.getSchema(environment); // Extract relationships using domain service const allRelationships = this.relationshipAnalyzer.extractRelationships([...schema.tables]); // Filter by table if specified const relationships = request.tableName ? this.filterRelationshipsByTable(allRelationships, request.tableName) : allRelationships; // Format and return response return { databaseName: schema.name, environment: schema.environment, relationships: relationships.map((rel) => this.formatRelationship(rel)), relationshipCount: relationships.length, }; } /** * Get schema from cache or repository * * Semantic: Reuses cached schema to avoid repeated API calls */ private async getSchema(environment: Environment): Promise<DatabaseSchema> { const cacheKey = `schema:${environment}`; // Check cache first const cachedSchema = await this.cache.get<DatabaseSchema>(cacheKey); if (cachedSchema) { return cachedSchema; } // Fetch from repository const databaseId = this.databaseConfig.getDatabaseId(environment); const schema = await this.repository.fetchDatabaseSchema(databaseId); // Cache for future requests await this.cache.set(cacheKey, schema, GetRelationshipsUseCase.CACHE_TTL_SECONDS); return schema; } /** * Filter relationships by table name * * Observable: Filters based on observable table names in relationship */ private filterRelationshipsByTable( relationships: Relationship[], tableName: string, ): Relationship[] { return relationships.filter( (rel) => rel.fromTable === tableName || rel.toTable === tableName, ); } /** * Format relationship entity into DTO * * Semantic: Transforms domain entity into presentation format */ private formatRelationship(relationship: Relationship): RelationshipDTO { return { fromTable: relationship.fromTable, fromColumn: relationship.fromColumn, toTable: relationship.toTable, toColumn: relationship.toColumn, onDelete: relationship.onDelete, onUpdate: relationship.onUpdate, isRequired: relationship.isRequired(), }; } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/semanticintent/semantic-d1-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server