Modular, context-aware and aspect-oriented dendritic Nix configurations. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ den.oeiuwq.com
configurations den dendritic nix aspect oriented
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(class): Allow top-level forwarded-alias classes (#309)

authored by

Victor Borja and committed by
GitHub
39e8df95 5c1a1a4c

+269 -12
+78 -11
docs/src/content/docs/guides/custom-classes.mdx
··· 6 6 import { Aside } from '@astrojs/starlight/components'; 7 7 8 8 <Aside title="Source" icon="github"> 9 - [`modules/aspects/provides/forward.nix`](https://github.com/vic/den/blob/main/modules/aspects/provides/forward.nix) -- 10 - [`modules/aspects/provides/os-user.nix`](https://github.com/vic/den/blob/main/modules/aspects/provides/os-user.nix) -- 11 - [forward tests](https://github.com/vic/den/blob/main/templates/ci/modules/features/forward-from-custom-class.nix) 9 + [`forward.nix`](https://github.com/vic/den/blob/main/modules/aspects/provides/forward.nix) -- 10 + [`os-user.nix`](https://github.com/vic/den/blob/main/modules/aspects/provides/os-user.nix) -- 11 + [`forward-alias-class.nix`](https://github.com/vic/den/blob/main/templates/ci/modules/features/forward-alias-class.nix) -- 12 + [`forward-from-custom-class.nix`](https://github.com/vic/den/blob/main/templates/ci/modules/features/forward-from-custom-class.nix) -- 13 + [`guarded-forward.nix`](https://github.com/vic/den/blob/main/templates/ci/modules/features/guarded-forward.nix) 12 14 </Aside> 13 15 14 16 ## What is a Custom Class ··· 44 46 | `each` | List of items to forward (typically `[ user ]` or `[ true ]`) | 45 47 | `fromClass` | The custom class name to read from | 46 48 | `intoClass` | The target class to write into | 47 - | `intoPath` | Target attribute path in the target class | 49 + | `intoPath` | Target attribute path in the target class| 48 50 | `fromAspect` | The aspect to read the custom class from | 49 51 52 + 50 53 ## Example: The Built-in `user` Class 51 54 52 - The `user` class (`modules/aspects/provides/os-user.nix`) forwards OS-level 53 - user settings without requiring Home Manager: 55 + The `user` class ([`provides/os-user.nix`](https://github.com/vic/den/tree/main/modules/aspects/provides/os-user.nix)) 56 + forwards OS-level user settings to NixOS/nix-Darwin lightweight user-environment. 54 57 55 58 ```nix 56 59 # Instead of: ··· 156 159 157 160 ## User contributed examples 158 161 159 - #### Example: Config across `nixos` and `darwin` classes. 162 + ### Example: Alias a Class into the Target Root 163 + 164 + This pattern is useful when you want a class to behave like an alias for another 165 + class while keeping a separate name in your aspects. 166 + 167 + ```nix 168 + hmAlias = 169 + { class, aspect-chain }: 170 + den._.forward { 171 + each = lib.singleton class; 172 + fromClass = _: "hm"; 173 + intoClass = _: "homeManager"; 174 + intoPath = _: [ ]; 175 + fromAspect = _: lib.head aspect-chain; 176 + adaptArgs = { config, ... }: { osConfig = config; }; 177 + }; 178 + 179 + den.aspects.tux = { 180 + includes = [ hmAlias ]; 181 + hm = 182 + { osConfig, ... }: 183 + { 184 + programs.fish.enable = true; 185 + home.keyboard.model = osConfig.networking.hostName; 186 + }; 187 + }; 188 + ``` 189 + 190 + This forwards `hm.*` directly into `homeManager.*`. A more interesting use case is the following: 191 + 192 + 193 + ### Example: Platform specific `hm` classes 194 + 195 + This pattern is useful when you need HM to distinguish between 196 + different OS Platforms, because some packages only build in 197 + Darwin and not NixOS. 198 + 199 + 200 + ```nix 201 + hmPlatforms = 202 + { class, aspect-chain }: 203 + den._.forward { 204 + each = [ "Linux" "Darwin" "Aarch64" "64bit" ]; 205 + fromClass = platform: "hm${platform}"; 206 + intoClass = _: "homeManager"; 207 + intoPath = _: [ ]; 208 + fromAspect = _: lib.head aspect-chain; 209 + guard = { pkgs, ... }: platform: lib.mkIf pkgs.stdenv."is${platform}"; 210 + adaptArgs = { config, ... }: { osConfig = config; }; 211 + }; 212 + 213 + den.aspects.tux = { 214 + includes = [ hmPlatforms ]; 215 + 216 + hmLinux = { pkgs, ... }: { 217 + home.packages = [ pkgs.wl-clipboard-rs ]; 218 + }; 219 + 220 + hmDarwin = { pkgs, ... }: { 221 + home.packages = [ pkgs.iterm2 ]; 222 + }; 223 + }; 224 + ``` 225 + 226 + ### Example: Config across `nixos` and `darwin` classes. 160 227 161 228 The `os` forward class ([provided by Den](https://github.com/vic/den/blob/main/modules/aspects/provides/os-class.nix)) can be useful for settings that must be forwarded to both on NixOS and MacOS. 162 229 ··· 180 247 }; 181 248 ``` 182 249 183 - #### Example: Role based configuration between users and hosts 250 + ### Example: Role based configuration between users and hosts 184 251 185 252 A dynamic class for matching roles between users and hosts. 186 253 ··· 215 282 }; 216 283 ``` 217 284 218 - #### Example: A git class that checks enable. 285 + ### Example: A git class that checks enable. 219 286 220 287 ```nix 221 288 gitClass = ··· 237 304 238 305 This will set at host: `home-manager.users.tux.programs.git.userEmail` 239 306 240 - #### Example: A `nix` class that propagates settings to NixOS and HomeManager 307 + ### Example: A `nix` class that propagates settings to NixOS and HomeManager 241 308 242 309 This can be used when you don't want NixOS and HomeManager to share the 243 310 same pkgs but still configure both at the same time. ··· 265 332 den.aspects.tux.includes = [ nix-allowed ]; 266 333 ``` 267 334 268 - #### Example: An impermanence class 335 + ### Example: An impermanence class 269 336 270 337 > Suggested by @Doc-Steve 271 338
+37 -1
modules/aspects/provides/forward.nix
··· 50 50 "adaptArgs" 51 51 "adapterModule" 52 52 ]; 53 + 53 54 item = lib.head fwd.each; 54 55 fromClass = fwd.fromClass item; 55 56 intoClass = fwd.intoClass item; 56 57 intoPath = fwd.intoPath item; 58 + 59 + sourceModule = den.lib.aspects.resolve fromClass [ ] (fwd.fromAspect item); 60 + 57 61 freeformMod = { 58 62 config._module.freeformType = lib.types.lazyAttrsOf lib.types.unspecified; 59 63 }; 64 + 60 65 adapterKey = lib.concatStringsSep "/" ( 61 66 [ 62 67 fromClass ··· 101 106 }; 102 107 }; 103 108 109 + topLevelAdapter.${intoClass} = { 110 + __functionArgs = guardArgs; 111 + __functor = 112 + _: args: 113 + let 114 + extraArgs = 115 + if adaptArgs == null then { } else builtins.removeAttrs (adaptArgs args) (builtins.attrNames args); 116 + specialArgs = 117 + builtins.removeAttrs args [ 118 + "config" 119 + "options" 120 + "lib" 121 + ] 122 + // extraArgs; 123 + evaluated = lib.evalModules { 124 + inherit specialArgs; 125 + modules = (if adapterModule == null then [ freeformMod ] else [ adapterModule ]) ++ [ 126 + sourceModule 127 + ]; 128 + }; 129 + in 130 + guardFn args evaluated.config; 131 + }; 132 + 104 133 needsAdapter = guard != null || adaptArgs != null || adapterModule != null; 134 + needsTopLevelAdapter = needsAdapter && intoPath == [ ]; 105 135 forwarded = den.lib.aspects.forward clean; 136 + 106 137 in 107 - if needsAdapter then adapter else forwarded; 138 + if needsTopLevelAdapter then 139 + topLevelAdapter 140 + else if needsAdapter then 141 + adapter 142 + else 143 + forwarded; 108 144 109 145 in 110 146 {
+154
templates/ci/modules/features/forward-alias-class.nix
··· 1 + { denTest, ... }: 2 + { 3 + flake.tests.forward-alias-class = { 4 + 5 + test-home-alias-forwards-into-home-manager-root = denTest ( 6 + { 7 + den, 8 + lib, 9 + igloo, 10 + ... 11 + }: 12 + let 13 + forwarded = 14 + { class, aspect-chain }: 15 + den._.forward { 16 + each = lib.singleton class; 17 + fromClass = _: "home"; 18 + intoClass = _: "homeManager"; 19 + intoPath = _: [ ]; 20 + fromAspect = _: lib.head aspect-chain; 21 + adaptArgs = 22 + { config, ... }: 23 + { 24 + osConfig = config; 25 + }; 26 + }; 27 + in 28 + { 29 + den.hosts.x86_64-linux.igloo.users.tux = { }; 30 + 31 + den.aspects.igloo.nixos.networking.hostName = "storm"; 32 + 33 + den.aspects.tux = { 34 + includes = [ forwarded ]; 35 + home = 36 + { osConfig, ... }: 37 + { 38 + programs.fish.enable = true; 39 + home.keyboard.model = osConfig.networking.hostName; 40 + }; 41 + }; 42 + 43 + expr = { 44 + enable = igloo.home-manager.users.tux.programs.fish.enable; 45 + model = igloo.home-manager.users.tux.home.keyboard.model; 46 + }; 47 + expected = { 48 + enable = true; 49 + model = "storm"; 50 + }; 51 + } 52 + ); 53 + 54 + test-guarded-home-alias-forwards-into-home-manager-root = denTest ( 55 + { 56 + den, 57 + lib, 58 + igloo, 59 + ... 60 + }: 61 + let 62 + forwarded = 63 + { class, aspect-chain }: 64 + den._.forward { 65 + each = lib.singleton class; 66 + fromClass = _: "home"; 67 + intoClass = _: "homeManager"; 68 + intoPath = _: [ ]; 69 + fromAspect = _: lib.head aspect-chain; 70 + guard = { config, ... }: _: lib.mkIf config.programs.fish.enable; 71 + adaptArgs = 72 + { config, ... }: 73 + { 74 + osConfig = config; 75 + }; 76 + }; 77 + in 78 + { 79 + den.hosts.x86_64-linux.igloo.users.tux = { }; 80 + 81 + den.aspects.igloo.nixos.networking.hostName = "storm"; 82 + den.aspects.tux.homeManager.programs.fish.enable = true; 83 + 84 + den.aspects.tux = { 85 + includes = [ forwarded ]; 86 + home = 87 + { osConfig, ... }: 88 + { 89 + home.keyboard.model = osConfig.networking.hostName; 90 + }; 91 + }; 92 + 93 + expr = { 94 + enable = igloo.home-manager.users.tux.programs.fish.enable; 95 + model = igloo.home-manager.users.tux.home.keyboard.model; 96 + }; 97 + expected = { 98 + enable = true; 99 + model = "storm"; 100 + }; 101 + } 102 + ); 103 + 104 + test-hm-platforms-example = denTest ( 105 + { 106 + den, 107 + lib, 108 + igloo, 109 + apple, 110 + ... 111 + }: 112 + let 113 + forwarded = 114 + { class, aspect-chain }: 115 + den._.forward { 116 + each = [ 117 + "Linux" 118 + "Darwin" 119 + ]; 120 + fromClass = platform: "hm${platform}"; 121 + intoClass = _: "homeManager"; 122 + intoPath = _: [ ]; 123 + fromAspect = _: lib.head aspect-chain; 124 + guard = { pkgs, ... }: platform: lib.mkIf pkgs.stdenv."is${platform}"; 125 + adaptArgs = 126 + { config, ... }: 127 + { 128 + osConfig = config; 129 + }; 130 + }; 131 + in 132 + { 133 + den.hosts.x86_64-linux.igloo.users.tux = { }; 134 + den.hosts.aarch64-darwin.apple.users.tux = { }; 135 + 136 + den.aspects.tux = { 137 + includes = [ forwarded ]; 138 + hmLinux.home.keyboard.model = "freedom"; 139 + hmDarwin.home.keyboard.model = "closed"; 140 + }; 141 + 142 + expr = { 143 + linux = igloo.home-manager.users.tux.home.keyboard.model; 144 + darwin = apple.home-manager.users.tux.home.keyboard.model; 145 + }; 146 + expected = { 147 + linux = "freedom"; 148 + darwin = "closed"; 149 + }; 150 + } 151 + ); 152 + 153 + }; 154 + }