Saltar al contenido
← Volver a proyectos

Pact Runtime

Runtime support library for Pact Lang

#pact-runtime

Runtime support library for code generated by the pact-lang compiler.

When pact compile --runtime generates Rust code, that code imports pact_runtime::prelude::* and depends on the types, traits, and builtins defined here.

#What's Inside

#Types (src/types.rs)

Type Purpose
Uuid Re-exported from the uuid crate (with serde support)
ValidationError { field: String, message: String } — returned by validation methods
StoreError UniqueViolation { field } or NotFound { id } — returned by store operations

#Store Trait (src/store.rs)

pub trait Store<T: Clone + HasId + HasUniqueFields> {
    fn query_by_id(&self, id: &Uuid) -> Option<T>;
    fn insert(&mut self, item: T) -> Result<T, StoreError>;
    fn list_all(&self) -> Vec<T>;
    fn delete(&mut self, id: &Uuid) -> Option<T>;
}

Types stored in a Store must implement:

  • HasId — provides fn id(&self) -> Uuid
  • HasUniqueFields — provides fn unique_fields(&self) -> Vec<(&'static str, String)> for unique constraint checking

InMemoryStore<T> is a HashMap-backed implementation that enforces unique constraints on insert and cleans them up on delete.

#Builtins (src/builtins.rs)

Function Signature Purpose
validate_uuid fn(&str) -> Result<Uuid, ValidationError> Parse a string as UUID
non_empty fn(&[T]) -> bool Check if a slice is non-empty

#Prelude

use pact_runtime::prelude::*;
// Brings in: Uuid, ValidationError, StoreError, Store, HasId,
//            HasUniqueFields, InMemoryStore, validate_uuid, non_empty

#Usage

Add to your Cargo.toml:

[dependencies]
pact-runtime = { path = "../pact-runtime" }

#Building and Testing

cargo build
cargo test   # 8 tests

#How Generated Code Uses This

The pact compile --runtime command produces Rust that depends on pact-runtime. For example, a Pact type definition:

(type User
  (field id    UUID   :immutable :generated)
  (field name  String :min-len 1 :max-len 200)
  (field email String :format :email :unique-within user-store))

Generates:

use pact_runtime::prelude::*;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
    pub id: Uuid,
    pub name: String,
    pub email: String,
}

impl HasId for User {
    fn id(&self) -> Uuid { self.id }
}

impl HasUniqueFields for User {
    fn unique_fields(&self) -> Vec<(&'static str, String)> {
        vec![("email", self.email.clone())]
    }
}

impl User {
    pub fn validate(&self) -> Vec<ValidationError> { /* ... */ }
    pub fn validate_input(input: &CreateUserInput) -> Vec<ValidationError> { /* ... */ }
    pub fn from_input(input: CreateUserInput) -> Self { /* ... */ }
}

And functions use Store<T> trait bounds:

pub fn get_user_by_id(store: &impl Store<User>, id: &str) -> GetUserByIdResult {
    match validate_uuid(id) {
        Err(_) => GetUserByIdResult::InvalidId { id: id.to_string() },
        Ok(uuid) => match store.query_by_id(&uuid) {
            None => GetUserByIdResult::NotFound { id: uuid.to_string() },
            Some(u) => GetUserByIdResult::Ok(u),
        },
    }
}

#Related Crates

  • pact-lang — The compiler that generates code targeting this runtime
  • pact-web — Axum web app that uses InMemoryStore to serve generated CRUD services

Nueva versión disponible.