arcly-http 0.4.0

Enterprise-grade NestJS-inspired web framework on axum: zero-lock DI, declarative controllers, multi-tenant data routing, transactional outbox, ABAC, and a self-documenting OpenAPI surface
Documentation
use std::any::TypeId;
use std::sync::Arc;

use arcly_http::core::engine::{AnyProvider, DiContainerBuilder, ProviderDescriptor, Resolver};
use arcly_http::observability::lean_telemetry::parse_traceparent;

#[test]
fn di_container_resolves_singleton() {
    #[derive(Debug, PartialEq)]
    struct Svc(u32);
    let mut b = DiContainerBuilder::new();
    b.register(Svc(7));
    let c = b.freeze();
    assert_eq!(c.get::<Svc>(), &Svc(7));
}

struct CycleA;
struct CycleB;

static A_DESC: ProviderDescriptor = ProviderDescriptor {
    name: "CycleA",
    type_id_fn: || TypeId::of::<CycleA>(),
    deps_fn: || vec![TypeId::of::<CycleB>()],
    build: |_r: &Resolver<'_>| -> AnyProvider { Arc::new(CycleA) },
};
static B_DESC: ProviderDescriptor = ProviderDescriptor {
    name: "CycleB",
    type_id_fn: || TypeId::of::<CycleB>(),
    deps_fn: || vec![TypeId::of::<CycleA>()],
    build: |_r: &Resolver<'_>| -> AnyProvider { Arc::new(CycleB) },
};

#[test]
#[should_panic(expected = "cycle")]
fn di_cycle_is_rejected() {
    let mut b = DiContainerBuilder::new();
    b.add_provider(&A_DESC);
    b.add_provider(&B_DESC);
    b.freeze();
}

#[test]
fn traceparent_parser_zero_alloc() {
    let h = b"00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01";
    let t = parse_traceparent(h).unwrap();
    assert_eq!(&t.trace_id[..4], &[0x0a, 0xf7, 0x65, 0x19]);
    assert_eq!(
        &t.span_id,
        &[0xb7, 0xad, 0x6b, 0x71, 0x69, 0x20, 0x33, 0x31]
    );
    assert!(parse_traceparent(b"garbage").is_none());
}

#[test]
fn error_into_problem_details_is_static() {
    use arcly_http::http::IntoResponse;
    let r = arcly_http::web::Error::NotFound.into_response();
    assert_eq!(r.status().as_u16(), 404);
}