feat: expose nixosModules, homeModules, darwinModules, flakeModules as flake outputs

Closes #799.

Adds standard flake outputs so modules can be accessed via:
  nur.nixosModules.repos.${repo}.${module}
  nur.homeModules.repos.${repo}.${module}
  nur.darwinModules.repos.${repo}.${module}
  nur.flakeModules.repos.${repo}.${module}

nixosModules falls back to the legacy 'modules' attribute when
'nixosModules' is not present in a repo. Missing attributes in
any repo gracefully return {}.

Amp-Thread-ID: https://ampcode.com/threads/T-019d1fc6-58ae-750f-bac6-f5e66598ddfc
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
XYenon 2026-03-24 20:38:33 +08:00
parent a1a0048666
commit ee7462f2c6
2 changed files with 101 additions and 9 deletions

View file

@ -164,8 +164,10 @@ Using overlays and modules from NUR in your configuration is fairly straightforw
modules = [
# Adds the NUR overlay
nur.modules.nixos.default
# NUR modules to import
nur.legacyPackages."${system}".repos.iopq.modules.xraya
# NUR modules can be imported directly via nixosModules:
nur.nixosModules.repos.iopq.xraya
# Or via legacyPackages (legacy path):
# nur.legacyPackages."${system}".repos.iopq.modules.xraya
# This adds the NUR nixpkgs overlay.
# Example:
# ({ pkgs, ... }: {
@ -182,12 +184,12 @@ Using overlays and modules from NUR in your configuration is fairly straightforw
Integrating with [Home Manager](https://github.com/rycee/home-manager) can be done by adding your modules to the `imports` attribute.
You can then configure your services like usual.
When using flakes, Home Manager modules can be accessed directly:
```nix
let
nur-no-pkgs = import (builtins.fetchTarball "https://github.com/nix-community/NUR/archive/main.tar.gz") {};
in
# In your Home Manager configuration
{
imports = lib.attrValues nur-no-pkgs.repos.moredhel.hmModules.rawModules;
imports = lib.attrValues nur.homeModules.repos.moredhel;
services.unison = {
enable = true;
@ -202,6 +204,17 @@ in
}
```
Without flakes:
```nix
let
nur-no-pkgs = import (builtins.fetchTarball "https://github.com/nix-community/NUR/archive/main.tar.gz") {};
in
{
imports = lib.attrValues nur-no-pkgs.repos.moredhel.homeModules;
}
```
## Finding packages
You can find all packages using
@ -407,11 +420,11 @@ they must be put them in their own namespace within the repository.
#### Providing NixOS modules
NixOS modules should be placed in the `modules` attribute:
NixOS modules should be placed in the `nixosModules` attribute:
```nix
{ pkgs }: {
modules = import ./modules;
nixosModules = import ./modules;
}
```
@ -422,10 +435,48 @@ NixOS modules should be placed in the `modules` attribute:
}
```
These modules are then accessible as `nur.nixosModules.repos.<repo>.<module>` in flakes.
The legacy `modules` attribute is also supported as a fallback for `nixosModules`.
An example can be found [here](https://github.com/Mic92/nur-packages/tree/master/modules).
Modules should be defined as paths, not functions, to avoid conflicts if imported from multiple locations.
A module with no [_class](https://nixos.org/manual/nixpkgs/stable/index.html#module-system-lib-evalModules-param-class) will be assumed to be both a NixOS and Home Manager module. If a module is NixOS or Home Manager specific, the `_class` attribute should be set to `"nixos"` or [`"home-manager"`](https://github.com/nix-community/home-manager/commit/26e72d85e6fbda36bf2266f1447215501ec376fd).
#### Providing Home Manager modules
Home Manager modules should be placed in the `homeModules` attribute:
```nix
{ pkgs }: {
homeModules = import ./hm-modules;
}
```
These modules are then accessible as `nur.homeModules.repos.<repo>.<module>` in flakes.
#### Providing Darwin modules
Darwin (nix-darwin) modules should be placed in the `darwinModules` attribute:
```nix
{ pkgs }: {
darwinModules = import ./darwin-modules;
}
```
These modules are then accessible as `nur.darwinModules.repos.<repo>.<module>` in flakes.
#### Providing flake-parts modules
Flake-parts modules should be placed in the `flakeModules` attribute:
```nix
{ pkgs }: {
flakeModules = import ./flake-modules;
}
```
These modules are then accessible as `nur.flakeModules.repos.<repo>.<module>` in flakes.
#### Providing Overlays

View file

@ -20,6 +20,33 @@
pkgs = prev;
};
};
lockedRevisions = (builtins.fromJSON (builtins.readFile ./repos.json.lock)).repos;
repoSource =
name: attr:
import ./lib/repoSource.nix {
inherit
name
attr
manifest
lockedRevisions
lib
;
fetchgit = builtins.fetchGit or lib.id;
fetchzip = builtins.fetchTarball or lib.id;
};
# Lazily evaluate each repo with pkgs = null; the result is only forced
# when a specific repo's attribute is accessed.
repos = lib.mapAttrs (
name: attr:
import ./lib/evalRepo.nix {
inherit name lib;
inherit (attr) url;
src = repoSource name attr + ("/" + (attr.file or ""));
pkgs = null;
}
) manifest;
collectModules = attrName: lib.mapAttrs (name: _: repos.${name}.${attrName} or { }) manifest;
in
flake-parts.lib.mkFlake { inherit inputs; } {
systems = builtins.filter (
@ -62,5 +89,19 @@
# This trick with the overlay is used because it allows NUR packages to depend on other NUR packages
legacyPackages = (pkgs.extend overlay).nur;
};
}
// {
# Expose modules from individual NUR repos as standard flake outputs.
# Merged outside flake-parts to avoid deferredModule type wrapping.
nixosModules.repos = lib.mapAttrs (
name: _:
let
r = repos.${name};
in
r.nixosModules or r.modules or { }
) manifest;
homeModules.repos = collectModules "homeModules";
darwinModules.repos = collectModules "darwinModules";
flakeModules.repos = collectModules "flakeModules";
};
}