Skip to content

feat(media): add start field to LibraryDetail for TV shows#45

Merged
koinsaari merged 2 commits into
mainfrom
feat/library-detail-start-field
Jun 28, 2026
Merged

feat(media): add start field to LibraryDetail for TV shows#45
koinsaari merged 2 commits into
mainfrom
feat/library-detail-start-field

Conversation

@koinsaari

Copy link
Copy Markdown
Contributor

Summary

  • Add start: ResumeInfo? to LibraryDetail in OpenAPI spec — populated for TV shows pointing at S1E1 with zeroed progress, null for movies
  • Add GetFirstEpisode to Jellyfin client using a shared fetchEpisodes helper (eliminates duplication with GetEpisodes)
  • Fetch S1E1 in parallel with GetSeasons and GetNextUp in getSeriesDetail
  • Add Start field to media.Detail; map and emit through mapper and handler

Implementation notes

start.progress is always zeroed in the mapper — the handler passes it through rather than hardcoding zeros, so the mapper owns the invariant.

Closes #37

🤖 Generated with Claude Code

Clients need S1E1 info upfront to render a Play button without a
second round-trip to the episodes endpoint. start is null for movies
and always carries zeroed progress (position 0, played false).

- Add start: ResumeInfo? to LibraryDetail in OpenAPI spec
- Add GetFirstEpisode to Jellyfin client via shared fetchEpisodes helper
- Fetch S1E1 in parallel with GetSeasons and GetNextUp in getSeriesDetail
- Add Start field to media.Detail; map and emit it through mapper and handler
- Add tests for GetFirstEpisode, toSeriesDetail Start, and handler response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@koinsaari koinsaari added the enhancement New feature or request label Jun 28, 2026
@koinsaari koinsaari self-assigned this Jun 28, 2026
@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown

Claude finished @koinsaari's task in 2m 15s —— View job


Review: feat(media): add start field to LibraryDetail for TV shows

  • Read REVIEW.md and CLAUDE.md for review instructions
  • Read PR diff and all changed files
  • Check security invariants (JWT, SQL, auth isolation)
  • Check Go code quality (hoisting, URL building, discarded returns)
  • Check test coverage for new routes
  • Post review findings and set commit status

No blocking issues. CI passes (tests + lint). Clean, well-structured change that follows existing patterns throughout.

What I checked

  • Auth isolation: internal/auth does not import internal/clients/jellyfin — confirmed.
  • SQL / JWT: No SQL or JWT changes in this PR.
  • URL building: fetchEpisodes uses url.JoinPath correctly (shows.go:112).
  • Discarded returns: No new discards introduced.
  • Hoisting: No closures or handlers introduced — N/A.
  • Test coverage: Handler test (TestGetLibraryId_SeriesDetail_HasStart), mapper tests (TestToSeriesDetail_Start_PopulatedFromFirstEpisode, TestToSeriesDetail_NoFirstEpisode_NilStart), and client tests (TestGetFirstEpisode_ReturnsEpisode, TestGetFirstEpisode_EmptyResult_ReturnsNil) all present. No new routes were added (existing /library/{id} gains a new response field), so no new route-level test is required.

Nits

🟡 Nit — fetchEpisodes userID param is only used for the auth header, not the query. The caller is responsible for setting UserId in the url.Values and passing userID separately for the header. If a future caller forgets to add UserId to the query params, the request will silently omit it. Consider having fetchEpisodes always set q.Set("UserId", userID) itself, so the contract is harder to misuse. Not a bug today since both callers set it correctly.

🟡 Nit — no service-level test for non-nil firstEpisode. TestGetItem_Series_ReturnsSeasonsAndResume exercises getSeriesDetail but leaves getFirstEpisode as nil (the fake's zero value). A test where fakeJF.getFirstEpisode returns an episode and asserts d.Start != nil would close the integration gap between service.go and the mapper. The mapper and handler tests cover the mapping itself, so this is low-risk.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown

Claude finished @koinsaari's task in 2m 10s —— View job


Review: feat(media): add start field to LibraryDetail for TV shows

  • Read REVIEW.md and CLAUDE.md for review instructions
  • Read PR diff and all changed files
  • Check security invariants (JWT, SQL, auth isolation)
  • Check Go code quality (hoisting, URL building, discarded returns)
  • Check test coverage for new routes
  • Post review findings and set commit status

No blocking issues. Clean, well-structured change that follows existing patterns consistently across all layers.

What I checked

  • Auth isolation: internal/auth does not import internal/clients/jellyfin — confirmed.
  • SQL / JWT: No SQL or JWT changes in this PR.
  • URL building: fetchEpisodes uses url.JoinPath correctly (shows.go:110).
  • Discarded returns: No new discards introduced.
  • Hoisting: No closures or handlers introduced — N/A.
  • Test coverage: Full coverage across all layers:
    • Client: TestGetFirstEpisode_ReturnsEpisode, TestGetFirstEpisode_EmptyResult_ReturnsNil
    • Mapper: TestToSeriesDetail_Start_PopulatedFromFirstEpisode (verifies progress zeroing even when source episode has non-zero progress), TestToSeriesDetail_NoFirstEpisode_NilStart
    • Service: TestService_GetItem_Series_WithFirstEpisode_PopulatesStart (closes the integration gap noted by the prior review)
    • Handler: TestGetLibraryId_SeriesDetail_HasStart
    • No new routes were added (existing /library/{id} gains a new response field), so no new route-level test required.

Highlights

  • The fetchEpisodes refactoring (shows.go:109-143) is well done — it centralizes the UserId query param and auth headers, eliminating the misuse risk the prior review raised as a nit (the prior nit was actually already addressed by this code).
  • Progress zeroing in the mapper (mapper.go:64) is the right place for that invariant, and the test at mapper_test.go:283-296 properly verifies it with a source episode that has non-zero PlaybackPositionTicks and Played: true.
  • Parallel fetch of GetFirstEpisode alongside GetSeasons/GetNextUp in service.go:55-69 is correctly structured with wg.Add(3).

No nits to report.

@koinsaari koinsaari merged commit 11d8c05 into main Jun 28, 2026
8 checks passed
@koinsaari koinsaari deleted the feat/library-detail-start-field branch June 28, 2026 10:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add start field to LibraryDetail for TV shows

1 participant