diff --git a/docs/.agent/docs_coverage.md b/docs/.agent/docs_coverage.md index 6fea8992..6783a49a 100644 --- a/docs/.agent/docs_coverage.md +++ b/docs/.agent/docs_coverage.md @@ -18,3 +18,6 @@ | Job Queue | `crates/rustapi_jobs.md` | `rustapi-jobs` | OK | | **Learning** | | | | | Structured Path | `learning/curriculum.md` | N/A | OK | +| **Recipes** | | | | +| File Uploads | `recipes/file_uploads.md` | `rustapi-core` | OK | +| Deployment | `recipes/deployment.md` | `cargo-rustapi` | OK | diff --git a/docs/.agent/last_run.json b/docs/.agent/last_run.json index 78a69dc6..5c79a4cf 100644 --- a/docs/.agent/last_run.json +++ b/docs/.agent/last_run.json @@ -1,5 +1,5 @@ { "last_processed_ref": "v0.1.335", - "date": "2025-02-19", - "notes": "Initial run to sync version and improve cookbook" + "date": "2025-02-21", + "notes": "Enhanced learning path with quizzes and capstones. Fixed file upload recipe. Added deployment docs tracking." } diff --git a/docs/.agent/run_report_2025-02-21.md b/docs/.agent/run_report_2025-02-21.md new file mode 100644 index 00000000..6316a451 --- /dev/null +++ b/docs/.agent/run_report_2025-02-21.md @@ -0,0 +1,28 @@ +# Run Report: 2025-02-21 + +## 1. Version Detection +- **Detected Code Version**: `0.1.335` (based on `Cargo.toml`) +- **Last Processed Version**: `v0.1.335` +- **Status**: Version sync complete. Proceeding with Continuous Improvement phase. + +## 2. Changes Since Last Run +- No version bump detected. +- Focus: Improving Learning Path and Cookbook clarity. + +## 3. Documentation Updates +- **Cookbook**: + - `recipes/file_uploads.md`: Fixed unused variable warning and clarified streaming logic. + - `learning/README.md`: Marked `file-upload` recipe as available (removed "coming soon"). +- **Learning Path**: + - `learning/curriculum.md`: + - Added comprehensive "Knowledge Checks" to each module. + - Added "Capstone Project" suggestions for each phase. + - Updated "Production Readiness" module to include `cargo rustapi deploy`. + +## 4. Improvements +- Enhanced the structured curriculum with more interactive elements (quizzes and projects) to better guide learners. +- Verified and fixed code snippets in the File Upload recipe. + +## 5. Open Questions / TODOs +- [ ] Create a dedicated `file-upload` example project in `rustapi-rs-examples` (outside scope of this agent, but recommended). +- [ ] Add more deep-dive recipes for advanced `rustapi-jobs` patterns (e.g., custom backends). diff --git a/docs/cookbook/src/learning/README.md b/docs/cookbook/src/learning/README.md index 302c2cb4..7efe7f2a 100644 --- a/docs/cookbook/src/learning/README.md +++ b/docs/cookbook/src/learning/README.md @@ -249,7 +249,7 @@ Each example includes: | [JWT Authentication](../recipes/jwt_auth.md) | `auth-api` | | [CSRF Protection](../recipes/csrf_protection.md) | `auth-api`, `middleware-chain` | | [Database Integration](../recipes/db_integration.md) | `sqlx-crud`, `event-sourcing` | -| [File Uploads](../recipes/file_uploads.md) | `file-upload` (coming soon) | +| [File Uploads](../recipes/file_uploads.md) | `file-upload` (planned) | | [Custom Middleware](../recipes/custom_middleware.md) | `middleware-chain` | | [Real-time Chat](../recipes/websockets.md) | `websocket` | | [Production Tuning](../recipes/high_performance.md) | `microservices-advanced` | diff --git a/docs/cookbook/src/learning/curriculum.md b/docs/cookbook/src/learning/curriculum.md index dd6450fb..8a50fa7d 100644 --- a/docs/cookbook/src/learning/curriculum.md +++ b/docs/cookbook/src/learning/curriculum.md @@ -13,6 +13,11 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u - **Expected Output:** A running server that responds to `GET /` with "Hello World". - **Pitfalls:** Not enabling `tokio` features if setting up manually. +#### 🧠 Knowledge Check +1. What command scaffolds a new RustAPI project? +2. Which feature flag is required for the async runtime? +3. Where is the main entry point of the application typically located? + ### Module 2: Routing & Handlers - **Prerequisites:** Module 1. - **Reading:** [Handlers & Extractors](../concepts/handlers.md). @@ -20,6 +25,11 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u - **Expected Output:** Endpoints that return static JSON data. - **Pitfalls:** Forgetting to register routes in `main.rs` if not using auto-discovery. +#### 🧠 Knowledge Check +1. Which macro is used to define a GET handler? +2. How do you return a JSON response from a handler? +3. What is the return type of a typical handler function? + ### Module 3: Extractors - **Prerequisites:** Module 2. - **Reading:** [Handlers & Extractors](../concepts/handlers.md). @@ -27,6 +37,22 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u - **Expected Output:** `GET /users/{id}` returns the ID. `POST /users` echoes the JSON body. - **Pitfalls:** Consuming the body twice (e.g., using `Json` and `Body` in the same handler). +#### 🧠 Knowledge Check +1. Which extractor is used for URL parameters like `/users/:id`? +2. Which extractor parses the request body as JSON? +3. Can you use multiple extractors in a single handler? + +### 🏆 Phase 1 Capstone: "The Todo List API" +**Objective:** Build a simple in-memory Todo List API. +**Requirements:** +- `GET /todos`: List all todos. +- `POST /todos`: Create a new todo. +- `GET /todos/:id`: Get a specific todo. +- `DELETE /todos/:id`: Delete a todo. +- Use `State` to store the list in a `Mutex>`. + +--- + ## Phase 2: Core Development **Goal:** Add real logic, validation, and documentation. @@ -38,6 +64,11 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u - **Expected Output:** A stateful API where POST adds a user and GET retrieves it (in-memory). - **Pitfalls:** Using `std::sync::Mutex` instead of `tokio::sync::Mutex` in async code (though `std` is fine for simple data). +#### 🧠 Knowledge Check +1. How do you inject global state into the application? +2. Which extractor retrieves the application state? +3. Why should you use `Arc` for shared state? + ### Module 5: Validation - **Prerequisites:** Module 4. - **Reading:** [Validation](../crates/rustapi_validation.md). @@ -45,6 +76,11 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u - **Expected Output:** Requests with invalid email or short password return `422 Unprocessable Entity`. - **Pitfalls:** Forgetting to add `#[validate]` attributes to struct fields. +#### 🧠 Knowledge Check +1. Which trait must a struct implement to be validatable? +2. What HTTP status code is returned on validation failure? +3. How do you combine JSON extraction and validation? + ### Module 6: OpenAPI & HATEOAS - **Prerequisites:** Module 5. - **Reading:** [OpenAPI](../crates/rustapi_openapi.md), [Pagination Recipe](../recipes/pagination.md). @@ -52,6 +88,21 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u - **Expected Output:** Swagger UI at `/docs` showing full schema. Paginated responses with `_links`. - **Pitfalls:** Using types that don't implement `Schema` (like raw `serde_json::Value`) inside response structs. +#### 🧠 Knowledge Check +1. What does `#[derive(Schema)]` do? +2. Where is the Swagger UI served by default? +3. What is HATEOAS and why is it useful? + +### 🏆 Phase 2 Capstone: "The Secure Blog Engine" +**Objective:** Enhance the Todo API into a Blog Engine. +**Requirements:** +- Add `Post` resource with title, content, and author. +- Validate that titles are not empty and content is at least 10 chars. +- Add pagination to `GET /posts`. +- Enable Swagger UI to visualize the API. + +--- + ## Phase 3: Advanced Features **Goal:** Security, Real-time, and Production readiness. @@ -63,6 +114,11 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u - **Expected Output:** Protected routes return `401 Unauthorized` without a valid token. - **Pitfalls:** Hardcoding secrets. Not checking token expiration. +#### 🧠 Knowledge Check +1. What is the role of the `AuthUser` extractor? +2. How do you protect a route with JWT? +3. Where should you store the JWT secret? + ### Module 8: WebSockets & Real-time - **Prerequisites:** Phase 2. - **Reading:** [WebSockets Recipe](../recipes/websockets.md). @@ -70,23 +126,34 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u - **Expected Output:** Multiple clients connected via WS receiving messages in real-time. - **Pitfalls:** Blocking the WebSocket loop with long-running synchronous tasks. -### Module 9: Production Readiness +#### 🧠 Knowledge Check +1. How do you upgrade an HTTP request to a WebSocket connection? +2. Can you share state between HTTP handlers and WebSocket handlers? +3. What happens if a WebSocket handler panics? + +### Module 9: Production Readiness & Deployment - **Prerequisites:** Phase 3. -- **Reading:** [Production Tuning](../recipes/high_performance.md), [Resilience](../recipes/resilience.md). -- **Task:** Add `RateLimitLayer`, `CompressionLayer`, and `TimeoutLayer`. -- **Expected Output:** An API that handles load gracefully and rejects abuse. +- **Reading:** [Production Tuning](../recipes/high_performance.md), [Resilience](../recipes/resilience.md), [Deployment](../recipes/deployment.md). +- **Task:** + 1. Add `RateLimitLayer`, `CompressionLayer`, and `TimeoutLayer`. + 2. Use `cargo rustapi deploy docker` to generate a Dockerfile. +- **Expected Output:** A resilient API ready for deployment. - **Pitfalls:** Setting timeouts too low for slow operations. -## Knowledge Check +#### 🧠 Knowledge Check +1. Why is rate limiting important? +2. What command generates a production Dockerfile? +3. How do you enable compression for responses? + +### 🏆 Phase 3 Capstone: "The Real-Time Collaboration Tool" +**Objective:** Build a real-time collaborative note-taking app. +**Requirements:** +- **Auth:** Users must log in to edit notes. +- **Real-time:** Changes to a note are broadcast to all viewers via WebSockets. +- **Resilience:** Rate limit API requests to prevent abuse. +- **Deployment:** specify a `Dockerfile` for the application. -1. **Q:** Which extractor consumes the request body? - * **A:** `Json`, `ValidatedJson`, `Body`. -2. **Q:** How do you share a database connection pool across handlers? - * **A:** Use the `State` extractor and initialize it in `RustApi::new().with_state(state)`. -3. **Q:** What is the purpose of `derive(Schema)`? - * **A:** It generates the OpenAPI schema definition for the struct, allowing it to be documented in Swagger UI. -4. **Q:** How do you handle pagination links automatically? - * **A:** Return `ResourceCollection` and call `.with_pagination()`. +--- ## Next Steps diff --git a/docs/cookbook/src/recipes/file_uploads.md b/docs/cookbook/src/recipes/file_uploads.md index e706efed..74002779 100644 --- a/docs/cookbook/src/recipes/file_uploads.md +++ b/docs/cookbook/src/recipes/file_uploads.md @@ -39,10 +39,8 @@ async fn upload_file(mut multipart: Multipart) -> Result { let mut file = File::create(&path).await.map_err(|e| ApiError::InternalServerError(e.to_string()))?; // Write stream to file chunk by chunk - let mut field_bytes = field; // field implements Stream itself (in some drivers) or we read chunks - // In RustAPI/Axum multipart, `field.bytes()` loads the whole field into memory. - // To stream, we use `field.chunk()`: + // To stream efficiently, we use `field.chunk()`: while let Some(chunk) = field.chunk().await.map_err(|_| ApiError::BadRequest)? { file.write_all(&chunk).await.map_err(|e| ApiError::InternalServerError(e.to_string()))?;