Add app source and tests
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
85
lib/Peach/about/internal/application/ServerProfile.dart
Normal file
85
lib/Peach/about/internal/application/ServerProfile.dart
Normal file
@@ -0,0 +1,85 @@
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'ServiceConfig.dart';
|
||||
|
||||
/// A unique server the user connects to. Holds the connection details plus a
|
||||
/// list of deployable [ServiceConfig]s that live on it.
|
||||
///
|
||||
/// The [password] is NOT serialized into the plain config JSON — it is held in
|
||||
/// memory and persisted separately via encrypted secure storage.
|
||||
class ServerProfile {
|
||||
final String id;
|
||||
String name; // friendly label, e.g. "prod-1"
|
||||
String host;
|
||||
int port;
|
||||
String username;
|
||||
String password; // runtime only; persisted via SecretStore
|
||||
bool useSudo;
|
||||
List<ServiceConfig> services;
|
||||
|
||||
/// Saved deployment order: service ids in the order the user arranged them
|
||||
/// for batch build & deploy. Ids not present are appended in natural order.
|
||||
List<String> deployOrder;
|
||||
|
||||
ServerProfile({
|
||||
String? id,
|
||||
this.name = 'New server',
|
||||
this.host = '',
|
||||
this.port = 22,
|
||||
this.username = '',
|
||||
this.password = '',
|
||||
this.useSudo = true,
|
||||
List<ServiceConfig>? services,
|
||||
List<String>? deployOrder,
|
||||
}) : id = id ?? const Uuid().v4(),
|
||||
services = services ?? [],
|
||||
deployOrder = deployOrder ?? [];
|
||||
|
||||
/// Services arranged by the saved [deployOrder], with any not-listed ones
|
||||
/// appended in their natural order.
|
||||
List<ServiceConfig> get orderedServices {
|
||||
final byId = {for (final s in services) s.id: s};
|
||||
final result = <ServiceConfig>[];
|
||||
for (final id in deployOrder) {
|
||||
final s = byId.remove(id);
|
||||
if (s != null) result.add(s);
|
||||
}
|
||||
// Preserve original order for the remaining (new/unordered) services.
|
||||
for (final s in services) {
|
||||
if (byId.containsKey(s.id)) result.add(s);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ServerProfile copy() {
|
||||
final c = ServerProfile.fromJson(toJson());
|
||||
c.password = password;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// JSON WITHOUT the password (that goes to secure storage).
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'host': host,
|
||||
'port': port,
|
||||
'username': username,
|
||||
'useSudo': useSudo,
|
||||
'services': services.map((s) => s.toJson()).toList(),
|
||||
'deployOrder': deployOrder,
|
||||
};
|
||||
|
||||
factory ServerProfile.fromJson(Map<String, dynamic> j) => ServerProfile(
|
||||
id: j['id'] as String?,
|
||||
name: (j['name'] ?? 'server') as String,
|
||||
host: (j['host'] ?? '') as String,
|
||||
port: (j['port'] ?? 22) as int,
|
||||
username: (j['username'] ?? '') as String,
|
||||
useSudo: (j['useSudo'] ?? true) as bool,
|
||||
services: ((j['services'] ?? []) as List<dynamic>)
|
||||
.map((e) => ServiceConfig.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
deployOrder: ((j['deployOrder'] ?? []) as List<dynamic>)
|
||||
.map((e) => e.toString())
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user