diff --git a/lib/jsonschema/default.nix b/lib/jsonschema/default.nix index 177fef8d5..855739897 100644 --- a/lib/jsonschema/default.nix +++ b/lib/jsonschema/default.nix @@ -123,7 +123,7 @@ rec { # parse options to jsonschema properties properties = lib.mapAttrs (_name: option: (parseOption' (path ++ [ _name ]) option)) options'; # TODO: figure out how to handle if prop.anyOf is used - isRequired = prop: !(prop ? default || prop.type or null == "object"); + isRequired = prop: !(prop ? default || prop."$exportedModuleInfo".required or false); requiredProps = lib.filterAttrs (_: prop: isRequired prop) properties; required = lib.optionalAttrs (requiredProps != { }) { required = lib.attrNames requiredProps; }; header' = if addHeader then header else { }; @@ -150,9 +150,9 @@ rec { { }; # Metadata about the module that is made available to the schema via '$propagatedModuleInfo' - exportedModuleInfo = lib.optionalAttrs true (makeModuleInfo { + exportedModuleInfo = makeModuleInfo { inherit path; - }); + }; in # return jsonschema header' @@ -377,7 +377,13 @@ rec { # return jsonschema property definition for attrs then default - // exposedModuleInfo + // (lib.recursiveUpdate exposedModuleInfo ( + lib.optionalAttrs (!default ? default) { + "$exportedModuleInfo" = { + required = true; + }; + } + )) // example // description // { diff --git a/lib/jsonschema/example-schema.json b/lib/jsonschema/example-schema.json index 3944cca62..ca2175472 100644 --- a/lib/jsonschema/example-schema.json +++ b/lib/jsonschema/example-schema.json @@ -3,6 +3,7 @@ "$exportedModuleInfo": { "path": [] }, "type": "object", "additionalProperties": false, + "required": [ "services" ], "properties": { "name": { "$exportedModuleInfo": { "path": ["name"] }, diff --git a/lib/jsonschema/test_parseOptions.nix b/lib/jsonschema/test_parseOptions.nix index 137bf52a1..0c2ff8a93 100644 --- a/lib/jsonschema/test_parseOptions.nix +++ b/lib/jsonschema/test_parseOptions.nix @@ -13,7 +13,17 @@ testParseNestedOptions = let evaled = lib.evalModules { - modules = [ { options.foo.bar = lib.mkOption { type = lib.types.bool; }; } ]; + modules = [ + { + options.foo.bar = lib.mkOption { + type = lib.types.bool; + }; + options.foo.baz = lib.mkOption { + type = lib.types.bool; + default = false; + }; + } + ]; }; in { @@ -40,12 +50,23 @@ }; type = "boolean"; }; + baz = { + "$exportedModuleInfo" = { + path = [ + "foo" + "baz" + ]; + }; + type = "boolean"; + default = false; + }; }; required = [ "bar" ]; type = "object"; }; }; type = "object"; + required = [ "foo" ]; }; };