Initial commit

This commit is contained in:
kirbara 2025-12-01 13:23:24 +07:00
commit cfcc57a8bd
Signed by: exp
GPG key ID: D7E63AD0019E75D9
353 changed files with 18756 additions and 0 deletions

View file

@ -0,0 +1,8 @@
# creates den.default aspect
{ lib, den, ... }:
{
config.den.default.__functor = den.lib.parametric.atLeast;
options.den.default = lib.mkOption {
type = den.lib.aspects.types.aspectSubmodule;
};
}

View file

@ -0,0 +1,34 @@
# create aspect dependencies from hosts/users
{
lib,
den,
...
}:
let
inherit (den.lib) parametric;
makeAspect = from: {
${from.aspect} = {
${from.class} = { };
includes = [ den.default ];
__functor = parametric.atLeast;
};
};
hosts = map builtins.attrValues (builtins.attrValues den.hosts);
homes = map builtins.attrValues (builtins.attrValues den.homes);
aspectClass = from: { inherit (from) aspect class; };
deps = lib.pipe hosts [
(lib.flatten)
(map (h: builtins.attrValues h.users))
(users: users ++ hosts ++ homes)
(lib.flatten)
(map aspectClass)
(lib.unique)
(map makeAspect)
];
in
{
den.aspects = lib.mkMerge deps;
}

View file

@ -0,0 +1,97 @@
{
den,
lib,
...
}:
let
inherit (den.lib)
owned
statics
parametric
;
inherit (den.lib.take) exactly;
dependencies = [
(exactly osDependencies)
(exactly hmUserDependencies)
(exactly hmStandaloneDependencies)
];
osDependencies =
{ OS, host }:
{
includes = [
(owned den.default)
(statics den.default)
(owned OS)
(statics OS)
{
includes =
let
users = builtins.attrValues host.users;
contrib = osUserDependencies { inherit OS host; };
in
map contrib users;
}
];
};
osUserDependencies =
{ OS, host }:
user:
let
USR = den.aspects.${user.aspect};
in
{
includes = [
(owned USR)
(statics USR)
(USR { inherit OS host user; })
];
};
# from OS home-managed integration.
hmUserDependencies =
{
OS-HM,
host,
user,
}:
let
inherit (OS-HM) OS HM;
in
{
includes = [
(owned den.default)
(statics den.default)
(owned HM)
(statics HM)
(owned OS)
(statics OS)
(parametric {
inherit
OS
HM
user
host
;
} OS)
];
};
hmStandaloneDependencies =
{ HM, home }:
{
includes = [
(owned den.default)
(statics den.default)
(owned HM)
(statics HM)
];
};
in
{
den.default.includes = dependencies;
}

View file

@ -0,0 +1,17 @@
{ lib, config, ... }:
{
options.den = lib.mkOption {
type = lib.types.submodule {
imports = [
(lib.mkAliasOptionModule [ "_" ] [ "provides" ])
];
options.provides = lib.mkOption {
default = { };
description = "Batteries Included - re-usable high-level aspects";
type = lib.types.submodule {
freeformType = lib.types.attrsOf config.den.lib.aspects.types.providerType;
};
};
};
};
}

View file

@ -0,0 +1,55 @@
{ lib, den, ... }:
let
description = ''
Defines a user at OS and Home levels.
Works in NixOS/Darwin and standalone Home-Manager
## Usage
# for NixOS/Darwin
den.aspects.my-user.includes = [ den._.define-user ]
# for standalone home-manager
den.aspects.my-home.includes = [ den._.define-user ]
or globally (automatically applied depending on context):
den.default.includes = [ den._.define-user ]
'';
homeDir =
host: user:
if lib.hasSuffix "darwin" host.system then "/Users/${user.userName}" else "/home/${user.userName}";
userContext =
{ host, user, ... }:
{
nixos.users.users.${user.userName}.isNormalUser = true;
darwin.users.users.${user.userName} = {
name = user.userName;
home = homeDir host user;
};
homeManager = {
home.username = user.userName;
home.homeDirectory = homeDir host user;
};
};
hmContext =
{ home, ... }:
userContext {
host.system = home.system;
user.userName = home.userName;
};
in
{
den.provides.define-user = {
inherit description;
includes = [
userContext
hmContext
];
__functor = den.lib.parametric.atLeast;
};
}

View file

@ -0,0 +1,76 @@
{
inputs,
lib,
den,
...
}:
let
description = ''
integrates home-manager into nixos/darwin OS classes.
usage:
for using home-manager in just a particular host:
den.aspects.my-laptop.includes = [ den._.home-manager ];
for enabling home-manager by default on all hosts:
den.default.includes = [ den._.home-manager ];
Does nothing for hosts that have no users with `homeManager` class.
Expects `inputs.home-manager` to exist. If `<host>.hm-module` exists
it is the home-manager.{nixos/darwin}Modules.home-manager.
For each user resolves den.aspects.''${user.aspect} and imports its homeManager class module.
'';
homeManager =
{ OS, host }:
{ class, aspect-chain }:
let
hmClass = "homeManager";
hmUsers = builtins.filter (u: u.class == hmClass) (lib.attrValues host.users);
hmUserModule =
user:
let
ctx = {
inherit aspect-chain;
class = hmClass;
};
HM = den.aspects.${user.aspect};
aspect = HM {
inherit host user;
OS-HM = { inherit OS HM; };
};
module = aspect.resolve ctx;
in
module;
users = map (user: {
name = user.userName;
value.imports = [ (hmUserModule user) ];
}) hmUsers;
hmModule = host.hm-module or inputs.home-manager."${class}Modules".home-manager;
aspect.${class} = {
imports = [ hmModule ];
home-manager.users = lib.listToAttrs users;
};
supportedOS = builtins.elem class [
"nixos"
"darwin"
];
enabled = supportedOS && builtins.length hmUsers > 0;
in
if enabled then aspect else { };
in
{
den.provides.home-manager = {
inherit description;
__functor = _: den.lib.take.exactly homeManager;
};
}

View file

@ -0,0 +1,77 @@
{
inputs,
den,
...
}:
{
den.provides.import-tree.description = ''
Recursively imports non-dendritic .nix files depending on their Nix configuration `class`.
This can be used to help migrating from huge existing setups.
```
# this is at <repo>/modules/non-dendritic.nix
den.aspects.my-laptop.includes = [
(den._.import-tree._.host ../non-dendritic)
]
```
With following structure, it will automatically load modules depending on their class.
```
<repo>/
modules/
non-dendritic.nix # configures this aspect
non-dendritic/ # name is just an example here
hosts/
my-laptop/
_nixos/ # a directory for `nixos` class
auto-generated-hardware.nix # any nixos module
_darwin/
foo.nix
_homeManager/
me.nix
```
## Requirements
- inputs.import-tree
## Usage
this aspect can be included explicitly on any aspect:
# example: will import ./disko/_nixos files automatically.
den.aspects.my-disko.includes = [ (den._.import-tree ./disko/) ];
or it can be default imported per host/user/home:
# load from ./hosts/<host>/_nixos
den.default.includes = [ (den._.import-tree._.host ./hosts) ];
# load from ./users/<user>/{_homeManager, _nixos}
den.default.includes = [ (den._.import-tree._.user ./users) ];
# load from ./homes/<home>/_homeManager
den.default.includes = [ (den._.import-tree._.home ./homes) ];
you are also free to create your own auto-imports layout following the implementation of these.
'';
den._.import-tree.__functor =
_: root:
# deadnix: skip
{ class, aspect-chain }:
let
path = "${toString root}/_${class}";
aspect.${class}.imports = [ (inputs.import-tree path) ];
in
if builtins.pathExists path then aspect else { };
den._.import-tree.provides = {
host = root: { host, ... }: den._.import-tree "${toString root}/${host.name}";
home = root: { home, ... }: den._.import-tree "${toString root}/${home.name}";
user = root: { user, ... }: den._.import-tree "${toString root}/${user.name}";
};
}

View file

@ -0,0 +1,37 @@
{ lib, ... }:
let
description = ''
Sets user as *primary*.
On NixOS adds wheel and networkmanager groups.
On Darwin sets user as system.primaryUser
On WSL sets wsl.defaultUser if host has an `wsl` attribute.
## Usage
den.aspects.my-user.includes = [ den._.primary-user ];
'';
userToHostContext =
{ user, host, ... }:
let
on-wsl.nixos.wsl.defaultUser = user.userName;
in
{
inherit description;
includes = lib.optionals (host ? wsl) [ on-wsl ];
darwin.system.primaryUser = user.userName;
nixos.users.users.${user.userName} = {
isNormalUser = true;
extraGroups = [
"wheel"
"networkmanager"
];
};
};
in
{
den.provides.primary-user = userToHostContext;
}

View file

@ -0,0 +1,22 @@
{ lib, ... }:
{
den.provides.unfree.description = ''
A class generic aspect that enables unfree packages by name.
Works for any class (nixos/darwin/homeManager,etc) on any host/user/home context.
## Usage
den.aspects.my-laptop.includes = [ (den._.unfree [ "code" ]) ];
It will dynamically provide a module for each class when accessed.
'';
den.provides.unfree.__functor =
_self: allowed-names:
# deadnix: allow
{ class, aspect-chain }:
{
${class}.nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) allowed-names;
};
}

View file

@ -0,0 +1,41 @@
{ den, ... }:
let
description = ''
Sets a user default shell, enables the shell at OS and Home level.
Usage:
den.aspects.vic.includes = [
# will always love red snappers.
(den._.user-shell "fish")
];
'';
userShell =
shell: user:
let
nixos =
{ pkgs, ... }:
{
programs.${shell}.enable = true;
users.users.${user.userName}.shell = pkgs.${shell};
};
darwin = nixos;
homeManager.programs.${shell}.enable = true;
in
{
inherit nixos darwin homeManager;
};
in
{
den.provides.user-shell = shell: {
inherit description;
__functor = den.lib.parametric.atLeast;
includes = [
({ user, ... }: userShell shell user)
({ home, ... }: userShell shell home)
];
};
}