Skip to main content

Environments

Struct Environments 

Source
pub struct Environments { /* private fields */ }
Expand description

Engine-owned environment system: compiled/file tables + resolution + active-env state.

Implementations§

Source§

impl Environments

Source

pub fn new(default_env: impl Into<String>) -> Self

Creates an environment system with the given default environment name.

If default_env is sourced from the consumer’s own persisted state, read that state raw rather than through anything that calls back into resolve or a lazily-initialized singleton’s instance(). A consumer wiring a lazy singleton whose default depends on its own config can otherwise deadlock re-entering that singleton’s own initialization while it is still being constructed.

Source

pub fn with_environment( self, name: impl Into<String>, table: impl Into<EnvTable>, ) -> Self

Registers a compiled-in environment’s table, merging onto whatever is already registered for name (later call wins, key-by-key — same overlay rule as the environments.toml file layer). Accepts an EnvTable directly, or any #[derive(EnvConfig)] struct value — the derive generates impl From<Self> for EnvTable, so a compiled-in environment can be written as a plain typed struct instead of a stringly-keyed builder:

use cli_engine::{EnvConfig, environments::Environments};

#[derive(Default, EnvConfig)]
struct ApiConfig {
    api_url: String,
    #[env_config(default = String::new())]
    client_id: String,
}

let environments = Environments::new("prod").with_environment(
    "prod",
    ApiConfig { api_url: "https://api.example.com".to_owned(), client_id: "abc".to_owned() },
);

A struct value has no “absent” state — every field is written, even ones left at their type’s default — so splitting concerns across several smaller structs (each covering only the keys it cares about) composes better than one struct with placeholder values for fields it doesn’t set; merging (rather than replacing) is what makes that composition possible across repeated calls for the same name.

Source

pub fn with_config_file(self, enabled: bool) -> Self

Enables loading <config-dir>/<app_id>/environments.toml during resolution.

Source

pub fn with_app_id(self, app_id: impl Into<String>) -> Self

Sets the application id used to locate the config file and as the prefix for the app-scoped environment-variable override tier (see resolve).

The consumer must set this to the same app_id passed to CliConfig::new before sharing the Environments with both CliConfig::with_environments and PkceAuthProvider::with_environments (with the pkce-auth feature), or config_file_path returns None and the environments.toml file layer silently resolves empty.

Source

pub fn with_config_file_path_override(self, path: PathBuf) -> Self

Test/advanced seam: force the environments file path.

Source

pub fn with_fallback<F>(self, fallback: F) -> Self
where F: Fn(&str) -> Option<EnvTable> + Send + Sync + 'static,

Registers an opt-in seam for defining an environment purely from outside the compiled/file layers.

resolve/source — and therefore every path built on them, including the built-in --env flag and the env command group — consult fallback with the requested name whenever that name is unknown to both the compiled-in and environments.toml layers. Returning Some(table) lets a brand-new, never-declared name resolve (typically by having fallback read its own <NAME>_* environment variables and build a table from them); returning None preserves the existing “unknown environment” error.

The returned EnvTable is treated the same as a compiled-in table: it does not skip the environments.toml layer, which still merges on top of it (later wins). fallback is never consulted for a name already known to the compiled-in or file layer.

Source

pub fn default_env(&self) -> &str

The default environment name.

Source

pub fn app_id(&self) -> &str

The app id set via with_app_id, or empty if never set. Exposed so a consumer building its own crate::env_config::SourceChain (for example PkceAuthProvider, which has fallback tiers outside this system’s own compiled/file layers) can reuse the same app-scoped environment-variable prefix that resolve uses internally.

Source

pub fn list(&self) -> Vec<String>

Enumerable environment names (compiled-in + file-defined), sorted.

Any error from reading or parsing the environments file (missing file, permission/read error, or malformed TOML) is silently swallowed and only the compiled-in names are returned. Use source or resolve when you need those errors surfaced.

§Blocking

When the config-file layer is enabled, this performs synchronous filesystem I/O to read and parse environments.toml (like resolve). Avoid calling it repeatedly on a latency-sensitive async path.

Source

pub fn source(&self, name: &str) -> Result<EnvSource>

Builds the merged EnvSource for name: the compiled-in table overlaid by the environments.toml file table for the same name (file wins key-by-key), or a registered with_fallback table when name is unknown to both.

This is the seam behind resolve, exposed directly for generic introspection (for example, env info printing whatever keys an environment’s merged table actually has) without needing to know about any particular EnvConfig struct.

§Blocking

When the config-file layer is enabled, this performs synchronous filesystem I/O to read and parse environments.toml. Avoid calling it repeatedly on a latency-sensitive async path.

§Errors

Returns an error when name is not known to any layer (including a registered with_fallback) or when the environments file exists but cannot be read or parsed.

Source

pub fn resolve<T: EnvConfig>(&self, name: &str) -> Result<T, EnvConfigError>

Resolves name into a typed EnvConfig section: the common path, T::assemble over a chain of the app-scoped environment-variable source (see the design note below) and name’s merged EnvSource.

§Environment-variable overrides are app-scoped, not environment-scoped

A field’s #[env_config(env = "SUFFIX")] checks <APP_ID_UPPER>_<SUFFIX> here — not <NAME_UPPER>_<SUFFIX>. At any single resolution there is exactly one environment being asked about, so scoping the override variable by environment name buys nothing an app-scoped name doesn’t already give for free, while a bare environment name as a prefix (PROD_, DEV_) is a real collision risk in a shared shell/CI environment that an app-scoped prefix (GDDY_...) avoids categorically. A consumer needing extra fallback tiers outside this system’s own compiled/file/fallback layers (for example a legacy provider-scoped env var) builds its own crate::env_config::SourceChain and calls T::assemble directly — see PkceAuthProvider.

§Blocking

See source.

§Errors

Returns an error under the same conditions as source, or when a field’s present value fails to convert to its type, or a required field has no value in any source and no default (see EnvConfigError).

Source

pub fn config_file_path(&self) -> Option<PathBuf>

Path to environments.toml next to the engine config file, or None when the file layer is disabled or the config dir cannot be determined.

Source

pub fn active_from_config(config: &ConfigFile) -> Option<String>

Reads the persisted active environment from a loaded config file.

Source

pub fn effective_active( &self, flag: Option<&str>, config: &ConfigFile, ) -> String

Resolves the active environment name with precedence: explicit --env override > persisted active > configured default.

Source

pub fn persist_active(&self, name: &str) -> Result<()>

Persists name as the active environment (loads, sets, saves a fresh config file for app_id). Validates that name resolves first.

§Errors

Returns an error when name does not resolve to a known environment, or when the config file cannot be written.

Trait Implementations§

Source§

impl Clone for Environments

Source§

fn clone(&self) -> Environments

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Environments

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more