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 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 deployOrder; ServerProfile({ String? id, this.name = 'New server', this.host = '', this.port = 22, this.username = '', this.password = '', this.useSudo = true, List? services, List? 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 get orderedServices { final byId = {for (final s in services) s.id: s}; final result = []; 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 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 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) .map((e) => ServiceConfig.fromJson(e as Map)) .toList(), deployOrder: ((j['deployOrder'] ?? []) as List) .map((e) => e.toString()) .toList(), ); }