diff --git a/modules/aspects/definition.nix b/modules/aspects/definition.nix index 5b6ff04..6b62d59 100644 --- a/modules/aspects/definition.nix +++ b/modules/aspects/definition.nix @@ -5,12 +5,14 @@ ... }: let + inherit (den.lib) parametric; + # creates den.aspects.${home.aspect} homeAspect = home: { ${home.aspect} = { ${home.class} = { }; includes = [ den.default ]; - __functor = den.lib.parametric { inherit home; }; + __functor = HM: parametric { inherit HM home; } HM; }; }; @@ -19,7 +21,7 @@ let ${host.aspect} = { ${host.class} = { }; includes = [ den.default ]; - __functor = den.lib.parametric { OS = { inherit host; }; }; + __functor = OS: parametric { inherit OS host; } OS; }; }; @@ -28,7 +30,7 @@ let ${user.aspect} = { ${user.class} = { }; includes = [ den.default ]; - __functor = den.lib.parametric true; + __functor = parametric.expands { inherit user; }; }; }; diff --git a/modules/aspects/dependencies.nix b/modules/aspects/dependencies.nix index f955a69..0a29eb1 100644 --- a/modules/aspects/dependencies.nix +++ b/modules/aspects/dependencies.nix @@ -13,80 +13,93 @@ let inherit (den.lib.take) exactly; dependencies = [ - (exactly ({ home }: baseDeps home)) - (exactly ({ host }: baseDeps host)) - (exactly ({ user }: baseDeps user)) (exactly osDependencies) - (exactly hmDependencies) + (exactly hmUserDependencies) + (exactly hmStandaloneDependencies) ]; - baseDeps = - from: - let - exists = from ? aspect && builtins.hasAttr from.aspect den.aspects; - aspect = den.aspects.${from.aspect}; - in + osDependencies = + { OS, host }: { - includes = lib.optionals exists [ - (statics den.default) - (statics aspect) + includes = [ (owned den.default) - (owned aspect) + (statics den.default) + (owned OS) + (statics OS) + { + includes = + let + users = builtins.attrValues host.users; + contrib = osUserDependencies OS host; + in + map contrib users; + } ]; }; - from = o: (lib.flip parametric) den.aspects.${o.aspect}; - - osDependencies = - { OS }: + osUserDependencies = + OS: host: user: let - inherit (OS) host; - users = builtins.attrValues host.users; - hostIncludes = [ - (from host { inherit host; }) - (from host { - inherit OS host; - fromHost = host; - }) - ]; - userIncludes = user: [ - (from user { inherit user; }) - (from user { - inherit OS user host; - fromUser = user; - }) - (from host { - inherit OS user host; - fromHost = host; - }) - ]; + USR = den.aspects.${user.aspect}; + ctx = { inherit OS host user; }; in { - includes = hostIncludes ++ (map (u: { includes = userIncludes u; }) users); + includes = [ + (owned USR) + (statics USR) + (USR ctx) + ]; }; - hmDependencies = - { HM }: - let - inherit (HM) user host; - hostIncludes = [ - (from host { inherit host; }) - (from host { - inherit HM user host; - fromHost = host; - }) - ]; - userIncludes = [ - (from user { inherit user; }) - (from user { - inherit HM user host; - fromUser = user; - }) + # from home-manager integration. + hmUserDependencies = + { + HM, + host, + user, + }: + { + includes = [ + (owned den.default) + (statics den.default) + (owned HM) + (statics HM) + (hmOsDependencies HM host user) ]; + }; + + hmOsDependencies = + HM: host: user: + let + OS = den.aspects.${host.aspect}; + newCtx = { + inherit + HM + OS + host + user + ; + }; in { - includes = hostIncludes ++ userIncludes; + includes = [ + (owned OS) + (statics OS) + (parametric newCtx OS) + ]; }; + + hmStandaloneDependencies = + { HM, home }: + { + includes = [ + (owned den.default) + (statics den.default) + (owned HM) + (statics HM) + ]; + }; + in { den.default.includes = dependencies; diff --git a/modules/aspects/provides/home-manager.nix b/modules/aspects/provides/home-manager.nix index 92ae788..18a436a 100644 --- a/modules/aspects/provides/home-manager.nix +++ b/modules/aspects/provides/home-manager.nix @@ -44,11 +44,11 @@ in inherit aspect-chain; class = hmClass; }; - aspect = den.aspects.${user.aspect} { - HM = { inherit host user; }; - }; + HM = den.aspects.${user.aspect}; + aspect = HM { inherit HM host; }; + module = aspect.resolve ctx; in - aspect.resolve ctx; + module; users = map (user: { name = user.userName; diff --git a/modules/aspects/provides/user-shell.nix b/modules/aspects/provides/user-shell.nix index 9899ae6..3988153 100644 --- a/modules/aspects/provides/user-shell.nix +++ b/modules/aspects/provides/user-shell.nix @@ -28,16 +28,14 @@ let inherit nixos darwin homeManager; }; - inherit (den.lib.take) exactly; - in { den.provides.user-shell = shell: { inherit description; - __functor = den.lib.parametric true; + __functor = den.lib.parametric.atLeast; includes = [ - (exactly ({ user }: userShell shell user)) - (exactly ({ home }: userShell shell home)) + ({ user, ... }: userShell shell user) + ({ home, ... }: userShell shell home) ]; }; } diff --git a/nix/lib.nix b/nix/lib.nix index a9bbeb4..d86c6e8 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -69,7 +69,7 @@ let parametric.atLeast = funk (lib.flip take.atLeast); parametric.exactly = funk (lib.flip take.exactly); parametric.context = lib.flip parametric.atLeast; - parametric.expands = attrs: funk (ctx: (lib.flip take.atLeast) (attrs // ctx)); + parametric.expands = attrs: funk (ctx: (lib.flip take.atLeast) (ctx // attrs)); parametric.__functor = self: ctx: if ctx == true then diff --git a/templates/default/modules/aspects/eg/routes.nix b/templates/default/modules/aspects/eg/routes.nix index ec6f4df..908c02e 100644 --- a/templates/default/modules/aspects/eg/routes.nix +++ b/templates/default/modules/aspects/eg/routes.nix @@ -13,41 +13,18 @@ let inherit (den.lib) parametric; - os-from-user = - { - user, - host, - # deadnix: skip - OS, - # deadnix: skip - fromUser, - }: - parametric { inherit user host; } (mutual user host); + # eg, `._.` and `._.` + mutual = from: to: den.aspects.${from.aspect}._.${to.aspect} or { }; - hm-from-host = + routes = + { host, user, ... }@ctx: { - user, - host, - # deadnix: skip - HM, - # deadnix: skip - fromHost, - }: - parametric { inherit user host; } (mutual host user); - - mutual = from: to: { - includes = [ - # eg, `._.` and `._.` - (den.aspects.${from.aspect}._.${to.aspect} or { }) - ]; - }; - + __functor = parametric ctx; + includes = [ + (mutual user host) + (mutual host user) + ]; + }; in - { - __functor = parametric.exactly; - includes = [ - os-from-user - hm-from-host - ]; - }; + routes; } diff --git a/templates/examples/modules/_example/ci/custom-nixos-module.nix b/templates/examples/modules/_example/ci/custom-nixos-module.nix index d6e1c5a..d8ca14a 100644 --- a/templates/examples/modules/_example/ci/custom-nixos-module.nix +++ b/templates/examples/modules/_example/ci/custom-nixos-module.nix @@ -2,13 +2,22 @@ let # A custom `nixos` class module that defines an option `names`. # Used to test that we are not duplicating values from owned configs. - nixosNames.options.names = lib.mkOption { type = lib.types.listOf lib.types.str; }; + nixosNames = names: { options.${names} = lib.mkOption { type = lib.types.listOf lib.types.str; }; }; in { + den.default.nixos.imports = [ (nixosNames "people") ]; + den.default.includes = [ + ( + { user, ... }: + { + nixos.people = [ user.name ]; + } + ) + ]; den.aspects.rockhopper.includes = [ # Example: importing a third-party nixos module. - { nixos.imports = [ nixosNames ]; } + { nixos.imports = [ (nixosNames "names") ]; } ]; den.aspects.rockhopper.nixos.names = [ "tux" ]; @@ -16,6 +25,9 @@ in perSystem = { checkCond, rockhopper, ... }: { + checks.rockhopper-default-people = checkCond "set from den.default for each user" ( + rockhopper.config.people == [ "alice" ] + ); checks.rockhopper-names-single-entry = checkCond "custom nixos array option set once" ( rockhopper.config.names == [ "tux" ] ); diff --git a/templates/examples/modules/_example/ci/host-user-conditional-hm.nix b/templates/examples/modules/_example/ci/host-user-conditional-hm.nix index 2975c2b..d2ff848 100644 --- a/templates/examples/modules/_example/ci/host-user-conditional-hm.nix +++ b/templates/examples/modules/_example/ci/host-user-conditional-hm.nix @@ -1,21 +1,18 @@ -{ den, lib, ... }: +{ lib, ... }: let # Example: configuration that depends on both host and user. provides only to HM. host-to-user-conditional = { - HM, user, host, ... }: - den.lib.take.unused [ HM ] ( - if user.userName == "alice" && !lib.hasSuffix "darwin" host.system then - { - homeManager.programs.git.enable = true; - } - else - { } - ); + if user.userName == "alice" && !lib.hasSuffix "darwin" host.system then + { + homeManager.programs.git.enable = true; + } + else + { }; in { diff --git a/templates/examples/modules/_example/ci/one-os-package-per-user.nix b/templates/examples/modules/_example/ci/one-os-package-per-user.nix index 49c7c01..aa21730 100644 --- a/templates/examples/modules/_example/ci/one-os-package-per-user.nix +++ b/templates/examples/modules/_example/ci/one-os-package-per-user.nix @@ -1,16 +1,13 @@ -{ den, ... }: let # Example: adds hello into each user. provides only to OS. hello-package-for-user = { - OS, - fromUser, user, host, ... }: - den.lib.take.unused [ OS fromUser ] { + { ${host.class} = { pkgs, ... }: { @@ -21,10 +18,7 @@ let in { - den.default.includes = [ - # Example: parametric { OS, fromUser } aspect. - hello-package-for-user - ]; + den.default.includes = [ hello-package-for-user ]; perSystem = { diff --git a/templates/examples/modules/_example/ci/standalone-hm-special-args-osconfig.nix b/templates/examples/modules/_example/ci/standalone-hm-special-args-osconfig.nix index 1aa8a6b..8981e3d 100644 --- a/templates/examples/modules/_example/ci/standalone-hm-special-args-osconfig.nix +++ b/templates/examples/modules/_example/ci/standalone-hm-special-args-osconfig.nix @@ -2,7 +2,7 @@ let # Example: luke standalone home-manager has access to rockhopper osConfig specialArg. os-conditional-hm = - { home }: + { home, ... }: { # access osConfig, wired via extraSpecialArgs in homes.nix. homeManager =