armature-framework 0.2.2

A modern, type-safe HTTP framework for Rust inspired by Angular and NestJS. Features dependency injection, decorators, middleware, authentication (JWT/OAuth2/SAML), validation, OpenAPI/Swagger, caching, job queues, and observability.
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
# Documentation Testing Guide

Comprehensive guide for writing and testing documentation in the Armature framework.

## Overview

Documentation testing ensures that code examples in documentation actually work. Rust's `cargo test --doc` runs all code blocks in doc comments as tests.

## Why Document Tests?

✅ **Ensures examples work** - Code in docs stays up-to-date
✅ **Prevents bit rot** - Breaking changes caught immediately
✅ **Living documentation** - Examples are always tested
✅ **Better onboarding** - New users get working code

## Writing Doc Tests

### Basic Example

```rust
/// Add two numbers together.
///
/// # Examples
///
/// ```
/// use armature_core::utils::add;
///
/// let result = add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}
```

### Async Examples

```rust
/// Render a template asynchronously.
///
/// # Examples
///
/// ```
/// use handlebars::Handlebars;
/// use serde_json::json;
///
/// # tokio_test::block_on(async {
/// let mut hbs = Handlebars::new();
/// hbs.register_template_string("index", "Hello {{name}}!")?;
///
/// let data = json!({"name": "World"});
/// let html = hbs.render("index", &data)?;
/// assert_eq!(html, "Hello World!");
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// # });
/// ```
pub async fn render_template() -> Result<String, Error> {
    // Implementation
}
```

### Examples with Setup

```rust
/// Create a user in the database.
///
/// # Examples
///
/// ```
/// use armature_auth::User;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # // Hidden setup code
/// # let db = setup_test_db()?;
/// let user = User::create("alice@example.com", "password123")?;
/// assert_eq!(user.email, "alice@example.com");
/// # Ok(())
/// # }
/// #
/// # fn setup_test_db() -> Result<Database, Box<dyn std::error::Error>> {
/// #     Ok(Database::new())
/// # }
/// ```
pub fn create_user(email: &str, password: &str) -> Result<User, Error> {
    // Implementation
}
```

## Doc Test Attributes

### `no_run` - Compile but don't run

Use for examples that require external resources:

```rust
/// Start the server.
///
/// # Examples
///
/// ```no_run
/// use armature_framework::prelude::*;
///
/// #[module()]
/// #[derive(Default)]
/// struct AppModule;
///
/// #[tokio::main]
/// async fn main() {
///     let app = Application::create::<AppModule>().await;
///     app.listen(3000).await.unwrap();
/// }
/// ```
pub async fn start_server() {}
```

### `ignore` - Skip completely

Use for examples that are placeholders or pseudo-code:

```rust
/// Complex algorithm (simplified).
///
/// # Examples
///
/// ```ignore
/// // This is pseudo-code
/// let result = complex_algorithm(data);
/// ```
pub fn complex_algorithm(data: &[u8]) -> Vec<u8> {
    vec![]
}
```

### `should_panic` - Expect panic

Use for error condition examples:

```rust
/// Divide two numbers (panics on zero).
///
/// # Examples
///
/// ```should_panic
/// use armature_core::utils::divide;
///
/// // This will panic
/// divide(10, 0);
/// ```
pub fn divide(a: i32, b: i32) -> i32 {
    if b == 0 {
        panic!("Division by zero");
    }
    a / b
}
```

### `compile_fail` - Expect compile error

Use to show incorrect usage:

```rust
/// Type-safe ID wrapper.
///
/// This example shows incorrect usage:
///
/// ```compile_fail
/// use armature_core::UserId;
///
/// // This won't compile (UserId != OrderId)
/// let user_id: UserId = OrderId::new(123);
/// ```
pub struct UserId(u64);
```

## Hidden Lines

Use `#` to hide setup/teardown code:

```rust
/// Query the database.
///
/// # Examples
///
/// ```
/// use armature_cache::Cache;
///
/// # tokio_test::block_on(async {
/// # let cache = Cache::new_memory();
/// let value: Option<String> = cache.get("key").await?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// # });
/// ```
pub async fn query_cache() {}
```

Hidden lines are compiled and run but not shown in documentation.

## Testing Standards

### Module-Level Documentation

Every module should have an example:

```rust
//! Authentication module for JWT and OAuth2.
//!
//! # Example
//!
//! ```
//! use armature_auth::{JwtManager, JwtConfig};
//!
//! let config = JwtConfig::new("secret_key");
//! let manager = JwtManager::new(config)?;
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```

pub mod jwt;
pub mod oauth2;
```

### Public API Documentation

Every public function/struct should have:

1. **Description** - What it does
2. **Examples** - How to use it
3. **Errors** - What can go wrong (if applicable)
4. **Panics** - When it panics (if applicable)

```rust
/// Create a new HTTP response.
///
/// # Examples
///
/// ```
/// use armature_core::HttpResponse;
///
/// let response = HttpResponse::ok()
///     .with_header("Content-Type", "application/json")
///     .with_body(b"{}".to_vec());
///
/// assert_eq!(response.status, 200);
/// ```
///
/// # Errors
///
/// Returns an error if serialization fails.
pub fn with_json<T: Serialize>(self, data: &T) -> Result<Self, Error> {
    // Implementation
}
```

### Test Coverage Goals

- **100%** of public APIs have documentation
- **90%+** of public APIs have runnable examples
- **All** crate-level docs have examples
- **All** doc examples compile and run

## Running Doc Tests

### All Workspace Members

```bash
# Run all doc tests
cargo test --doc --all

# With all features
cargo test --doc --all --all-features

# Specific crate
cargo test --doc -p armature-core
```

### Using the Script

```bash
# Run doc tests for all members
./scripts/test-docs.sh
```

### In GitHub Actions

```yaml
- name: Run documentation tests
  run: cargo test --doc --all --all-features
```

## Common Patterns

### Result Types

```rust
/// # Examples
///
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let result = fallible_operation()?;
/// assert_eq!(result, "success");
/// # Ok(())
/// # }
/// ```
pub fn fallible_operation() -> Result<String, Error> {
    Ok("success".to_string())
}
```

### Async Functions

```rust
/// # Examples
///
/// ```
/// # tokio_test::block_on(async {
/// let data = fetch_data().await?;
/// assert!(!data.is_empty());
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// # });
/// ```
pub async fn fetch_data() -> Result<Vec<u8>, Error> {
    Ok(vec![1, 2, 3])
}
```

### With Dependencies

```rust
/// # Examples
///
/// ```
/// use armature_core::{Application, HttpRequest, HttpResponse};
/// use armature_macro::get;
///
/// #[get("/hello")]
/// async fn hello(_req: HttpRequest) -> Result<HttpResponse, Error> {
///     Ok(HttpResponse::ok().with_body(b"Hello!".to_vec()))
/// }
/// ```
```

## Troubleshooting

### "cannot find type X in this scope"

**Problem:** Missing import in example.

**Solution:** Add all required imports:

```rust
/// ```
/// use armature_core::HttpRequest;  // ✅ Add this
/// use armature_core::HttpResponse; // ✅ And this
///
/// let response = HttpResponse::ok();
/// ```
```

### "async block yields a value but never gets executed"

**Problem:** Async code without runtime.

**Solution:** Use `tokio_test::block_on`:

```rust
/// ```
/// # tokio_test::block_on(async {  // ✅ Add this
/// let result = async_function().await?;
/// # Ok::<(), Box<dyn std::error::Error>>(())  // ✅ And this
/// # });  // ✅ And this
/// ```
```

### "error: cannot borrow as mutable"

**Problem:** Example doesn't show mutable binding.

**Solution:** Show the correct usage:

```rust
/// ```
/// let mut config = Config::new();  // ✅ Show mut
/// config.set_option("value");
/// ```
```

## Best Practices

### DO

✅ Test every public API
✅ Show realistic examples
✅ Include error handling
✅ Hide boilerplate with `#`
✅ Use `no_run` for resource-intensive examples
✅ Keep examples simple and focused

### DON'T

❌ Use `ignore` for real code
❌ Write examples that can break
❌ Omit necessary imports
❌ Show only happy path
❌ Make examples too complex

## Coverage Report

Check doc test coverage:

```bash
# Run with verbose output
cargo test --doc --all -- --nocapture

# Count doc tests
cargo test --doc --all 2>&1 | grep "test result"

# Generate coverage report
cargo tarpaulin --doc --all
```

## CI/CD Integration

### GitHub Actions Workflow

```yaml
name: Documentation Tests

on: [push, pull_request]

jobs:
  doc-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable

      - name: Run doc tests
        run: cargo test --doc --all --all-features

      - name: Check doc coverage
        run: ./scripts/test-docs.sh
```

## Summary

**Key Principles:**

1. **Every public API has an example**
2. **Examples are tested automatically**
3. **Hidden lines keep examples clean**
4. **Attributes handle edge cases**
5. **Documentation is code quality**

**Testing is Documentation! Document with Tests!** 📚✅