Skip to main content

ddd_toolkit/
lib.rs

1//! Domain-Driven Design building blocks for Rust, plus derive macros for
2//! the common cases, behind a single dependency.
3//!
4//! This crate is a facade: it re-exports
5//! [`ddd-toolkit-core`](https://docs.rs/ddd-toolkit-core) in full, plus,
6//! behind the `derive` feature (on by default),
7//! [`ddd-toolkit-macro`](https://docs.rs/ddd-toolkit-macro)'s derives.
8//! Everything below is reachable directly under `ddd_toolkit::`, whichever
9//! of the two it originates in.
10//!
11//! - [`domain`] - the domain-layer traits: [`domain::Entity`],
12//!   [`domain::AggregateRoot`], [`domain::ValueObject`]/[`domain::Wrapped`],
13//!   [`domain::EntityId`], [`domain::SecretVo`], [`domain::EnumVo`],
14//!   [`domain::DomainEvent`]. With `derive` enabled,
15//!   `#[derive(ValueObject, EntityId, SecretVo, EnumVo)]` generates the
16//!   boilerplate for those four.
17//! - [`port`] - the ports a domain depends on: repository (`Load`/`Save`/
18//!   `Delete`), [`port::event::EventDispatcher`], `port::clock::Clock`
19//!   (behind `chrono`), [`port::id::IdGenerator`].
20//! - [`adapter`] - real adapters for those ports, behind the `chrono`/`uuid`
21//!   features.
22//! - [`mock`] - in-memory/fixed adapters, useful as test doubles or a
23//!   starting point for a real backend.
24//! - [`application`] - [`application::usecase::UseCase`].
25//!
26//! # Features
27//!
28//! | Feature   | Default | Enables |
29//! |-----------|---------|---------|
30//! | `derive`  | yes | `#[derive(ValueObject, EntityId, SecretVo, EnumVo)]` |
31//! | `chrono`  | no  | `port::clock::Clock` and its [`adapter`]/[`mock`] implementations |
32//! | `uuid`    | no  | the `uuid`-backed [`port::id::IdGenerator`] adapter |
33//! | `zeroize` | no  | `#[vo(zeroize)]` support on [`domain::SecretVo`] (also needs the `zeroize` crate as a direct dependency - see its docs) |
34//! | `serde`   | no  | `Serialize`/`Deserialize` on [`domain::ValueObject`]/[`domain::EntityId`]/[`domain::EnumVo`] derives, not [`domain::SecretVo`] (also needs the `serde` crate as a direct dependency - see its docs) |
35//!
36//! # Examples
37//!
38//! ```
39//! use ddd_toolkit::domain::{SecretVo, ValidationError, Wrapped};
40//!
41//! #[derive(ddd_toolkit::ValueObject, Clone, PartialEq, Debug)]
42//! #[vo(validate = "validate_email")]
43//! struct Email(String);
44//!
45//! fn validate_email(s: &str) -> Result<(), ValidationError> {
46//!     if s.contains('@') {
47//!         Ok(())
48//!     } else {
49//!         Err(ValidationError::new("Email", "missing @"))
50//!     }
51//! }
52//!
53//! #[derive(ddd_toolkit::SecretVo, Clone, PartialEq)]
54//! struct ApiKey(String);
55//!
56//! let email = Email::try_from("a@b.com".to_string()).unwrap();
57//! assert_eq!(email.as_inner(), "a@b.com");
58//!
59//! let key = ApiKey::try_new("sekret".to_string()).unwrap();
60//! assert_eq!(format!("{key:?}"), "ApiKey(***)"); // never leaks the secret
61//! ```
62//!
63//! See this crate's README for a longer walkthrough, including
64//! [`domain::EntityId`] and wiring an [`domain::AggregateRoot`] through a
65//! [`port::repository`]/[`port::event::EventDispatcher`] pair.
66
67pub use ddd_toolkit_core::*;
68
69#[cfg(feature = "derive")]
70pub use ddd_toolkit_macro::*;