-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Labels
✨ Type: FeatureNew functionality or enhancementNew functionality or enhancement🟢 Priority: LowNice to have, can waitNice to have, can wait
Milestone
Description
Overview
Add support for SQL migration files alongside existing TypeScript migrations, similar to Flyway. This enables users to choose the best tool for each migration:
- SQL files for simple DDL operations (CREATE TABLE, ALTER TABLE, etc.)
- TypeScript for complex data migrations and business logic
Proposed Solution
Implement a hybrid handler that detects file type and executes appropriately:
// Example migration structure
migrations/
├── V202501230001_create_tables.sql # SQL for DDL
├── V202501230002_seed_data.ts # TypeScript for complex logic
├── V202501230003_alter_columns.sql # SQL for schema changes
└── V202501230004_migrate_data.ts # TypeScript for data transformationsFeatures
Basic SQL Support
- Execute
.sqlfiles directly - Parse and execute multiple statements (split by semicolons)
- Support standard SQL DDL/DML operations
Up/Down Migrations (Optional)
- Support
-- @UPand-- @DOWNsections in SQL files - Store down migrations for rollback capability
- Parse SQL file sections
Example:
-- V202501230001_create_users.sql
-- @UP
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL
);
-- @DOWN
DROP TABLE users;Hybrid Handler
- Automatically detect file type (.sql vs .ts)
- Execute SQL files directly
- Load and execute TypeScript migrations
- Consistent error handling for both types
Implementation
export class HybridMigrationHandler implements IMigrationScriptHandler {
async handle(script: MigrationScript): Promise<string> {
if (script.filepath.endsWith('.sql')) {
return this.handleSQL(script);
} else if (script.filepath.endsWith('.ts')) {
return this.handleTypeScript(script);
}
throw new Error(`Unsupported file type: ${script.filepath}`);
}
private async handleSQL(script: MigrationScript): Promise<string> {
const sql = fs.readFileSync(script.filepath, 'utf8');
// Parse and execute SQL statements
const statements = this.parseSQL(sql);
for (const statement of statements) {
await this.db.query(statement);
}
return `Executed ${statements.length} SQL statements`;
}
private async handleTypeScript(script: MigrationScript): Promise<string> {
await script.init(); // Load TS migration
return await script.script.up(this.db);
}
}Configuration
Update Config to support SQL files:
export class Config {
filePattern: RegExp = /^V(\d+)_(.+)\.(ts|sql)$/; // Support both .ts and .sql
sqlMigrationSeparator?: string = '_';
supportDownMigrations?: boolean = false;
}Benefits
- Flyway familiarity: Developers coming from Flyway can use same patterns
- Flexibility: Choose the right tool (SQL vs TypeScript) for each migration
- Simplicity: Simple schema changes don't need TypeScript boilerplate
- Power: Complex data migrations still use TypeScript's full capabilities
- Database-agnostic: Works with any database (PostgreSQL, MySQL, MongoDB via SQL-like DSL)
Acceptance Criteria
- Handler detects and executes .sql files
- Handler supports existing .ts migrations
- SQL statements are parsed correctly (handle semicolons, comments)
- Tests for SQL migration execution
- Tests for hybrid (mixed SQL/TS) migrations
- Documentation with examples
- Support for UP/DOWN migrations (optional enhancement)
- Error handling for invalid SQL
- 100% test coverage maintained
Related Issues
- Make backup/restore optional to support down() migrations #50 - Make backup/restore optional to support down() migrations (UP/DOWN migrations in SQL files complement down() methods in TypeScript)
- Complements database-specific implementations (PostgreSQL, MySQL, etc.)
- Works with existing backup/restore functionality
- Compatible with planned CLI commands
Notes
- This should be a separate optional handler, not modify existing TypeScript handler
- Users can create their own SQL handlers if needed
- Consider creating example implementations in documentation
- SQL file UP/DOWN sections work well with optional backup/restore (Make backup/restore optional to support down() migrations #50)
Metadata
Metadata
Assignees
Labels
✨ Type: FeatureNew functionality or enhancementNew functionality or enhancement🟢 Priority: LowNice to have, can waitNice to have, can wait