Skip to content

Release/v0.6.0#20

Merged
umpire274 merged 12 commits into
mainfrom
release/v0.6.0
Apr 27, 2026
Merged

Release/v0.6.0#20
umpire274 merged 12 commits into
mainfrom
release/v0.6.0

Conversation

@umpire274

Copy link
Copy Markdown
Owner

🧱 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

Extract verbose, print, log and import_helpers into dedicated files.
Update mod.rs to declare all submodules and re-export symbols explicitly
(no more blanket glob re-exports inside utils).
- 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
All callers unchanged; public API surface identical.
…mands enum

- Create cli/fields.rs: EDITABLE_FIELDS is a CLI concern, not a generic utility
- Update cli/mod.rs: declare fields submodule, remove dead Commands enum
  (only 3 of 8 commands were represented, never used by dispatch)
- Update cli/args.rs, commands/edit_book.rs: import from crate::cli::fields
- Refactor commands/config.rs: replace Commands enum parameter with explicit
  bool args (init, print, edit, editor) - cleaner API, no enum dependency
- Update cli/dispatch.rs: call handle_config with direct bool params
- Remove utils/fields.rs (deleted)
- models/book.rs: pure data model only (Book struct + from_row + Serde)
  Remove tabled/i18n dependencies
- models/display.rs: new file with BookFull, BookShort and their Tabled
  implementations (presentation concern, depends on i18n)
- models/mod.rs: declare display submodule, re-export Book/BookFull/BookShort
- commands/list.rs: update imports to explicit paths
  (models::book::Book, models::display::{BookFull, BookShort})
- load_db.rs  → connection.rs  (clearer name for DB connection management)
- migrate_db.rs → migrations.rs (clearer name for migration logic)
- search.rs absorbed into books.rs: search_books() belongs with book operations
- db/mod.rs: update pub mod/use to new names, expose search_books from books
- main.rs: update direct reference db::migrate_db → db::migrations
- Old files removed: load_db.rs, migrate_db.rs, search.rs
… mapping

- Remove commands/add.rs: 18-line wrapper that just called handle_add_book().
  dispatch.rs already invokes handle_add_book() directly (dead code)
- commands/mod.rs: drop pub mod/use for removed add module
- commands/list.rs: simplify row_to_book() to delegate to Book::from_row()
  and only apply ISBN hyphen formatting on top; remove unused chrono imports
- commands/db.rs: replace inline create_schema() duplicate (tripled) with a
  call to db::connection::ensure_schema() - single source of truth for schema
…all internal imports

- lib.rs: remove pub use commands/config/db/i18n/models/utils::*
  Replace with explicit re-exports (AppConfig, load_or_init, init_db,
  start_db, Book, load_language, tr, tr_s, tr_with) - clear public API
- main.rs: remove duplicate run_migrations() call (already run in start_db)
- All internal modules now use explicit crate paths instead of crate root shortcuts:
  * utils/isbn.rs: crate::tr_with -> crate::i18n::tr_with
  * utils/table.rs: crate::{print_warn,tr} -> crate::utils/i18n explicit paths
  * commands/add_book.rs: normalize_isbn, is_verbose, print_* via explicit paths
  * commands/del_book.rs: print_*, write_log, tr_with via explicit paths
  * commands/edit_book.rs: lang_code_to_name, print_*, tr/tr_with explicit
  * commands/import.rs: Book from models, print_err from utils
  * commands/search_book.rs: print_warn from utils
  * commands/list.rs: normalize_isbn from utils::isbn
  * commands/db.rs: AppConfig, tr/tr_with, print_* all explicit
  * cli/dispatch.rs: AppConfig, commands, i18n all explicit
- tests/isbn_tests.rs: update import path to librius::utils::isbn
- utils/isbn.rs doctest: update example path to utils::isbn::normalize_isbn
Documents the full src/ tree after the 6-phase refactor:
- one-line description per file
- key design rules table
- explicit public API surface from lib.rs
CHANGELOG.md:
- Add [0.6.0] entry documenting all 6 refactor phases:
  utils/ split, cli/fields.rs, models/display.rs, db renames,
  commands cleanup, lib.rs explicit API, main.rs dedup
README.md:
- Replace 'New in v0.5.1' section with 'New in v0.6.0' refactor summary
- Update Project structure tree (connection.rs, migrations.rs,
  display.rs, utils submodules, etc.)
- Update Development notes: correct public API examples, remove stale
  glob-import example, add single-responsibility design rules
- Remove already-implemented items from Future roadmap
STRUCTURE.md:
- Amend table formatting for GitHub Markdown rendering
Cargo.toml:
- Bump version 0.5.1 -> 0.6.0
Cargo.lock:
- Regenerated after version bump

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/commands/list.rs
Closes #21
SQLite CURRENT_TIMESTAMP writes 'YYYY-MM-DD HH:MM:SS' (no timezone),
but rusqlite's built-in DateTime<Utc> deserialization expects RFC3339.
This caused a row conversion error on any database populated via the
default schema, making 'librius list' fail instead of rendering results.
Fix: read added_at as Option<String> and parse with a multi-format
fallback function (parse_sqlite_datetime), gracefully degrading to None
if no format matches — identical behaviour to the pre-refactor mapper.
Formats handled:
  1. RFC3339 with timezone  (2025-10-13T21:32:07+02:00)
  2. SQLite CURRENT_TIMESTAMP  (2025-10-13 21:32:07)
  3. SQLite CURRENT_TIMESTAMP with sub-seconds  (2025-10-13 21:32:07.123)
Tests added (tests/db_tests.rs):
  - test_from_row_parses_sqlite_current_timestamp  (regression case)
  - test_from_row_parses_rfc3339_timestamp
@umpire274
umpire274 merged commit f3c7c7e into main Apr 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant