fix(playlist): keep cleared optional fields cleared on desktop (#1904)

Clearing an optional playlist field (User-Agent, Referrer, Origin,
credentials, EPG URL lists, file path) did not persist in Electron: the
codec maps an empty value to `undefined`, `ON CONFLICT DO UPDATE` skips
undefined keys, and `parseAppPlaylist` prefers the stale column over the
updated payload, so the old value came back on the next read.

`playlistConflictUpdate` now sets every optional column the document
leaves empty to NULL, so both desktop upserts (`DB_UPSERT_APP_PLAYLIST`
and `DB_UPSERT_APP_PLAYLISTS`) replace the stored row. The cleared-columns
list moves from the web backend's playlist repository into the shared
conflict module, and the server now uses the shared version.
`date_created`, `name`, `type`, `autoRefresh`, `payload` and `last_usage`
are never cleared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 authored and GitHub committed 2026-10-12 23:08:35 +02:00
1 parent b546fe0123
commit 434cbf3681
6 files changed
+244 -60

No files matched your search

+11
View File
@@ -618,6 +618,17 @@ Xtream-only row shape:
12. `DB_GET_APP_STATE`
13. `DB_SET_APP_STATE`
`DB_UPSERT_APP_PLAYLIST(S)` write whole documents: the row built by the shared
codec (`buildPlaylistRow` in `libs/shared/database`) replaces the stored one.
`playlistConflictUpdate` sets every optional column the document leaves empty
(an empty string or a missing key) to NULL instead of skipping it, because
`parseAppPlaylist` prefers a column over the payload and would otherwise bring
a cleared User-Agent, Referrer, Origin, credential, EPG list or file path back.
Only `date_created` is kept from the first insert. Callers must send the full
document (`PlaylistsService` reads, patches and writes the whole row); a
column-only change goes through `DB_UPDATE_PLAYLIST`. The self-hosted web
backend's playlist repository uses the same conflict update.
`DB_GET_APP_PLAYLIST_METAS` is the preferred path for summary surfaces such as
the workspace sidebar and dashboard source rail. It selects playlist metadata
columns only and deliberately skips the large `payload` column, which can