1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! Dependency injection: what a handler needs, proved at compile time.
//!
//! ```text
//! cargo run -p kynos --example state
//! ```
//!
//! The application's own struct *is* the context. `#[derive(Provider)]` emits
//! one `Provides` implementation per field, a handler asks for what it needs
//! with `Inject<T>`, and the two meet at `mount` — which is where the context
//! type first becomes concrete, and therefore where asking for something the
//! context does not have stops compiling.
//!
//! The comparison worth drawing: axum, actix-web and poem all resolve erased
//! state at run time and panic when it is absent, and salvo's `Depot` is keyed
//! by string. Here there is nothing to look up. Try adding
//!
//! ```ignore
//! #[kynos::get("/mailer")]
//! async fn broken(Inject(mailer): Inject<Mailer>) -> NoContent { NoContent }
//! ```
//!
//! and mounting it: the build fails at the `mount` call with "the context `App`
//! provides no `Mailer`", naming both types and the field to add.
use ;
use ;
/// A database handle. Cheap to clone, which is what an injected value should
/// be: one is handed out per request.
/// A cache handle.
/// The application context.
///
/// Every provided field's type must be `Clone`. `#[provide(skip)]` opts a field
/// out, because not everything an application holds is a dependency.
/// Reads through the cache, falling back to the pool.
///
/// Two injected values, in any order, alongside anything the request carries.
/// Neither appears in the description: application state has no effect on the
/// wire, so `Inject<T>` describes nothing — and says so, rather than being
/// silently skipped.
async
/// What checking a connection out of the pool can fail with.
///
/// A named type rather than a bare `Problem`, because the statuses an operation
/// advertises have to be known without running it. `statuses()` here is
/// `&[503]`, and that is what reaches the description.
// The variant is constructed by the checkout this example does not implement.
/// Acquisition that can fail is not injection.
///
/// Inject the *handle* and check it out here, where the failure lands in the
/// return type and therefore in the description. A provider that could fail
/// would produce a response no operation declares — which is the one thing this
/// framework exists to prevent.
///
/// The return type is a plain `Result`. `kynos::Result` defaults its error to
/// the framework's own build-time failure, which is what `main` below returns;
/// in a handler position that default would suggest a relationship that does
/// not exist.
async
async