{ lib, self, ... }: let /* Recursively find all .nix files in a directory tree. This traverses a directory recursively and returns a flat list of paths to every .nix file found. Type: dirToModuleList :: Path -> [Path] Example: dirToModuleList ./modules/nixos => [ /path/to/modules/nixos/users/default.nix /path/to/modules/nixos/networking/default.nix ] */ dirToModuleList = directory: let entries = builtins.readDir directory; processEntry = name: type: if type == "directory" then dirToModuleList "${directory}/${name}" else if lib.hasSuffix ".nix" name then [ "${directory}/${name}" ] else [ ]; in lib.flatten (lib.mapAttrsToList processEntry entries); /* Recursively import all .nix files from a directory into an attrset. Traverses a directory tree, imports each .nix file with the provided arguments, and merges all results into a single attribute set. Subdirectories are recursively processed. Type: dirToAttrset :: Path -> AttrSet -> AttrSet Example: Given directory structure: lib/ strings.nix -> { trim = s: ...; } math.nix -> { add = a: b: ...; } dirToAttrset ./lib { inherit lib; } => { trim = ...; add = ...; } Arguments: directory: Path to scan for .nix files importArgs: Attribute set to pass to each imported file */ dirToAttrset = directory: importArgs: let entries = builtins.readDir directory; processEntry = name: type: if type == "directory" then dirToAttrset "${directory}/${name}" importArgs else if lib.hasSuffix ".nix" name then import "${directory}/${name}" importArgs else { }; in builtins.foldl' (acc: element: acc // element) { } (lib.mapAttrsToList processEntry entries); in { flake = { lib = dirToAttrset ../../lib { inherit lib self; } // { filesystem = { inherit dirToModuleList dirToAttrset; }; }; }; }