Release/v0.6.0 #20

Merged
umpire274 merged 12 commits from release/v0.6.0 into main 2026-04-27 23:37:27 +02:00
umpire274 commented 2026-04-27 23:25:31 +02:00 (Migrated from github.com)

🧱 Full internal refactor — v0.6.0

Summary

Complete restructuring of the source tree into single-responsibility modules.
No user-facing behaviour changes — all commands, flags and output are identical to v0.5.1.


Motivation

The codebase had grown organically with several design issues:

  • utils/mod.rs was a 155-line monolith mixing verbose flags, print helpers, log and import utilities
  • models/book.rs mixed pure data with tabled / i18n presentation logic
  • commands/add.rs was an 18-line dead wrapper over handle_add_book()
  • create_schema() was duplicated in three separate files
  • lib.rs used blanket pub use module::* glob re-exports, making the public API opaque
  • run_migrations() was called twice at startup
  • The dead Commands enum in cli/mod.rs covered only 3 of 8 commands and was never used by dispatch

Changes by phase

Phase 1 — utils/ monolith → focused submodules

New file Responsibility
utils/verbose.rs VERBOSE static, set_verbose(), is_verbose()
utils/print.rs icons module + print_ok/err/warn/info()
utils/log.rs now_str(), write_log()
utils/import_helpers.rs open_import_file(), handle_import_result()
utils/mod.rs Aggregator with explicit pub use only

Phase 2 — CLI concerns separated

  • cli/fields.rsEDITABLE_FIELDS moved from utils/ (it is a CLI concern, not a generic utility)
  • cli/mod.rs — dead Commands enum removed
  • commands/config.rshandle_config(&Commands)handle_config(init, print, edit, editor) (explicit params, no enum dependency)

Phase 3 — Data model separated from presentation

  • models/book.rs — pure Book struct + from_row() + Serde; no tabled / i18n dependency
  • models/display.rs (new)BookFull, BookShort with Tabled implementations and localised column headers

Phase 4 — db/ module consolidation

Old New Reason
db/load_db.rs db/connection.rs Clearer name for DB connection management
db/migrate_db.rs db/migrations.rs Clearer name for migration logic
db/search.rs absorbed into db/books.rs search_books() belongs with book operations

Phase 5 — commands/ dead code removal

  • commands/add.rs deleted — dispatch already calls handle_add_book() directly (dead wrapper)
  • commands/list.rsrow_to_book() simplified to delegate to Book::from_row() + ISBN hyphen formatting only
  • commands/db.rs — local create_schema() removed; replaced by db::connection::ensure_schema() (single source of truth)

Phase 6 — lib.rs explicit public API

Removed all glob pub use module::* re-exports. Replaced with a minimal, explicit surface:

pub use config::{AppConfig, load_or_init};
pub use db::{init_db, start_db};
pub use models::Book;
pub use i18n::{load_language, tr, tr_s, tr_with};

All internal modules updated to use full crate::x::y import paths.
main.rs: removed duplicate run_migrations() call (already run inside start_db()).


Documentation

STRUCTURE.md added — full map of every source file with single-responsibility description, design rules table and explicit public API surface
CHANGELOG.md[0.6.0] entry added
README.md — "New in v0.6.0" section, updated project structure tree, corrected development notes and public API examples
Cargo.toml — version bumped 0.5.10.6.0


Testing

cargo fmt --all -- --check        ✅
cargo clippy --all-targets \
  --all-features -- -D warnings   ✅
cargo test --all                  ✅  (8 unit + 5 doctests, all green)

All existing integration tests pass unchanged.


Commits

81b573a  docs: update CHANGELOG, README and STRUCTURE for v0.6.0
64ae0a7  docs: add STRUCTURE.md with post-refactor module layout
51e97d6  refactor(lib): replace glob re-exports with explicit public API
da38009  refactor(commands): remove wrapper, deduplicate schema/row_to_book
c191f6c  refactor(db): rename modules, absorb search into books
1ddc61a  refactor(models): separate data model from presentation layer
9408139  refactor(cli): move EDITABLE_FIELDS, remove dead Commands enum
064b6ec  refactor(utils): split monolithic mod.rs into focused submodules
## 🧱 Full internal refactor — v0.6.0 ### Summary Complete restructuring of the source tree into single-responsibility modules. **No user-facing behaviour changes** — all commands, flags and output are identical to v0.5.1. --- ### Motivation The codebase had grown organically with several design issues: - `utils/mod.rs` was a 155-line monolith mixing verbose flags, print helpers, log and import utilities - `models/book.rs` mixed pure data with `tabled` / `i18n` presentation logic - `commands/add.rs` was an 18-line dead wrapper over `handle_add_book()` - `create_schema()` was duplicated in three separate files - `lib.rs` used blanket `pub use module::*` glob re-exports, making the public API opaque - `run_migrations()` was called twice at startup - The dead `Commands` enum in `cli/mod.rs` covered only 3 of 8 commands and was never used by dispatch --- ### Changes by phase #### Phase 1 — `utils/` monolith → focused submodules | New file | Responsibility | |---|---| | `utils/verbose.rs` | `VERBOSE` static, `set_verbose()`, `is_verbose()` | | `utils/print.rs` | `icons` module + `print_ok/err/warn/info()` | | `utils/log.rs` | `now_str()`, `write_log()` | | `utils/import_helpers.rs` | `open_import_file()`, `handle_import_result()` | | `utils/mod.rs` | Aggregator with explicit `pub use` only | #### Phase 2 — CLI concerns separated - `cli/fields.rs` — `EDITABLE_FIELDS` moved from `utils/` (it is a CLI concern, not a generic utility) - `cli/mod.rs` — dead `Commands` enum removed - `commands/config.rs` — `handle_config(&Commands)` → `handle_config(init, print, edit, editor)` (explicit params, no enum dependency) #### Phase 3 — Data model separated from presentation - `models/book.rs` — pure `Book` struct + `from_row()` + Serde; **no** `tabled` / `i18n` dependency - `models/display.rs` *(new)* — `BookFull`, `BookShort` with `Tabled` implementations and localised column headers #### Phase 4 — `db/` module consolidation | Old | New | Reason | |---|---|---| | `db/load_db.rs` | `db/connection.rs` | Clearer name for DB connection management | | `db/migrate_db.rs` | `db/migrations.rs` | Clearer name for migration logic | | `db/search.rs` | absorbed into `db/books.rs` | `search_books()` belongs with book operations | #### Phase 5 — `commands/` dead code removal - `commands/add.rs` deleted — dispatch already calls `handle_add_book()` directly (dead wrapper) - `commands/list.rs` — `row_to_book()` simplified to delegate to `Book::from_row()` + ISBN hyphen formatting only - `commands/db.rs` — local `create_schema()` removed; replaced by `db::connection::ensure_schema()` (single source of truth) #### Phase 6 — `lib.rs` explicit public API Removed all glob `pub use module::*` re-exports. Replaced with a minimal, explicit surface: ```rust pub use config::{AppConfig, load_or_init}; pub use db::{init_db, start_db}; pub use models::Book; pub use i18n::{load_language, tr, tr_s, tr_with}; ``` All internal modules updated to use full `crate::x::y` import paths. `main.rs`: removed duplicate `run_migrations()` call (already run inside `start_db()`). --- ### Documentation `STRUCTURE.md` added — full map of every source file with single-responsibility description, design rules table and explicit public API surface `CHANGELOG.md` — `[0.6.0]` entry added `README.md` — "New in v0.6.0" section, updated project structure tree, corrected development notes and public API examples `Cargo.toml` — version bumped `0.5.1` → `0.6.0` --- ### Testing ``` cargo fmt --all -- --check ✅ cargo clippy --all-targets \ --all-features -- -D warnings ✅ cargo test --all ✅ (8 unit + 5 doctests, all green) ``` All existing integration tests pass unchanged. --- ### Commits ``` 81b573a docs: update CHANGELOG, README and STRUCTURE for v0.6.0 64ae0a7 docs: add STRUCTURE.md with post-refactor module layout 51e97d6 refactor(lib): replace glob re-exports with explicit public API da38009 refactor(commands): remove wrapper, deduplicate schema/row_to_book c191f6c refactor(db): rename modules, absorb search into books 1ddc61a refactor(models): separate data model from presentation layer 9408139 refactor(cli): move EDITABLE_FIELDS, remove dead Commands enum 064b6ec refactor(utils): split monolithic mod.rs into focused submodules ```
chatgpt-codex-connector[bot] (Migrated from github.com) reviewed 2026-04-27 23:29:13 +02:00
chatgpt-codex-connector[bot] (Migrated from github.com) left a comment

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 81b573a77e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

### 💡 Codex Review Here are some automated review suggestions for this pull request. **Reviewed commit:** `81b573a77e` <details> <summary>ℹ️ About Codex in GitHub</summary> <br/> [Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". </details>
chatgpt-codex-connector[bot] (Migrated from github.com) commented 2026-04-27 23:29:13 +02:00

P1 Badge Parse non-RFC3339 added_at values in list rows

row_to_book now calls Book::from_row, which loads added_at as Option<DateTime<Utc>>. In rusqlite, that conversion expects RFC3339 or unix timestamps, but this codebase writes added_at via SQLite CURRENT_TIMESTAMP (YYYY-MM-DD HH:MM:SS), so listing can now fail with a row conversion error instead of rendering results. The previous mapper explicitly parsed SQLite timestamp formats and degraded to None, so this introduces a regression for databases containing default timestamp strings.

Useful? React with 👍 / 👎.

**<sub><sub>![P1 Badge](https://img.shields.io/badge/P1-orange?style=flat)</sub></sub> Parse non-RFC3339 `added_at` values in list rows** `row_to_book` now calls `Book::from_row`, which loads `added_at` as `Option<DateTime<Utc>>`. In rusqlite, that conversion expects RFC3339 or unix timestamps, but this codebase writes `added_at` via SQLite `CURRENT_TIMESTAMP` (`YYYY-MM-DD HH:MM:SS`), so listing can now fail with a row conversion error instead of rendering results. The previous mapper explicitly parsed SQLite timestamp formats and degraded to `None`, so this introduces a regression for databases containing default timestamp strings. Useful? React with 👍 / 👎.
Sign in to join this conversation.
No description provided.