den - an aspect-oriented approach to Dendritic Nix configurations.#
den and vic's dendritic libs made for you with Love++ and AI--. If you like my work, consider sponsoring
Need more batteries? See vic/denful. Join our community discussion. |
🏠 Define Hosts, Users & Homes concisely. See schema in 🧩 Aspect-oriented incremental features. (example) Any module can contribute configurations to aspects. For real-world examples, see ❄️ Try it now! Launch our template VM: Or, initialize a project: Our default template provides a profile-based layout for a quick start. |
You are done! You know everything to start creating configurations with den.
Feel free to to explore the codebase, particularly our included batteries and tests.
Learn More#
If you want to learn how den works, the following sections detail its concepts and patterns.
Basic Concepts#
Learn about static vs. parametric aspects, the default aspect, and dependencies.
Learn about static vs. parametric aspects, the default aspect, and dependencies.
den has two fundamental types of aspects: static and parametric.
Static aspects are attribute sets.#An aspect is a set of modules for different |
Parametric aspects are functions.#They take a |
den uses several default contexts to manage dependencies:
{ host },{ user, host },{ home }{ fromUser, toHost },{ fromHost, toUser }
The Default Aspect and Dependencies#
den features a special aspect, den.default, which applies global configurations. It is automatically included in all hosts, users, and homes, receiving the appropriate context (e.g., den.default { inherit home; }).
You can register static values or context-aware parametric aspects within den.default. This allows you to define defaults that apply conditionally to all hosts or users.
A key feature of den is its management of aspect dependencies. When an aspect is resolved, flake-aspects includes its class-specific module along with those of its transitive includes. den extends this by registering special dependencies to link hosts and users. For instance, a host's configuration includes contributions from each of its users' aspects, and a user's home configuration includes contributions from its host's aspect, creating a bidirectional flow of settings. This is achieved without recursion by using distinct contexts for each direction.
Organization Patterns#
Learn patterns for organizing and reusing aspects.
Learn patterns for organizing and reusing aspects.
While den is unopinionated about organization, these patterns can help structure your aspects for clarity and reuse.
Aspect Namespaces#
Group related aspects under a single top-level aspect and alias it as a module argument for easier access. The den.namespace function streamlines this.
Using local and remote namespaces# |
Directly read and write to namespace# |
Angle-Bracket Syntax#
For deeply nested aspects, den offers an experimental feature to shorten access paths. By bringing den.lib.__findFile into scope, you can use angle brackets to reference aspects more concisely.
<my-laptop>resolves toden.aspects.my-laptop<my-laptop/gaming>resolves toden.aspects.my-laptop.provides.gaming<den/import-tree/host>resolves toden.provides.import-tree.provides.home<vix/foo/bar>namespace aware:den.ful.vix.foo.provides.bar
This feature is powered by a custom __findFile implementation. See the profile example to learn how to enable it.
Parametric Routing#
You can use parametric aspects to create routing logic that dynamically includes other aspects based on context. This pattern allows you to build a flexible and declarative dependency tree.
# modules/routes.nix
{ den, pro, ... }:
let
# Route to a platform-specific profile
by-platform = { host }: pro.${host.system} or { };
in
{
# Apply routes globally
den.default.includes = [ by-platform ];
}
You made it to the end! Thanks for reading. I hope you enjoy using
den. It is feature-complete and unlikely to change.
Contributing#
Contributions are welcome! Feel free to fix typos, improve documentation, or share ideas in our discussions.
Contributions are welcome! Feel free to fix typos, improve documentation, or share ideas in our discussions.
All PRs are checked against the CI. New features should include a test in _example/ci.nix.
To run tests locally:
nix flake check ./checkmate --override-input target .
nix flake check ./templates/examples --override-input den .
Ensure code is formatted:
nix run ./checkmate#fmt --override-input target .
If you have found a bug, please open a discussion (issues are for agreed, actionable items).
We provide a bogus template you can use
to create a minimal bug reproduction repository. Please share your repo.
mkdir bogus && cd bogus
nix flake init -t github:vic/den#bogus
nix flake update den
nix flake check