nestrs_idempotency/lib.rs
1//! NestJS [`@nestjs/idempotency`](https://docs.nestjs.com/reliability/idempotency) analogue —
2//! `Idempotency-Key` request deduplication.
3//!
4//! # Behavior
5//!
6//! 1. Missing key → pass through (or **400** if [`IdempotencyOptions::required`]).
7//! 2. Completed key → replay stored status/body with header `idempotency-replayed: true`.
8//! 3. In-flight key → **409** (`IDEMPOTENCY_IN_FLIGHT`).
9//! 4. First writer → run handler, then [`IdempotencyStore::complete`].
10//!
11//! # Security
12//!
13//! Always set [`IdempotencyOptions::scope`] to the authenticated principal so tenants cannot
14//! replay another user's response. Prefer Redis TTL in multi-instance deploys (`cache-redis`).
15//!
16//! # Middleware
17//!
18//! ```ignore
19//! use axum::middleware::from_fn_with_state;
20//! use nestrs_idempotency::{idempotency_middleware, IdempotencyOptions};
21//! use std::sync::Arc;
22//!
23//! let opts = Arc::new(IdempotencyOptions::default());
24//! let router = router.layer(from_fn_with_state(opts, idempotency_middleware));
25//! ```
26//!
27//! Umbrella feature: `nestrs` / `idempotency` → `nestrs::idempotency`.
28
29#![doc(html_root_url = "https://docs.rs/nestrs-idempotency/1.7.1")]
30
31mod middleware;
32mod module;
33mod options;
34mod store;
35
36pub use middleware::idempotency_middleware;
37pub use module::IdempotencyModule;
38pub use options::IdempotencyOptions;
39pub use store::{IdempotencyRecord, IdempotencyStore, InMemoryIdempotencyStore};
40
41#[cfg(feature = "cache-redis")]
42pub use store::RedisIdempotencyStore;
43
44pub use nestrs_core::{DynamicModule, Injectable, ProviderRegistry};