Add all minified fields to expanded library item JSON so socket updates remain a strict superset of shelf payloads

This commit is contained in:
mikiher 2026-07-01 22:30:21 +03:00
parent 6f03467f35
commit 3bb53d939d
4 changed files with 196 additions and 36 deletions

View file

@ -647,6 +647,11 @@ class Book extends Model {
}
}
/**
* Minified book JSON for list/shelf endpoints.
* `toOldJSONExpanded()` must be a strict superset: every key here must exist in expanded
* with the same value semantics. Only additive changes to expanded; never remove or rename keys.
*/
toOldJSONMinified() {
if (!this.authors) {
throw new Error(`[Book] Cannot convert to old JSON because authors are not loaded`)
@ -669,6 +674,12 @@ class Book extends Model {
}
}
/**
* Expanded book JSON for item detail and socket events.
* Must be a strict superset of `toOldJSONMinified()` built by spreading minified, then adding expanded-only fields.
*
* @param {string} libraryItemId
*/
toOldJSONExpanded(libraryItemId) {
if (!libraryItemId) {
throw new Error(`[Book] Cannot convert to old JSON because libraryItemId is not provided`)
@ -681,16 +692,12 @@ class Book extends Model {
}
return {
id: this.id,
libraryItemId: libraryItemId,
...this.toOldJSONMinified(),
libraryItemId,
metadata: this.oldMetadataToJSONExpanded(),
coverPath: this.coverPath,
tags: [...(this.tags || [])],
audioFiles: structuredClone(this.audioFiles),
chapters: structuredClone(this.chapters),
ebookFile: structuredClone(this.ebookFile),
duration: this.duration,
size: this.size,
tracks: this.getTracklist(libraryItemId)
}
}

View file

@ -1004,6 +1004,11 @@ class LibraryItem extends Model {
}
}
/**
* Minified library item JSON for list/shelf endpoints.
* `toOldJSONExpanded()` must be a strict superset: every key here must exist in expanded
* with the same value semantics. Only additive changes to expanded; never remove or rename keys.
*/
toOldJSONMinified() {
if (!this.media) {
throw new Error(`[LibraryItem] Cannot convert to old JSON without media for library item "${this.id}"`)
@ -1032,30 +1037,18 @@ class LibraryItem extends Model {
}
}
/**
* Expanded library item JSON for item detail and socket events.
* Must be a strict superset of `toOldJSONMinified()` built by spreading minified, then adding expanded-only fields.
*/
toOldJSONExpanded() {
return {
id: this.id,
ino: this.ino,
oldLibraryItemId: this.extraData?.oldLibraryItemId || null,
libraryId: this.libraryId,
folderId: this.libraryFolderId,
path: this.path,
relPath: this.relPath,
isFile: this.isFile,
mtimeMs: this.mtime?.valueOf(),
ctimeMs: this.ctime?.valueOf(),
birthtimeMs: this.birthtime?.valueOf(),
addedAt: this.createdAt.valueOf(),
updatedAt: this.updatedAt.valueOf(),
...this.toOldJSONMinified(),
lastScan: this.lastScan?.valueOf(),
scanVersion: this.lastScanVersion,
isMissing: !!this.isMissing,
isInvalid: !!this.isInvalid,
mediaType: this.mediaType,
media: this.media.toOldJSONExpanded(this.id),
// LibraryFile JSON includes a fileType property that may not be saved in libraryFiles column in the database
libraryFiles: this.getLibraryFilesJson(),
size: this.size
libraryFiles: this.getLibraryFilesJson()
}
}
}

View file

@ -451,6 +451,11 @@ class Podcast extends Model {
}
}
/**
* Minified podcast JSON for list/shelf endpoints.
* `toOldJSONExpanded()` must be a strict superset: every key here must exist in expanded
* with the same value semantics. Only additive changes to expanded; never remove or rename keys.
*/
toOldJSONMinified() {
return {
id: this.id,
@ -468,6 +473,12 @@ class Podcast extends Model {
}
}
/**
* Expanded podcast JSON for item detail and socket events.
* Must be a strict superset of `toOldJSONMinified()` built by spreading minified, then adding expanded-only fields.
*
* @param {string} libraryItemId
*/
toOldJSONExpanded(libraryItemId) {
if (!libraryItemId) {
throw new Error(`[Podcast] Cannot convert to old JSON because libraryItemId is not provided`)
@ -477,18 +488,9 @@ class Podcast extends Model {
}
return {
id: this.id,
libraryItemId: libraryItemId,
metadata: this.oldMetadataToJSONExpanded(),
coverPath: this.coverPath,
tags: [...(this.tags || [])],
episodes: this.podcastEpisodes.map((e) => e.toOldJSONExpanded(libraryItemId)),
autoDownloadEpisodes: this.autoDownloadEpisodes,
autoDownloadSchedule: this.autoDownloadSchedule,
lastEpisodeCheck: this.lastEpisodeCheck?.valueOf() || null,
maxEpisodesToKeep: this.maxEpisodesToKeep,
maxNewEpisodesToDownload: this.maxNewEpisodesToDownload,
size: this.size
...this.toOldJSONMinified(),
libraryItemId,
episodes: this.podcastEpisodes.map((e) => e.toOldJSONExpanded(libraryItemId))
}
}
}