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 getNode() => _client.getNode(); Future updateNode(NodeInfo node) => _client.updateNode(node); Future getBackup() => _client.getNodeBackup(); Future updateBackup(BackupConfig config) => _client.updateNodeBackup(config); Future runBackup() => _client.runNodeBackup(); Future> getBackupTargets() => _client.getNodeBackupTargets(); Future addBackupTarget(BackupTarget target) => _client.addNodeBackupTarget(target); Future updateBackupTarget(String targetId, BackupTarget target) => _client.updateNodeBackupTarget(targetId, target); Future deleteBackupTarget(String targetId) => _client.deleteNodeBackupTarget(targetId); Future runBackupTarget(String targetId) => _client.runNodeBackupTarget(targetId); Future getBackupTargetProgress(String targetId) => _client.getNodeBackupTargetProgress(targetId); Future> getBackupProgress() => _client.getNodeBackupProgress(); Future scan({String? folder}) => _client.scan(folder: folder); Future> getUpdates() => _client.getUpdates(); Future addUpdate(UpdateRecord record) => _client.addUpdate(record); Future 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 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(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> updatesList(Ref ref) async { final repo = ref.watch(nodeRepositoryProvider); if (repo == null) return []; return repo.getUpdates(); }