docs(nix): clarify convention examples
This commit is contained in:
219
docs/nix.md
219
docs/nix.md
@@ -5,31 +5,232 @@ Prefer these conventions when changing this flake.
|
|||||||
|
|
||||||
## Names
|
## Names
|
||||||
|
|
||||||
|
### Reserve `lib` for `nixpkgs.lib`
|
||||||
|
|
||||||
Use `lib` only for the base `nixpkgs.lib` value.
|
Use `lib` only for the base `nixpkgs.lib` value.
|
||||||
Do not use `lib` for project helper functions.
|
Do not use `lib` for project helper functions.
|
||||||
Use `dotfiles.lib` for pure project helpers passed through module arguments.
|
Use `dotfiles.lib` for pure project helpers passed through module arguments.
|
||||||
Use `dotfiles.<name>` for project assembly helpers passed through module arguments.
|
Use `dotfiles.<name>` for project assembly helpers passed through module arguments.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
lib = dotfilesHelpers;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
lib = nixpkgs.lib;
|
||||||
|
dotfiles.lib = dotfilesHelpers;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Imports
|
## Imports
|
||||||
|
|
||||||
Prefer explicit import arguments.
|
### Use closed interfaces for helper imports
|
||||||
Use exact function argument patterns without `...` when the imported file has a closed interface.
|
|
||||||
Use `...` only when the file intentionally accepts extra arguments.
|
|
||||||
|
|
||||||
## `let` bindings
|
Use exact function argument patterns when an imported helper file has a closed interface.
|
||||||
|
A helper file has a closed interface when the importer owns the argument set.
|
||||||
|
The imported file must name each accepted attribute.
|
||||||
|
This rejects stale or accidental extra attributes.
|
||||||
|
|
||||||
Minimize `let` bindings.
|
Avoid:
|
||||||
Use a `let` binding when it names an important intermediate value or avoids repeated complex expressions.
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
}:
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pass import arguments explicitly
|
||||||
|
|
||||||
|
Pass only the values an imported helper file needs.
|
||||||
|
Bind `lib` to the base `nixpkgs.lib` value at the call site.
|
||||||
|
Use `inherit` for values that keep the same name.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
import ./flake inputs
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
import ./flake {
|
||||||
|
inherit inputs self;
|
||||||
|
lib = nixpkgs.lib;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keep NixOS module interfaces open
|
||||||
|
|
||||||
|
NixOS modules must accept extra arguments because the module system owns their argument shape.
|
||||||
|
Name the arguments the module uses.
|
||||||
|
Keep `...` so the module accepts standard module arguments and special arguments.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
registry,
|
||||||
|
}:
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
registry,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use `@` for forwarding wrappers
|
||||||
|
|
||||||
|
Use `@` when a wrapper must pass the complete argument set to another module function.
|
||||||
|
Name the arguments the wrapper uses before `...`.
|
||||||
|
Forward the bound argument set unchanged.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ dotfiles, ... }:
|
||||||
|
dotfiles.guest { name = "sample"; } { inherit dotfiles; }
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
args@{ dotfiles, ... }:
|
||||||
|
dotfiles.guest { name = "sample"; } args
|
||||||
|
```
|
||||||
|
|
||||||
|
## `let` Bindings
|
||||||
|
|
||||||
|
### Use `let` for important intermediate values
|
||||||
|
|
||||||
|
Use a `let` binding when it names an important intermediate value.
|
||||||
|
Use a `let` binding when it avoids repeating a complex expression.
|
||||||
Do not use a `let` binding only to shorten a standard library call.
|
Do not use a `let` binding only to shorten a standard library call.
|
||||||
|
|
||||||
## Standard library calls
|
Avoid:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
inherit (lib) mapAttrs;
|
||||||
|
in
|
||||||
|
mapAttrs f attrs
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
lib.mapAttrs f attrs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Standard Library Calls
|
||||||
|
|
||||||
|
### Qualify standard library calls in flake assembly
|
||||||
|
|
||||||
Prefer qualified standard library calls inside flake assembly code.
|
Prefer qualified standard library calls inside flake assembly code.
|
||||||
Use `lib.mapAttrs` instead of inheriting `mapAttrs` from `lib`.
|
Use `lib.mapAttrs` instead of inheriting `mapAttrs` from `lib`.
|
||||||
This keeps the source of helper functions visible.
|
This keeps the source of helper functions visible.
|
||||||
|
|
||||||
## Flake assembly
|
Avoid:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
inherit (lib) mapAttrs;
|
||||||
|
in
|
||||||
|
mapAttrs f attrs
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
lib.mapAttrs f attrs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Flake Assembly
|
||||||
|
|
||||||
|
### Keep assembly code under `flake/`
|
||||||
|
|
||||||
Keep flake assembly code under `flake/`.
|
Keep flake assembly code under `flake/`.
|
||||||
Do not expose assembly helpers as public flake outputs unless an external consumer needs them.
|
|
||||||
Keep `flake.nix` focused on inputs and public outputs.
|
Keep `flake.nix` focused on inputs and public outputs.
|
||||||
|
A public output is any attribute returned by the flake `outputs` function.
|
||||||
|
Another flake can reference a public output through `inputs.<name>.<output>`.
|
||||||
|
Tools such as `nix flake show` also display public outputs.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
# flake.nix
|
||||||
|
let
|
||||||
|
mkHosts = hostsDir: ...;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
nixosConfigurations = mkHosts (self + "/hosts");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
# flake.nix
|
||||||
|
let
|
||||||
|
flakeAssembly = import ./flake {
|
||||||
|
inherit inputs self;
|
||||||
|
lib = nixpkgs.lib;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
nixosConfigurations = flakeAssembly.mkHosts (self + "/hosts");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Expose only supported flake outputs
|
||||||
|
|
||||||
|
Use public outputs for the supported interface of this flake.
|
||||||
|
Do not expose assembly helpers as public outputs unless an external consumer needs them.
|
||||||
|
Keep internal helpers in `flake/` or `dotfiles` special arguments.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
lib = flakeAssembly;
|
||||||
|
nixosConfigurations = flakeAssembly.mkHosts (self + "/hosts");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
nixosConfigurations = flakeAssembly.mkHosts (self + "/hosts");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user