powered by POP: Pure Object Prototypes && yants && haumea
A nix language configuration framework based on POP: Pure Object
If you want to understand this repo and its use cases quickly, follow one stable reading path instead of jumping between directories.
- docs index: docs/index.md
- reading path: docs/practice/reading-path.md
- yants contract manual: docs/reference/yants-contracts.md
- internal algorithm map: docs/reference/internal-algorithms.md
- POP example: examples/pop-vocabulary.nix
- yants example: examples/yants-contracts.nix
- POP constructor test: tests/popConstructors/expr.nix
- yants contract test: tests/yantsContracts/expr.nix
- yants contract note: docs/practice/yants-contracts.md
- tests overview: tests/README.md
- templates overview: templates/README.md
- semantic test snapshots: tests/_snapshots/
If you want the flake-specific entry first, stay on the same POP-first grammar used everywhere else in the repo:
- start from
popflow.lib.flake.pops.default - call
withInitInputson a path, lock fixture, or called flake - optionally grow the workflow with
addInputsExtenderoraddExporter - materialize the result with
outputsForSystemoroutputsForSystems
linuxOutputs =
(popflow.lib.flake.pops.default.withInitInputs ./lib/__lock)
.outputsForSystem
"x86_64-linux";The walkthrough note is docs/practice/flake-input-workflow.md, the fuller example is examples/flake-workflow.nix, and the semantic check is tests/flake/expr.nix.
The public API is organized by domain:
popflow.lib.configs.popspopflow.lib.flake.popspopflow.lib.haumea.pops
The corresponding structural contracts live under *.contracts and are backed
by yants.
For a downstream starting point, use the default template and keep the same grammar the docs teach:
- start from a public POP object such as
popflow.lib.haumea.pops.default - configure one reusable workflow with
withInitLoad - consume that workflow from your concrete outputs
outputs = { nixpkgs, popflow, ... }:
let
loadModules = popflow.lib.haumea.pops.default.withInitLoad {
src = ./nixosModules;
type = "nixosModules";
};
in
{
eval = nixpkgs.lib.evalModules {
modules = [ loadModules.outputs.default.programs.git ];
};
nixos = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ loadModules.outputs.default.programs.git ];
};
};The compact starting point is templates/default/flake.nix, and the directory guide is templates/README.md. The walkthrough note is docs/practice/downstream-quickstart.md.
The flake also exposes a curated examples surface for learning POP and the
current project shape:
examples.popexamples.yantsexamples.configsexamples.flakeexamples.haumea.dataexamples.haumea.modules
The directory-level guide lives in examples/README.md.
The tests are now part of the learning path as well as the validation path:
- tests/popConstructors/expr.nix explains `pop`, `extendPop`, `kPop`, and `kxPop`
- tests/yantsContracts/expr.nix explains the `yants` contract layer and current runtime guards
- tests/configs/expr.nix explains the configs workflow semantics
- tests/flake/expr.nix explains the flake workflow semantics
- tests/haumeaData/expr.nix explains plain Haumea data loading
- tests/haumeaNixOSModules/expr.nix explains the `nixosModules` loading experiment
- tests/evalModules/expr.nix explains the later `evalModules` path
The directory-level guide lives in tests/README.md.
you can’t use the dmerge for the nixosModules
- David Arnold (blaggacao) said
dmerge can only work with json-serializable data on both sides. That’s by design.
test = with dmerge;
merge {
a.b.c = [];
a.c = lib.mkOption {
type = lib.types.submodule {
freeformType = lib.types.attrs;
options = {
enable = lib.mkEnableOption (lib.mdDoc "Whether to enable git profile");
};
};
};
} {a.b.c = append ["a" "b" "c"];};
testNonMerge =
{
a.b.c = [];
a.c = lib.mkOption {
type = lib.types.submodule {
freeformType = lib.types.attrs;
options = {
enable = lib.mkEnableOption (lib.mdDoc "Whether to enable git profile");
};
};
};
}
// {d = "d";};So, we use withoutMergedOptions to keep the native options after the action of merged.