Pattern: each file is a flake-parts module

After nine moths of using flake-parts in several projects I’ve refactored my personal infrastructure repository to adhere to a pattern; each Nix file is a flake-parts module.

I have found this pattern liberating and therefore sharing. The readme has a few words on the matter.

14 Likes

Massive, very interesting!

1 Like

How is that some modules are a function that return an attribute set, others are a function that return an attribute set whose main value is also a function and others are plain attribute sets?

2 Likes

Modules are of the structure x or moduleArgs: x, where x is some conformant attrset.

In flake-parts there are nested module system evaluations, so you could have fpModuleArgs: { perSystem = perSystemModuleArgs: perSystemAttrs; ... }, and so on. I guess that’s why some find f-p confusing to use.

1 Like

I don’t find fp confusing at all. I’m more than used to high order functions (in either direction, taking or returning functions), recursion and all the usual jazz. But after reading the flakes on that repo, and reading probably 55% of flake-parts docs I was completely oblivious at what is making possible to return one or the other, and even worse, what to expect as input or what will be produced as output.

This black magic is probably very convenient, but it is very hard to understand for a newcomer

f-p as in flake-parts, not functional programming.

1 Like

Ah, ok my bad. Because nix is a functional language, and I am a functional programming fan I got triggered by my bias

Oh Cool.

We did the same thing here.:

But I wrote the omnibus.pops.nixosModules/nixosProfiles loader to load them, which is based on the fileSystems.

Also, I think omnibus.pops.nixosModules/Profiles can help you reorganize the modules to be a tree structure and export to any type.

 pops.nixosProfiles.exports.default.presets
{
  audio = { ... };
  boot = «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»;
  cloud = { ... };
  coding = { ... };
  display = { ... };
  fileSystems = { ... };
  fontconfig = «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»;
  gpu = { ... };
  mimalloc = «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»;
  networking = { ... };
  nix = «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»;
  nix-ld = «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»;
  opengl = «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»;
  openssh = «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»;
  scenarios = { ... };
  secrets = { ... };
  security = { ... };
  shell = { ... };
  virtualisation = { ... };
  zswap = «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»;
}

nix-repl> pops.nixosProfiles.exports.exportModulesRecursive
[
  «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»
  «lambda @ /nix/store/859yblp6911asw03i546awv2zkz0979g-source/src/haumea/importModule.nix:59:11»

That looks like a file that is a NixOS module, isn’t it? In the pattern I’m describing each file is a flake-parts module. All files are flake-parts modules.

Were did you get your flake-parts knowledge? Just from their docs? I don’t see a clear reference of what the structure a flake-module should be

1 Like

I had to make some effort and got some help. I agree that the flake-parts documentation needs significant improvement.

The docs at https://flake.parts technically have everything, but it didn’t click for me until I read through others’ code that use f-p.

Nice! I really like this pattern.

I guess I can see the advantages of importing all files instead of having to follow a predefined folder structure (like rails conventions). Reading your configs I can see the advantage of defining cross-cutting concerns independent of the file location.

I’ll be exploring your pattern on my own setup, and will use flake-parts a lot more on my published nix flakes :).

Now , -at the cost of being taken as a person who would publish two-lines isEven function as an npm package- I just published a flake inspired by yours here:

3 Likes

If you’re interested there’s a more fleshed-out version of your concept at GitHub - nix-community/haumea: Filesystem-based module system for Nix [maintainer=@figsoda]. But that’s quite the opposite of what’s presented in the “every file as module” idea.

But that’s quite the opposite of what’s presented in the “every file as module” idea.

I have specially written a module loader based on haumea, whether it is every file as module or importNixOS modules as a tree or other hierarchical requirements, it depends on the direct functions of the loader and transformer.

In my instance:

1 Like