enum DeployStatus { success, failure, reverted } extension DeployStatusX on DeployStatus { String get label => switch (this) { DeployStatus.success => 'Success', DeployStatus.failure => 'Failure', DeployStatus.reverted => 'Reverted', }; } /// One historical deployment attempt, tracked for auditing. class DeploymentRecord { final String id; final String serverId; final String serverName; final String serviceId; final String serviceLabel; final String jarName; final String remotePath; final DateTime time; final DeployStatus status; final String message; DeploymentRecord({ required this.id, required this.serverId, required this.serverName, required this.serviceId, required this.serviceLabel, required this.jarName, required this.remotePath, required this.time, required this.status, required this.message, }); Map toJson() => { 'id': id, 'serverId': serverId, 'serverName': serverName, 'serviceId': serviceId, 'serviceLabel': serviceLabel, 'jarName': jarName, 'remotePath': remotePath, 'time': time.toIso8601String(), 'status': status.name, 'message': message, }; factory DeploymentRecord.fromJson(Map j) => DeploymentRecord( id: j['id'] as String, serverId: (j['serverId'] ?? '') as String, serverName: (j['serverName'] ?? '') as String, serviceId: (j['serviceId'] ?? '') as String, serviceLabel: (j['serviceLabel'] ?? '') as String, jarName: (j['jarName'] ?? '') as String, remotePath: (j['remotePath'] ?? '') as String, time: DateTime.tryParse((j['time'] ?? '') as String) ?? DateTime(2000), status: DeployStatus.values.firstWhere( (s) => s.name == j['status'], orElse: () => DeployStatus.failure, ), message: (j['message'] ?? '') as String, ); }