@TLATER Thanks for your detailed reply. Had no idea you could do that .
I have found an implementation that I like , which is essentially use it like a generic function with arguments.
So in general terms I created a module file(my-module.nix) with vars argument
{ vars }
{
networking.hostName = vars.hostName;
};
}
and then while importing it I can provide this variable
let
myVars = {
hostName = "my-server";
domain = "example.com";
};
in
{
imports = [
(import ./my-module.nix { vars = myVars; })
];
}
And more specifically to my syncthing module I do.
let
cfg = config.custom.services.syncthing;
syncthingDevices = [
{ name = "work-pc"; id = "id_1"; }
{ name = "home-desktop"; id = "id_2"; }
{ name = "homelab"; id = "id_3"; }
{ name = "kvm-nixos-server"; id = "id_4"; }
];
deviceImports = builtins.map (device: import ./devices/defaul.nix {
inherit config lib;
name = device.name;
id = device.id;
}) syncthingDevices;
in
{
# Each machine switches in the devices and folders it needs.
imports = deviceImports ++ [
];
Your implementation should also do the trick but not in the case where I am defining options., And speaking of option
I should provide some context to what I am doing. I recently refactored my entire repository to the “import all and enable” pattern. The goal was to have all my custom modules/configurations to be imported by all of my hosts regardless of if they will be using them or not and then enable the once the host needs. I wanted to achieve the same implementation I have with the nixpkgs modules, E.g:
services.syncthing.enable = true;
But for my custom modules/configurations. So I would import my foo.nix once into common file that is imported by all of my hosts and then just do
custom.services.foo.enable = true;
My goal was to use the same pattern for syncthing devices and folders. Meaning my hosts will import all of my devices and folders and then use enable to get the desired state.
So some models already have enable option, like bat, meaning I can write my config for it and just wrap it
{ config, lib, ... }:
{
config = lib.mkIf config.programs.bat.enable {
programs.bat = {
config = {
theme = "Visual Studio Dark+";
wrap = "character";
terminal-width = "80";
};
};
};
}
But options like syncthing devices and folders
services.syncthing.settings.devices.<name>
services.syncthing.settings.folders.<name>
do not, meaning I need to add to then an option to enable them.
After your input, I did looked on both my folders.nix and devices.nix modules and removed one of the options form devices(so it only has the enable option now).
But I disagree with you about “not to try and slightly restructure existing structured options” As a developer will gladly wrap some generic function in another function that will do nothing more then providing better readability, by giving it an explicit name.
For example in the case on my folders.nix
{ config, lib, name, dirName, ... }:
let
cfg = config.custom.services.syncthing;
# name = "dev_resources";
# dirName = "dev_resources";
in
{
options.custom.services.syncthing.settings.folders.${name} = {
enable = lib.mkEnableOption "Enable Syncthing folder: ${name}";
devices = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = "List of devices to use for folder synchronization.";
};
};
config = lib.mkIf cfg.settings.folders.${name}.enable {
services.syncthing = {
settings = {
folders = {
"${name}" = {
id = "${name}";
path = "${cfg.syncDir}/${dirName}";
devices = cfg.settings.folders.${name}.devices;
versioning = cfg.simpleFileVersioningForBackUpMachinesOnly;
};
};
};
};
};
}
there is no real reason to define
options.custom.services.syncthing.settings.folders.${name}.devices
just to pass it to
services.syncthing.settings.folders.${name}.devices = cfg.settings.folders.${name}.devices;
But then I won"t be to both enable a folder and set the devices it will be shared with under the same “namespace” like this
custom = {
services.syncthing = {
settings = {
devices = {
homelab.enable = true;
home-desktop.enable = true;
};
folders = {
taskwarrior = {
enable = true;
devices = [
"${config.services.syncthing.settings.devices.homelab.name}"
"${config.services.syncthing.settings.devices.home-desktop.name}"
];
};
};
};
};
};
and if I wanted I could go further and change
options.custom.services.syncthing.settings.folders.${name}.devices
To:
options.custom.services.syncthing.settings.folders.${name}.devicesToShareWith
And get even more readable text.