Attribute Macro config

#[config]
Expand description

Define a configuration type.

§Example

use pavex::config;

#[config(key = "pool")]
#[derive(serde::Deserialize, Debug, Clone)]
pub struct PoolConfig {
    pub max_n_connections: u32,
    pub min_n_connections: u32,
}

§Guide

Check out the “Configuration” section of Pavex’s guide for a thorough introduction to configuration in Pavex applications.

§Import

Use Blueprint::config or Blueprint::import to add the newly-defined configuration type to your application.

§Arguments

The sections below provide an exhaustive list of all the arguments and flags supported by the config macro:

NameKindRequired
keyArgumentYes
default_if_missingFlagNo
include_if_unusedFlagNo
never_cloneFlagNo

§key

The config macro expects a key argument.
key will be used as the name of the corresponding field in the generated ApplicationConfig struct.

The provided key must satisfy a few constraints:

  • It can’t be empty.
  • It must start with a letter.
  • It can only contain letters, numbers, and underscores.
  • It must be unique within the application.

§Example

use pavex::config;

#[config(key = "pool")]
//       👆 The key for this configuration type.
#[derive(serde::Deserialize, Debug, Clone)]
pub struct PoolConfig {
    pub max_n_connections: u32,
    pub min_n_connections: u32,
}

§default_if_missing

By default, Pavex considers all configuration types to be required. There must be a value for each configuration key in the source we’re reading from—e.g. a YAML configuration file. If a key is missing, Pavex will return an error.

The default_if_missing flag disables this behaviour. Pavex will invoke Default::default() to provide a default value if the configuration key was omitted by the configuration source. No error will be raised.

default_if_missing can only be used on types that implement the Default trait.

§Example

Consider the following configuration type:

use pavex::config;

#[config(key = "pool", default_if_missing)]
//                     👆 The flag
#[derive(serde::Deserialize, Debug, Clone)]
pub struct PoolConfig {
    pub max_n_connections: u32,
    pub min_n_connections: u32,
}

impl Default for PoolConfig {
    fn default() -> Self {
        Self {
            max_n_connections: 10,
            min_n_connections: 2,
        }
    }
}

The definition of ApplicationConfig, in the generated server SDK code, will look like this:

#[derive(serde::Deserialize, Debug, Clone)]
pub struct ApplicationConfig {
    #[serde(default)]
    // 👆 Tell `serde` to use the default value
    //    if the field is missing.
    pub pool: PoolConfig,
    // [..other config types..]
}

Therefore, given this YAML configuration file as input,

tls:
  enabled: true
# No `pool` entry!

Pavex will initialize PoolConfig using its default values, rather than returning an error.

§include_if_unused

By default, Pavex will prune unused configuration types from the final ApplicationConfig type.

The include_if_unused flag disables this behaviour. There will always be an entry in ApplicationConfig for configuration types marked as include_if_unused, even if their value is never accessed by any constructor, route, or middleware.

§Example

Consider this configuration type:

use pavex::config;

#[config(key = "pool", include_if_unused)]
//                     👆 The flag
#[derive(serde::Deserialize, Debug, Clone)]
pub struct PoolConfig {
    pub max_n_connections: u32,
    pub min_n_connections: u32,
}

The resulting ApplicationConfig will always contain an entry for PoolConfig, even if it’s never used. In the generated server SDK code:

#[derive(Debug, Clone, serde::Deserialize)]
pub struct ApplicationConfig {
    pub pool: PoolConfig,
    // 👆 You'll always find this field.

    // [..other config types..]
}

§never_clone

By default, Pavex will invoke .clone() on configuration types if it helps to satisfy Rust’s borrow checker.

The never_clone flag disables this behaviour:

use pavex::config;

#[config(key = "pool", never_clone)]
//                     👆 The flag
#[derive(serde::Deserialize, Debug)]
pub struct PoolConfig {
    pub max_n_connections: u32,
    pub min_n_connections: u32,
}

Pavex will report an error during the code-generation phase if cloning is required but forbidden.