Skip to content

feat(server): add program_extra table and scanner hooks (Phase 0) - #1897

Draft
coreyjv wants to merge 2 commits into
chrisbenincasa:devfrom
coreyjv:program-extras-phase-0
Draft

feat(server): add program_extra table and scanner hooks (Phase 0)#1897
coreyjv wants to merge 2 commits into
chrisbenincasa:devfrom
coreyjv:program-extras-phase-0

Conversation

@coreyjv

@coreyjv coreyjv commented May 27, 2026

Copy link
Copy Markdown
Contributor

Introduce the vendor-agnostic foundation for persisting program extras from remote media sources.

  • Add program_extra table with dual nullable parent FKs covering all four content levels (movie, episode, show, season)
  • Add ProgramExtraMinter injectable class for minting extra + artwork DAOs from MediaSourceExtra input
  • Add ProgramExtraRepository and upsertProgramExtras() on IProgramDB / ProgramDB
  • Add MediaSourceExtra type to Media.ts using RemoteSourceType
  • Add no-op scanExtrasForMovie() hook to MediaSourceMovieLibraryScanner, called for both unchanged and newly-upserted movies
  • Add no-op scanExtrasForShow/Season/Episode() hooks to MediaSourceTvShowLibraryScanner with equivalent call-site coverage

@chrisbenincasa chrisbenincasa left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Wondering if you've thought at all about how we'll represent these in the search index?

Comment thread server/src/db/schema/ProgramExtra.ts Outdated
Comment thread server/src/migration/db/sql/0045_yummy_lucky_pierre.sql
Comment thread server/src/db/converters/ProgramExtraMinter.ts
Comment thread server/src/services/scanner/MediaSourceTvShowLibraryScanner.ts Outdated
Comment thread server/src/services/scanner/MediaSourceTvShowLibraryScanner.ts Outdated
Comment thread server/src/db/program/ProgramExtraRepository.ts Outdated
Comment thread server/src/db/program/ProgramExtraRepository.ts Outdated
.returning({ uuid: ProgramExtra.uuid })
.all();

for (let i = 0; i < batch.length; i++) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think this could be slightly cleaner, avoid the issue with array index access nullish stuff, and avoid object spreads with something like:

zip(upserted, batch).forEach(([{uuid: persistedUuid}, extra]) => {
  for (const art of extra.artwork) {
    art.programExtraId = persistedUuid;
    allArtwork.push(art);
  }
})

This assumes that the length of upserted and batch are strictly the same, which I think we can assume.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This didn't actually resolve the undefined issues so I put in isNonEmptyString for now.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Ah hm, I didn't think that drizzle would return that as optional on the query (I figured the nullish was just coming from the chaining on the array)

Comment thread server/src/db/program/ProgramExtraRepository.ts Outdated
@coreyjv
coreyjv force-pushed the program-extras-phase-0 branch from 83cef4e to 3ba65c3 Compare May 30, 2026 15:19
@coreyjv

coreyjv commented May 30, 2026

Copy link
Copy Markdown
Contributor Author

Wondering if you've thought at all about how we'll represent these in the search index?

I have not to be perfectly honest.

@chrisbenincasa

Copy link
Copy Markdown
Owner

re: search index - like other things I'm guessing these will be nested objects on the programs index. noting because some special considerations have to be taken when dealing with nested objects on search documents depending on how we want to search / filter against them within the app, see: https://www.meilisearch.com/docs/resources/internals/datatypes#nested-document-querying-and-subdocuments

Introduce the vendor-agnostic foundation for persisting program extras
from remote media sources.

- Add `program_extra` table with dual nullable parent FKs covering all
  four content levels (movie, episode, show, season)
- Add `ProgramExtraMinter` injectable class for minting extra + artwork
  DAOs from `MediaSourceExtra` input
- Add `ProgramExtraRepository` and `upsertProgramExtras()` on
  `IProgramDB` / `ProgramDB`
- Add `MediaSourceExtra` type to `Media.ts` using `RemoteSourceType`
- Add no-op `scanExtrasForMovie()` hook to
  `MediaSourceMovieLibraryScanner`, called for both unchanged and
  newly-upserted movies
- Add no-op `scanExtrasForShow/Season/Episode()` hooks to
  `MediaSourceTvShowLibraryScanner` with equivalent call-site coverage

� Conflicts:
�	server/src/services/scanner/MediaSourceMovieLibraryScanner.ts
�	server/src/services/scanner/MediaSourceTvShowLibraryScanner.ts
@coreyjv
coreyjv force-pushed the program-extras-phase-0 branch from 6dc3c3d to ab37497 Compare June 7, 2026 14:03
@coreyjv

coreyjv commented Jun 7, 2026

Copy link
Copy Markdown
Contributor Author

I believe I've addressed all the comments I can. I'm not certain if that melisearch limitation is a blocker and if you want me to make specific changes related to it.

Let me know if you want me to flip this PR to ready for review. Thanks!

@coreyjv
coreyjv force-pushed the program-extras-phase-0 branch from ab37497 to 6638a4f Compare June 7, 2026 14:04
@chrisbenincasa

Copy link
Copy Markdown
Owner

Yup, let's un-draft it!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants