Skip to main content
Glama
Relationship.ts•2.99 kB
import type { OnDeleteAction } from './ForeignKey'; /** * 🎯 SEMANTIC INTENT: Relationship represents semantic connection between tables * * WHY: Relationships are higher-level semantic abstractions of foreign keys * - Foreign keys are implementation details (column-level) * - Relationships are semantic connections (table-level) * - Preserves referential integrity semantics * * SEMANTIC ANCHORING: Based on observable foreign key constraints * OBSERVABLE PROPERTIES: Derived from foreign key metadata * IMMUTABILITY: Frozen to preserve relationship semantics */ export class Relationship { public readonly fromTable: string; public readonly fromColumn: string; public readonly toTable: string; public readonly toColumn: string; public readonly onDelete: OnDeleteAction | null; public readonly onUpdate: OnDeleteAction | null; constructor( fromTable: string, fromColumn: string, toTable: string, toColumn: string, onDelete: OnDeleteAction | null = null, onUpdate: OnDeleteAction | null = null ) { if (!fromTable || fromTable.trim().length === 0) { throw new Error('Relationship fromTable cannot be empty'); } if (!fromColumn || fromColumn.trim().length === 0) { throw new Error('Relationship fromColumn cannot be empty'); } if (!toTable || toTable.trim().length === 0) { throw new Error('Relationship toTable cannot be empty'); } if (!toColumn || toColumn.trim().length === 0) { throw new Error('Relationship toColumn cannot be empty'); } this.fromTable = fromTable.trim(); this.fromColumn = fromColumn.trim(); this.toTable = toTable.trim(); this.toColumn = toColumn.trim(); this.onDelete = onDelete; this.onUpdate = onUpdate; Object.freeze(this); } /** * Check if relationship is required (CASCADE or RESTRICT) * * Semantic: CASCADE/RESTRICT implies tight coupling */ isRequired(): boolean { return this.onDelete === 'CASCADE' || this.onDelete === 'RESTRICT'; } /** * Check if relationship cascades deletes * * Semantic: CASCADE means child records are deleted with parent */ cascadesOnDelete(): boolean { return this.onDelete === 'CASCADE'; } /** * Check if relationship is optional (SET NULL or NO ACTION) * * Semantic: Optional relationships can exist independently */ isOptional(): boolean { return this.onDelete === 'SET NULL' || this.onDelete === 'NO ACTION' || this.onDelete === null; } /** * Get relationship direction description * * Semantic: "posts references users" (many-to-one typical pattern) */ getDescription(): string { return `${this.fromTable}.${this.fromColumn} → ${this.toTable}.${this.toColumn}`; } /** * Check if this is a self-referential relationship * * Semantic: Table referencing itself (e.g., parent_id in categories) */ isSelfReferential(): boolean { return this.fromTable === this.toTable; } }

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