rix101/modules/flake/lib/things.nix

113 lines
3.2 KiB
Nix
Raw Normal View History

{ lib, config, self, inputs, ... }:
let
inherit (config.lib)
and
eq
hasFiles
;
in
{
config.lib = rec {
# Try to passthru `inputs` by default
defaultThingHandle = { raw, thingType }: name: result: let
thing =
if raw
then result
else result.${thingType};
passthru = {
inherit inputs;
};
handledThing =
if and [
(builtins.isFunction
thing)
# FIXME: check for subset, not `eq`
(eq
(lib.pipe thing [ builtins.functionArgs builtins.attrNames ])
(lib.pipe passthru [ builtins.attrNames ]))
]
# { inputs, ... }: { foo, ... }: bar
then thing passthru
# { foo, ... }: bar
else thing;
handledResult =
if raw
then handledThing
else result // { ${thingType} = handledThing; };
in handledResult;
# TODO: make `passthru` more generic (maybe take `thing` as arg and decide itself what to do?)
createThings =
{ baseDir
, thingType ? "thing"
, filter ? (name: type: true)
, handle ? (defaultThingHandle { inherit raw thingType; })
, raw ? true
, extras ? {}
, ...
}:
assert raw -> extras == {};
lib.pipe baseDir [
# Read given directory
builtins.readDir
# Filter out unwanted things
(lib.filterAttrs
filter)
# Map each entry to a thing
(lib.mapAttrs'
(name: type:
let
# BUG: cannot use `append` because of `${self}` (not a path)
# thingDir = lib.path.append baseDir "${name}";
thingDir = "${baseDir}/${name}";
importedExtras = lib.pipe extras [
(lib.mapAttrs (name: { default, ... }:
assert name != "default";
assert name != thingType;
let
extraPath = "${thingDir}/${name}.nix";
in
if builtins.pathExists extraPath
then import extraPath
else default))
];
thing = import thingDir;
result =
if raw
then thing
else lib.attrsets.unionOfDisjoint
{ ${thingType} = thing; }
importedExtras;
in
if and [
(type == "directory")
(hasFiles [ "default.nix" ] (builtins.readDir thingDir))
] then
# Classic thing in a directory
lib.nameValuePair
name
result
else if and [
(type == "regular")
(lib.hasSuffix ".nix" name)
] then
# Classic thing in a file
lib.nameValuePair
(lib.removeSuffix ".nix" name)
result
else
# Invalid thing
lib.nameValuePair
name
null))
# Filter invalid things
(lib.filterAttrs
(thingName: thing:
thing != null))
# Handle if needed
(lib.mapAttrs handle)
];
};
}