mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 06:06:18 -08:00
Merge branch 'master' of https://github.com/4gray/iptvnator into claude/server-storage-pwa
# Conflicts: # docs/architecture/pwa-self-hosted.md
This commit is contained in:
commit
de87c1e4d3
78 files changed
+4367
-276
No files matched your search
@@ -6,10 +6,7 @@ import {
|
||||
playlistConflictUpdate,
|
||||
} from '@iptvnator/shared/database/app-playlist';
|
||||
import { appState, playlists } from '@iptvnator/shared/database/schema';
|
||||
import type {
|
||||
NewPlaylist,
|
||||
Playlist as PlaylistRow,
|
||||
} from '@iptvnator/shared/database/schema';
|
||||
import type { Playlist as PlaylistRow } from '@iptvnator/shared/database/schema';
|
||||
import { SERVER_PAYLOAD_FIELDS } from '@iptvnator/shared/interfaces';
|
||||
import {
|
||||
metadataDocument,
|
||||
@@ -42,46 +39,6 @@ function metadataColumns() {
|
||||
|
||||
const metaColumns = metadataColumns();
|
||||
|
||||
/**
|
||||
* Columns a whole-document upsert must rewrite even when the document no
|
||||
* longer has a value: the codec maps empty values to `undefined`, which an
|
||||
* `ON CONFLICT DO UPDATE` skips, so a cleared field would keep its old
|
||||
* column value and `parseAppPlaylist` would bring it back.
|
||||
*/
|
||||
const REPLACEABLE_COLUMNS = [
|
||||
'serverUrl',
|
||||
'username',
|
||||
'password',
|
||||
'lastUpdated',
|
||||
'userAgent',
|
||||
'origin',
|
||||
'referrer',
|
||||
'filePath',
|
||||
'epgUrls',
|
||||
'detectedEpgUrls',
|
||||
'manualEpgUrls',
|
||||
'disabledEpgUrls',
|
||||
'macAddress',
|
||||
'url',
|
||||
'portalUrl',
|
||||
'count',
|
||||
'importDate',
|
||||
'updateDate',
|
||||
'position',
|
||||
'favorites',
|
||||
'recentlyViewed',
|
||||
] as const satisfies readonly (keyof NewPlaylist)[];
|
||||
|
||||
function clearedColumns(row: NewPlaylist): Partial<NewPlaylist> {
|
||||
const cleared: Partial<Record<keyof NewPlaylist, null>> = {};
|
||||
for (const column of REPLACEABLE_COLUMNS) {
|
||||
if (row[column] === undefined) {
|
||||
cleared[column] = null;
|
||||
}
|
||||
}
|
||||
return cleared as Partial<NewPlaylist>;
|
||||
}
|
||||
|
||||
/** Playlist documents in the shared `playlists` table, same rows as desktop. */
|
||||
export class ServerPlaylistRepository {
|
||||
constructor(private readonly db: DatabaseInstance) {}
|
||||
@@ -146,10 +103,7 @@ export class ServerPlaylistRepository {
|
||||
throw new InvalidPlaylistDocumentError();
|
||||
}
|
||||
|
||||
const update = {
|
||||
...playlistConflictUpdate(row, next),
|
||||
...clearedColumns(row),
|
||||
};
|
||||
const update = playlistConflictUpdate(row, next);
|
||||
this.db.transaction((tx) => {
|
||||
tx.insert(playlists)
|
||||
.values(row)
|
||||
|
||||
Reference in new issue
Block a user