lib.module-schema
Library for conversion from Nixpkgs module system options to JSON schema
The Nixpkgs module system makes use of lib.types to validate configurations
against the expectations of modules. A configuration that does not satisfy
the validation generates a helpful error message. The results are similar to
what you might see in a dynamically typed language. Nix is an untyped
language. We use the word "type" to refer to attrsets with various
attributes, refer to lib.types for more detail, one of these attributes is
check, which does the "type checking."
The constraints of these types are not accessible outside of Nix, nor can they be introspected from Nix. This library converts these types and options that make use of them to JSON schema. JSON is convenient to produce from Nix and is easy to process from just about any programming language.
The resulting JSON schema can be used to validate configurations that are not specified in Nix. This makes it possible to produce configuration values from alternative interfaces that trade off expressiveness for simplicity, without losing the validation. An alternative interface doesn't need to convert the configuration to Nix, run a Nix evaluation, collect potential error messages and somehow translate them back to the interface shown to a user. Instead, the interface composes a JSON value, this can be validated against the schema and eventually read into Nix.
The pseudo-type signatures in this library refer to several types that deserve a definition for clarity.
ModuleType- An attrset that conforms to the Nixpkgs module system notion of a type,
usually produced by functions in
lib.types ModuleOption- An attrset that conforms to the Nixpkgs module system notion of an option,
usually produced by functions in
lib.options JSONSchema- An attrset that when converted with
builtins.toJSONresults in a valid JSON schema. Note that onlyoptionsToSchemaproduces a schema suitable as the document root schema object. Other functions do not include a$schemaattribute for the convenience of using them as building blocks of a larger schema.
lib.module-schema.optionToSchema
Convert a Nixpkgs module system option to a JSON schema, if data validates against the schema it should be acceptable as a configuration specifying the option.
Inputs
option- Nixpkgs module system option, the result of
mkOption
Type
optionToSchema :: ModuleOption -> JSONSchema
Examples
Example
lib.module-schema.optionToSchema usage example
optionToSchema (lib.mkEnableOption "SERVICE")
=> {
default = false;
description = "Whether to enable SERVICE.";
examples = [ true ];
type = "boolean";
}
optionToSchema ((nixos {}).options.services.peertube.database.port)
=> {
default = 5432;
description = "Database host port.";
maximum = 65535;
minimum = 0;
type = "integer";
}
lib.module-schema.optionsToSchema
Convert an attribute set of Nixpkgs module system options, i.e., all the options declared for a service, to a JSON schema, if data validates against the schema it should be acceptable as a configuration for the service.
Inputs
options- Attrset of Nixpkgs module system options
Type
optionsToSchema :: Attrs ModuleOption -> JSONSchema
Examples
Example
lib.module-schema.optionsToSchema usage example
optionsToSchema ((nixos {}).options.services.peertube.database)
=> {
"$defs" = {
# The schema of a valid Nix attribute name, elided here.
attrName = { };
};
"$schema" = "https://json-schema.org/draft/2020-12/schema";
additionalProperties = false;
properties = {
createLocally = {
default = false;
description = "Configure local PostgreSQL database server for PeerTube.";
type = "boolean";
};
host = {
default = "if config.services.peertube.database.createLocally\nthen \"/run/postgresql\"\nelse null\n";
description = "Database host address or unix socket.";
examples = [ "192.168.15.47" ];
type = "string";
};
name = {
default = "peertube";
description = "Database name.";
type = "string";
};
passwordFile = {
default = null;
description = "Password for PostgreSQL database.";
examples = [ "/run/keys/peertube/password-postgresql" ];
type = [
"null"
"string"
];
};
port = {
default = 5432;
description = "Database host port.";
maximum = 65535;
minimum = 0;
type = "integer";
};
user = {
default = "peertube";
description = "Database user.";
type = "string";
};
};
propertyNames = {
"$ref" = "#/$defs/attrName";
};
type = "object";
}
lib.module-schema.resolvePackages
Replace each package value in data that matches a schema from this
library, such as data from builtins.fromJSON, with the package it refers
to in a package set. A package value is an attribute set with _type
"package", see internal.package. Other values stay as they are.
Inputs
pkgs- The package set to look up attrpaths in
value- The data
Type
resolvePackages :: AttrSet -> a -> a
Examples
Example
lib.module-schema.resolvePackages usage example
resolvePackages pkgs {
enable = true;
package = { _type = "package"; attrpath = [ "pkgs" "hello" ]; };
}
=> { enable = true; package = pkgs.hello; }
lib.module-schema.typeToSchema
Convert a Nixpkgs module system type to a JSON schema.
The goal is a schema that validates the same values that the type's check
attribute would. Some conversions do not reach this goal: for example, the
schema of strMatching accepts each string. docs/manual/coverage.md gives
the schema of each type.
Inputs
type- Nixpkgs module system type, more or less anything produced by lib.types
Type
typeToSchema :: ModuleType -> JSONSchema
Examples
Example
lib.module-schema.typeToSchema usage example
typeToSchema (lib.types.ints.between 1 2)
=> { maximum = 2; minimum = 1; type = "integer"; }
typeToSchema (with lib.types;
oneOf [ bool (nullOr str) (numbers.between 1 2) ]
)
=> {
maximum = 2;
minimum = 1;
type = [
"boolean"
"null"
"number"
"string"
];
}
lib.module-schema.internal
Local bindings can be hard to reach outside of an expression. This set contains attributes used in the implementation of this library, exposing them to tests or users for whom the intended API is not sufficient. There are no guarantees of API stability for these attributes.
This convention is inherited from the Haskell ecosystem.