From ace62b0e4a606c27cd2e5ce65ccd3399f9dbfe33 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Wed, 15 May 2024 23:21:00 +0200
Subject: [PATCH] Store providers as modules

---
 lib/modules/rclone.nix | 143 ++++++++++++++++++++---------------------
 1 file changed, 68 insertions(+), 75 deletions(-)

diff --git a/lib/modules/rclone.nix b/lib/modules/rclone.nix
index 0d20ffb..5a93f2b 100644
--- a/lib/modules/rclone.nix
+++ b/lib/modules/rclone.nix
@@ -22,63 +22,8 @@ let
       inherit default;
     };
 
-  mkWebdavProvider = { vendor, vendorName }: (
-    { providerOptions, ... }: {
-      displayName = vendorName;
-
-      options = {
-        vendor = lib.mkOption {
-          type = lib.types.str;
-          description = "The vendor of the WebDAV share.";
-          default = vendor;
-        };
-
-        url = lib.mkOption {
-          type = lib.types.str;
-          description = "The WebDAV URL of the ${vendorName} server to connect to.";
-        };
-
-        username = lib.mkOption {
-          type = lib.types.nullOr lib.types.str;
-          description = "The user name for logging in to the ${vendorName} server.";
-          default = null;
-        };
-
-        obscuredPassword = lib.mkOption {
-          type = lib.types.nullOr lib.types.str;
-          description = "The password obscured using the `rclone obscure` command for logging in to the ${vendorName} server.";
-          default = null;
-        };
-
-        obscuredPasswordFile = lib.mkOption {
-          type = lib.types.nullOr (lib.types.either lib.types.path lib.types.str);
-          description = "The path to a file containing the password obscured using the `rclone obscure` command for logging in to the ${vendorName} server.";
-          default = null;
-        };
-      };
-
-      config = lib.mkMerge [
-        {
-          inherit vendor;
-          url = providerOptions.url;
-        }
-        (mkIfNotNull providerOptions.username { user = providerOptions.username; })
-        (mkIfNotNull providerOptions.obscuredPassword { pass = providerOptions.obscuredPassword; })
-      ];
-    });
-
-  syncProviders = {
-    nextcloud = rec {
-      displayName = "Nextcloud";
-      provider = (mkWebdavProvider {
-        vendor = "nextcloud";
-        vendorName = displayName;
-      });
-    };
-  };
-
-  mkSyncType = provider: lib.types.submodule (
-    { config, name, ... }: {
+  mkProvider = (
+    { config, ... }: {
       options = {
         path = lib.mkOption {
           type = lib.types.str;
@@ -91,12 +36,6 @@ let
           default = true;
         };
 
-        providerOptions = lib.mkOption {
-          description = "The options of the sync";
-          type = lib.types.submodule { inherit (provider config) options; };
-          default = { };
-        };
-
         systemdDependencies = mkSystemdDependencyOption {
           default = cfg.systemdDependencies;
         };
@@ -104,7 +43,7 @@ let
         environment = lib.mkOption {
           type = lib.types.attrsOf lib.types.envVar;
           description = "The environment variables to pass to the service.";
-          default = {};
+          default = { };
         };
 
         secretsScript = lib.mkOption {
@@ -119,15 +58,69 @@ let
           visible = false;
         };
       };
-
-      config = {
-        inherit (provider (lib.debug.traceVal config))
-          environment
-          secretsScript
-          config
-        ;
-      };
     });
+
+  mkWebdavProvider = (
+    { displayName, vendor, ... }: (
+      { config, ... }: {
+        imports = [
+          mkProvider
+        ];
+
+        options.providerOptions = {
+          vendor = lib.mkOption {
+            type = lib.types.str;
+            description = "The vendor of the WebDAV share.";
+            default = vendor;
+          };
+
+          url = lib.mkOption {
+            type = lib.types.str;
+            description = "The WebDAV URL of the ${displayName} server.";
+            default = null;
+          };
+
+          username = lib.mkOption {
+            type = lib.types.nullOr lib.types.str;
+            description = "The user name for logging in to the ${displayName} server.";
+            default = null;
+          };
+
+          obscuredPassword = lib.mkOption {
+            type = lib.types.nullOr lib.types.str;
+            description = "The password obscured using the `rclone obscure` command for logging in to the ${displayName} server.";
+            default = null;
+          };
+
+          obscuredPasswordFile = lib.mkOption {
+            type = lib.types.nullOr (lib.types.either lib.types.path lib.types.str);
+            description = "The path to a file containing the password obscured using the `rclone obscure` command for logging in to the ${displayName} server.";
+            default = null;
+          };
+        };
+
+        config = {
+          config = lib.mkMerge [
+            {
+              inherit vendor;
+              url = config.providerOptions.url;
+            }
+            (mkIfNotNull config.providerOptions.username { user = config.providerOptions.username; })
+            (mkIfNotNull config.providerOptions.obscuredPassword { pass = config.providerOptions.obscuredPassword; })
+          ];
+        };
+      }));
+
+  syncProviders = {
+    nextcloud = rec {
+      displayName = "Nextcloud";
+
+      module = mkWebdavProvider {
+        inherit displayName;
+        vendor = "nextcloud";
+      };
+    };
+  };
 in {
   options = {
     programs.rclone = {
@@ -139,9 +132,9 @@ in {
       };
 
       configs = (builtins.mapAttrs
-        (name: providerDefinition: lib.mkOption {
-          type = lib.types.attrsOf (mkSyncType providerDefinition.provider);
-          description = "The ${providerDefinition.displayName} synchronizations to set up.";
+        (name: provider: lib.mkOption {
+          type = lib.types.attrsOf (lib.types.submodule provider.module);
+          description = "The ${provider.displayName} synchronizations to set up.";
           default = { };
         })
         syncProviders);