Skip to content

New configuration entries

Use the #[config] attribute to define a new configuration entry:

use pavex::config;
use redact::Secret;

#[config(key = "database")]
#[derive(serde::Deserialize, Debug, Clone)] // (1)!
pub struct DatabaseConfig {
    pub username: String,
    pub password: Secret<String>,
    pub host: String,
    pub database_name: String,
    pub require_ssl: bool,
}
  1. Deriving the required traits.

The #[config] attribute expects a unique configuration key as argument.

Required traits

The annotated type must implement the Debug, Clone, and serde::Deserialize traits.

As you have seen in the example above, the required trait implementations can be derived automatically. If necessary, check out serde's documentation for more information on how to customize the deserialization process.

Registration

Use an import to register in bulk all the configuration entries defined in the current crate:

use pavex::{Blueprint, blueprint::from};

pub fn blueprint() -> Blueprint {
    let mut bp = Blueprint::new();
    bp.import(from![crate]); // (1)!
    // [...]
}
  1. You can also import configuration entries from other crates or specific modules.

Alternatively, register configuration entries one by one using Blueprint::config:

use super::DATABASE_CONFIG;
use pavex::Blueprint;

pub fn blueprint() -> Blueprint {
    let mut bp = Blueprint::new();
    bp.config(DATABASE_CONFIG); // (1)!
    // [...]
}
  1. DATABASE_CONFIG is a strongly-typed constant generated by the #[config] attribute on the DatabaseConfig type.
    Check out the documentation on component ids for more details.

Configuration key

The configuration key uniquely identifies a configuration entry within a Pavex application. It must start with a letter and can contain letters, digits and underscores.

Every configuration entry becomes a field in ApplicationConfig, and the configuration key is used as the field name. The key determines the expected configuration schema—e.g. which environment variables can be used to set its value and the structure of configuration files.

Lifecycle

Configuration entries are treated as singletons from Pavex's dependency injection system.

Most configuration entries are only needed to construct other singletons, so they'll be discarded after ApplicationState::new returns.

If a configuration entry is needed at runtime (e.g. to configure the behaviour of middleware or a request handler), it'll be added as a field to ApplicationState. In this case, Pavex will expect the configuration type to implement the Send and Sync traits in addition to the other trait requirements.