CurseTechnique/learning/walkthrough.md

124 lines
3.6 KiB
Markdown

# CurseTechnique Codebase Walkthrough
This document is a practical map of the app, aimed at learning-oriented Rust reading.
## 1. High-level architecture
The app uses a lightweight 4-layer layout:
1. `src/main.rs` - startup and route wiring
2. `src/handlers.rs` - HTTP handlers and input validation
3. `src/db.rs` - SQLite queries and data structs
4. `src/views.rs` - HTML rendering (server-side string rendering)
The goal is to keep each file focused and easy to read without adding extra frameworks.
## 2. Request flow (end-to-end)
Example: open `GET /day/2026-02-07`
1. Route is defined in `src/main.rs` and points to `handlers::show_day_entries`.
2. `show_day_entries` in `src/handlers.rs` validates the date path param.
3. It calls `db::fetch_day_entries` in `src/db.rs` to load rows from SQLite.
4. It passes those rows to `views::render_day_page` in `src/views.rs`.
5. The rendered HTML is returned to the browser.
Example: submit add-entry form `POST /day/{date}/add`
1. Route points to `handlers::create_entry`.
2. Handler validates date and form fields (`name`, `calories`).
3. Handler calls `db::insert_entry`.
4. Handler redirects back to `/day/{date}`.
## 3. File-by-file reading guide
## `src/main.rs`
Read this file first. It is intentionally small.
- Creates data directory and opens SQLite DB.
- Calls DB init/seed helpers.
- Builds Axum router.
- Starts Tokio TCP listener.
If you ever wonder "where is this endpoint connected?", this file is the source of truth.
## `src/handlers.rs`
This is the HTTP boundary.
Core concepts here:
- `AppState` holds shared DB connection behind `Arc<Mutex<Connection>>`.
- Each handler receives typed route/form data.
- Handlers do three steps:
1. Validate input
2. Call DB function
3. Return HTML or redirect
Useful helper functions:
- `validate_date` ensures `YYYY-MM-DD` format.
- `parse_entry_form_fields` validates `name` + `calories`.
- `month_bounds` computes first/next month boundaries.
## `src/db.rs`
This file contains all SQL.
Data structs:
- `FoodEntry` represents one row.
- `DaySummary` represents aggregated values for calendar cards.
Functions are split by intent:
- Setup: `init_db`, `seed_db_if_empty`
- Reads: `fetch_month_summaries`, `fetch_day_entries`
- Writes: `insert_entry`, `update_entry`, `delete_entry`
If behavior looks wrong (totals, filtering, ordering), start debugging here.
## `src/views.rs`
This file builds HTML strings for SSR.
- `render_calendar_page` renders `/`.
- `render_day_page` renders `/day/{date}`.
- Small helpers reduce clutter:
- `render_day_card`
- `render_entry_rows`
- `entry_count_label`
- `escape_html`
Important: `escape_html` is used when rendering user-provided food names.
## 4. Key Rust patterns used
- `Result<T, E>` for explicit error handling.
- `?` operator to propagate errors.
- `Arc<Mutex<_>>` for shared mutable state across async handlers.
- Simple structs over tuple-heavy values for readability (`DaySummary`).
- Module organization (`mod db; mod handlers; mod views;`) to keep files focused.
## 5. How to add a feature safely
Use this checklist:
1. Add/adjust SQL function in `db.rs`.
2. Add or update handler logic in `handlers.rs`.
3. Update route wiring in `main.rs` if endpoint path changes.
4. Update HTML output/forms in `views.rs`.
5. Run:
- `cargo fmt`
- `cargo check`
## 6. Suggested beginner exercises
1. Add a "notes" text column to food entries.
2. Show count of entries in the day header.
3. Add confirmation step on delete (simple query param or separate page).
4. Add a helper in handlers to prevent editing future dates.
These exercises touch all 4 layers and are great practice for understanding the whole flow.