feat(lib)!: add createThings
Redefine `createPackages` and `createModules` in terms of `createThings` Move `lib` flake module to a subdirectory
This commit is contained in:
parent
cd148400bf
commit
7cf980d913
5 changed files with 135 additions and 119 deletions
163
modules/flake/lib/default.nix
Normal file
163
modules/flake/lib/default.nix
Normal file
|
@ -0,0 +1,163 @@
|
|||
{ lib, config, self, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./things.nix
|
||||
];
|
||||
|
||||
options = let
|
||||
inherit (lib) types;
|
||||
in {
|
||||
lib = lib.mkOption {
|
||||
type = types.unspecified;
|
||||
};
|
||||
};
|
||||
|
||||
config.lib = rec {
|
||||
# Boolean helpers
|
||||
and = lib.all lib.id;
|
||||
or = lib.any lib.id;
|
||||
eq = x: y: x == y;
|
||||
|
||||
# Directory walking helpers
|
||||
recurseDir = dir:
|
||||
lib.mapAttrs
|
||||
(file: type:
|
||||
if type == "directory"
|
||||
then recurseDir "${dir}/${file}"
|
||||
else type)
|
||||
(builtins.readDir dir);
|
||||
|
||||
allSatisfy = predicate: attrs: attrset:
|
||||
lib.all
|
||||
(attr:
|
||||
and [
|
||||
(builtins.hasAttr attr attrset)
|
||||
(predicate (builtins.getAttr attr attrset))
|
||||
])
|
||||
attrs;
|
||||
|
||||
# NOTE: Implying last argument is the output of `recurseDir`
|
||||
hasFiles = allSatisfy (eq "regular");
|
||||
|
||||
# NOTE: Implying last argument is the output of `recurseDir`
|
||||
hasDirectories = allSatisfy lib.isAttrs;
|
||||
|
||||
camelToKebab =
|
||||
lib.stringAsChars
|
||||
(c: if c == lib.toUpper c then "-${lib.toLower c}" else c);
|
||||
|
||||
# NOTE: adapted from Tweag's Nix Hour 76 - <https://github.com/tweag/nix-hour/blob/c4fd0f2fc3059f057571bbfd74f3c5e4021f526c/code/76/default.nix#L4-L22>
|
||||
mutFirstChar =
|
||||
f: s:
|
||||
let
|
||||
firstChar = f (lib.substring 0 1 s);
|
||||
rest = lib.substring 1 (-1) s;
|
||||
in firstChar + rest;
|
||||
|
||||
kebabToCamel = lib.flip lib.pipe [
|
||||
(lib.splitString "-")
|
||||
(lib.concatMapStrings
|
||||
(mutFirstChar lib.toUpper))
|
||||
(mutFirstChar lib.toLower)
|
||||
];
|
||||
# s:
|
||||
# mutFirstChar
|
||||
# lib.toLower
|
||||
# (lib.concatMapStrings
|
||||
# (mutFirstChar lib.toUpper)
|
||||
# (lib.splitString "-" s));
|
||||
|
||||
gen-configuration-type-to = mappings: mkError: configuration-type:
|
||||
mappings.${configuration-type} or
|
||||
(builtins.throw
|
||||
(mkError configuration-type));
|
||||
|
||||
# TODO: abstract away `_Hosts` and `_Modules`
|
||||
|
||||
configuration-type-to-outputs-hosts =
|
||||
gen-configuration-type-to
|
||||
{
|
||||
nixos = "nixosHosts";
|
||||
nix-on-droid = "nixOnDroidHosts";
|
||||
nix-darwin = "darwinHosts";
|
||||
home-manager = "homeManagerHosts";
|
||||
}
|
||||
(configuration-type:
|
||||
builtins.throw
|
||||
"Invaild configuration-type \"${configuration-type}\" for flake outputs' hosts");
|
||||
|
||||
configuration-type-to-outputs-modules =
|
||||
gen-configuration-type-to
|
||||
{
|
||||
nixos = "nixosModules";
|
||||
nix-on-droid = "nixOnDroidModules";
|
||||
nix-darwin = "darwinModules";
|
||||
home-manager = "homeManagerModules";
|
||||
flake = "flakeModules";
|
||||
}
|
||||
(configuration-type:
|
||||
builtins.throw
|
||||
"Invaild configuration-type \"${configuration-type}\" for flake outputs' modules");
|
||||
|
||||
configuration-type-to-outputs-configurations =
|
||||
gen-configuration-type-to
|
||||
{
|
||||
nixos = "nixosConfigurations";
|
||||
nix-on-droid = "nixOnDroidConfigurations";
|
||||
nix-darwin = "darwinConfigurations";
|
||||
home-manager = "homeConfigurations";
|
||||
}
|
||||
(configuration-type:
|
||||
builtins.throw
|
||||
"Invaild configuration-type \"${configuration-type}\" for flake outputs' configurations");
|
||||
|
||||
configuration-type-to-deploy-type =
|
||||
gen-configuration-type-to
|
||||
{
|
||||
nixos = "nixos";
|
||||
nix-darwin = "darwin";
|
||||
}
|
||||
(configuration-type:
|
||||
builtins.throw
|
||||
"Invaild configuration-type \"${configuration-type}\" for deploy-rs deployment");
|
||||
|
||||
accumulateHosts = configuration-types: host-system-configuration-type-configuration-fn:
|
||||
lib.flip lib.concatMapAttrs
|
||||
(lib.genAttrs
|
||||
configuration-types
|
||||
(configuration-type:
|
||||
config.flake.autoConfigurations.${configuration-type}.resultHosts))
|
||||
(configuration-type: hosts:
|
||||
lib.pipe
|
||||
hosts
|
||||
[
|
||||
# Filter out nondirectories
|
||||
(lib.filterAttrs
|
||||
(system: configurations:
|
||||
builtins.isAttrs configurations))
|
||||
# Convert non-template configs into `system-and-config` pairs
|
||||
(lib.concatMapAttrs
|
||||
(system: configurations:
|
||||
(lib.concatMapAttrs
|
||||
(host: configuration:
|
||||
lib.optionalAttrs
|
||||
(host != "__template__")
|
||||
{
|
||||
${host} = {
|
||||
inherit system;
|
||||
configuration =
|
||||
let
|
||||
configurations = configuration-type-to-outputs-configurations configuration-type;
|
||||
in
|
||||
self.${configurations}.${host};
|
||||
};
|
||||
})
|
||||
configurations)))
|
||||
# Convert each `system-and-config` pair into a *whatever*
|
||||
(lib.concatMapAttrs
|
||||
(host: { system, configuration }:
|
||||
host-system-configuration-type-configuration-fn { inherit host system configuration-type configuration; }))
|
||||
]);
|
||||
};
|
||||
}
|
112
modules/flake/lib/things.nix
Normal file
112
modules/flake/lib/things.nix
Normal file
|
@ -0,0 +1,112 @@
|
|||
{ 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)
|
||||
];
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue