import Foundation struct Configuration { let serverPort: Int let mail: EMail? /** Use a database file and reduce logging. If this property is set to `false`, then an in-memory database is used with increased logging. */ let production: Bool struct EMail { /// The url to the root of the server let serverDomain: String /// SMTP server address let emailHostname: String /// username to login let email: String /// password to login let password: String /// The number of minutes until a password reset token is no longer valid let tokenExpiryDuration: Int } /// The authentication tokens to access the metrics let monitoringTokens: Set } extension Configuration { init(loadFromUrl url: URL) throws { let data: Data do { data = try Data(contentsOf: url) } catch { log("Failed to load configuration data from \(url.path): \(error)") throw error } try self.init(data: data) } init(data: Data) throws { do { self = try JSONDecoder().decode(Configuration.self, from: data) } catch { log("Failed to decode configuration: \(error)") throw error } } } extension Configuration.EMail: Codable { } extension Configuration: Codable { }