Files
2026-07-27 14:42:23 +02:00

80 lines
3.3 KiB
Dart

import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../core/models/models.dart';
import '../../core/network/api_client_provider.dart';
import '../../core/network/node_master_api_client.dart';
part 'node_repository.g.dart';
/// Wraps the `/node/*` endpoints — this host's own identity, backup config,
/// scan trigger, and update log.
class NodeRepository {
const NodeRepository(this._client);
final NodeMasterApiClient _client;
Future<NodeInfo> getNode() => _client.getNode();
Future<void> updateNode(NodeInfo node) => _client.updateNode(node);
Future<BackupConfig> getBackup() => _client.getNodeBackup();
Future<void> updateBackup(BackupConfig config) => _client.updateNodeBackup(config);
Future<void> runBackup() => _client.runNodeBackup();
Future<List<BackupTarget>> getBackupTargets() => _client.getNodeBackupTargets();
Future<BackupTarget> addBackupTarget(BackupTarget target) => _client.addNodeBackupTarget(target);
Future<BackupTarget> updateBackupTarget(String targetId, BackupTarget target) =>
_client.updateNodeBackupTarget(targetId, target);
Future<void> deleteBackupTarget(String targetId) => _client.deleteNodeBackupTarget(targetId);
Future<void> runBackupTarget(String targetId) => _client.runNodeBackupTarget(targetId);
Future<RunState> getBackupTargetProgress(String targetId) =>
_client.getNodeBackupTargetProgress(targetId);
Future<List<RunState>> getBackupProgress() => _client.getNodeBackupProgress();
Future<ScanResult> scan({String? folder}) => _client.scan(folder: folder);
Future<List<UpdateRecord>> getUpdates() => _client.getUpdates();
Future<UpdateRecord> addUpdate(UpdateRecord record) => _client.addUpdate(record);
Future<void> deleteUpdate(String id) => _client.deleteUpdate(id);
}
/// Null when no connection is active — mirrors [apiClientProvider] so every
/// downstream provider that watches this gets the same "no connection"
/// signal without re-deriving it from the connection state itself.
@riverpod
NodeRepository? nodeRepository(Ref ref) {
final client = ref.watch(apiClientProvider);
if (client == null) return null;
return NodeRepository(client);
}
/// The active connection's node info, or null if no connection is
/// configured. Exceptions from an unreachable/misbehaving node surface as
/// [AsyncError] — this is also the smoke-test path proving the client →
/// repository → provider chain works end to end against a live server.
@riverpod
Future<NodeInfo?> currentNode(Ref ref) async {
final repo = ref.watch(nodeRepositoryProvider);
if (repo == null) return null;
return repo.getNode();
}
/// The node-level backup config — manual-refresh only, same reasoning as
/// `servicesListProvider`: this backs a detail-heavy screen with its own
/// edit dialog, where a silent background refresh could yank state out
/// from under an in-progress edit.
@riverpod
Future<BackupConfig?> backupConfig(Ref ref) async {
final repo = ref.watch(nodeRepositoryProvider);
if (repo == null) return null;
return repo.getBackup();
}
/// The OS update log — manual-refresh only, same reasoning as the other
/// list providers in this app.
@riverpod
Future<List<UpdateRecord>> updatesList(Ref ref) async {
final repo = ref.watch(nodeRepositoryProvider);
if (repo == null) return [];
return repo.getUpdates();
}