recordMigration function

Future<String> recordMigration(
  1. String id, {
  2. required String directory,
  3. required MigrationHistory history,
})

Records a reviewed edit to the latest unpublished migration. Its source is retained verbatim apart from the fingerprint literal. Applied files must not be edited or recorded again; this offline tool cannot know deployment state.

Implementation

Future<String> recordMigration(
  String id, {
  required String directory,
  required MigrationHistory history,
}) async {
  if (history.entries.isEmpty || history.entries.last.$1.id != id) {
    throw const GenerationException(
      'Only the latest unpublished migration can be recorded.',
    );
  }
  MigrationHistory(
    history.entries.take(history.entries.length - 1),
    dialect: history.dialect,
  ).checked;
  final migrations = history.entries.map((e) => e.$1).toList();
  validateMigrations(migrations, dialect: history.dialect);
  await _registryDialect(directory, history.dialect);
  await _checkMigrationFiles(Directory(directory), migrations);
  final path = p.join(directory, 'm$id.dart');
  final file = File(path);
  final content = await file.readAsString();
  final unit = parseString(content: content, path: path).unit;
  final fingerprints = [
    for (final declaration
        in unit.declarations.whereType<TopLevelVariableDeclaration>())
      if (declaration.variables.isConst)
        for (final variable in declaration.variables.variables)
          if (variable.name.lexeme == 'migrationChecksum') variable,
  ];
  if (fingerprints.length != 1 ||
      fingerprints.single.initializer is! SimpleStringLiteral) {
    throw const GenerationException(
      'Use one const migrationChecksum string literal.',
    );
  }
  final literal = fingerprints.single.initializer!;
  await _replaceSource(
    path,
    content.replaceRange(
      literal.offset,
      literal.end,
      dartLiteral(migrations.last.checksum),
    ),
  );
  return migrations.last.checksum;
}