feat(kobo): sync smart scopes to kobo#570
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a ChangesSync Smart Scopes to Kobo
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant KoboSyncController
participant KoboSyncService
participant BookQueryBuilder
participant Database
Client->>KoboSyncController: request delta / tag items
KoboSyncController->>KoboSyncService: getDelta / buildTagItems
KoboSyncService->>Database: load synced smart scopes
KoboSyncService->>BookQueryBuilder: buildWhere(filter, libraryIds)
BookQueryBuilder-->>KoboSyncService: SQL where clause
KoboSyncService->>Database: fetch matching book ids (cached)
Database-->>KoboSyncService: eligible book ids
KoboSyncService-->>KoboSyncController: tags/entitlements including smart-scope matches
KoboSyncController-->>Client: response
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
server/src/modules/kobo/services/kobo-sync.service.ts (1)
471-495: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUsing the SmartScope object itself as a Map key is fragile.
Map<schema.SmartScope, number[]>relies on reference identity of the fetched row objects. It works today because the same instances are produced and consumed within this method/caller, but it's an unusual pattern that could break silently if scopes are ever re-fetched or reconstructed between set/get. Keying byscope.id(storing{ scope, bookIds }as the value) would be more robust and conventional.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/src/modules/kobo/services/kobo-sync.service.ts` around lines 471 - 495, The SmartScope lookup in getSyncedSmartScopeMatches uses the fetched SmartScope object itself as the Map key, which depends on reference identity and is fragile. Update getSyncedSmartScopeMatches in kobo-sync.service.ts to key the result by a stable identifier such as scope.id, or store the scope alongside the book IDs in the Map value, and then adjust the caller that consumes this map to use that identifier instead of the object reference.client/src/features/smart-scope/components/SmartScopeEditorPanel.vue (1)
204-214: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd ARIA switch semantics to the toggle button.
The custom toggle only conveys state visually; screen readers will announce it as a plain button without an on/off state. Adding
role="switch"with a boundaria-checkedfixes this.♿️ Proposed fix
<button type="button" class="w-11 h-6 rounded-full transition-colors relative shrink-0" :class="draftSyncToKobo ? 'bg-primary' : 'bg-muted'" + role="switch" + :aria-checked="draftSyncToKobo" + aria-label="Sync to Kobo" `@click`="draftSyncToKobo = !draftSyncToKobo" >🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@client/src/features/smart-scope/components/SmartScopeEditorPanel.vue` around lines 204 - 214, Add switch semantics to the custom toggle in SmartScopeEditorPanel so assistive tech can announce its state: update the existing toggle button that flips draftSyncToKobo to expose it as a switch with a bound checked state. Keep the current click behavior, but add the appropriate ARIA role and state binding on the button element so screen readers report on/off instead of a generic button.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@server/src/modules/kobo/services/kobo-sync.service.ts`:
- Around line 438-441: The smart-scope matching logic in getDelta is being
queried repeatedly within the same sync request, causing unnecessary DB round
trips. Compute getSyncedSmartScopeMatches once per request using the existing
userId and accessibleLibraryIds, then pass or reuse that cached result in
buildEligibleBooksWhereClause, fetchEligibleSnapshotRows,
fetchEligibleBooksByIds, and buildTagItems instead of recomputing it. If
threading the value through is too invasive, add request-scoped memoization
keyed by (userId, accessibleLibraryIds) inside KoboSyncService.
- Around line 471-495: The getSyncedSmartScopeMatches method is issuing one
awaited db.select() per SmartScope inside the for...of loop, creating sequential
N+1 queries on the sync path. Refactor this so the per-scope book lookups run
independently in parallel, e.g. by building the queries from each scope’s filter
and resolving them together before populating the Map. Keep the existing
behavior for scopes without a filter and preserve the same return shape from
getSyncedSmartScopeMatches.
- Around line 471-495: The special-case in getSyncedSmartScopeMatches is wrong
for SmartScopes with no filter, because it forces an empty match list instead of
using the existing BookQueryBuilder.buildWhere behavior that returns all
accessible books. Remove the !scope.filter branch and always build the where
clause for each scope so no-filter scopes sync the full accessible set. Make
sure the change preserves the existing accessibleLibraryIds/userId inputs and
also covers the eligibility path that reuses getSyncedSmartScopeMatches.
---
Nitpick comments:
In `@client/src/features/smart-scope/components/SmartScopeEditorPanel.vue`:
- Around line 204-214: Add switch semantics to the custom toggle in
SmartScopeEditorPanel so assistive tech can announce its state: update the
existing toggle button that flips draftSyncToKobo to expose it as a switch with
a bound checked state. Keep the current click behavior, but add the appropriate
ARIA role and state binding on the button element so screen readers report
on/off instead of a generic button.
In `@server/src/modules/kobo/services/kobo-sync.service.ts`:
- Around line 471-495: The SmartScope lookup in getSyncedSmartScopeMatches uses
the fetched SmartScope object itself as the Map key, which depends on reference
identity and is fragile. Update getSyncedSmartScopeMatches in
kobo-sync.service.ts to key the result by a stable identifier such as scope.id,
or store the scope alongside the book IDs in the Map value, and then adjust the
caller that consumes this map to use that identifier instead of the object
reference.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 87de185d-00c2-42fc-8585-968c563b6eae
📒 Files selected for processing (15)
client/src/features/smart-scope/components/CreateSmartScopeDialog.vueclient/src/features/smart-scope/components/SmartScopeEditorPanel.vueclient/src/features/smart-scope/composables/__tests__/useSmartScopes.spec.tspackages/types/src/smart-scope.tsserver/src/db/migrations/0037_add_sync_to_kobo_smart_scopes.sqlserver/src/db/migrations/meta/0037_snapshot.jsonserver/src/db/migrations/meta/_journal.jsonserver/src/db/schema/smart-scopes.tsserver/src/modules/kobo/kobo-sync.controller.tsserver/src/modules/kobo/services/kobo-sync.service.test.tsserver/src/modules/kobo/services/kobo-sync.service.tsserver/src/modules/smart-scope/dto/create-smart-scope.dto.tsserver/src/modules/smart-scope/dto/update-smart-scope.dto.tsserver/src/modules/smart-scope/smart-scope.service.test.tsserver/src/modules/smart-scope/smart-scope.service.ts
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
a642ad0 to
1220f3a
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@server/src/modules/kobo/services/kobo-sync.service.ts`:
- Around line 719-722: The smart-scope membership filter in kobo-sync.service.ts
is flattening all matched book IDs into a large inArray(...) bind list, which
can explode parameter counts on the request path. Update the logic around
getSyncedSmartScopeMatchesCached and membershipFilter to avoid materializing all
smartScopeBookIds; instead build SQL/EXISTS-based OR predicates like the
collection branch, or chunk the IDs before combining them if reuse is needed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 6323589d-944a-442f-85d1-37b5fcf28a47
📒 Files selected for processing (3)
client/src/features/smart-scope/components/SmartScopeEditorPanel.vueserver/src/modules/kobo/services/kobo-sync.service.test.tsserver/src/modules/kobo/services/kobo-sync.service.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- client/src/features/smart-scope/components/SmartScopeEditorPanel.vue
- server/src/modules/kobo/services/kobo-sync.service.test.ts
821b0b4 to
1f63acc
Compare
Allow smart scopes to opt into Kobo sync while preserving collection sync behavior. Generate the current Drizzle migration and keep smart-scope matching aligned with the normal book query path. Fixes bookorbit#202 Co-authored-by: Jane Doe <[email protected]>
1f63acc to
4498117
Compare
|
🎉 This PR is included in version 2.2.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
What does this PR do?
Add a possibility to sync Smart Scopes to Kobo
Fixes #202
How did you test this?
Automatic tests + spun up dev environment, tested the UI and sync works locally.
Screenshots
Anything non-obvious in the diff?
Tried to keep it to the minimum, so it should be clear.
AI Disclosure
AI tools used: Claude
Extent: all code, including tests, was generated. I was only reviewer and tester.
Checklist
.env, personal configs)Summary by CodeRabbit
New Features
Bug Fixes