Skip to main content

nestrs_core/
pipe.rs

1//! Pipes — transform / validate a single value before it reaches the handler (NestJS `PipeTransform`).
2//!
3//! ## Layers
4//!
5//! 1. [`PipeTransform`] — the base trait. Takes an `Input`, returns an `Output`,
6//!    possibly failing. Generic over the input type so a single pipe can be
7//!    reused across parameters.
8//!
9//! 2. [`HttpPipeTransform`] — a marker sub-trait that adds the `Default`
10//!    bound the `#[use_pipes]` macro needs (so each macro-generated
11//!    extractor can call `<P as Default>::default()` without DI). Mirrors
12//!    the transport-specific sub-traits in `nestrs-ws` (`WsPipeTransform`)
13//!    and `nestrs-microservices` (`MicroPipeTransform`).
14
15/// Transform one value into another, possibly failing (validation / coercion).
16///
17/// Use from handlers by calling [`PipeTransform::transform`] on a unit struct (or stateful pipe
18/// type registered in DI). Route-level `#[use_pipes]` integration is not required for this trait to
19/// be useful.
20#[async_trait::async_trait]
21pub trait PipeTransform<Input>: Send + Sync {
22    type Output;
23    type Error;
24    async fn transform(&self, value: Input) -> Result<Self::Output, Self::Error>;
25}
26
27/// Marker trait for pipe types usable in HTTP `#[use_pipes]`. Adds the
28/// `Default` bound the macro needs to instantiate each pipe at extraction
29/// time without going through DI, and constrains `Error` to
30/// `std::error::Error` so the per-arity extractors can box pipe errors and
31/// downcast to `HttpException` (preserving the per-pipe status code).
32///
33/// Implement this alongside your [`PipeTransform`] impl for each input
34/// type your pipe accepts. The macro emits a per-arity extractor that
35/// calls `<P as Default>::default().transform(value).await?` for each
36/// pipe in declaration order.
37pub trait HttpPipeTransform<Input>:
38    PipeTransform<Input, Error: std::error::Error + Send + Sync> + Default + Send + Sync + 'static
39{
40}