Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Aspects

aspects is a flake-parts extension for arbitrarily nested module namespaces. Every namespace can provide NixOS, Home Manager, nix-darwin, and flake-parts modules while also aggregating matching modules from its children. Importing a parent endpoint therefore imports all matching descendants unless aggregation is restricted. The design is inspired by Rust's module system.

Real-world example

I use Aspects in my public Nix configuration.

Installation

{
  inputs = {
    flake-parts.url = "github:hercules-ci/flake-parts";

    aspects = {
      url = "gitlab:rubogubo/aspects";
      inputs.flake-parts.follows = "flake-parts";
    };
  };

  outputs = inputs@{ flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      imports = [ inputs.aspects.flakeModules.default ];
    };
}

Explicit definitions

An ordinary flake-parts module can define an aspect at any depth:

{
  aspects.steam = {
    nixos = { programs.steam.enable = true; };
    home = { home.sessionVariables.STEAM_FRAME_FORCE_CLOSE = "1"; };
  };

  aspects.rubogubo.desktop.steam.nixos =
    { aspects, ... }:
    {
      imports = [ aspects.steam.nixos ];
      programs.steam.remotePlay.openFirewall = true;
    };
}

Consume the specialized module with:

imports = [ inputs.self.aspects.rubogubo.desktop.steam.nixos ];

Every namespace aggregates matching modules from its immediate children. Thus inputs.self.aspects.rubogubo.desktop.nixos also includes the Steam module. Use _include, _exclude, or _aggregate = false to control aggregation. Modules reuse other modules through ordinary Nix imports; aspects provides no separate inheritance mechanism. Every resolved endpoint injects the complete tree as the aspects module argument, so aspect modules can import one another without receiving self through specialArgs. The initial module that enters the aspect tree still uses the flake output, or can receive aspects = self.aspects through its evaluator's specialArgs.

Directory loader

modules/
├── steam/
│   ├── nixos.nix
│   └── home.nix
└── rubogubo/
    └── desktop/
        ├── mod.nix
        └── steam/
            ├── nixos.nix
            └── home.nix

Load it from a flake-parts module:

{ inputs, ... }:
{
  aspects = inputs.aspects.lib.loadTree ./modules;
}

Or import a complete tree, including any aggregated flakeParts.nix modules:

imports = [
  inputs.aspects.flakeModules.default
  (inputs.aspects.lib.mkTree ./modules)
];

The resolved tree is exported as self.aspects. Import an endpoint into a machine configuration with inputs.self.aspects.<path>.<type>. Aspect modules themselves receive the complete tree through the aspects module argument.

Unlike a generic recursive importer such as import-tree, Aspects does not only combine every file into one module. It exposes typed, independently addressable endpoints such as aspects.desktop.nixos, aspects.desktop.home, and aspects.desktop.steam.nixos. Use a simpler import-tree utility if you only need to import every discovered file together.

A directory's mod.nix is merged with its discovered children and typed module files. It can be a plain attribute set or a function receiving children and path:

{ children, path }:
{
  _include = [ "steam" ];

  nixos = {
    networking.networkmanager.enable = true;
  };
}

children contains children discovered from both directories and dotted files. path is the logical namespace path, including expansion of dotted directory names.

  • _include is an allowlist of immediate children to aggregate.
  • _exclude removes immediate children from aggregation.
  • _aggregate = false disables child aggregation at that namespace.
  • Directories and files prefixed with _ are ignored by discovery.

Dotted path shorthand

Dots in discovered file and directory names are namespace separators. These layouts are equivalent:

common/nixos.nix
common.nixos.nix

Likewise, rubogubo.desktop/ is loaded as aspects.rubogubo.desktop. Shorthands can be combined:

rubogubo.desktop/steam.nixos.nix

This defines aspects.rubogubo.desktop.steam.nixos. Empty components, underscore-prefixed components, and module-type names used as namespace components are rejected so path interpretation stays unambiguous.

Contact

If something is unclear, open an issue or message me on Matrix at @rubogubo:matrix.org. If the project becomes popular, I will create a dedicated room.

Repo

The main repo is on Gitlab but mirrored to Github

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages