Skip to content

Parametric Aspects

A parametric aspect is an aspect defined as a function whose arguments are pipeline context values — host, user, home, or any custom entity kind. Den introspects the function’s argument pattern and only calls it in contexts where all required arguments are available.

# This aspect only activates in {host} contexts
den.aspects.networking = { host, ... }: {
nixos.networking.hostName = host.name;
};
# This only activates when both {host, user} are present
den.aspects.user-groups = { host, user, ... }: {
nixos.users.users.${user.userName}.extraGroups = [ "wheel" ];
};
# This only activates for standalone {home} contexts
den.aspects.shell-config = { home, ... }: {
homeManager.programs.zsh.enable = true;
};

No wrapper needed — a bare function requiring { host, user } is silently skipped in contexts that only have { host }. The argument shape is the condition. No mkIf, no enable flags.

Static attrsets (non-functions) are always included regardless of context:

den.aspects.firewall = {
nixos.networking.firewall.enable = true;
};

Aspect-level parametric — the function wraps the whole aspect:

# host is a pipeline arg — the whole aspect is parametric
den.aspects.laptop = { host, ... }: {
nixos.networking.hostName = host.name;
homeManager.programs.git.userName = host.hostName;
};

Class-level context injection — Den args inside a class module:

# host here is pre-applied by wrapClassModule, not parametric dispatch
den.aspects.laptop = {
nixos = { host, config, pkgs, ... }: {
networking.hostName = host.name;
};
};

Both patterns are valid and composable. Use aspect-level parametric when the context drives the entire aspect (which classes to include, what includes to add). Use class-level injection when only a specific class module needs entity data alongside module-system args.

Contribute Community Sponsor