updateKvVectorCoordinatorBinding function
KV Vectorize coordinator用DO bindingとclass migrationを冪等に追加する。
Implementation
String updateKvVectorCoordinatorBinding(String source,
{required String binding, required String className, required String tag}) {
for (final name in [binding, className]) {
if (!RegExp(r"^[A-Za-z_][A-Za-z0-9_]*$").hasMatch(name)) {
throw ArgumentError("KV vector coordinator識別子が不正です。");
}
}
final bindingPattern = RegExp(
r'"durable_objects"\s*:\s*\{\s*"bindings"\s*:\s*(\[[\s\S]*?\])\s*\}');
final found = bindingPattern.firstMatch(source);
final bindings = found == null
? <dynamic>[]
: jsonDecode(found.group(1)!) as List<dynamic>;
final same = bindings.where((value) => value["name"] == binding);
if (same.any((value) => value["class_name"] != className)) {
throw StateError("既存KV coordinator bindingの接続先が異なります。");
}
if (same.isEmpty) {
bindings.add({"name": binding, "class_name": className});
}
final property = '"durable_objects":{"bindings":${jsonEncode(bindings)}}';
source = found == null
? source.replaceFirst("{", "{$property,")
: source.replaceRange(found.start, found.end, property);
final migrationMatch = _kvArrayProperty(source, "migrations");
final migrations =
migrationMatch == null ? <dynamic>[] : migrationMatch.value;
final desired = {
"tag": tag,
"new_sqlite_classes": [className]
};
final tagged = migrations.where((value) => value["tag"] == tag);
if (tagged.any((value) => jsonEncode(value) != jsonEncode(desired))) {
throw StateError("KV coordinator migration tagが競合しています。");
}
if (tagged.isEmpty) {
migrations.add(desired);
}
final migrationProperty = '"migrations":${jsonEncode(migrations)}';
return migrationMatch == null
? source.replaceFirst("{", "{$migrationProperty,")
: source.replaceRange(
migrationMatch.start, migrationMatch.end, migrationProperty);
}