std/config

Configuration in layers: defaults, then files such as the user's and the workspace's, then the environment, each over the ones before; checked against a JSON Schema; and read again when its files change.

import "std/config"

ConfigOptions options = ConfigOptions()
options.defaults = parse_json("{\"server\": {\"port\": 8080}}")?
options.files = [config_dir() + "/app/settings.json", ".app/settings.json"]
options.env_prefix = "APP_"       // APP_SERVER__PORT=9000 sets server.port
Config c = load_config(options)?
print(c.number("server.port", 80.0))
Settings settings = Settings.from_json(c.data)?   // a struct with #[derive(Json)]
Function or method Result
load_config(options) a Result[Config]: the layers merged, with data, the merged Json, and sources, where each layer came from
c.get(path) the value at a path such as "server.port", as an Option[Json]
c.text(path, fallback), c.number(path, fallback), c.flag(path, fallback) a value of a kind, or fallback
config_merge(under, over) two values merged as layers are
watch_config(options, changed) a ConfigWatch that reads the settings again when a file changes, while the event loop runs, and gives changed the result; close() stops it

A ConfigOptions has defaults, a Json; files, read in order, each over the ones before, and left out when not there; env_prefix, so that a variable APP_SERVER__PORT sets server.port, its value read as JSON when it is JSON and as text otherwise; and schema, a JSON Schema the merged settings must meet, or an ERROR of kind "invalid_config" lists what does not. Files are JSON with comments and trailing commas, as editors' settings are, or TOML when their names end in .toml; objects merge field by field, and any other value, arrays too, replaces the one before.