1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
use crate::blueprint::constructor::{CloningStrategy, Lifecycle, RegisteredConstructor};
use crate::blueprint::conversions::{lint2lint, raw_identifiers2callable};
use crate::blueprint::linter::Lint;
use crate::blueprint::reflection::RawIdentifiers;
use crate::blueprint::Blueprint;
use pavex_bp_schema::{Callable, LintSetting};
use std::collections::BTreeMap;
/// A constructor that has been configured but has not yet been registered with a [`Blueprint`].
///
/// # Guide
///
/// Check out the ["Dependency injection"](https://pavex.dev/docs/guide/dependency_injection)
/// section of Pavex's guide for a thorough introduction to dependency injection
/// in Pavex applications.
///
/// # Use cases
///
/// [`Constructor`] is primarily used by kits (e.g. [`ApiKit`](crate::kit::ApiKit))
/// to allow users to customize (or disable!)
/// the bundled constructors **before** registering them with a [`Blueprint`].
#[derive(Clone, Debug)]
pub struct Constructor {
pub(in crate::blueprint) callable: Callable,
pub(in crate::blueprint) lifecycle: Lifecycle,
pub(in crate::blueprint) cloning_strategy: Option<CloningStrategy>,
pub(in crate::blueprint) error_handler: Option<Callable>,
pub(in crate::blueprint) lints: BTreeMap<pavex_bp_schema::Lint, LintSetting>,
}
impl Constructor {
/// Create a new (unregistered) constructor.
///
/// Check out the documentation of [`Blueprint::constructor`] for more details
/// on constructors.
#[track_caller]
pub fn new(callable: RawIdentifiers, lifecycle: Lifecycle) -> Self {
Self {
callable: raw_identifiers2callable(callable),
lifecycle,
cloning_strategy: None,
error_handler: None,
lints: Default::default(),
}
}
/// Create a new (unregistered) constructor with a [singleton](Lifecycle::Singleton) lifecycle.
///
/// It's a shorthand for [`Constructor::new(callable, Lifecycle::Singleton)`](Constructor::new).
#[track_caller]
pub fn singleton(callable: RawIdentifiers) -> Self {
Constructor::new(callable, Lifecycle::Singleton)
}
/// Create a new (unregistered) constructor with a [request-scoped](Lifecycle::RequestScoped) lifecycle.
///
/// It's a shorthand for [`Constructor::new(callable, Lifecycle::RequestScoped)`](Constructor::new).
#[track_caller]
pub fn request_scoped(callable: RawIdentifiers) -> Self {
Constructor::new(callable, Lifecycle::RequestScoped)
}
/// Create a new (unregistered) constructor with a [transient](Lifecycle::Transient) lifecycle.
///
/// It's a shorthand for [`Constructor::new(callable, Lifecycle::Transient)`](Constructor::new).
#[track_caller]
pub fn transient(callable: RawIdentifiers) -> Self {
Constructor::new(callable, Lifecycle::Transient)
}
/// Register an error handler for this constructor.
///
/// Check out the documentation of [`RegisteredConstructor::error_handler`] for more details.
#[track_caller]
pub fn error_handler(mut self, error_handler: RawIdentifiers) -> Self {
self.error_handler = Some(raw_identifiers2callable(error_handler));
self
}
/// Set the cloning strategy for the output type returned by this constructor.
///
/// Check out the documentation of [`CloningStrategy`] for more details.
pub fn cloning(mut self, cloning_strategy: CloningStrategy) -> Self {
self.cloning_strategy = Some(cloning_strategy);
self
}
/// Set the cloning strategy to [`CloningStrategy::CloneIfNecessary`].
/// Check out [`Constructor::cloning`] for more details.
pub fn clone_if_necessary(self) -> Self {
self.cloning(CloningStrategy::CloneIfNecessary)
}
/// Set the cloning strategy to [`CloningStrategy::NeverClone`].
/// Check out [`Constructor::cloning`] for more details.
pub fn never_clone(self) -> Self {
self.cloning(CloningStrategy::NeverClone)
}
/// Tell Pavex to ignore a specific [`Lint`] when analysing
/// this constructor and the way it's used.
pub fn ignore(mut self, lint: Lint) -> Self {
self.lints.insert(lint2lint(lint), LintSetting::Ignore);
self
}
/// Tell Pavex to enforce a specific [`Lint`] when analysing
/// this constructor and the way it's used.
pub fn enforce(mut self, lint: Lint) -> Self {
self.lints.insert(lint2lint(lint), LintSetting::Enforce);
self
}
/// Register this constructor with a [`Blueprint`].
///
/// Check out the documentation of [`Blueprint::constructor`] for more details.
pub fn register(self, bp: &mut Blueprint) -> RegisteredConstructor {
bp.register_constructor(self)
}
}