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(docs): diagrams pan/zoom using mouse wheel and drag.

+126 -24
+2
docs/src/components/Head.astro
··· 7 7 8 8 <Font cssVariable="--font-victor-mono" preload /> 9 9 <Font cssVariable="--font-jetbrains-mono" preload /> 10 + 11 + <script src="./svg-zoom.js"/>
+50
docs/src/components/svg-zoom.js
··· 1 + (function(){ 2 + window.setTimeout(function() { 3 + document.querySelectorAll("svg").forEach(svgZoom); 4 + },1000); 5 + 6 + function svgZoom(svgContainer) { 7 + let panX = 0; 8 + let panY = 0; 9 + let scale = 1; 10 + 11 + let isDragging = false; 12 + let startX, startY; 13 + 14 + svgContainer.addEventListener('mousedown', function (e) { 15 + isDragging = true; 16 + startX = e.clientX - panX; 17 + startY = e.clientY - panY; 18 + svgContainer.style.cursor = 'grabbing'; 19 + }); 20 + 21 + svgContainer.addEventListener('mousemove', function (e) { 22 + if (isDragging) { 23 + panX = e.clientX - startX; 24 + panY = e.clientY - startY; 25 + updateTransform(); 26 + } 27 + }); 28 + 29 + svgContainer.addEventListener('mouseup', function () { 30 + isDragging = false; 31 + svgContainer.style.cursor = 'grab'; 32 + }); 33 + 34 + svgContainer.addEventListener('wheel', function (e) { 35 + e.preventDefault(); 36 + const zoomAmount = 1.05; 37 + if (e.deltaY < 0) { 38 + scale *= zoomAmount; 39 + } else { 40 + scale /= zoomAmount; 41 + } 42 + updateTransform(); 43 + }); 44 + 45 + function updateTransform() { 46 + svgContainer.style.transform = `translate(${panX}px, ${panY}px) scale(${scale})`; 47 + } 48 + 49 + } 50 + })();
+69 -10
docs/src/content/docs/guides/bidirectional.mdx
··· 1 1 --- 2 - title: Host<->User Mutual Configurations 2 + title: Host<->User Bidirectionality 3 3 description: How to configure bidirectional behavior in Den. 4 4 --- 5 5 ··· 12 12 [`mutual-provider.nix`](https://github.com/vic/den/blob/main/modules/aspects/provides/mutual-provider.nix) 13 13 </Aside> 14 14 15 - ## What Mutual Configurations Means 15 + ## What Bidirectionality Means 16 16 17 17 __Bidirectionality__ means that not only a User contributes 18 18 configuration to a Host, but **also** that a Host contributes ··· 41 41 We need to build the `nixos` Nix module that will later be used by `lib.nixosSystem`. 42 42 To do so, Den invokes the `den.ctx.host` pipeline like this: 43 43 44 + > `Tip: Zoom diagrams using your mouse wheel or drag to move.` 44 45 45 46 ```mermaid 46 47 sequenceDiagram ··· 53 54 Den ->> host : {host = igloo} 54 55 55 56 host ->> igloo : request nixos class 56 - igloo -->> igloo : each igloo.includes takes { host } 57 + igloo -->> igloo : each .includes takes { host } 57 58 igloo -->> host : { nixos = ... } owned and parametric results 58 59 59 60 host ->> user : fan-outs for each user: { host, user } 60 61 61 62 user ->> tux : request nixos class 62 63 tux -->> tux : home classes forwarded as nixos class 63 - tux -->> tux : each tux.includes takes { host, user } 64 + tux -->> tux : each .includes takes { host, user } 64 65 tux -->> user : { nixos = ... } owned and parametric results 65 66 66 67 user -->> host : { nixos = ... } all user contributions ··· 88 89 89 90 When Bidirectionality is enabled, the interaction looks like this: 90 91 92 + > `Tip: Zoom diagrams using your mouse wheel or drag to move.` 93 + 91 94 ```mermaid 92 95 sequenceDiagram 93 96 participant Den ··· 99 102 Den ->> host : {host = igloo} 100 103 101 104 host ->> igloo : request nixos class 102 - igloo -->> igloo : each igloo.includes takes { host } 105 + igloo -->> igloo : each .includes takes { host } 103 106 igloo -->> host : { nixos = ... } owned and parametric results 104 107 105 108 host ->> user : fan-outs for each user: { host, user } ··· 107 110 user ->> tux : request nixos class 108 111 109 112 tux ->> igloo : request home class 110 - igloo -->> igloo : each igloo.includes takes { host, user } 113 + igloo -->> igloo : each .includes takes { host, user } 111 114 igloo -->> tux : { hjem = ... } owned and parametric results 112 115 113 116 tux -->> tux : home classes forwarded as nixos class 114 117 115 - tux -->> tux : each tux.includes takes { host, user } 118 + tux -->> tux : each .includes takes { host, user } 116 119 tux -->> user : { nixos = ... } owned and parametric results 117 120 118 121 user -->> host : { nixos = ... } all user contributions ··· 121 124 122 125 ``` 123 126 124 - Crucial points here are `igloo.includes takes { host }` and `igloo.includes takes { host, user }`. 127 + Crucial points here are when `den.aspects.igloo.includes` are called with `{ host }` and later with `{ host, user }` per-user. 125 128 126 - Because the list of aspects at `igloo.includes` get invoked twice, with different contexts, 129 + Because the list of aspects at `igloo.includes` get invoked more than once, with different contexts, 127 130 functions at `igloo.includes` must take care of the following: 128 131 129 132 ```nix ··· 143 146 This battery is safer, instead of using the host aspect directly, it requires you to define other named aspects under `.provides.` to create an explicit relationship between users and hosts. 144 147 145 148 ```nix 146 - den.default.includes = [ den._.mutual-provider ]; 149 + # mutual-provider is activated at a `{host,user}` context 150 + den.ctx.user.includes = [ den._.mutual-provider ]; 147 151 148 152 # user aspect provides to specific host or to all where it lives 149 153 den.aspects.tux = { ··· 161 165 }; 162 166 }; 163 167 ``` 168 + 169 + > `Tip: Zoom diagrams using your mouse wheel or drag to move.` 170 + 171 + ```mermaid 172 + sequenceDiagram 173 + participant Den 174 + participant host as den.ctx.host 175 + participant user as den.ctx.user 176 + participant igloo as den.aspects.igloo 177 + participant igloo-users as den.aspects.igloo.provides.to-users 178 + participant igloo-tux as den.aspects.igloo.provides.tux 179 + participant tux as den.aspects.tux 180 + participant tux-hosts as den.aspects.tux.provides.to-hosts 181 + participant tux-igloo as den.aspects.tux.provides.igloo 182 + 183 + Den ->> host : {host = igloo} 184 + 185 + host ->> igloo : request nixos class 186 + igloo -->> igloo : each .includes takes { host } 187 + igloo -->> host : { nixos = ... } owned and parametric results 188 + 189 + host ->> user : fan-outs for each user: { host, user } 190 + 191 + user ->> tux : request nixos class 192 + tux -->> tux : home classes forwarded as nixos class 193 + tux -->> tux : each .includes takes { host, user } 194 + tux -->> user : { nixos = ... } owned and parametric results 195 + 196 + user ->> igloo-users : host configs its users: { host, user } 197 + igloo-users -->> igloo-users : home classes forwarded as nixos class 198 + igloo-users -->> igloo-users : each .includes takes { host, user } 199 + igloo-users -->> user : { nixos = ... } 200 + 201 + user ->> igloo-tux : host configs tux: { host, user } 202 + igloo-tux -->> igloo-tux : home classes forwarded as nixos class 203 + igloo-tux -->> igloo-tux : each .includes takes { host, user } 204 + igloo-tux -->> user : { nixos = ... } 205 + 206 + user ->> tux-hosts : user configs its hosts: { host, user } 207 + tux-hosts -->> tux-hosts : home classes forwarded as nixos class 208 + tux-hosts -->> tux-hosts : each .includes takes { host, user } 209 + tux-hosts -->> user : { nixos = ... } 210 + 211 + user ->> tux-igloo : user configs igloo: { host, user } 212 + tux-igloo -->> tux-igloo : home classes forwarded as nixos class 213 + tux-igloo -->> tux-igloo : each .includes takes { host, user } 214 + tux-igloo -->> user : { nixos = ... } 215 + 216 + 217 + user -->> host : { nixos = ... } all user contributions 218 + 219 + host -->> Den : complete nixos module for lib.nixosSystem 220 + 221 + ``` 222 +
+1 -10
modules/aspects/provides/mutual-provider.nix
··· 14 14 The reason is that this battery does not re-invoke the `host-aspect.includes`, 15 15 instead it relies on you defining provides. 16 16 17 - Unlike `den.default` which is `parametric.atLeast` we use 18 - `parametric.fixedTo` here, which help us propagate an already computed 19 - context to all includes. 20 - 21 - This battery, when installed in a `parametric.atLeast` will just forward 22 - the same context. The `find-mutual` helper returns an static configuration 23 - which is ignored by parametric aspects, thus allowing non-existing 24 - aspects to be just ignored. 25 - 26 17 Be sure to read diagrams for the Host context pipeline: 27 18 https://den.oeiuwq.com/guides/bidirectional 28 19 29 20 ## Usage 30 21 31 22 den.hosts.x86_64-linux.igloo.users.tux = { }; 32 - den.default.includes = [ den._.mutual-provider ]; 23 + den.ctx.user.includes = [ den._.mutual-provider ]; 33 24 34 25 # user aspect provides to specific host or to all where it lives 35 26 den.aspects.tux = {
+4 -4
templates/ci/modules/features/batteries/mutual-provider.nix
··· 7 7 { 8 8 den.hosts.x86_64-linux.igloo.users.tux = { }; 9 9 10 - den.default.includes = [ den._.mutual-provider ]; 10 + den.ctx.user.includes = [ den._.mutual-provider ]; 11 11 12 12 den.aspects.igloo.provides.tux = den.lib.parametric { 13 13 homeManager.home.shellAliases.g = "git"; ··· 24 24 { 25 25 den.hosts.x86_64-linux.igloo.users.tux = { }; 26 26 27 - den.default.includes = [ den._.mutual-provider ]; 27 + den.ctx.user.includes = [ den._.mutual-provider ]; 28 28 29 29 den.aspects.tux.provides.igloo = den.lib.parametric { 30 30 nixos.boot.crashDump.reservedMemory = "99999M"; ··· 41 41 { 42 42 den.hosts.x86_64-linux.igloo.users.tux = { }; 43 43 44 - den.default.includes = [ den._.mutual-provider ]; 44 + den.ctx.user.includes = [ den._.mutual-provider ]; 45 45 46 46 den.aspects.igloo.provides.tux = den.lib.parametric { 47 47 homeManager.home.keyboard.model = "denboard"; ··· 68 68 { 69 69 den.hosts.x86_64-linux.igloo.users.tux = { }; 70 70 71 - den.default.includes = [ den._.mutual-provider ]; 71 + den.ctx.user.includes = [ den._.mutual-provider ]; 72 72 73 73 den.aspects.igloo.provides.to-users = { 74 74 homeManager.home.keyboard.model = "denboard";