Commit Graph

651 Commits

Author SHA1 Message Date
neon 58031c1c83 feat(metadata): add community rating and rating count
Users rely on community feedback when evaluating books in their library. This change
introduces aggregated community ratings and rating counts from external metadata
providers, allowing users to see popular opinion directly within the book details
without needing to leave the application.

Closes #414
2026-06-25 21:50:17 +00:00
neon 9b946fc83e fix(metadata): preserve Book Dock epub metadata
Reuse the shared OPF mapper for Book Dock EPUB staging so embedded subject genres and Calibre page counts stay aligned with library imports.

Closes #423
2026-06-25 19:12:02 +00:00
neon 2af4895e69 feat(metadata): store and write hardcover edition IDs
Adds hardcoverEditionId to the database schema and shared types, enabling it to be stored as first-class metadata. Updates the file metadata parsers and writers (EPUB, PDF, CBZ) to read and embed this ID, and exposes it in the frontend metadata editor.

Closes #420
2026-06-25 18:55:22 +00:00
neon d1442b6d44 fix(metadata): prioritize edition release date over book release year
Previously, the edition release_date was ignored if the book had a release_year, due to the nullish coalescing operator treating the book release_year as a match for the first argument to parseYear. The new logic resolves the edition published year using both of its own date fields before falling back to the book date fields.

Closes #413
2026-06-25 18:03:21 +00:00
neon 113eeefeaf feat(metadata): add configuration for custom book metadata fields
Allow users to define new custom fields for books beyond the standard
metadata properties. This provides flexibility for cataloging arbitrary
data like reading formats, editions, or personal ratings.

Closes #419
2026-06-25 17:34:24 +00:00
neon c4ffa2c85e fix(client): preserve scroll position when navigating back to book grid views
- Cache view state (DOM, scroll, virtual lists) using KeepAlive during navigation.
- Restore scroll position on view activation using requestAnimationFrame for grids and TanStack scrollToIndex for tables.
- Wrap multi-root views in single elements to support Transition animations.
- Blur focused descendants when aria-hidden is applied to fix Reka UI Chrome 124+ warnings.

Closes #417
2026-06-25 03:28:35 +00:00
neon 9bfd134092 fix(server): resolve bulk selection queries for collections and email
Both AddToCollection and SendBook previously only operated on the explicitly provided list of book IDs. This prevented them from working correctly when a user selected all items across multiple pages in the UI. They now inherit from BulkSelectionDto and resolve queries to apply to all matching books.

Closes #416
2026-06-25 01:13:45 +00:00
neon 8f79e92053 feat(hardcover): add per-book sync controls and book sync scope
Introduce a per-book sync toggle in the book detail view that lets
users include or exclude individual books from Hardcover sync.

Add a book sync scope setting with two modes:
- all_eligible: sync all books unless explicitly excluded (default)
- selected_only: sync only books the user explicitly includes

Extract sync eligibility logic into hardcover-sync-policy.ts for
testability. The toggle handles unread books correctly: sync is skipped
while the book is unread, but the user's inclusion intent is stored so
sync activates automatically once reading starts.

Closes #412
2026-06-25 00:32:27 +00:00
neon e7956dadee fix(metadata): use ISBN context for Hardcover slug lookup
Pass metadata search params into stored provider lookups so providers can reject cached work identifiers that resolve to the wrong edition. Match Hardcover editions by normalized ISBN before falling back to provider search.

Closes #411
2026-06-23 22:33:44 +00:00
neon 0fb7e46913 feat(book-dock): allow importing duplicates and same-path collisions
Add two per-file override flags to the Book Dock finalize flow:

- skipDuplicateCheck: bypasses ISBN/title+author duplicate detection for
  a specific file. In book_per_folder mode the file naturally lands in
  the same folder as the existing book, so createBookRecord auto-attaches
  it as a second format on the same record.

- targetFileName: lets the user rename the file at the destination to
  resolve a same-path collision. The extension is always appended from
  the file format; if the user includes the extension it is stripped
  first to avoid doubling. Setting targetFileName also implicitly skips
  the duplicate check. A directory-traversal guard rejects any name
  whose resolved path escapes the intended destination folder.

Frontend: results panel shows an "Import anyway" button for isDuplicate
rows and an inline rename input for file-exists-at-target rows. Both
retry calls forward defaultLibraryId/defaultFolderId so files that rely
on dialog-level defaults get the right destination. Concurrent double-
click is guarded. reimportingIds uses reactive(Set) so spinner and
disabled states update correctly.

Closes #213
2026-06-23 21:13:16 +00:00
neon 78e02770a1 fix(metadata): always unpause queue on manual trigger
triggerGlobal and triggerForLibrary skipped unpauseIfNeeded when no new
books were eligible (queued = 0), leaving a previously paused queue
permanently stuck on re-trigger.

Also add a live statusLabel to the auto-fetch settings components that
shows remaining queue count when active, replacing the misleading
"~0 eligible" count that appeared immediately after triggering a run.

Closes #408
2026-06-23 19:16:57 +00:00
neon 484ad0b9be fix(metadata): persist auto-fetch library overrides
Ensure the settings UI saves inherit toggles immediately and guards eligible-count previews against stale async responses. Align library override DTO validation with the shared partial override contract, and record manual library runs even when nothing queues.
2026-06-23 16:37:59 +00:00
Haoqian 303f7f2d6a fix(reader): skip throttling for EPUB file streams (#410)
Allow authenticated EPUB archive file requests to bypass the global request throttle so the streaming reader can load fragmented books without tripping 429 responses. Keep the existing access and archive path checks in place.

Fixes: #409
2026-06-23 10:33:52 -06:00
neon 193079621f fix(client): fix copy to clipboard fallback mechanism
Update copyToClipboard to reliably handle the legacy execCommand fallback across browsers. The utility now selects text before copying, returns a success boolean, and ensures proper element cleanup. Added comprehensive tests for clipboard.ts and updated MagicLinksSettings tests.

Closes #204
2026-06-22 23:55:42 +00:00
neon 488ef04b17 feat(metadata): allow matching of multiple series
Extract and map multiple series memberships from AudNexus (primary, secondary, and fallback series) to a new seriesMemberships array. Update Goodreads mapper tests to verify correct extraction of the first series.

Closes #383
2026-06-22 23:31:07 +00:00
neon 7661765853 fix(reader): allow dictionary APIs in CSP connect-src
The epub reader's "Define" feature relies on api.dictionaryapi.dev and
wiktionary.org. These domains were being blocked by the server's Content
Security Policy. Adding them to the connect-src directive allows the
client to successfully fetch word definitions.

Closes #403
2026-06-22 17:29:09 +00:00
neon f5079d5f04 fix(reader): remove tooltips from selection popup
Tooltips on the color and style pickers were rendering behind the
popup due to z-index conflicts. Removing them fixes the issue and
simplifies the UI.

Closes #402
2026-06-22 17:13:47 +00:00
neon ad5068cefb fix(reader): show delete annotation button in selection popup
Calculate CFI range overlaps to detect when a selection intersects with
an existing annotation. Pass the overlapping annotation ID to the popup
so the delete option correctly renders.

Closes #401
2026-06-22 17:10:03 +00:00
neon cd502a00ee fix(reader): provide feedback for copy action in selection popup
Extracts clipboard logic into a shared utility and updates the selection popup to display a temporary success state after copying text.

Closes #400
2026-06-22 16:46:28 +00:00
neon 4197a8fc2e feat: add Hardcover import workflow
Add a preview-and-review workflow that matches Hardcover books by cached IDs, ISBNs, slugs, and title/author confidence before updating BookOrbit read status.

Import reading progress only when requested and safe, preserve existing local progress, and keep status imports resilient when progress writes fail.

Closes #394
2026-06-22 02:43:07 +00:00
neon ea6f10df53 feat(metadata): scope provider metadata fields by library
Use the current book's effective metadata provider configuration to decide which provider ID fields and search providers are available in metadata editing flows.

Preserve explicit empty provider selections so library overrides can remove all provider fields.

Closes #320
2026-06-21 20:55:10 +00:00
neon 2143b00cc5 fix(scanner): handle watched moves across docker libraries
Emit transfer events when watcher reconciliation moves a book between libraries. Keep file-as-book and folder-as-book watcher paths consistent across Docker, direct runs, and delayed copy-delete moves.

Closes #386
2026-06-21 19:15:39 +00:00
neon c00bd57ca5 fix(kobo): prevent sync crashes on empty tag requests
Send injected empty JSON bodies as Buffer chunks so Nest Fastify parsers can consume them without crashing.

Acknowledge BookOrbit collection item updates locally instead of proxying synthetic tags upstream.

Closes #396
2026-06-21 14:55:19 +00:00
neon 920aa3b477 build(deps): refresh client and server dependencies
Keep the dependency baseline current after the release window, and adapt the icon and zip integrations to current package APIs.
2026-06-21 06:00:55 +00:00
neon 1c38cf2084 fix(books): prevent focus loss when typing in empty series row
The SeriesMembershipEditor was losing focus on every keystroke when typing into a previously empty series row because the key was bound to the seriesName, causing the input component to remount. This introduces stable row keys to ensure the input retains focus while updating the model.

Closes #370
2026-06-21 04:25:03 +00:00
neon 1988ed0956 feat(metadata): add empty entity cleanup controls
Expose zero-book first-class metadata entities in browse so admins can review orphaned rows before deleting them.

Keep inline metadata values out of empty filtering because they only exist through book metadata rows.

Closes #370
2026-06-21 04:16:44 +00:00
neon 60383417a3 fix(cover): extract first naturally-sorted image for cbz cover
The central directory entries are now sorted by filename to ensure the correct first image is used as the cover, rather than relying on the order of entries in the ZIP archive.

Closes #378
2026-06-21 00:40:34 +00:00
neon dfa238e33f security(deps): update undici to fix vulnerabilities
The GitHub Actions Trivy scan was failing due to CVE-2026-12151, CVE-2026-6734, and CVE-2026-9697 in undici version 7.24.7. It is a transitive dependency of cheerio in the server package. Running pnpm update undici removes the vulnerable version from the lockfile.
2026-06-20 22:36:10 +00:00
neon 825e39a3ad chore(deps): bump node dependencies across monorepo
Updates various client, server, and root packages to their latest versions.
2026-06-20 22:15:12 +00:00
neon 21f15c3116 fix(metadata): offload large pdf parsing to worker thread
Offload large PDF parsing to a worker thread to prevent the Node.js event loop from being blocked. This ensures the application remains responsive during heavy metadata extraction tasks.

Closes #371
2026-06-20 21:42:10 +00:00
neon f1a7ba6070 fix(cover): refresh cached cover URLs
Update cover mutation paths to bump the book timestamp used for cover cache busting, and carry per-book collapsed-series cover versions so child covers do not reuse a representative book timestamp.
2026-06-20 20:52:43 +00:00
neon c4ab4a9153 feat: add in-app release notes viewer
Introduces a new feature to fetch, parse, and display app release notes
and update highlights directly within the UI.

- Backend: Adds the `release-notes` module to fetch GitHub releases
  and parse markdown highlight sections.
- Frontend: Adds the `WhatsNew` dialog and view, including custom
  markdown rendering and an image lightbox for update media.
- Tools: Adds validation scripts (`whats-new-lint`, `whats-new-preview`)
  to ensure release content parses correctly before publication.
2026-06-18 03:37:53 +00:00
neon c92ab8cf49 fix(library): skip file write for encrypted PDFs
pdf-lib cannot re-encrypt files, so saving an encrypted PDF strips its encryption but writes back still-encrypted byte streams, silently corrupting the file. Skipping the file write entirely prevents this corruption while allowing DB metadata to persist separately.

Fixes #368
2026-06-18 01:20:24 +00:00
neon 39e53a5d36 fix(books): treat missing read status as unread for sorting
Books without a row in user_book_status returned NULL and sorted differently than books explicitly marked as 'unread'. Coalescing the missing status to 'unread' ensures both explicitly and implicitly unread books are grouped and ordered consistently.

Fixes #367
2026-06-18 01:11:30 +00:00
neon 65f4fa7fca fix(library): only process books marked for rename in bulk rename
The bulk rename job was incorrectly iterating over every book in the library instead of restricting the operation to books that actually require a rename. This caused unnecessary processing and logged excessive noise. We now compute the preview first and filter the list of candidate book IDs down to those with the 'will_rename' status before executing the rename loop.

Closes #361
2026-06-17 23:14:30 +00:00
neon ceb2bb72d6 chore: add tests for BE strategies, repositories, and FE composables
Expand coverage across previously untested modules to close gaps identified
in the coverage audit.

BE: entity-manager strategies (inline, junction, author), koreader chapter
extractor, series and achievement repositories.

FE: reader settings/progress composables, notifications, live-scan books,
entity manager, and API wrapper modules (author, statistics, entity-manager).
2026-06-17 21:41:16 +00:00
neon ed87c14135 test(user): use valid PNG fixture for avatar test (sharp 0.35 libpng) 2026-06-17 20:25:12 +00:00
dependabot[bot] 2bb3b6e5d9 chore(deps): bump the production-dependencies group across 1 directory with 15 updates (#366)
Bumps the production-dependencies group with 15 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@embedpdf/vue-pdf-viewer](https://github.com/embedpdf/embed-pdf-viewer/tree/HEAD/viewers/vue) | `2.14.3` | `2.14.4` |
| [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.3.0` | `4.3.1` |
| [@tanstack/vue-virtual](https://github.com/TanStack/virtual/tree/HEAD/packages/vue-virtual) | `3.13.28` | `3.13.29` |
| [dompurify](https://github.com/cure53/DOMPurify) | `3.4.8` | `3.4.11` |
| [reka-ui](https://github.com/unovue/reka-ui) | `2.9.9` | `2.9.10` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) | `4.3.0` | `4.3.1` |
| [vue](https://github.com/vuejs/core) | `3.5.35` | `3.5.38` |
| [@nestjs/common](https://github.com/nestjs/nest/tree/HEAD/packages/common) | `11.1.24` | `11.1.27` |
| [@nestjs/core](https://github.com/nestjs/nest/tree/HEAD/packages/core) | `11.1.24` | `11.1.27` |
| [@nestjs/platform-fastify](https://github.com/nestjs/nest/tree/HEAD/packages/platform-fastify) | `11.1.24` | `11.1.27` |
| [@nestjs/platform-socket.io](https://github.com/nestjs/nest/tree/HEAD/packages/platform-socket.io) | `11.1.24` | `11.1.27` |
| [@nestjs/websockets](https://github.com/nestjs/nest/tree/HEAD/packages/websockets) | `11.1.24` | `11.1.27` |
| [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) | `5.8.0` | `5.9.2` |
| [mysql2](https://github.com/sidorares/node-mysql2) | `3.22.4` | `3.22.5` |
| [sharp](https://github.com/lovell/sharp) | `0.34.5` | `0.35.1` |



Updates `@embedpdf/vue-pdf-viewer` from 2.14.3 to 2.14.4
- [Release notes](https://github.com/embedpdf/embed-pdf-viewer/releases)
- [Changelog](https://github.com/embedpdf/embed-pdf-viewer/blob/main/viewers/vue/CHANGELOG.md)
- [Commits](https://github.com/embedpdf/embed-pdf-viewer/commits/v2.14.4/viewers/vue)

Updates `@tailwindcss/vite` from 4.3.0 to 4.3.1
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.1/packages/@tailwindcss-vite)

Updates `@tanstack/vue-virtual` from 3.13.28 to 3.13.29
- [Release notes](https://github.com/TanStack/virtual/releases)
- [Changelog](https://github.com/TanStack/virtual/blob/main/packages/vue-virtual/CHANGELOG.md)
- [Commits](https://github.com/TanStack/virtual/commits/@tanstack/vue-virtual@3.13.29/packages/vue-virtual)

Updates `dompurify` from 3.4.8 to 3.4.11
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.8...3.4.11)

Updates `reka-ui` from 2.9.9 to 2.9.10
- [Release notes](https://github.com/unovue/reka-ui/releases)
- [Commits](https://github.com/unovue/reka-ui/compare/v2.9.9...v2.9.10)

Updates `tailwindcss` from 4.3.0 to 4.3.1
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.1/packages/tailwindcss)

Updates `vue` from 3.5.35 to 3.5.38
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.5.35...v3.5.38)

Updates `@nestjs/common` from 11.1.24 to 11.1.27
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.27/packages/common)

Updates `@nestjs/core` from 11.1.24 to 11.1.27
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.27/packages/core)

Updates `@nestjs/platform-fastify` from 11.1.24 to 11.1.27
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.27/packages/platform-fastify)

Updates `@nestjs/platform-socket.io` from 11.1.24 to 11.1.27
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.27/packages/platform-socket.io)

Updates `@nestjs/websockets` from 11.1.24 to 11.1.27
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.27/packages/websockets)

Updates `fast-xml-parser` from 5.8.0 to 5.9.2
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.8.0...v5.9.2)

Updates `mysql2` from 3.22.4 to 3.22.5
- [Release notes](https://github.com/sidorares/node-mysql2/releases)
- [Changelog](https://github.com/sidorares/node-mysql2/blob/master/Changelog.md)
- [Commits](https://github.com/sidorares/node-mysql2/compare/v3.22.4...v3.22.5)

Updates `sharp` from 0.34.5 to 0.35.1
- [Release notes](https://github.com/lovell/sharp/releases)
- [Commits](https://github.com/lovell/sharp/compare/v0.34.5...v0.35.1)

---
updated-dependencies:
- dependency-name: "@embedpdf/vue-pdf-viewer"
  dependency-version: 2.14.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@tailwindcss/vite"
  dependency-version: 4.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@tanstack/vue-virtual"
  dependency-version: 3.13.29
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: dompurify
  dependency-version: 3.4.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: reka-ui
  dependency-version: 2.9.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: tailwindcss
  dependency-version: 4.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: vue
  dependency-version: 3.5.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@nestjs/common"
  dependency-version: 11.1.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@nestjs/core"
  dependency-version: 11.1.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@nestjs/platform-fastify"
  dependency-version: 11.1.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@nestjs/platform-socket.io"
  dependency-version: 11.1.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@nestjs/websockets"
  dependency-version: 11.1.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: fast-xml-parser
  dependency-version: 5.9.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: mysql2
  dependency-version: 3.22.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: sharp
  dependency-version: 0.35.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
2026-06-17 13:55:50 -06:00
dependabot[bot] 154933b429 chore(deps): bump dompurify from 3.4.8 to 3.4.9 (#364)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.8 to 3.4.9.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.8...3.4.9)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.9
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 13:49:59 -06:00
dependabot[bot] 94e92063d2 chore(deps): bump vite from 8.0.13 to 8.0.16 (#359)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.0.13 to 8.0.16.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.16/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.0.16
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 13:49:46 -06:00
dependabot[bot] e710d26b3e chore(deps): bump codecov/codecov-action in the github-actions group (#316)
Bumps the github-actions group with 1 update: [codecov/codecov-action](https://github.com/codecov/codecov-action).


Updates `codecov/codecov-action` from 6.0.1 to 7.0.0
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/e79a6962e0d4c0c17b229090214935d2e33f8354...fb8b3582c8e4def4969c97caa2f19720cb33a72f)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 13:49:34 -06:00
Kyungwook Park 6677f2f5ea feat(metadata): add Aladin Korean book metadata provider (#351)
* feat(metadata): add Aladin Korean book metadata provider

Add support for fetching Korean book metadata from Aladin OpenAPI.
Includes search by title/author/ISBN and lookup by ISBN-10/13.

- Add ALADIN to MetadataProviderKey in @bookorbit/types
- Add AladinProviderConfig to ProviderConfigurations
- Create AladinProvider with IdentifiableProvider interface
- Add mapper for Aladin API response to MetadataCandidate
- Register provider in MetadataFetchModule
- Add provider config merge, validation, and connection test
- Include 24 unit tests (provider + mapper)

* feat(client): add Aladin provider UI integration

* refactor(metadata): use 'Aladin' label and favicon-based icon

* feat(metadata): complete Aladin provider end-to-end wiring

Persist the Aladin ItemId across fetch, scoring, locks, and file metadata round-trip, and update the affected tests.

Co-authored-by: Kyungwook Park <288273+kyungw00k@users.noreply.github.com>

---------

Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
Co-authored-by: Kyungwook Park <288273+kyungw00k@users.noreply.github.com>
2026-06-17 13:33:35 -06:00
neon 9afddc34d2 feat(books): add support for multiple series per book
This introduces a many-to-many relationship between books and series, resolving the previous limitation where a book could only belong to a single series. It updates the database schema, query builders, server DTOs, and the Vue client interface to manage multiple series memberships per book.

Closes #353
2026-06-17 06:15:59 +00:00
neon 9b4408c610 fix(server): fix floating point precision in series index formatting
String/math based extraction of floating point series index fraction parts caused floating point precision artifacts. This extracts formatting into a shared utility and uses string splitting to avoid precision issues.

Closes #360
2026-06-17 05:36:48 +00:00
neon 86654bece8 fix(settings): add create link button to magic links admin tab
The "Create link" button was missing from the magic links admin tab because the header was hidden. This adds an embedded create action so the button is available when the component is rendered without a header.

Closes #357
2026-06-17 05:31:51 +00:00
neon 6eec39cb8a fix: allow resetting migration source setup
Add an API endpoint and UI action to reset the migration source configuration when no migration runs have been created yet.

Closes #354
2026-06-17 05:24:58 +00:00
neon a36a615b9a fix(client): add shift-click selection to entity manager
Add shift-click range selection in EntityBrowseTable to allow selecting multiple entities at once.

Closes #352
2026-06-17 05:13:05 +00:00
neon 7b48d49351 fix(server): accept empty requests with unsupported media types
Inject an empty JSON object for requests that have an unsupported content type but zero content length. Fastify defaults to rejecting these with a 415 error.

Closes #348
2026-06-17 05:07:44 +00:00
neon 0cddaf050c feat(metadata): add fallback scanner for EPUBs with missing ISBNs
Extract ISBNs from the EPUB spine contents if missing from the OPF metadata.

Closes #350
2026-06-15 23:24:56 +00:00
neon 671828d1b8 fix(client): restore shadow display for natural-bottom covers
The cover shadow moves to the inner artwork frame. The surface's own overflow:hidden would clip that shadow, so let it render by setting it to visible. The inner frame keeps its own overflow:hidden, so the image stays clipped to its rounded rect.

Closes #298
2026-06-15 16:27:47 +00:00