Add image infrastructure, API, and detail page integration:
- EntityImage domain model with ImageRepository trait
- SQLite storage for images and thumbnails as BLOBs
- Image processing with data URL decoding and thumbnail generation
- REST API: upload, get, delete, thumbnail at /{entity_type}/{id}/image
- resolve_image_url helper for image fallback chains
- image-upload web component for direct upload on detail pages
- Image display with vignette overlay and lightbox viewer
- Template macros: image_thumbnail, readonly_image, lightbox_script
- All 7 detail pages updated with image thumbnails
- Brew images fall back to roast; cup images fall back to cafe then roast
- Delete handler macro extended with optional image cleanup
99 lines
3.1 KiB
TOML
99 lines
3.1 KiB
TOML
[package]
|
|
name = "brewlog"
|
|
version = "1.0.0"
|
|
edition = "2024"
|
|
|
|
[dependencies]
|
|
anyhow = "1.0"
|
|
async-trait = "0.1"
|
|
axum = { version = "0.8", features = ["macros"] }
|
|
askama = "0.15"
|
|
base64 = "0.22"
|
|
chrono = { version = "0.4", features = ["serde", "clock"] }
|
|
clap = { version = "4.5", features = ["derive", "env"] }
|
|
dotenvy = "0.15"
|
|
image = { version = "0.25", default-features = false, features = ["jpeg", "png", "webp"] }
|
|
isocountry = "0.3"
|
|
open = "5"
|
|
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "gzip"] }
|
|
serde = { version = "1.0", features = ["derive"] }
|
|
serde_json = "1.0"
|
|
rand = "0.8"
|
|
sha2 = "0.10"
|
|
sqlx = { version = "0.7", default-features = false, features = [
|
|
"runtime-tokio",
|
|
"tls-rustls",
|
|
"macros",
|
|
"chrono",
|
|
"sqlite",
|
|
"migrate",
|
|
] }
|
|
thiserror = "1.0"
|
|
tokio = { version = "1.38", features = ["rt-multi-thread", "macros", "signal"] }
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "fmt"] }
|
|
tower = "0.5"
|
|
tower-cookies = "0.11"
|
|
tower-http = { version = "0.6", features = ["compression-gzip", "limit", "set-header", "trace"] }
|
|
slug = "0.1.6"
|
|
url = "2"
|
|
uuid = { version = "1", features = ["v4"] }
|
|
webauthn-rs = { version = "0.5", features = ["danger-allow-state-serialisation"] }
|
|
webauthn-rs-proto = "0.5"
|
|
|
|
[features]
|
|
e2e = []
|
|
|
|
[dev-dependencies]
|
|
portpicker = "0.1"
|
|
reqwest = { version = "0.12", default-features = false, features = ["blocking", "cookies", "rustls-tls"] }
|
|
tempfile = "3.8"
|
|
once_cell = "1.19"
|
|
webauthn-authenticator-rs = { version = "0.5", features = ["softpasskey"] }
|
|
wiremock = "0.6"
|
|
paste = "1.0.15"
|
|
thirtyfour = "0.36"
|
|
|
|
[[test]]
|
|
name = "cli"
|
|
path = "tests/cli/main.rs"
|
|
harness = true
|
|
|
|
[profile.release]
|
|
lto = "thin"
|
|
strip = true
|
|
|
|
[profile.test]
|
|
# Run CLI tests serially to share single server instance
|
|
opt-level = 0
|
|
|
|
[[test]]
|
|
name = "server"
|
|
path = "tests/server/main.rs"
|
|
harness = true
|
|
|
|
[[test]]
|
|
name = "e2e"
|
|
path = "tests/e2e/main.rs"
|
|
harness = true
|
|
required-features = ["e2e"]
|
|
|
|
[lints.clippy]
|
|
# Enable pedantic lints with lower priority so individual allows take precedence
|
|
pedantic = { level = "warn", priority = -1 }
|
|
|
|
# Pedantic lints to disable (too noisy or not applicable)
|
|
missing_errors_doc = "allow" # Would require extensive doc changes
|
|
missing_panics_doc = "allow" # Would require extensive doc changes
|
|
module_name_repetitions = "allow" # Common pattern in domain types (e.g., RoasterId in roasters)
|
|
must_use_candidate = "allow" # Too aggressive for this codebase
|
|
return_self_not_must_use = "allow" # Builder methods returning Self are common
|
|
needless_pass_by_value = "allow" # Generic T: ToString pattern and consumed value types
|
|
cast_possible_truncation = "allow" # Pagination values won't exceed u32 in practice
|
|
cast_sign_loss = "allow" # Database counts are non-negative
|
|
|
|
# Cherry-picked restriction lints (production safety)
|
|
dbg_macro = "deny" # Prevent debug macros in production
|
|
todo = "warn" # Flag TODOs for attention
|
|
unwrap_used = "warn" # Flag unwrap() for review; allow where justified
|
|
expect_used = "warn" # Flag expect() for review; allow where justified
|