migrate method
Applies all pending migrations.
Creates the _dartapi_migrations tracking table if it does not exist.
Runs each unapplied .sql file inside a transaction and records it.
When dryRun is true, pending migrations are printed but not applied —
useful for CI checks or previewing what migrate() would do:
await runner.migrate(dryRun: true);
// → [DRY RUN] Would apply: 0003_add_index.sql
Implementation
Future<void> migrate({bool dryRun = false}) async {
if (!dryRun) await _ensureMigrationsTable();
final applied = dryRun ? <String>{} : await _appliedMigrations();
final pending = await _pendingMigrations(applied);
if (pending.isEmpty) {
print(dryRun
? '[DRY RUN] No pending migrations.'
: '✅ No pending migrations.');
return;
}
if (dryRun) {
print('[DRY RUN] ${pending.length} pending migration(s):');
for (final file in pending) {
print(' • ${_fileName(file)}');
}
return;
}
for (final file in pending) {
final name = _fileName(file);
print('⏳ Applying migration: $name');
final sql = file.readAsStringSync();
await db.transaction((tx) async {
await tx.rawQuery(sql);
await tx.rawQuery(
'INSERT INTO _dartapi_migrations (name) VALUES (:name);',
values: {'name': name},
);
});
print('✅ Applied: $name');
}
print('🎉 All migrations applied (${pending.length} total).');
}