Files
PeachDeployments/lib/Peach/informatics/AppDataManager.dart
alvocool 38881d1fe1 Add app source and tests
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 10:15:30 +03:00

441 lines
13 KiB
Dart

import 'dart:typed_data';
import '../about/external/data/Docker.dart';
import '../about/external/data/Health.dart';
import '../about/external/data/Kafka.dart';
import '../about/external/data/Redis.dart';
import '../about/internal/application/DeploymentRecord.dart';
import '../about/internal/application/ServerProfile.dart';
import '../about/internal/application/ServiceConfig.dart';
import '../about/internal/application/StepTracker.dart';
import '../about/internal/file/BuildService.dart';
import '../about/internal/file/ConnectFileStorage.dart';
import '../comms/Comms.dart';
import '../comms/ConnectComms.dart';
import '../memory/ConnectInternalMemory.dart';
import 'DataManager.dart';
/// The single concrete [DataManager], constructed once in `ParentViewModel` and
/// shared by every screen. It holds no logic — it only forwards each call to
/// whichever of the three collaborators owns it.
class AppDataManager implements DataManager {
final ConnectInternalMemory memory;
final ConnectComms comms;
final ConnectFileStorage files;
AppDataManager(this.memory, this.comms, this.files);
// ── memory ────────────────────────────────────────────────────────────────
@override
Future<List<ServerProfile>> getServers() => memory.getServers();
@override
Future setServers(List<ServerProfile> servers) => memory.setServers(servers);
@override
Future deleteServerSecret(String serverId) =>
memory.deleteServerSecret(serverId);
@override
Future<List<DeploymentRecord>> getDeployments() => memory.getDeployments();
@override
Future<List<DeploymentRecord>> addDeployment(DeploymentRecord record) =>
memory.addDeployment(record);
@override
Future clearDeployments() => memory.clearDeployments();
@override
Future<String> getThemeMode() => memory.getThemeMode();
@override
Future setThemeMode(String mode) => memory.setThemeMode(mode);
// ── comms: session ────────────────────────────────────────────────────────
@override
bool get isConnected => comms.isConnected;
@override
bool get canRevert => comms.canRevert;
@override
Stream<LogLine> get logs => comms.logs;
@override
Stream<TransferProgress?> get transferProgress => comms.transferProgress;
@override
Stream<List<DeployStep>> get stepStream => comms.stepStream;
@override
Future<void> connect(ServerProfile s) => comms.connect(s);
@override
void requestCancel() => comms.requestCancel();
@override
void disconnect() => comms.disconnect();
@override
void dispose() => comms.dispose();
// ── comms: deployment ─────────────────────────────────────────────────────
@override
Future<DeployResult> deploy({
required ServerProfile server,
required ServiceConfig service,
required Uint8List jarBytes,
required String jarLabel,
}) => comms.deploy(
server: server,
service: service,
jarBytes: jarBytes,
jarLabel: jarLabel,
);
@override
Future<DeployResult> deployWeb({
required ServerProfile server,
required ServiceConfig service,
required Uint8List archiveBytes,
required int fileCount,
}) => comms.deployWeb(
server: server,
service: service,
archiveBytes: archiveBytes,
fileCount: fileCount,
);
@override
Future<DeployResult> restartOnly(
ServerProfile server,
ServiceConfig service,
) => comms.restartOnly(server, service);
@override
Future<DeployResult> revert() => comms.revert();
@override
Future<void> discardBackup() => comms.discardBackup();
// ── comms: provisioning ───────────────────────────────────────────────────
@override
Future<DeployResult> installSystemdUnit({
required ServerProfile server,
required String unitName,
required String unitContent,
bool enable = true,
bool startNow = true,
}) => comms.installSystemdUnit(
server: server,
unitName: unitName,
unitContent: unitContent,
enable: enable,
startNow: startNow,
);
@override
Future<String> detectPackageManager(ServerProfile server) =>
comms.detectPackageManager(server);
@override
Future<Map<String, String>> probeEnvironment(
ServerProfile server,
List<String> detectByKey,
) => comms.probeEnvironment(server, detectByKey);
@override
Future<DeployResult> installEnvironment({
required ServerProfile server,
required String command,
required List<String> units,
}) =>
comms.installEnvironment(server: server, command: command, units: units);
@override
Future<DeployResult> installPackages({
required ServerProfile server,
required String command,
String? enableUnit,
}) => comms.installPackages(
server: server,
command: command,
enableUnit: enableUnit,
);
// ── comms: service & health ───────────────────────────────────────────────
@override
Future<HealthResult> checkHealth(
ServerProfile server,
ServiceConfig service,
) => comms.checkHealth(server, service);
@override
Future<String> serviceStatus(ServerProfile server, ServiceConfig service) =>
comms.serviceStatus(server, service);
@override
Future<DeployResult> serviceControl(
ServerProfile server,
ServiceConfig service,
String action,
) => comms.serviceControl(server, service, action);
@override
Future<List<String>> nginxRoots(ServerProfile server) =>
comms.nginxRoots(server);
// ── comms: logs ───────────────────────────────────────────────────────────
@override
Future<void> fetchLogs(
ServerProfile server,
ServiceConfig service, {
DateTime? since,
DateTime? until,
}) => comms.fetchLogs(server, service, since: since, until: until);
@override
Future<void> followLogs(ServerProfile server, ServiceConfig service) =>
comms.followLogs(server, service);
@override
void stopLogs() => comms.stopLogs();
// ── comms: redis ──────────────────────────────────────────────────────────
@override
Future<(bool, String)> redisPing(
ServerProfile server, {
String host = '127.0.0.1',
int port = 6379,
String pass = '',
int db = 0,
}) => comms.redisPing(server, host: host, port: port, pass: pass, db: db);
@override
Future<String> redisConfigPassword(ServerProfile server) =>
comms.redisConfigPassword(server);
@override
Future<int> redisDbSize(
ServerProfile server, {
String host = '127.0.0.1',
int port = 6379,
String pass = '',
int db = 0,
}) => comms.redisDbSize(server, host: host, port: port, pass: pass, db: db);
@override
Future<(int, Map<int, int>)> redisDatabases(
ServerProfile server, {
String host = '127.0.0.1',
int port = 6379,
String pass = '',
}) => comms.redisDatabases(server, host: host, port: port, pass: pass);
@override
Future<List<(String, String)>> redisKeysTyped(
ServerProfile server, {
String pattern = '*',
String filterType = '',
int limit = 50000,
String host = '127.0.0.1',
int port = 6379,
String pass = '',
int db = 0,
}) => comms.redisKeysTyped(
server,
pattern: pattern,
filterType: filterType,
limit: limit,
host: host,
port: port,
pass: pass,
db: db,
);
@override
Future<List<String>> redisKeys(
ServerProfile server, {
String pattern = '*',
int limit = 100000,
String host = '127.0.0.1',
int port = 6379,
String pass = '',
int db = 0,
}) => comms.redisKeys(
server,
pattern: pattern,
limit: limit,
host: host,
port: port,
pass: pass,
db: db,
);
@override
Future<RedisEntry> redisGet(
ServerProfile server,
String key, {
String host = '127.0.0.1',
int port = 6379,
String pass = '',
int db = 0,
}) => comms.redisGet(server, key, host: host, port: port, pass: pass, db: db);
// ── comms: docker ─────────────────────────────────────────────────────────
@override
Future<DockerStatus> dockerStatus(ServerProfile server) =>
comms.dockerStatus(server);
@override
Future<List<DockerContainer>> dockerPs(
ServerProfile server, {
bool all = true,
}) => comms.dockerPs(server, all: all);
@override
Future<String> dockerAction(ServerProfile server, String id, String action) =>
comms.dockerAction(server, id, action);
@override
Future<String> dockerLogs(
ServerProfile server,
String id, {
int tail = 300,
}) => comms.dockerLogs(server, id, tail: tail);
@override
Future<String> dockerTest(ServerProfile server) => comms.dockerTest(server);
@override
Future<(bool, String)> dockerRun(ServerProfile server, DockerRunSpec spec) =>
comms.dockerRun(server, spec);
// ── comms: kafka ──────────────────────────────────────────────────────────
@override
Future<KafkaStatus> kafkaDetect(ServerProfile server) =>
comms.kafkaDetect(server);
@override
Future<String> kafkaTest(
ServerProfile server, {
required String binDir,
required String suffix,
required String bootstrap,
}) => comms.kafkaTest(
server,
binDir: binDir,
suffix: suffix,
bootstrap: bootstrap,
);
@override
Future<List<KafkaTopic>> kafkaTopics(
ServerProfile server, {
required String binDir,
required String suffix,
required String bootstrap,
bool includeInternal = false,
}) => comms.kafkaTopics(
server,
binDir: binDir,
suffix: suffix,
bootstrap: bootstrap,
includeInternal: includeInternal,
);
@override
Future<List<KafkaConsumerGroup>> kafkaGroups(
ServerProfile server, {
required String binDir,
required String suffix,
required String bootstrap,
}) => comms.kafkaGroups(
server,
binDir: binDir,
suffix: suffix,
bootstrap: bootstrap,
);
@override
Future<KafkaCluster> kafkaCluster(
ServerProfile server, {
required String binDir,
required String suffix,
required String bootstrap,
}) => comms.kafkaCluster(
server,
binDir: binDir,
suffix: suffix,
bootstrap: bootstrap,
);
// ── comms: remote filesystem ──────────────────────────────────────────────
@override
Future<List<RemoteEntry>> listDir(ServerProfile server, String path) =>
comms.listDir(server, path);
@override
Future<String> resolveHome(ServerProfile server) => comms.resolveHome(server);
@override
Future<void> uploadFile(
ServerProfile server,
Uint8List bytes,
String remotePath,
) => comms.uploadFile(server, bytes, remotePath);
@override
Future<Uint8List> downloadFile(ServerProfile server, String remotePath) =>
comms.downloadFile(server, remotePath);
@override
Future<void> deleteRemote(
ServerProfile server,
String remotePath,
bool isDir,
) => comms.deleteRemote(server, remotePath, isDir);
// ── files ─────────────────────────────────────────────────────────────────
@override
bool get buildSupported => files.buildSupported;
@override
Stream<LogLine> get buildLogs => files.buildLogs;
@override
Stream<List<DeployStep>> get buildStepStream => files.buildStepStream;
@override
Future<BuildResult> build(ServiceConfig service) => files.build(service);
@override
Future<BuildResult> buildWeb(ServiceConfig service) =>
files.buildWeb(service);
@override
void cancelBuild() => files.cancelBuild();
@override
Future<Uint8List> readArtifact(String path) => files.readArtifact(path);
@override
Future<bool> artifactExists(String path) => files.artifactExists(path);
@override
Future<(Uint8List, int)> packageWeb(String directoryPath) =>
files.packageWeb(directoryPath);
}