# home/lib/default.nix # Profile loading utilities for home-manager configurations. # # Usage: # let homeLib = import ../lib { inherit lib; }; # in { # imports = [ # (homeLib.mkHomeConfig { profiles = ["coding" "gaming"]; context = "desktop"; }) # ]; # } { lib }: let # Infrastructure layer — nixpkgs overlays, nix-colors, m3ta-nixpkgs modules. # Always loaded on every host. commonModule = ../common; # Base user environment — shell (nushell, starship), CLI tools, secrets. # Always loaded on every host. baseModule = ../base; # Context-specific modules — desktop and server are mutually exclusive. contextModuleMap = { desktop = ../desktop; server = ../server; }; # Profile modules — freely combinable additions on top of base + context. profileModuleMap = { coding = ../coding; gaming = ../profiles/gaming; media = ../profiles/media; }; in { # Generate a home-manager module with imports based on profiles and context. # # Args: # profiles: list of profile names (e.g. ["coding" "gaming" "media"]) # context: host context, one of "desktop" | "server" | null # # Returns: a home-manager module attrset with imports and assertions. # Desktop and server contexts are mutually exclusive by design — passing # any value other than "desktop", "server", or null causes an assertion # failure at evaluation time. mkHomeConfig = { profiles ? [], context ? null, }: let contextImport = if context == "desktop" then [ contextModuleMap.desktop ] else if context == "server" then [ contextModuleMap.server ] else []; # Partition profiles into known and unknown for assertion + safe import. unknownProfiles = builtins.filter (profileName: ! builtins.hasAttr profileName profileModuleMap) profiles; # Only import known profiles; the assertion below catches unknowns. activeProfiles = builtins.filter (profileName: builtins.hasAttr profileName profileModuleMap) profiles; profileImports = map (profileName: profileModuleMap.${profileName}) activeProfiles; contextStr = if context == null then "null" else context; in { imports = [ commonModule baseModule ] ++ contextImport ++ profileImports; assertions = [ { assertion = builtins.elem context [ "desktop" "server" null ]; message = "m3ta home: context must be 'desktop', 'server', or null" + " (got: '${contextStr}')"; } { assertion = unknownProfiles == []; message = "m3ta home: unknown profiles requested:" + " [ ${builtins.concatStringsSep " " unknownProfiles} ]." + " Valid profiles are:" + " [ ${builtins.concatStringsSep " " (builtins.attrNames profileModuleMap)} ]"; } ]; }; }