#macro-derive #pattern #domain #architecture #design #design-pattern

macro domain_derive

domain_derive holds derive macros for the domain_patterns crate

27 releases

0.2.137 Nov 12, 2019
0.2.136 Sep 26, 2019
0.1.99 Sep 10, 2019

#28 in #design-pattern

Download history 3/week @ 2024-03-08 2/week @ 2024-03-15 92/week @ 2024-03-29 29/week @ 2024-04-05

63 downloads per month
Used in domain_patterns

MIT license

60KB
562 lines

domain_derive

This crate provides domain_patterns derive macros.

Entity macro

The Entity derive macro can be used to automatically implement all methods of the Entity trait from the domain_patterns crate. This only works if certain preconditions are met:

  1. You are applying this to a struct.
  2. Your struct has an id field of type Uuid.
  3. Your struct has a version field which is some integer type.
#[macro_use]
extern crate domain_derive;
use uuid::Uuid;

#[derive(Entity)]
struct User {
    id: Uuid,
    version: u64
};

ValueSetup macro

The ValueSetup derive macro can be used to setup as much boilerplate as possible for your choosen value object. It checks some preconditions:

  1. You are applying this to a struct.
  2. Your struct has a single field called value of any type that is clonable.

Once you've used this macro, you will still need to implement the ValueObject trait, but you will not have to implement TryFrom (or create the validation error for TryFrom, this is handled by the macro), or implement PartialEq or Clone.

In case you need to use the validation error elsewhere, the created validation error will be the name of your struct with ValidationError appended. For example, if you have an Email struct, then the generated validation error will be called EmailValidationError.

#[macro_use]
extern crate domain_derive;

use domain_patterns::ValueObject;
use regex::Regex;

#[derive(ValueSetup)]
pub struct Email {
    pub value: String,
}

impl ValueObject<String> for Email {
    fn validate(value: &String) -> bool {
        let email_rx = Regex::new(
            r"^(?i)[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$"
        ).unwrap();

        email_rx.is_match(value)
    }

    fn value(&self) -> &String {
        return &self.value;
    }
}

DomainEvent macro

The DomainEvent macro should be applied to a struct that represents a DomainEvent. It completely implements all methods of the DomainEvent trait, as long as some preconditions are met:

  1. You are applying this to a struct.
  2. There needs to be an id field of type Uuid.
  3. There needs to be a version field of any integer type (floating point not allowed).
  4. There needs to be an aggregate_id field of type Uuid.
  5. There needs to be an occurred field of type i64.
#[macro_use]
extern crate domain_derive;

use uuid::Uuid;
use domain_patterns::event::DomainEvent;

#[derive(Serialize, Clone, DomainEvent)]
pub struct FirstNameUpdatedEvent {
    pub aggregate_id: Uuid,
    pub first_name: String,
    pub version: u64,
    pub id: Uuid,
    pub occurred: i64,
}

DomainEvents macro

The DomainEvents macro should be applied to an enum that holds variants which are all Domain Events. This is a very thin wrapper, and all the macro does is check that the structure is an enum, and then applies the trait, which has no methods.

#[macro_use]
extern crate domain_derive;

use uuid::Uuid;
use domain_patterns::event::{DomainEvent, DomainEvents};

#[derive(Serialize, Clone, DomainEvent)]
pub struct FirstNameUpdatedEvent {
    pub aggregate_id: Uuid,
    pub first_name: String,
    pub version: u64,
    pub id: Uuid,
    pub occurred: i64,
}

#[derive(Clone, DomainEvents)]
pub enum UserEvents {
    FirstNameUpdated(FirstNameUpdatedEvent),
}

License: MIT

Dependencies

~0.4–1MB
~23K SLoC