Skip to main content

Crate ddd_toolkit

Crate ddd_toolkit 

Source
Expand description

Domain-Driven Design building blocks for Rust, plus derive macros for the common cases, behind a single dependency.

This crate is a facade: it re-exports ddd-toolkit-core in full, plus, behind the derive feature (on by default), ddd-toolkit-macro’s derives. Everything below is reachable directly under ddd_toolkit::, whichever of the two it originates in.

§Features

FeatureDefaultEnables
deriveyes#[derive(ValueObject, EntityId, SecretVo, EnumVo)]
chrononoport::clock::Clock and its adapter/mock implementations
uuidnothe uuid-backed port::id::IdGenerator adapter
zeroizeno#[vo(zeroize)] support on domain::SecretVo (also needs the zeroize crate as a direct dependency - see its docs)
serdenoSerialize/Deserialize on domain::ValueObject/domain::EntityId/domain::EnumVo derives, not domain::SecretVo (also needs the serde crate as a direct dependency - see its docs)

§Examples

use ddd_toolkit::domain::{SecretVo, ValidationError, Wrapped};

#[derive(ddd_toolkit::ValueObject, Clone, PartialEq, Debug)]
#[vo(validate = "validate_email")]
struct Email(String);

fn validate_email(s: &str) -> Result<(), ValidationError> {
    if s.contains('@') {
        Ok(())
    } else {
        Err(ValidationError::new("Email", "missing @"))
    }
}

#[derive(ddd_toolkit::SecretVo, Clone, PartialEq)]
struct ApiKey(String);

let email = Email::try_from("a@b.com".to_string()).unwrap();
assert_eq!(email.as_inner(), "a@b.com");

let key = ApiKey::try_new("sekret".to_string()).unwrap();
assert_eq!(format!("{key:?}"), "ApiKey(***)"); // never leaks the secret

See this crate’s README for a longer walkthrough, including domain::EntityId and wiring an domain::AggregateRoot through a port::repository/port::event::EventDispatcher pair.

Modules§

adapter
Real (non-test-double) implementations of the crate::port traits.
application
The application layer: orchestrating domain objects and ports to carry out a single use case.
domain
The domain layer: entities, value objects, aggregates, and events.
mock
Test doubles for the crate::port traits: fixed/in-memory implementations useful in tests, or as a starting point for a real adapter.
port
The ports a domain depends on: repository, event dispatch, clock, and id generation.

Derive Macros§

EntityId
Derives EntityId - and everything #[derive(ValueObject)] derives - for a single-field tuple struct.
EnumVo
Derives EnumVo, Display, and FromStr for a fieldless enum.
SecretVo
Derives SecretVo for a single-field tuple struct, with a Debug impl that always redacts the wrapped value.
ValueObject
Derives ValueObject, Wrapped, TryFrom<Inner>, From<Self> for Inner, and Display for a single-field tuple struct.