fake.modules transposition for aspect-oriented Dendritic Nix. with cross-aspect dependencies. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ dendrix.oeiuwq.com/Dendritic.html
dendritic nix aspect oriented

fix links in docs

fix argument of providers to be just aspect and name.

+18 -13
+12 -12
README.md
··· 12 12 On [aspect oriented](https://vic.github.io/dendrix/Dendritic.html) [Dendritic](https://github.com/mightyiam/dendritic) setups, it is common to expose modules using `flake.modules.<class>.<aspect>`. 13 13 However, for humans, it might be more intuitive to use a transposed attrset `<aspect>.<class>`. Because it feels more natural to nest classes inside aspects than the other way around. 14 14 15 - This project provides a [`transpose`](tree/main/default.nix) primitive, small and powerful enough to implement [cross-aspect dependencies](tree/main/aspects.nix) for *any* nix configuration class, and a [flake-parts module](./tree/main/flakeModule.nix) for turning `flake.aspects` into `flake.modules`. 15 + This project provides a [`transpose`](default.nix) primitive, small and powerful enough to implement [cross-aspect dependencies](aspects.nix) for *any* nix configuration class, and a [flake-parts module](flakeModule.nix) for turning `flake.aspects` into `flake.modules`. 16 16 17 17 <table> 18 18 <tr> ··· 76 76 77 77 ### As a deps-free library from `./default.nix`: 78 78 79 - Our [`transpose`](tree/main/default.nix) library takes an optional `emit` function that 79 + Our [`transpose`](default.nix) library takes an optional `emit` function that 80 80 can be used to ignore some items, modify them or produce many other items on its place. 81 81 82 82 ```nix ··· 84 84 transpose { a.b.c = 1; } # => { b.a.c = 1; } 85 85 ``` 86 86 87 - This `emit` function is used by our [`aspects`](tree/main/aspects.nix) library 87 + This `emit` function is used by our [`aspects`](aspects.nix) library 88 88 (both libs are flakes-independent) to provide cross-aspects same-class module dependencies. 89 89 90 90 ### As a *Dendritic* flake-parts module that provides the `flake.aspects` option: ··· 126 126 127 127 #### Declaring cross-aspect dependencies 128 128 129 - `flake.aspects` also allow to dependencies between aspects. 129 + `flake.aspects` also allow **aspects** to declare dependencies between them. 130 130 131 131 Of course each module can have its own `imports`, however aspect requirements 132 132 are aspect-level instead of module-level. Dependencies will ultimately resolve to ··· 136 136 linux and macos hosts. 137 137 Note that `alice` prefers to use `nixos`+`homeManager`, while `bob` likes `darwin`+`hjem`. 138 138 139 - The `development-server` is a "usability concern", that configures the exact same 140 - development tools on two different OS. 141 - When it is applied to a NixOS machine, the `alice.nixos` module will likely 139 + The `development-server` aspect is a "_usability concern_", it configures the exact same 140 + development environment on two different OS. 141 + When applied to a NixOS machine, the `alice.nixos` module will likely 142 142 configure the alice user, but there is no nixos user for `bob`. 143 143 144 144 ```nix ··· 197 197 When a module `flake.modules.nixos.foo` is requested (eg, included in a nixosConfiguration), 198 198 a corresponding module will be computed from `flake.aspects.foo.nixos`. 199 199 200 - `flake.aspects.foo.requires` is a list of functions (named **providers**) 201 - that will be called with `{name = "foo"; class = "nixos"}` to obtain another aspect 200 + `flake.aspects.foo.requires` is a list of functions (**providers**) 201 + that will be called with `{aspect = "foo"; class = "nixos"}` to obtain another aspect 202 202 providing a module having the same `class` (`nixos` in our example). 203 203 204 204 _providers_ are a way of asking: if I have a (`foo`, `nixos`) module what other ··· 212 212 This is why you can use the `with config; [ bar baz ]` syntax. 213 213 They are actually `[ config.bar.provides.itself config.baz.provides.itself ]`. 214 214 215 - but you can also define custom providers that can inspect the argument's `name` and `class` 215 + but you can also define custom providers that can inspect the argument's `aspect` and `class` 216 216 and return some another aspect accordingly. 217 217 218 218 ```nix 219 - flake.aspects.alice.provides.os-user = { name, class, ... }: { 220 - # perhaps regexp matching on name or class. eg, match all "hosts" aspects. 219 + flake.aspects.alice.provides.os-user = { aspect, class, ... }: { 220 + # perhaps regexp matching on aspect or class. eg, match all "hosts" aspects. 221 221 nixos = { }; 222 222 } 223 223 ```
+6 -1
aspects.nix
··· 11 11 aspectModule = 12 12 aspect: class: 13 13 let 14 - require = f: aspectModule (f (aspect // { inherit class; })) class; 14 + require = 15 + f: 16 + aspectModule (f { 17 + aspect = aspect.name; 18 + inherit class; 19 + }) class; 15 20 module.imports = lib.flatten [ 16 21 (aspect.${class} or { }) 17 22 (lib.map require aspect.requires)