let scan = import ./scan.nix; flake' = self: { imports, exports , base }@schema: { ... }@inputs: { ... }@imports: let lib = { inherit scan schema inputs imports; extend = flake schema inputs imports; new = flake {} {} {}; # TODO: override }; convert = attr: value: value self inputs imports; result = (builtins.mapAttrs convert schema.exports); in result // { lib = lib // (result.lib or {}); }; flake = { imports?{}, exports?{}, base?[] }@schema'old: { ... }@inputs'old: { ... }@imports'old: { ... }@inputs'new: base: let schema = { imports = (schema'old.imports or {}) // scan { base = base + "/import"; recursive = true; }; exports = (schema'old.exports or {}) // scan { base = base + "/export"; }; base = [ base ] ++ (schema'old.base or []); }; merge = attr: let old = imports'old.${attr} or {}; new = imports'new.${attr} or {}; in builtins.mapAttrs (attr: _: (old.${attr} or []) ++ (new.${attr} or [])) (old//new); imports'new = builtins.mapAttrs (name: value: scan { base = base + "/${name}"; convert = name: content: [ (value name content) ]; }) schema.imports; result = flake' result schema (inputs'old // (builtins.removeAttrs inputs'new ["self"])) (builtins.mapAttrs (attr: _: merge attr) schema.imports); in result; in flake {} {} {}