|
| 1 | +# RustAPI Copilot Instructions |
| 2 | + |
| 3 | +## Architecture Overview |
| 4 | + |
| 5 | +RustAPI uses a **layered facade architecture**. Users import only `rustapi-rs` which re-exports types from internal crates: |
| 6 | + |
| 7 | +``` |
| 8 | +rustapi-rs (facade) → rustapi-core, rustapi-macros, rustapi-openapi, rustapi-validate |
| 9 | + → Optional: rustapi-extras, rustapi-toon, rustapi-ws, rustapi-view |
| 10 | +``` |
| 11 | + |
| 12 | +**Key principle:** "API surface is ours, engines can change." Internal dependencies (hyper, tokio, matchit) are wrapped—never exposed to users. |
| 13 | + |
| 14 | +## Crate Responsibilities |
| 15 | + |
| 16 | +| Crate | Purpose | |
| 17 | +|-------|---------| |
| 18 | +| `rustapi-rs` | Public facade, re-exports, feature flags | |
| 19 | +| `rustapi-core` | HTTP engine, routing (matchit), extractors, `RustApi` builder | |
| 20 | +| `rustapi-macros` | `#[rustapi_rs::get/post/...]`, `#[rustapi_rs::schema]` | |
| 21 | +| `rustapi-openapi` | OpenAPI spec generation, Swagger UI | |
| 22 | +| `rustapi-validate` | `ValidatedJson<T>`, validator integration | |
| 23 | +| `rustapi-extras` | JWT (`jwt`), CORS (`cors`), rate-limit (`rate-limit`) | |
| 24 | +| `rustapi-toon` | LLM-optimized TOON format (`toon`) | |
| 25 | +| `rustapi-ws` | WebSocket support (`ws`) | |
| 26 | +| `rustapi-view` | Tera templates (`view`) | |
| 27 | + |
| 28 | +## Code Patterns |
| 29 | + |
| 30 | +### Handler Pattern (5 lines philosophy) |
| 31 | +```rust |
| 32 | +#[rustapi_rs::get("/users/{id}")] |
| 33 | +async fn get_user(Path(id): Path<u64>) -> Json<User> { |
| 34 | + Json(User { id, name: "Alice".into() }) |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +### Zero-Config Auto-Registration |
| 39 | +Use `RustApi::auto()` to auto-discover `#[rustapi_rs::get/post/...]` decorated handlers. Manual: `RustApi::new().route(...)`. |
| 40 | + |
| 41 | +### Extractors implement `FromRequest`/`FromRequestParts` |
| 42 | +- `Json<T>`, `Path<T>`, `Query<T>`, `State<T>`, `Body`, `Headers`, `ValidatedJson<T>` |
| 43 | +- Each extracts from request and can fail with `ApiError` |
| 44 | + |
| 45 | +### Responses implement `IntoResponse` |
| 46 | +- `Json<T>`, `Created<T>`, `NoContent`, `Html<T>`, `Redirect`, `&'static str` |
| 47 | +- Tuples: `(StatusCode, T)`, `(StatusCode, [(header, value)], T)` |
| 48 | + |
| 49 | +## Development Commands |
| 50 | + |
| 51 | +```bash |
| 52 | +# Build everything |
| 53 | +cargo build --workspace --all-features |
| 54 | + |
| 55 | +# Test everything |
| 56 | +cargo test --workspace --all-features |
| 57 | + |
| 58 | +# Format (required before PR) |
| 59 | +cargo fmt --all |
| 60 | + |
| 61 | +# Lint (must pass -D warnings) |
| 62 | +cargo clippy --workspace --all-features -- -D warnings |
| 63 | + |
| 64 | +# Run examples |
| 65 | +cargo run -p hello-world |
| 66 | +cargo run -p crud-api |
| 67 | +cargo run -p auth-api |
| 68 | +``` |
| 69 | + |
| 70 | +## Publishing (Dependency Order) |
| 71 | + |
| 72 | +Crates must be published in order due to dependencies: |
| 73 | +1. `rustapi-macros` → 2. `rustapi-validate` → 3. `rustapi-openapi` → 4. `rustapi-core` |
| 74 | +5. `rustapi-extras` → 6. `rustapi-toon` → 7. `rustapi-ws` → 8. `rustapi-view` |
| 75 | +9. `rustapi-rs` → 10. `cargo-rustapi` |
| 76 | + |
| 77 | +Use `scripts/smart_publish.ps1` for automated version-aware publishing. |
| 78 | + |
| 79 | +## Key Implementation Details |
| 80 | + |
| 81 | +### Router: Uses `matchit` radix tree |
| 82 | +- Path params: `{id}` in macros → `:id` internally |
| 83 | +- Route conflicts detected at startup |
| 84 | + |
| 85 | +### Handler trait with type erasure |
| 86 | +```rust |
| 87 | +pub trait Handler<T>: Clone + Send + Sync + 'static { |
| 88 | + fn call(self, req: Request) -> impl Future<Output = Response> + Send; |
| 89 | +} |
| 90 | +``` |
| 91 | +Implemented for functions with 0-5 extractors. `BoxedHandler` erases types for router storage. |
| 92 | + |
| 93 | +### Error Handling |
| 94 | +```rust |
| 95 | +pub struct ApiError { status, error_type, message, error_id, fields } |
| 96 | +``` |
| 97 | +- Use `ApiError::not_found()`, `bad_request()`, etc. |
| 98 | +- Production (`RUSTAPI_ENV=production`) masks internal errors |
| 99 | + |
| 100 | +### Feature Flags |
| 101 | +When adding features, gate with `#[cfg(feature = "...")]` and update `rustapi-rs/Cargo.toml`. |
| 102 | + |
| 103 | +## File Locations |
| 104 | + |
| 105 | +- **Core types:** `crates/rustapi-core/src/{extract,response,handler,router,app}.rs` |
| 106 | +- **Macros:** `crates/rustapi-macros/src/lib.rs` |
| 107 | +- **Examples:** `examples/*/src/main.rs` |
| 108 | +- **Tests:** `crates/*/tests/` or inline `#[cfg(test)]` |
| 109 | +- **Docs:** `docs/{ARCHITECTURE,FEATURES,GETTING_STARTED}.md` |
0 commit comments