librius 0.5.0

A personal library manager CLI written in Rust.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# Changelog

All notable changes to this project will be documented in this file.

## [0.5.0] - 2025-11-11

### 🧪 Added

- Introduced a **complete automated test suite** covering both database and CLI layers.
- Implemented `setup_temp_db()` utility for creating **temporary SQLite databases** in the system temp directory:
  - Windows → `%TEMP%\librius_test_*.db`
  - macOS / Linux → `/tmp/librius_test_*.db`
- Added **unit tests** for database insert and search operations.
- Added **integration tests** for:
  - CLI commands (`--help`, `search`, etc.) using `assert_cmd` and `predicates`.
  - Database schema and consistency validation.
  - ISBN normalization and formatting.
- All tests now use the **real production schema** for reliable, cross-platform testing.

---

### 🔧 Changed

- Performed a **modular refactor of the CLI** (`cli.rs``cli/` directory):
  - Split the monolithic `cli.rs` into three logical units:
    - `args.rs` — defines the full command tree and global flags.
    - `dispatch.rs` — routes parsed commands to their handlers.
    - `mod.rs` — re-exports and integrates the CLI components.
  - Improved code readability, testability, and long-term maintainability.
  - Prepared CLI for future integration with the `librius_core` crate and the GUI frontend.
- Simplified the internal command dispatch logic and aligned display order for consistent help output.

---

### 🧱 Internal

- Removed obsolete in-source test modules (`#[cfg(test)]`) from production files.
- Eliminated build and Clippy warnings by conditionally compiling test-only code.
- Verified complete cross-platform compatibility (Windows, macOS, Linux).
- Established the foundation for **multi-platform CI testing** planned for `v0.5.1`.

---

## [0.4.6] - 2025-11-11

### 🔧 Changed

- **Reorganized command index** in the CLI help output for better logical grouping and readability.  
  Commands are now displayed in a clearer order, following a structured hierarchy (Book commands, App commands, etc.).

- **Localized help section titles (`help_heading`)** across the entire CLI, including:
    - “Global options”
    - “List-specific options”
    - “Import-specific options”
    - “Export-specific options”
    - and other command-related help blocks

- Improved overall **consistency and clarity** of command descriptions and section headings in both English and Italian.

### 🧩 Internal

- Updated `display_order` values to reflect the new command hierarchy.
- Refined `cli.rs` layout for easier maintenance of localized help headings.

---

## [0.4.5] - 2025-11-11

### Added

- **🔍 New `search` command**
    - Allows searching books by title, author, editor, genre, or language.
    - Usage:
      ```bash
      librius search "dune"
      librius search "frank herbert" --short
      ```
    - Supports both full (`BookFull`) and compact (`BookShort`) table views.
    - Integrated with i18n for localized output messages and help text.

### Changed

- Unified search output with `print_info`, `print_ok`, and `print_warn` for consistent message style.
- Renamed `commands/search.rs``commands/search_book.rs` to avoid ambiguous glob re-exports.
- Refactored `search_books()` in `db/search.rs` to remove redundant closure for Clippy compliance.

---

## [0.4.1] - 2025-10-22

### Added

- **New `del` command**
    - Allows deletion of books by **ID or ISBN** with hybrid detection.
    - Added **interactive confirmation prompt** to prevent accidental deletions.
    - Introduced **`--force`** flag to skip confirmation in automated workflows.
    - Integrated with **`write_log()`** to record all deletions (forced or confirmed).
- Localized all messages and help text for English and Italian.
- Updated CLI documentation and help output to include the new command.

### Example usage

```bash
# Interactive mode
$ librius del 129
Sei sicuro di voler eliminare il libro 129? [y/N]: y
✅ Libro 129 eliminato correttamente.

# Forced mode
$ librius del 9788820382698 --force
✅ Book 9788820382698 deleted successfully.
```

### Changed

- Minor cleanup in CLI argument ordering and localized help strings.
- Improved developer workflow consistency in the tools/ directory.

### Internal

- All deletions are now logged via write_log() for audit and traceability.
- Added developer scripts in /tools for build and submodule checks.
- Updated private submodule tools_private to latest revision.

---

## [0.4.0] - 2025-10-18

### Added

- New command `add book`:
    - Fetches book information automatically from the Google Books API using ISBN.
    - Populates title, author, editor, year, language, genre, and summary automatically.
    - Fallback to interactive mode (planned) for books not found.
- New command `edit book`:
    - Allows updating any existing book record by ID or ISBN.
    - Supports all editable fields (`title`, `author`, `editor`, `year`, `language`, `pages`,
      `genre`, `summary`, `room`, `shelf`, `row`, `position`), excluding ID and ISBN.
    - Automatically converts language codes (e.g., `"en" → "English"`) using `lang_code_to_name()`.
    - Dynamically generates CLI arguments for each editable field via a centralized
      `EDITABLE_FIELDS` definition in `fields.rs`.
    - Grouped and ordered help output using `display_order()` and `next_help_heading()`:
        - Global options appear first.
        - Book-specific options are clearly grouped under titled sections.
    - Field updates now display **localized detailed messages**:
        - e.g. `✅ Field "year" updated successfully (2018 → 2020).`
        - Shows both the previous and new values for each modified field.
    - Final update summary message supports **language-aware pluralization**:
        - English: `"✅ Book 9788820382698 successfully updated (2 fields modified)."`
        - Italian: `"✅ Libro 9788820382698 aggiornato correttamente (2 campi modificati)."`

- Integrated dynamic i18n support for all CLI help messages (`add`, `edit`, `book`, `isbn`).
- Added automatic language name resolution (e.g., `"it"``"Italian"`).
- New utility module `utils/lang.rs` for ISO 639-1 to language name conversion.
- **New utility module `utils/isbn.rs`:**
    - Introduced the `normalize_isbn()` helper for validation and bidirectional formatting.
    - Supports both ISBN-10 and ISBN-13 with hyphenation handling.
    - Returns localized error messages for invalid, undefined, or malformed ISBNs.
    - Includes comprehensive unit tests and doctests.
- Localized console messages for book lookup, edition, and insertion results.

### Changed

- Modularized command structure: added `add.rs`, `add_book.rs`, and `edit_book.rs` under `src/commands/`.
- Unified language handling logic between `add` and `edit` commands.
- Improved error handling for Google Books API responses and JSON decoding.
- Replaced manual `impl Default` blocks with idiomatic `#[derive(Default)]`.
- Enhanced ISBN display formatting in the `list` command using `normalize_isbn()` for readable hyphenated output.
- Refactored CLI (`cli.rs`) with ordered, grouped, and localized help output for all commands.
- Localized final book update message with plural-sensitive translation keys:
    - `"edit.book.updated.one"` and `"edit.book.updated.many"` in `en.json` / `it.json`.

### Fixed

- Deserialization issues with Google Books API fields (`volumeInfo`, `publishedDate`, `pageCount`).
- Empty fields on insertion caused by incorrect field mapping.
- Prevented duplicate ISBN insertion with user-friendly message (`"Book already present in your library"`).

### Example usage

```bash
# ➕ Add a new book automatically using its ISBN
$ librius add book --isbn 9788820382698
🔍 Searching for book with ISBN: 9788820382698
📘 Found: “La lingua dell'antico Egitto” — Emanuele M. Ciampini (2018)
✅ Book “La lingua dell'antico Egitto” successfully added to your library.

# 📚 List all books (compact view)
$ librius list --short

📚  Your Library

┌─────┬──────────────────────────────┬──────────────────────┬──────────────────────────────────────────────────────┬──────┬───────────────────┐
│ ID  │ Title                        │ Author               │ Editor                                               │ Year │ ISBN              │
├─────┼──────────────────────────────┼──────────────────────┼──────────────────────────────────────────────────────┼──────┼───────────────────┤
│ 91  │ The Hobbit                   │ J.R.R. Tolkien       │ Allen & Unwin                                        │ 1937 │ 978-0-345-33968-3 │
│ 92  │ Foundation                   │ Isaac Asimov         │ Gnome Press                                          │ 1951 │ 978-0-553-80371-0 │
│128  │ La lingua dell'antico Egitto │ Emanuele M. Ciampini │ Lingue antiche del Vicino Oriente e del Mediterraneo │ 2018 │ 978-88-203-8269-8 │
└─────┴──────────────────────────────┴──────────────────────┴──────────────────────────────────────────────────────┴──────┴───────────────────┘

# ✏️ Edit an existing record (by ISBN or ID)
$ librius edit book 9788820382698 --year 2020
📝 Updating book with ISBN 9788820382698...
✅ Field “year” updated successfully (2018 → 2020)

# 🌍 Update language using ISO code (automatically converted)
$ librius edit book 9788820382698 --lang_book en
📝 Updating book language...
✅ Field “language” updated successfully (“Italian” → “English”)

# 📖 Display detailed information
$ librius list --id 128 --details

📘  Book Details (ID 128)
────────────────────────────────────────────────────────────────────────────
Title:        La lingua dell'antico Egitto
Author:       Emanuele M. Ciampini
Editor:       Lingue antiche del Vicino Oriente e del Mediterraneo
Year:         2020
Language:     English
Genre:        Linguistics
Pages:        432
Room:         B
Shelf:        4
Row:          2
Position:     5
ISBN:         978-88-203-8269-8
────────────────────────────────────────────────────────────────────────────
```

---

## [0.3.5] - 2025-10-17

### Added

- Introduced official **Librius icon and branding assets**
    - Added `librius.svg`, `librius.png`, and `librius.ico` in `res/`
    - Included build integration for Windows executables
- Prepared cross-platform structure for future GUI integration

### Changed

- Updated documentation and README with new logo and asset references

---

## [0.3.0] - 2025-10-16

### Added

- Introduced the `tabled` crate (`v0.20.0`) for tabular output.
- New `--short` flag for `librius list` showing only key columns (ID, Title, Author, Editor, Year).
- New utility `build_table()` in `utils/table.rs` to render tables with consistent style and alignment.
- CLI option `--delimiter` / `-d` for `import` command.  
  Allows specifying a custom CSV field separator (default: `,`).

### Changed

- Refactored `list` command to use `BookFull` and `BookShort` wrappers implementing `Tabled`.
- Standardized module structure across the project:
    - Each main directory (`commands`, `db`, `config`, `i18n`, `models`, `utils`) now includes a `mod.rs`.
    - Unified import/export logic in `lib.rs` for cleaner module access.
- Improved code readability, organization, and adherence to Rust idioms.

### Refactored

- Extracted duplicated import logic into reusable helper functions:
    - `utils::open_import_file()` now handles file opening with localized error reporting.
    - `utils::handle_import_result()` manages database insert results and counters.
- Unified behavior between `handle_import_csv()` and `handle_import_json()`.
- Simplified error handling and improved localization consistency across import operations.
- Reduced code duplication and improved maintainability throughout the import module.

### Fixed

- **CSV/JSON import deserialization error**:  
  The `id` field in the `Book` struct is now optional (`Option<i32>`),  
  preventing missing-field errors during import when the ID column is not present.

### Removed

- Legacy manual `println!` formatting for book listings.

---

## [0.2.5] - 2025-10-15

### Added

- **Backup command** (`librius backup`)
    - Creates plain `.sqlite` backups in the `backups/` directory
    - Optional `--compress` flag for compressed backups
        - `.zip` format on Windows
        - `.tar.gz` format on macOS and Linux
    - Localized help and messages via i18n (English and Italian)
    - Timestamp-based file naming for safe sequential backups
    - Fixed backup compression error on macOS/Linux (`paths in archives must be relative`).

- **Export command** (`librius export`)
    - Added support for exporting library data in multiple formats:
        - `--csv` (default): plain text export with semicolon delimiter
        - `--json`: structured JSON array output
        - `--xlsx`: formatted Excel file using umya-spreadsheet
    - Localized CLI help and status messages (English/Italian)
    - Automatic export directory and timestamped filenames
    - Uses `dirs` crate for cross-platform export path handling

- **Import command** (`librius import`)
    - Supports importing book data from external sources
    - Available formats:
        - `--csv` (default): semicolon-delimited CSV
        - `--json`: JSON array of objects
    - Unified parsing via `serde` and shared `BookRecord` struct
    - Duplicate detection through unique index on `isbn`
    - Uses `INSERT OR IGNORE` for idempotent imports (no duplication)
    - Verbose mode logs skipped records (e.g., “Skipped duplicate ISBN: …”)
    - Non-blocking import completion logging

### Database

- Added migration `PATCH_004_ISBN_INDEX`:
    - Creates unique index on `books.isbn` to prevent duplicates
    - Automatically applied during startup migrations

### Technical

- Added dependency: `csv = "1.3"` for CSV import with serde
- Unified SQL insert logic via `insert_book_record()` helper
- Improved transaction safety and i18n message consistency

---

## [0.2.4] - 2025-10-15

### Added

- Full internationalization (i18n) for CLI help, subcommands, and arguments.
- Embedded JSON language files (`en.json`, `it.json`) — no external dependencies required.
- Dynamic language selection via `--lang <code>` or the `language` key in `librius.conf` (YAML).

### Fixed

- Resolved duplicated `--help` and `--version` flag conflicts in Clap.
- Restored proper `--help` propagation for subcommands (`list`, `config`).
- Ensured fallback to English if an unknown language code is provided.

### Changed

- Pre-language bootstrap messages (e.g., “Load configuration...”) remain in English for clarity.
- Improved initialization order: configuration and DB migrations now run after language setup.

### Notes

- Default language remains English unless overridden by `--lang` or the `language` field in `librius.conf` (YAML).
- This version finalizes the transition to a fully localized CLI core.

---

## [v0.2.3] - 2025-10-14

### Added

- **Multilanguage support (i18n)**:
    - Added `i18n` module with `load_language()` and `tr()` functions.
    - Introduced translation files under `src/i18n/locales/` (`en.json`, `it.json`).
    - Added `src/i18n/locales/README.md` with key naming conventions.
    - CLI option `--lang` (or `-l`) allows overriding the language from configuration.
    - Config file can define a `language:` field for persistent preference.
    - Added `tr_with()` utility for runtime placeholder substitution (e.g., `{path}`, `{title}`).
- **Fallback system**: if a translation key is missing or the language file is unavailable, English (`en.json`) is used
  automatically.
- **Python helper script** (`scripts/extract_translations.py`):
    - Scans Rust source files for user-facing strings.
    - Updates `en.json` with any missing entries without overwriting existing ones.

### Changed

- All user-facing messages (`print_info`, `print_ok`, `print_err`, `println!`, etc.) are now translatable.
- Main startup sequence (`main.rs`) loads the selected language before configuration and database initialization.

### Improved

- Added helper in `config.rs` to read language preference directly from `librius.conf`.
- Enhanced verbosity filtering to respect localized messages.
- Clearer structure for future locale additions (fr, es, de, ...).

---

## [v0.2.2] - 2025-10-14

### Added

- **Structured database migration system**
    - Introduced `MigrationResult` enum replacing the previous boolean return value.
    - `run_migrations()` now returns explicit results (`Applied([...])` or `None`).
    - Each applied patch is now logged in the database with detailed information.
- **Patch safety improvements**
    - `PATCH_002` now checks for the existence of columns (`language`, `pages`, `genre`, `summary`) before adding them.
    - Prevents duplicate column errors on repeated runs.
- **Enhanced migration logging**
    - Migrations now record results under `DB_MIGRATION_OK`, `DB_MIGRATION_FAIL`, and `MIGRATIONS_COMPLETED` events in
      the `log` table.
    - Clear distinction between actual migrations and up-to-date states.

### Changed

- Refactored `run_migrations()` logic for clarity and maintainability.
- Updated database initialization flow (`start_db()`) to react dynamically to migration results.
- Improved internal output messages for migrations and startup consistency.

### Fixed

- Ensured safe re-execution of migration patches on existing databases.
- Removed redundant success messages when no migrations were needed.
- Unified patch logging behavior across all modules.

---

## [v0.2.1] - 2025-10-13

### Added

- **Database migrations**: introduced `db/migrate.rs` with incremental patch system and automatic execution at startup.
- **Configuration migrations**: added `config/migrate.rs` to automatically upgrade YAML configuration files.
- **Logging system**: new `utils::write_log()` function records database and migration events into the `log` table.
- **Verbose mode**: added global `--verbose` flag for diagnostic and debug output.
    - Normal mode: silent operation, only command results shown.
    - Verbose mode: shows configuration loading, database opening, and migration messages.
- **`db::start_db()`**: unified entry point that handles opening, creating, and migrating the database automatically.
- **Timestamp utility**: new `utils::now_str()` returns ISO 8601 formatted timestamps (`%+`).

### Changed

- Initialization messages are now hidden in normal mode.
- `main.rs` simplified: initialization logic moved into `db::start_db()`.
- `print_info()` and `print_ok()` now depend on verbose mode.

### Fixed

- Prevented redundant database initialization messages on repeated launches.
- Ensured migrations and configuration updates are idempotent and silent if up-to-date.

---

## [v0.2.0] - 2025-10-13

- feat(cli): add `config` command with `--print`, `--init`, `--edit`, and `--editor` options
- fix(windows): correctly handle editors with spaces in their path using `Path::new(&editor_to_use)`
- refactor(cli): move command and subcommand definitions into dedicated `cli.rs` module
- feat(utils): introduce `utils.rs` module with standard CLI icons and colored output helpers
- docs(readme): update structure and configuration examples
- style: minor formatting and consistency improvements across CLI output

---

## [v0.1.1] - 2025-10-12

- feat(models): add location fields to `Book` and `books` table schema (room, shelf, row, position)

## [v0.1.0] - 2025-10-12

- docs: add crate, module and item-level documentation for docs.rs
- feat(models): update `Book` struct to match `books` table schema (editor, language, pages, genre, summary, added_at)
- feat(models): change `added_at` type to `chrono::DateTime<Utc>` and enable `chrono` `serde` feature in `cargo.toml`
- feat(cli): make `list` handler return `Result` and handle errors in `main`
- feat(list): parse `added_at` from DB (RFC3339 / SQLite formats) and display `added_at` in the list as `YYYY-MM-DD`
- feat(crate): add `src/lib.rs` to expose crate API and improve docs generation on docs.rs
- docs: add docs.rs badge and local documentation instructions to `README.md`
- style: run `rustfmt` and fix Clippy warnings (code style and minor refactors)