- home/lib/default.nix: add assertion for unknown profile names instead of
silently filtering them out; remove unused 'inherit (lib) optional'
- home/coding/agents/{opencode,pi}.nix: moved from home/features/coding/
to co-locate with agents.nix (eliminating cross-directory back-references)
- home/coding/agents/agents.nix: update imports to ./opencode.nix and ./pi.nix
- home/features/coding/: remove now-dead default.nix (nothing imported it)
94 lines
2.8 KiB
Nix
94 lines
2.8 KiB
Nix
# 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)} ]";
|
|
}
|
|
];
|
|
};
|
|
}
|