{ lib, ... }: let inherit (lib) fromJSON mapAttrs attrValues concatStringsSep elem ; option = required: name: prop: let description = if prop ? description then '' description = "${prop.description}"; '' else ""; default = if (!elem name required && prop ? default) then '' default = ${to-value prop.type prop.description}; '' else ""; to-type = type: { string = "str"; integer = "int"; boolean = "bool"; } .${type} or (throw "Unsupported schema type: ${type}"); to-value = type: value: { string = ''"${toString value}"''; integer = toString value; boolean = if value then "true" else "false"; } .${type} or (throw "Unsupported value type: ${type}"); in # TODO: squash '' ${name} = mkOption { ${ # TODO: indent description } type = types.${to-type prop.type}; ${ # TODO: indent default } }; ''; in jsonschema: name: # TODO: can't we get the name from the schema? let schema = fromJSON jsonschema; properties = schema.properties or { }; required = schema.required or [ ]; options = concatStringsSep "\n\n" (attrValues (mapAttrs (option required) properties)); in # TODO: test this '' { lib, ... }: let inherit (lib) mkOption types; in { options.services.${name} = { ${options} }; } ''