import 'dart:convert'; import 'dart:io'; import 'package:fl_lib/fl_lib.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:logging/logging.dart'; import 'package:server_box/data/res/misc.dart'; import 'package:server_box/data/res/store.dart'; part 'backup2.freezed.dart'; part 'backup2.g.dart'; final _loggerV2 = Logger('BackupV2'); @freezed abstract class BackupV2 with _$BackupV2 implements Mergeable { const BackupV2._(); /// Construct a backup with the latest format (v2). /// /// All `Map` are: /// ```json /// { /// "key1": Model{}, /// "_lastModTime": { /// "key1": 1234567890, /// }, /// } /// ``` const factory BackupV2({ required int version, required int date, required Map spis, required Map snippets, required Map keys, required Map container, required Map history, required Map settings, }) = _BackupV2; factory BackupV2.fromJson(Map json) => _$BackupV2FromJson(json); @override Future merge({bool force = false}) async { _loggerV2.info('Merging...'); // Merge each store await Mergeable.mergeStore(backupData: spis, store: Stores.server, force: force); await Mergeable.mergeStore(backupData: snippets, store: Stores.snippet, force: force); await Mergeable.mergeStore(backupData: keys, store: Stores.key, force: force); await Mergeable.mergeStore(backupData: container, store: Stores.container, force: force); await Mergeable.mergeStore(backupData: history, store: Stores.history, force: force); await Mergeable.mergeStore(backupData: settings, store: Stores.setting, force: force); // Reload providers and notify listeners Provider.reload(); RNodes.app.notify(); _loggerV2.info('Merge completed'); } static const formatVer = 2; static Future loadFromStore() async { return BackupV2( version: formatVer, date: DateTimeX.timestamp, spis: Stores.server.getAllMap(includeInternalKeys: true), snippets: Stores.snippet.getAllMap(includeInternalKeys: true), keys: Stores.key.getAllMap(includeInternalKeys: true), container: Stores.container.getAllMap(includeInternalKeys: true), history: Stores.history.getAllMap(includeInternalKeys: true), settings: Stores.setting.getAllMap(includeInternalKeys: true), ); } static Future backup([String? name]) async { final bak = await BackupV2.loadFromStore(); final result = json.encode(bak.toJson()); final path = Paths.doc.joinPath(name ?? Miscs.bakFileName); await File(path).writeAsString(result); return path; } factory BackupV2.fromJsonString(String jsonString) { final map = json.decode(jsonString) as Map; return BackupV2.fromJson(map); } }