supa-seed
Version:
A constraint-aware, framework-agnostic database seeding framework with deep PostgreSQL business logic discovery and MakerKit integration support
310 lines • 8.95 kB
TypeScript
/**
* Schema Evolution and Change Detection System
* Phase 4, Checkpoint D1 - Intelligent schema change detection and migration support
*/
import { SupabaseClient } from '@supabase/supabase-js';
export interface TableSchema {
name: string;
columns: ColumnSchema[];
constraints: ConstraintSchema[];
indexes: IndexSchema[];
triggers: TriggerSchema[];
policies: PolicySchema[];
relationships: RelationshipSchema[];
metadata: {
created: Date;
modified: Date;
owner: string;
comment?: string;
};
}
export interface ColumnSchema {
name: string;
type: string;
nullable: boolean;
defaultValue?: any;
isPrimaryKey: boolean;
isForeignKey: boolean;
isUnique: boolean;
maxLength?: number;
precision?: number;
scale?: number;
enumValues?: string[];
comment?: string;
}
export interface ConstraintSchema {
name: string;
type: 'PRIMARY KEY' | 'FOREIGN KEY' | 'UNIQUE' | 'CHECK' | 'NOT NULL';
columns: string[];
referencedTable?: string;
referencedColumns?: string[];
onUpdate?: 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | 'RESTRICT' | 'NO ACTION';
onDelete?: 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | 'RESTRICT' | 'NO ACTION';
checkCondition?: string;
}
export interface IndexSchema {
name: string;
columns: string[];
isUnique: boolean;
type: 'btree' | 'hash' | 'gist' | 'gin';
where?: string;
partial: boolean;
}
export interface TriggerSchema {
name: string;
event: 'INSERT' | 'UPDATE' | 'DELETE';
timing: 'BEFORE' | 'AFTER' | 'INSTEAD OF';
function: string;
condition?: string;
}
export interface PolicySchema {
name: string;
command: 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | 'ALL';
roles: string[];
using?: string;
check?: string;
permissive: boolean;
}
export interface RelationshipSchema {
name: string;
type: 'one-to-one' | 'one-to-many' | 'many-to-many' | 'self-referencing';
fromTable: string;
fromColumns: string[];
toTable: string;
toColumns: string[];
cascadeDelete: boolean;
cascadeUpdate: boolean;
}
export interface SchemaSnapshot {
id: string;
timestamp: Date;
version: string;
tables: Map<string, TableSchema>;
functions: Map<string, FunctionSchema>;
types: Map<string, TypeSchema>;
extensions: string[];
metadata: {
databaseVersion: string;
capturedBy: string;
environment: string;
description?: string;
};
}
export interface FunctionSchema {
name: string;
schema: string;
returnType: string;
parameters: ParameterSchema[];
language: string;
body: string;
security: 'DEFINER' | 'INVOKER';
volatility: 'VOLATILE' | 'STABLE' | 'IMMUTABLE';
}
export interface ParameterSchema {
name: string;
type: string;
mode: 'IN' | 'OUT' | 'INOUT';
defaultValue?: any;
}
export interface TypeSchema {
name: string;
schema: string;
type: 'enum' | 'composite' | 'domain';
definition: string;
values?: string[];
baseType?: string;
}
export interface SchemaChange {
id: string;
type: 'TABLE_ADDED' | 'TABLE_REMOVED' | 'TABLE_RENAMED' | 'COLUMN_ADDED' | 'COLUMN_REMOVED' | 'COLUMN_MODIFIED' | 'COLUMN_RENAMED' | 'CONSTRAINT_ADDED' | 'CONSTRAINT_REMOVED' | 'CONSTRAINT_MODIFIED' | 'INDEX_ADDED' | 'INDEX_REMOVED' | 'INDEX_MODIFIED' | 'TRIGGER_ADDED' | 'TRIGGER_REMOVED' | 'TRIGGER_MODIFIED' | 'POLICY_ADDED' | 'POLICY_REMOVED' | 'POLICY_MODIFIED' | 'FUNCTION_ADDED' | 'FUNCTION_REMOVED' | 'FUNCTION_MODIFIED' | 'TYPE_ADDED' | 'TYPE_REMOVED' | 'TYPE_MODIFIED';
severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
impact: 'NONE' | 'COMPATIBLE' | 'BREAKING' | 'DATA_LOSS';
tableName?: string;
columnName?: string;
constraintName?: string;
objectName?: string;
before?: any;
after?: any;
description: string;
recommendations: string[];
migrationRequired: boolean;
dataBackupRequired: boolean;
}
export interface ConfigurationImpact {
configFile: string;
affectedSections: string[];
changes: ConfigurationChange[];
migrationNeeded: boolean;
backupRecommended: boolean;
estimatedEffort: 'LOW' | 'MEDIUM' | 'HIGH' | 'EXTENSIVE';
}
export interface ConfigurationChange {
section: string;
field: string;
currentValue: any;
suggestedValue: any;
reason: string;
required: boolean;
breaking: boolean;
}
export interface MigrationSuggestion {
id: string;
title: string;
description: string;
type: 'AUTOMATIC' | 'SEMI_AUTOMATIC' | 'MANUAL';
priority: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
affectedChanges: string[];
steps: MigrationStep[];
estimatedTime: number;
riskLevel: 'LOW' | 'MEDIUM' | 'HIGH';
prerequisites: string[];
rollbackPlan: string[];
}
export interface MigrationStep {
order: number;
title: string;
description: string;
type: 'SQL' | 'CONFIG' | 'CODE' | 'MANUAL' | 'VALIDATION';
command?: string;
configPath?: string;
configChanges?: Record<string, any>;
validation?: string;
rollbackCommand?: string;
estimated_minutes: number;
}
export declare class SchemaEvolutionEngine {
private supabase;
private schemaAdapter;
private snapshots;
constructor(supabase: SupabaseClient);
/**
* Capture a complete schema snapshot
*/
captureSchemaSnapshot(version?: string, description?: string): Promise<SchemaSnapshot>;
/**
* Compare two schema snapshots to detect changes
*/
compareSchemas(beforeSnapshot: SchemaSnapshot, afterSnapshot: SchemaSnapshot): Promise<SchemaChange[]>;
/**
* Analyze the impact of schema changes on existing configurations
*/
analyzeConfigurationImpact(changes: SchemaChange[], configurationPaths?: string[]): Promise<ConfigurationImpact[]>;
/**
* Generate migration suggestions based on detected changes
*/
generateMigrationSuggestions(changes: SchemaChange[], impacts: ConfigurationImpact[]): MigrationSuggestion[];
/**
* Detect schema changes by comparing current schema with a previous snapshot
*/
detectSchemaChanges(previousSnapshotId?: string): Promise<{
changes: SchemaChange[];
impacts: ConfigurationImpact[];
suggestions: MigrationSuggestion[];
currentSnapshot: SchemaSnapshot;
}>;
/**
* Capture all table schemas from the database
*/
private captureTables;
/**
* Capture schema for a specific table
*/
private captureTableSchema;
/**
* Capture column information for a table
*/
private captureTableColumns;
/**
* Capture constraint information for a table
*/
private captureTableConstraints;
/**
* Capture index information for a table
*/
private captureTableIndexes;
/**
* Capture trigger information for a table
*/
private captureTableTriggers;
/**
* Capture RLS policy information for a table
*/
private captureTablePolicies;
/**
* Capture relationship information for a table
*/
private captureTableRelationships;
/**
* Capture all function schemas
*/
private captureFunctions;
/**
* Capture all custom type schemas
*/
private captureTypes;
/**
* Capture installed extensions
*/
private captureExtensions;
/**
* Get database version
*/
private getDatabaseVersion;
/**
* Compare table schemas between two snapshots
*/
private compareTableSchemas;
/**
* Compare columns between two table schemas
*/
private compareTableColumns;
/**
* Compare properties of two column schemas
*/
private compareColumnProperties;
/**
* Compare function schemas (placeholder)
*/
private compareFunctionSchemas;
/**
* Compare type schemas (placeholder)
*/
private compareTypeSchemas;
/**
* Compare extensions
*/
private compareExtensions;
/**
* Analyze impact on a specific configuration file
*/
private analyzeConfigurationFile;
/**
* Group changes by type for easier processing
*/
private groupChangesByType;
/**
* Generate automatic migration suggestions
*/
private generateAutomaticMigrations;
/**
* Generate semi-automatic migration suggestions
*/
private generateSemiAutomaticMigrations;
/**
* Generate manual migration suggestions
*/
private generateManualMigrations;
/**
* Get all captured snapshots
*/
getSnapshots(): SchemaSnapshot[];
/**
* Get a specific snapshot by ID
*/
getSnapshot(snapshotId: string): SchemaSnapshot | undefined;
/**
* Clear all snapshots (useful for testing)
*/
clearSnapshots(): void;
}
//# sourceMappingURL=schema-evolution.d.ts.map