{ definitions, lib }: let rawDeclarations = registryName: hosts: lib.mapAttrs (_hostName: host: host.config.registry.${registryName} or { }) hosts; replicatedEntries = registryName: raw: let entries = lib.concatLists ( lib.concatLists ( lib.mapAttrsToList ( _evalHost: hostDeclarations: lib.mapAttrsToList ( hostName: declarations: lib.mapAttrsToList (entryName: value: { path = "registry.${registryName}.${hostName}.${entryName}"; inherit entryName value; }) declarations ) hostDeclarations ) raw ) ); in lib.foldl' ( acc: entry: if lib.hasAttr entry.entryName acc then if acc.${entry.entryName}.value == entry.value then acc else throw "conflicting replicated registry entry ${entry.path} does not match ${acc.${entry.entryName}.path}" else acc // { ${entry.entryName} = entry; } ) { } entries; replicatedData = registryName: hosts: raw: let entries = lib.mapAttrs (_entryName: entry: entry.value) (replicatedEntries registryName raw); in lib.mapAttrs (_hostName: _host: entries) hosts; collectData = { hosts }: let raw = lib.mapAttrs (registryName: _registry: rawDeclarations registryName hosts) definitions; data = lib.mapAttrs ( registryName: registry: if registry.replicate or false then replicatedData registryName hosts raw.${registryName} else lib.mapAttrs (hostName: host: host.config.registry.${registryName}.${hostName} or { }) hosts ) definitions; in data; in { inherit collectData rawDeclarations replicatedData replicatedEntries ; }