supa-seed
Version:
A constraint-aware, framework-agnostic database seeding framework with deep PostgreSQL business logic discovery and MakerKit integration support
158 lines • 4.87 kB
TypeScript
/**
* Table Relationship Discovery System
* Discovers and maps database relationships for proper foreign key handling
* Enables intelligent data seeding that respects referential integrity
*/
import type { createClient } from '@supabase/supabase-js';
import { SchemaIntrospectionResult } from './schema-introspector';
type SupabaseClient = ReturnType<typeof createClient>;
export interface RelationshipGraph {
nodes: TableNode[];
edges: RelationshipEdge[];
cycles: TableCycle[];
seedingOrder: string[];
dependencyLevels: Map<string, number>;
}
export interface TableNode {
tableName: string;
nodeType: 'root' | 'intermediate' | 'leaf';
dependencies: string[];
dependents: string[];
seedingPriority: number;
constraints: RelationshipConstraint[];
}
export interface RelationshipEdge {
fromTable: string;
toTable: string;
foreignKey: string;
referencedKey: string;
relationship: 'one_to_one' | 'one_to_many' | 'many_to_many';
cascadeDelete: boolean;
isNullable: boolean;
constraintName: string;
}
export interface RelationshipConstraint {
type: 'required_parent' | 'conditional_child' | 'circular_reference' | 'self_reference';
description: string;
tables: string[];
resolution: 'create_parent_first' | 'use_deferred_constraint' | 'break_cycle' | 'allow_null';
}
export interface TableCycle {
tables: string[];
breakPoints: Array<{
table: string;
column: string;
strategy: 'allow_null' | 'defer_constraint' | 'create_placeholder';
}>;
}
export interface SeedingStrategy {
tableName: string;
strategy: 'independent' | 'dependent' | 'circular' | 'deferred';
prerequisites: string[];
creationOrder: number;
specialHandling?: {
type: 'create_parent_first' | 'use_temp_values' | 'batch_update' | 'skip_constraints';
instructions: string;
};
}
export interface RelationshipAnalysis {
graph: RelationshipGraph;
strategies: Map<string, SeedingStrategy>;
warnings: RelationshipWarning[];
recommendations: string[];
}
export interface RelationshipWarning {
type: 'circular_dependency' | 'missing_table' | 'constraint_conflict' | 'complex_relationship';
message: string;
tables: string[];
severity: 'high' | 'medium' | 'low';
suggestedAction: string;
}
export declare class RelationshipDiscoverer {
private client;
private schemaInfo;
constructor(client: SupabaseClient);
/**
* Analyze all table relationships and create seeding strategies
*/
analyzeRelationships(schemaInfo: SchemaIntrospectionResult): Promise<RelationshipAnalysis>;
/**
* Build a complete relationship graph
*/
private buildRelationshipGraph;
/**
* Create a table node with dependency analysis
*/
private createTableNode;
/**
* Create a relationship edge with detailed analysis
*/
private createRelationshipEdge;
/**
* Enhance relationship edges with additional database analysis
*/
private enhanceRelationshipEdges;
/**
* Detect the actual relationship type between tables
*/
private detectRelationshipType;
/**
* Check if a table is a junction table (for many-to-many relationships)
*/
private isJunctionTable;
/**
* Update node dependencies based on edges
*/
private updateNodeDependencies;
/**
* Detect circular dependencies in the relationship graph
*/
private detectCycles;
/**
* Create a table cycle with break point strategies
*/
private createTableCycle;
/**
* Calculate optimal seeding order considering dependencies and cycles
*/
private calculateSeedingOrder;
/**
* Calculate dependency levels for parallel seeding
*/
private calculateDependencyLevels;
/**
* Create seeding strategies for each table
*/
private createSeedingStrategies;
/**
* Create seeding strategy for a specific table
*/
private createTableSeedingStrategy;
/**
* Identify potential warnings in the relationship graph
*/
private identifyWarnings;
/**
* Generate recommendations for improved seeding
*/
private generateRecommendations;
/**
* Utility methods
*/
private isColumnNullable;
private calculateSeedingPriority;
/**
* Get seeding order for a specific set of tables
*/
getSeedingOrder(tableNames: string[]): Promise<string[]>;
/**
* Check if two tables can be seeded in parallel
*/
canSeedInParallel(table1: string, table2: string): Promise<boolean>;
/**
* Get all tables that can be seeded at a specific dependency level
*/
getTablesAtLevel(level: number): Promise<string[]>;
}
export {};
//# sourceMappingURL=relationship-discoverer.d.ts.map