{ lib, util, ... }: { checks = [ { assertion = util.registry.predicates.uniqueValue (entry: entry.value.domain); message = "Route domains must be unique."; } { assertion = entries: util.registry.predicates.uniqueValue (entry: entry.value) ( lib.concatMap (entry: map (port: entry // { value = port; }) entry.value.ports) entries ); message = "Route UDP ports must be unique."; } { assertion = entries: lib.all (entry: entry.value.port != null && entry.value.ports == [ ]) ( lib.filter (entry: entry.value.protocol != "udp") entries ); message = "HTTP and HTTPS routes must set port and not ports."; } { assertion = entries: lib.all (entry: entry.value.port == null && entry.value.ports != [ ]) ( lib.filter (entry: entry.value.protocol == "udp") entries ); message = "UDP routes must set ports and not port."; } ]; type = lib.types.submodule { options = { domain = lib.mkOption { type = lib.types.str; example = "files.alexion.dev"; description = "Public domain for this route."; }; protocol = lib.mkOption { type = lib.types.enum [ "http" "https" "udp" ]; description = "Public protocol for this route."; }; port = lib.mkOption { type = lib.types.nullOr lib.types.port; default = null; example = 3923; description = "HTTP backend port for an HTTP or HTTPS route."; }; ports = lib.mkOption { type = lib.types.listOf lib.types.port; default = [ ]; example = [ 2456 2457 ]; description = "UDP ports for a UDP route."; }; }; }; }