Skip to content

Conversation

@farfromrefug
Copy link
Contributor

@farfromrefug farfromrefug commented Dec 31, 2025

🚀 Pull Request

📝 Description

This PR adds a new Komga compatible API.

This is draft for now. I need to clean the workflow change i had to implement to get github packages docker releases.
Have to see about the doc.

🛠️ Changes Implemented

Added the new Komga API, added backend API and frontend setting to enable it
there is a new clean query parameter not supported by the official komga API. When enabled the API results will be cleared of unused/unnecessary fields for apps supporting it (koma for one). null fields, empy arrays, ...Lock fields are not returned

🧪 Testing Strategy

I use the API directly with a Komga plugin for Mihon. I am also writing a Booklore plugin with more features

⚠️ Required Pre-Submission Checklist

  • Code adheres to project style guidelines and conventions
  • Branch synchronized with latest develop branch
  • Automated unit/integration tests added/updated to cover changes
  • All tests pass locally (./gradlew test for backend)
  • Manual testing completed in local development environment
  • Flyway migration versioning follows correct sequence (if database schema modified)
  • Documentation pull request submitted to booklore-docs (required for features or enhancements that introduce user-facing or visual changes)

acx10 added 30 commits August 8, 2025 20:03
Merge Develop into Master for release
Merge Develop into Master for release
Merge Develop into Master for release
Merge Develop into Master for release
Merge Develop into Master for release
Merge Develop into Master for release
Merge develop into master for release
Merge develop into master for release
Merge develop into master for release
Merge Develop into Master for Release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into master for the release
Merge develop into the master for release
Merge develop into the master for release
Merge develop into master for release
Merge develop into master for release
Merge develop itno master for the release
Merge develop into master for the release
@beudbeud
Copy link

beudbeud commented Jan 6, 2026

@farfromrefug i haven't see new commit

@beudbeud
Copy link

beudbeud commented Jan 6, 2026

Do you manage reading progress ?
https://komga.org/docs/openapi/mihon

@farfromrefug
Copy link
Contributor Author

@beudbeud my bad pushed now. About reading progress no it is not implemented. But it seems booklore already have an api for this. So it is a matter of integrating this into other apps.

@beudbeud
Copy link

beudbeud commented Jan 6, 2026

thanks it's work now

About reading progression it will be difficult i think because we use not internal user of Booklore just the OPDS user

@beudbeud
Copy link

beudbeud commented Jan 6, 2026

For me, all work perfectly and can be merge

@farfromrefug
Copy link
Contributor Author

thanks it's work now

About reading progression it will be difficult i think because we use not internal user of Booklore just the OPDS user

good point. Then i could implement komga like progress api in the future. TBh i dont use it

Copilot AI and others added 6 commits January 6, 2026 20:41
- Optimize getAllSeries to only convert series on current page to DTOs
- Optimize getBooksBySeries to fetch books only once (not twice)
- Add database query methods for future optimizations
- Update tests to work with new optimizations
- All existing tests pass

Co-authored-by: farfromrefug <655344+farfromrefug@users.noreply.github.com>
Remove unused optimization queries that don't align with application-level series grouping logic

Co-authored-by: farfromrefug <655344+farfromrefug@users.noreply.github.com>
- Add database queries to fetch distinct series names directly (no need to load all books)
- Add queries to fetch books only for specific series (when building DTOs)
- Support both groupUnknown=true and groupUnknown=false modes
- Add test to verify optimization works and books aren't loaded unnecessarily
- Performance improvement: For 1000+ books grouped into 100+ series, now only queries series names (~100 rows) instead of loading all books (~1000+ rows), then loads books only for the current page (~20-50 books per series on page)

Co-authored-by: farfromrefug <655344+farfromrefug@users.noreply.github.com>
…erformance

Optimize Komga API series listing with database-level query optimization
@farfromrefug
Copy link
Contributor Author

farfromrefug commented Jan 7, 2026

@beudbeud i was not really happy with performances in this PR, so i made some changes for faster db requests. if you could test again that would be great

@acx10 could i ask for this to be reviewed now? I am afraid some new migrations will come which will conflict with this PR migration numbers
EDIT: actually it already happened :s 84 is now taken

@beudbeud
Copy link

beudbeud commented Jan 7, 2026

i have issue now about migration

booklore  | Caused by: org.flywaydb.core.api.FlywayException: Found more than one migration with version 84
booklore  | Offenders:
booklore  | -> /nested:/app/app.jar/!BOOT-INF/classes/!/db/migration/V84__Assign_admin_users_to_all_libraries.sql (SQL)
booklore  | -> /nested:/app/app.jar/!BOOT-INF/classes/!/db/migration/V84__Add_komga_api_enabled_setting.sql (SQL)
booklore  | 	at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.checkForIncompatibilities(CompositeMigrationResolver.java:92) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.doFindAvailableMigrations(CompositeMigrationResolver.java:125) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.resolveMigrations(CompositeMigrationResolver.java:112) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.resolveMigrations(CompositeMigrationResolver.java:118) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.internal.info.MigrationInfoServiceImpl.refresh(MigrationInfoServiceImpl.java:86) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.internal.command.DbValidate.lambda$validate$0(DbValidate.java:112) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.internal.jdbc.TransactionalExecutionTemplate.execute(TransactionalExecutionTemplate.java:59) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.internal.command.DbValidate.validate(DbValidate.java:105) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.Flyway.doValidate(Flyway.java:529) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.Flyway.lambda$migrate$1(Flyway.java:199) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.FlywayExecutor.execute(FlywayExecutor.java:210) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.flywaydb.core.Flyway.migrate(Flyway.java:188) ~[flyway-core-11.7.2.jar!/:na]
booklore  | 	at org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer.afterPropertiesSet(FlywayMigrationInitializer.java:66) ~[spring-boot-autoconfigure-3.5.8.jar!/:3.5.8]
booklore  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1873) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1822) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaSharedEM_entityManagerFactory': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument
booklore  | 	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:377) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:135) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:691) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:513) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1375) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1205) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:569) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:529) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:373) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:365) ~[spring-beans-6.2.14.jar!/:6.2.14]
booklore  | 	... 110 common frames omitted
booklore  | Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Found more than one migration with version 84

@farfromrefug
Copy link
Contributor Author

@beudbeud yes this is normal as migrations have changed in main branch and conflict with this branch.
You either have to reset your db and start from scratch or manually modify the booklore db (which i am doing right now).
I am sorry there is nothing i can do about that

@beudbeud
Copy link

beudbeud commented Jan 7, 2026

@farfromrefug can you give me explain for update manually the database?

@farfromrefug
Copy link
Contributor Author

@beudbeud you need to open the mariadb database (connect to it) then open the flyway_schema_history table and fix the errors as per the messages you get. Which means changing the checksum. Then when you run it again change the description as per errors.
image

@beudbeud
Copy link

beudbeud commented Jan 7, 2026

it's normal to have that ?
01-07-2026-1767794949

@farfromrefug
Copy link
Contributor Author

@beudbeud no it was not. sorry pushed and fix. You still have to fix your db

@beudbeud
Copy link

beudbeud commented Jan 7, 2026

i fixed the database, it's work nice

@acx10
Copy link
Collaborator

acx10 commented Jan 8, 2026

@farfromrefug The code looks good at a glance. I’ll review it thoroughly this weekend.
In the meantime, could you please add documentation to booklore-docs with screenshots and all the necessary details? Thanks!

@acx10 acx10 added the feature Addition of new functionality label Jan 8, 2026
@farfromrefug
Copy link
Contributor Author

@acx10 awesome thank you! here you go booklore-app/booklore-docs#23

# Conflicts:
#	booklore-api/src/main/java/com/adityachandel/booklore/repository/BookRepository.java
"/api/v1/auth/**", // Login and token refresh endpoints (must remain public)
"/api/v1/public-settings", // Public endpoint for checking OIDC or other app settings
"/api/v1/setup/**", // Setup wizard endpoints (must remain accessible before initial setup)
"/api/v1/healthcheck/**" // Healthcheck endpoints (must remain accessible for Docker healthchecks)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you please add this back

 "/api/v1/healthcheck/**"

* Jackson configuration for Komga API clean mode.
*/
@Configuration
public class JacksonConfig {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This config registers a @primary ObjectMapper and applies a BeanSerializerModifier globally, which will affect serialization across the entire app. That’s pretty risky.
Can we scope this to a dedicated ObjectMapper and only use it where needed (e.g., specific endpoints or services) instead of changing global behavior?


@Bean
@Order(2)
public SecurityFilterChain komgaBasicAuthSecurityChain(HttpSecurity http) throws Exception {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we really need a separate SecurityFilterChain for this? Can we reuse or extend the existing security configuration instead of introducing another one? It would be good to understand what this chain adds that the current setup doesn’t cover.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i was just "copying" OPDS api security chain. You want me to use the same one? I am ok with that but wouldn't that mean that the WWW-Authenticate header would report the OPDS realm?

"resulting in smaller and cleaner JSON payloads.")
@Slf4j
@RestController
@RequestMapping(value = "/komga/api", produces = "application/json")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we change the base path to something like /api/komga/v1? That way we can avoid having to update nginx.conf and keep the routing consistent with the existing API structure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@acx10 actually this is problematic to be compatible with komga clients. They all use /api/komga/v1 by happending to the host. If we change that none of them will work :s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Addition of new functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants