finalizeD1Schema function
build_runnerが管理するfragmentを統合する。未変更モデルも含め、削除済み入力は除く。
Implementation
void finalizeD1Schema(
{String root = ".", String outputPath = "d1/schema/schema.json"}) {
final lib = Directory("$root/lib");
if (!lib.existsSync()) {
return;
}
final tables = <Map<String, dynamic>>[];
final seen = <String>{};
final expectedDirectory = outputPath.replaceAll("\\", "/").split("/")
..removeLast();
for (final entry in lib.listSync(recursive: true, followLinks: false)) {
if (entry is! File || !entry.path.endsWith(".d1_schema")) {
continue;
}
final source =
File(entry.path.replaceFirst(RegExp(r"\.d1_schema$"), ".dart"));
if (!source.existsSync()) {
continue;
}
final fragment = jsonDecode(entry.readAsStringSync()) as Map;
if (fragment["schemaDirPath"] != expectedDirectory.join("/")) {
throw StateError(
"D1Schema.schemaDirPathとcloudflare.d1.schemaを一致させてください。");
}
for (final raw in (fragment["schema"] as Map)["tables"] as List) {
final table = Map<String, dynamic>.from(raw as Map);
if (!seen.add("${table["database"]}\u0000${table["table"]}")) {
throw StateError("D1 schemaのtable定義が重複しています。");
}
tables.add(table);
}
}
final normalized = outputPath.replaceAll("\\", "/");
if (normalized.startsWith("/") || normalized.split("/").contains("..")) {
throw ArgumentError("schemaはproject内の相対パスで指定してください。");
}
final file = File("$root/$normalized");
if (tables.isEmpty && !file.existsSync()) {
return;
}
tables.sort((a, b) => "${a["database"]}\u0000${a["table"]}"
.compareTo("${b["database"]}\u0000${b["table"]}"));
final schema = <String, dynamic>{
"version": "1",
"dialect": "sqlite",
"tables": tables
};
var hash = BigInt.parse("cbf29ce484222325", radix: 16);
for (final byte in utf8.encode(jsonEncode(schema))) {
hash =
((hash ^ BigInt.from(byte)) * BigInt.parse("100000001b3", radix: 16)) &
BigInt.parse("ffffffffffffffff", radix: 16);
}
schema["sourceHash"] = "fnv1a64:${hash.toRadixString(16).padLeft(16, "0")}";
file.parent.createSync(recursive: true);
final temporary = File("${file.path}.tmp");
temporary.writeAsStringSync(
"${const JsonEncoder.withIndent(" ").convert(schema)}\n");
temporary.renameSync(file.path);
}