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
at main 85 lines 1.8 kB view raw
1{ lib, den, ... }: 2let 3 inherit (den.lib) parametric; 4 5 cleanCtx = 6 self: 7 builtins.removeAttrs self [ 8 "name" 9 "description" 10 "into" 11 "provides" 12 "__functor" 13 "modules" 14 "resolve" 15 "_module" 16 "_" 17 ]; 18 19 transformAll = 20 source: self: ctx: 21 [ 22 { 23 inherit ctx source; 24 ctxDef = self; 25 } 26 ] 27 ++ lib.concatLists ( 28 lib.mapAttrsToList ( 29 name: into: 30 if !builtins.hasAttr name den.ctx then 31 [ ] 32 else 33 lib.concatMap (transformAll self den.ctx.${name}) (into ctx) 34 ) self.into 35 ); 36 37 noop = _: { }; 38 39 crossProvider = 40 p: 41 let 42 src = p.source; 43 name = p.ctxDef.name; 44 in 45 if src == null then noop else src.provides.${name} or noop; 46 47 dedupIncludes = 48 let 49 go = 50 acc: remaining: 51 if remaining == [ ] then 52 acc.result 53 else 54 let 55 p = builtins.head remaining; 56 rest = builtins.tail remaining; 57 name = p.ctxDef.name; 58 clean = cleanCtx p.ctxDef; 59 isFirst = !(acc.seen ? ${name}); 60 selfFun = p.ctxDef.provides.${name} or noop; 61 crossFun = crossProvider p; 62 items = [ 63 (if isFirst then parametric.fixedTo p.ctx clean else parametric.atLeast clean p.ctx) 64 (selfFun p.ctx) 65 (crossFun p.ctx) 66 ]; 67 in 68 go { 69 seen = acc.seen // { 70 ${name} = true; 71 }; 72 result = acc.result ++ items; 73 } rest; 74 in 75 go { 76 seen = { }; 77 result = [ ]; 78 }; 79 80 ctxApply = self: ctx: { 81 includes = dedupIncludes (transformAll null self ctx); 82 }; 83 84in 85ctxApply