@francofantomius/jellyfin 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +31 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -6
- package/dist/index.d.ts +12 -6
- package/dist/index.js +31 -10
- package/dist/index.js.map +1 -1
- package/llms.txt +542 -0
- package/package.json +6 -5
package/dist/index.d.cts
CHANGED
|
@@ -306,10 +306,11 @@ interface AudioStreamOptions {
|
|
|
306
306
|
transcodingContainer?: string;
|
|
307
307
|
audioCodec?: string;
|
|
308
308
|
deviceId?: string;
|
|
309
|
+
mediaSourceId?: string;
|
|
309
310
|
/**
|
|
310
|
-
* Whether to include the
|
|
311
|
+
* Whether to include the authentication token in the URL query parameters (ApiKey, api_key, X-Emby-Token).
|
|
311
312
|
* Defaults to true for HTML5 <audio> tag compatibility.
|
|
312
|
-
*
|
|
313
|
+
* Set to false when providing modern Authorization headers to avoid conflicting authentication credentials in Jellyfin 12+.
|
|
313
314
|
*/
|
|
314
315
|
useQueryToken?: boolean;
|
|
315
316
|
}
|
|
@@ -320,10 +321,11 @@ interface AudioHlsStreamOptions {
|
|
|
320
321
|
audioCodec?: string;
|
|
321
322
|
segmentLength?: number;
|
|
322
323
|
deviceId?: string;
|
|
324
|
+
mediaSourceId?: string;
|
|
323
325
|
/**
|
|
324
|
-
* Whether to include the
|
|
326
|
+
* Whether to include the authentication token in the URL query parameters (ApiKey, api_key, X-Emby-Token).
|
|
325
327
|
* Defaults to true for legacy compatibility.
|
|
326
|
-
*
|
|
328
|
+
* Set to false when players (e.g. hls.js) are configured with Authorization headers via xhrSetup to prevent 401s from conflicting auth methods in Jellyfin 12+.
|
|
327
329
|
*/
|
|
328
330
|
useQueryToken?: boolean;
|
|
329
331
|
}
|
|
@@ -1146,8 +1148,11 @@ declare class MediaModule {
|
|
|
1146
1148
|
/**
|
|
1147
1149
|
* Returns authentication headers for media streaming requests (e.g., configuring hls.js xhrSetup).
|
|
1148
1150
|
* Crucial for Jellyfin 12+ servers where query-based auth (?api_key=) is disabled.
|
|
1151
|
+
* Pass { legacy: false } to only send Authorization and avoid conflicting headers or reverse-proxy CORS rejections.
|
|
1149
1152
|
*/
|
|
1150
|
-
getStreamHeaders(
|
|
1153
|
+
getStreamHeaders(options?: {
|
|
1154
|
+
legacy?: boolean;
|
|
1155
|
+
}): Record<string, string>;
|
|
1151
1156
|
}
|
|
1152
1157
|
|
|
1153
1158
|
declare class LyricsModule {
|
|
@@ -1933,4 +1938,5 @@ declare class JellyfinAuthError extends JellyfinApiError {
|
|
|
1933
1938
|
constructor(message?: string, status?: number, endpoint?: string);
|
|
1934
1939
|
}
|
|
1935
1940
|
|
|
1936
|
-
export { AUDIO_QUALITY_PRESETS,
|
|
1941
|
+
export { AUDIO_QUALITY_PRESETS, AuthModule, COMMON_SEARCH_FIELDS, ChaptersModule, CollectionsModule, DisplayPreferencesModule, FavoritesModule, GenresModule, HttpTransport, IndexedDBCacheAdapter, JellyfinApiError, JellyfinAuthError, JellyfinClient, JellyfinError, LatestModule, LibraryModule, LocalStorageAdapter, LyricsModule, MediaModule, MemoryCacheAdapter, MemoryStorage, NextUpModule, OfflineStorageManager, PlaybackModule, PlaylistsModule, QuickConnectModule, ResumeModule, SearchModule, SessionsModule, SystemModule, TranscodeModule, TrickplayModule, VIDEO_QUALITY_PRESETS, WebSocketModule, buildAuthHeader, cleanUrl, fetchWithCache, formatBitrate, generateDeviceId, getAudioQualityList, getDefaultStorage, getVideoQualityList, isV12OrHigher, isVersionAtLeast, parseSemVer, resolveAudioQuality, resolveVideoQuality };
|
|
1942
|
+
export type { ArtworkUrlOptions, AudioHlsStreamOptions, AudioQualityOption, AudioQualityPresetKey, AudioStreamOptions, AuthenticationResult, BaseItemDto, CacheAdapter, CacheRecord, ChapterImageOptions, ChapterInfoDto, ClientCapabilities, ClientEventListener, ClientEventType, ClientInfo, CreateCollectionOptions, CreatePlaylistDto, CreatePlaylistOptions, DisplayPreferencesDto, DownloadItemOptions, DownloadProgress, DownloadRecord, DownloadUrlOptions, GeneralCommandDto, GeneralCommandType, GetAlbumsOptions, GetArtistsOptions, GetCollectionItemsOptions, GetCollectionsOptions, GetDisplayPreferencesOptions, GetEpisodesOptions, GetGenresOptions, GetLatestMediaOptions, GetMediaSegmentsOptions, GetMoviesOptions, GetNextUpOptions, GetResumeItemsOptions, GetSeasonsOptions, GetSeriesOptions, GetSessionsOptions, GetSongsOptions, GetStudiosOptions, GetVideosOptions, IntroCreditsMarkers, ItemsResponse, JellyfinClientOptions, LibraryChangedData, LyricLine, LyricsDto, MarkerRange, MediaSegmentDto, MediaSegmentType, MediaSourceInfo, MediaStreamInfo, PlayCommandType, PlaybackInfoOptions, PlaybackInfoResponse, PlaystateCommand, PublicSystemInfo, QuickConnectPollOptions, QuickConnectResult, QuickConnectState, RemotePlayOptions, RequestOptions, SearchOptions, SessionInfoDto, SessionMessageOptions, SessionPlayState, StopActiveEncodingOptions, StorageAdapter, SubtitleTrackInfo, SubtitleUrlOptions, SystemInfo, ThumbnailLookupOptions, ThumbnailLookupResult, TrickplayInfoDto, TrickplayManifestInfo, TrickplayManifestTile, TrickplayStreamOptions, UpdateDisplayPreferencesOptions, UpdatePlaylistOptions, UserDataChangedData, UserDto, UserItemDataDto, VideoHlsStreamOptions, VideoQualityOption, VideoQualityPresetKey, VideoStreamOptions, WebSocketEventListener, WebSocketInboundMessage, WebSocketMessageType, WebSocketModuleOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -306,10 +306,11 @@ interface AudioStreamOptions {
|
|
|
306
306
|
transcodingContainer?: string;
|
|
307
307
|
audioCodec?: string;
|
|
308
308
|
deviceId?: string;
|
|
309
|
+
mediaSourceId?: string;
|
|
309
310
|
/**
|
|
310
|
-
* Whether to include the
|
|
311
|
+
* Whether to include the authentication token in the URL query parameters (ApiKey, api_key, X-Emby-Token).
|
|
311
312
|
* Defaults to true for HTML5 <audio> tag compatibility.
|
|
312
|
-
*
|
|
313
|
+
* Set to false when providing modern Authorization headers to avoid conflicting authentication credentials in Jellyfin 12+.
|
|
313
314
|
*/
|
|
314
315
|
useQueryToken?: boolean;
|
|
315
316
|
}
|
|
@@ -320,10 +321,11 @@ interface AudioHlsStreamOptions {
|
|
|
320
321
|
audioCodec?: string;
|
|
321
322
|
segmentLength?: number;
|
|
322
323
|
deviceId?: string;
|
|
324
|
+
mediaSourceId?: string;
|
|
323
325
|
/**
|
|
324
|
-
* Whether to include the
|
|
326
|
+
* Whether to include the authentication token in the URL query parameters (ApiKey, api_key, X-Emby-Token).
|
|
325
327
|
* Defaults to true for legacy compatibility.
|
|
326
|
-
*
|
|
328
|
+
* Set to false when players (e.g. hls.js) are configured with Authorization headers via xhrSetup to prevent 401s from conflicting auth methods in Jellyfin 12+.
|
|
327
329
|
*/
|
|
328
330
|
useQueryToken?: boolean;
|
|
329
331
|
}
|
|
@@ -1146,8 +1148,11 @@ declare class MediaModule {
|
|
|
1146
1148
|
/**
|
|
1147
1149
|
* Returns authentication headers for media streaming requests (e.g., configuring hls.js xhrSetup).
|
|
1148
1150
|
* Crucial for Jellyfin 12+ servers where query-based auth (?api_key=) is disabled.
|
|
1151
|
+
* Pass { legacy: false } to only send Authorization and avoid conflicting headers or reverse-proxy CORS rejections.
|
|
1149
1152
|
*/
|
|
1150
|
-
getStreamHeaders(
|
|
1153
|
+
getStreamHeaders(options?: {
|
|
1154
|
+
legacy?: boolean;
|
|
1155
|
+
}): Record<string, string>;
|
|
1151
1156
|
}
|
|
1152
1157
|
|
|
1153
1158
|
declare class LyricsModule {
|
|
@@ -1933,4 +1938,5 @@ declare class JellyfinAuthError extends JellyfinApiError {
|
|
|
1933
1938
|
constructor(message?: string, status?: number, endpoint?: string);
|
|
1934
1939
|
}
|
|
1935
1940
|
|
|
1936
|
-
export { AUDIO_QUALITY_PRESETS,
|
|
1941
|
+
export { AUDIO_QUALITY_PRESETS, AuthModule, COMMON_SEARCH_FIELDS, ChaptersModule, CollectionsModule, DisplayPreferencesModule, FavoritesModule, GenresModule, HttpTransport, IndexedDBCacheAdapter, JellyfinApiError, JellyfinAuthError, JellyfinClient, JellyfinError, LatestModule, LibraryModule, LocalStorageAdapter, LyricsModule, MediaModule, MemoryCacheAdapter, MemoryStorage, NextUpModule, OfflineStorageManager, PlaybackModule, PlaylistsModule, QuickConnectModule, ResumeModule, SearchModule, SessionsModule, SystemModule, TranscodeModule, TrickplayModule, VIDEO_QUALITY_PRESETS, WebSocketModule, buildAuthHeader, cleanUrl, fetchWithCache, formatBitrate, generateDeviceId, getAudioQualityList, getDefaultStorage, getVideoQualityList, isV12OrHigher, isVersionAtLeast, parseSemVer, resolveAudioQuality, resolveVideoQuality };
|
|
1942
|
+
export type { ArtworkUrlOptions, AudioHlsStreamOptions, AudioQualityOption, AudioQualityPresetKey, AudioStreamOptions, AuthenticationResult, BaseItemDto, CacheAdapter, CacheRecord, ChapterImageOptions, ChapterInfoDto, ClientCapabilities, ClientEventListener, ClientEventType, ClientInfo, CreateCollectionOptions, CreatePlaylistDto, CreatePlaylistOptions, DisplayPreferencesDto, DownloadItemOptions, DownloadProgress, DownloadRecord, DownloadUrlOptions, GeneralCommandDto, GeneralCommandType, GetAlbumsOptions, GetArtistsOptions, GetCollectionItemsOptions, GetCollectionsOptions, GetDisplayPreferencesOptions, GetEpisodesOptions, GetGenresOptions, GetLatestMediaOptions, GetMediaSegmentsOptions, GetMoviesOptions, GetNextUpOptions, GetResumeItemsOptions, GetSeasonsOptions, GetSeriesOptions, GetSessionsOptions, GetSongsOptions, GetStudiosOptions, GetVideosOptions, IntroCreditsMarkers, ItemsResponse, JellyfinClientOptions, LibraryChangedData, LyricLine, LyricsDto, MarkerRange, MediaSegmentDto, MediaSegmentType, MediaSourceInfo, MediaStreamInfo, PlayCommandType, PlaybackInfoOptions, PlaybackInfoResponse, PlaystateCommand, PublicSystemInfo, QuickConnectPollOptions, QuickConnectResult, QuickConnectState, RemotePlayOptions, RequestOptions, SearchOptions, SessionInfoDto, SessionMessageOptions, SessionPlayState, StopActiveEncodingOptions, StorageAdapter, SubtitleTrackInfo, SubtitleUrlOptions, SystemInfo, ThumbnailLookupOptions, ThumbnailLookupResult, TrickplayInfoDto, TrickplayManifestInfo, TrickplayManifestTile, TrickplayStreamOptions, UpdateDisplayPreferencesOptions, UpdatePlaylistOptions, UserDataChangedData, UserDto, UserItemDataDto, VideoHlsStreamOptions, VideoQualityOption, VideoQualityPresetKey, VideoStreamOptions, WebSocketEventListener, WebSocketInboundMessage, WebSocketMessageType, WebSocketModuleOptions };
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,10 @@ var JellyfinAuthError = class extends JellyfinApiError {
|
|
|
25
25
|
// src/http.ts
|
|
26
26
|
function cleanUrl(url) {
|
|
27
27
|
if (!url) return "";
|
|
28
|
-
let cleaned = url.trim()
|
|
28
|
+
let cleaned = url.trim();
|
|
29
|
+
while (cleaned.endsWith("/")) {
|
|
30
|
+
cleaned = cleaned.slice(0, -1);
|
|
31
|
+
}
|
|
29
32
|
if (!/^https?:\/\//i.test(cleaned)) {
|
|
30
33
|
cleaned = "https://" + cleaned;
|
|
31
34
|
}
|
|
@@ -1186,6 +1189,7 @@ var MediaModule = class {
|
|
|
1186
1189
|
const qualityResolved = resolveAudioQuality(options.quality);
|
|
1187
1190
|
const maxStreamingBitrate = options.maxStreamingBitrate ?? qualityResolved.maxStreamingBitrate;
|
|
1188
1191
|
const {
|
|
1192
|
+
mediaSourceId,
|
|
1189
1193
|
static: isStatic = false,
|
|
1190
1194
|
startTimeTicks = 0,
|
|
1191
1195
|
container = "opus,mp3|mp3,aac,m4a,m4b,flac,wav,ogg",
|
|
@@ -1196,12 +1200,14 @@ var MediaModule = class {
|
|
|
1196
1200
|
const endpoint = isStatic ? `/Audio/${itemId}/stream` : `/Audio/${itemId}/universal`;
|
|
1197
1201
|
const url = new URL(`${serverUrl}${endpoint}`);
|
|
1198
1202
|
if (token && useQueryToken) {
|
|
1203
|
+
url.searchParams.append("ApiKey", token);
|
|
1199
1204
|
url.searchParams.append("api_key", token);
|
|
1200
1205
|
url.searchParams.append("X-Emby-Token", token);
|
|
1201
1206
|
}
|
|
1202
1207
|
if (userId) url.searchParams.append("UserId", userId);
|
|
1203
1208
|
const targetDeviceId = options.deviceId !== void 0 ? options.deviceId : clientInfo.deviceId;
|
|
1204
1209
|
if (targetDeviceId) url.searchParams.append("DeviceId", targetDeviceId);
|
|
1210
|
+
if (mediaSourceId) url.searchParams.append("MediaSourceId", mediaSourceId);
|
|
1205
1211
|
if (isStatic) {
|
|
1206
1212
|
url.searchParams.append("static", "true");
|
|
1207
1213
|
} else {
|
|
@@ -1232,6 +1238,7 @@ var MediaModule = class {
|
|
|
1232
1238
|
const qualityResolved = resolveAudioQuality(options.quality);
|
|
1233
1239
|
const maxStreamingBitrate = options.maxStreamingBitrate ?? qualityResolved.maxStreamingBitrate;
|
|
1234
1240
|
const {
|
|
1241
|
+
mediaSourceId,
|
|
1235
1242
|
startTimeTicks = 0,
|
|
1236
1243
|
audioCodec = "aac,mp3",
|
|
1237
1244
|
segmentLength = 3,
|
|
@@ -1239,13 +1246,16 @@ var MediaModule = class {
|
|
|
1239
1246
|
} = options;
|
|
1240
1247
|
const url = new URL(`${serverUrl}/Audio/${itemId}/master.m3u8`);
|
|
1241
1248
|
if (token && useQueryToken) {
|
|
1249
|
+
url.searchParams.append("ApiKey", token);
|
|
1242
1250
|
url.searchParams.append("api_key", token);
|
|
1243
1251
|
url.searchParams.append("X-Emby-Token", token);
|
|
1244
1252
|
}
|
|
1245
1253
|
if (userId) url.searchParams.append("UserId", userId);
|
|
1246
1254
|
const targetDeviceId = options.deviceId !== void 0 ? options.deviceId : clientInfo.deviceId;
|
|
1247
1255
|
if (targetDeviceId) url.searchParams.append("DeviceId", targetDeviceId);
|
|
1248
|
-
|
|
1256
|
+
if (mediaSourceId) {
|
|
1257
|
+
url.searchParams.append("MediaSourceId", mediaSourceId);
|
|
1258
|
+
}
|
|
1249
1259
|
url.searchParams.append("AudioCodec", audioCodec);
|
|
1250
1260
|
url.searchParams.append("TranscodingContainer", "ts");
|
|
1251
1261
|
url.searchParams.append("TranscodingProtocol", "hls");
|
|
@@ -1291,6 +1301,7 @@ var MediaModule = class {
|
|
|
1291
1301
|
const endpoint = container && !container.includes(",") ? `/Videos/${itemId}/stream.${container}` : `/Videos/${itemId}/stream`;
|
|
1292
1302
|
const url = new URL(`${serverUrl}${endpoint}`);
|
|
1293
1303
|
if (token && useQueryToken) {
|
|
1304
|
+
url.searchParams.append("ApiKey", token);
|
|
1294
1305
|
url.searchParams.append("api_key", token);
|
|
1295
1306
|
url.searchParams.append("X-Emby-Token", token);
|
|
1296
1307
|
}
|
|
@@ -1356,6 +1367,7 @@ var MediaModule = class {
|
|
|
1356
1367
|
} = options;
|
|
1357
1368
|
const url = new URL(`${serverUrl}/Videos/${itemId}/master.m3u8`);
|
|
1358
1369
|
if (token && useQueryToken) {
|
|
1370
|
+
url.searchParams.append("ApiKey", token);
|
|
1359
1371
|
url.searchParams.append("api_key", token);
|
|
1360
1372
|
url.searchParams.append("X-Emby-Token", token);
|
|
1361
1373
|
}
|
|
@@ -1398,6 +1410,7 @@ var MediaModule = class {
|
|
|
1398
1410
|
const sourceId = mediaSourceId || itemId;
|
|
1399
1411
|
const url = new URL(`${serverUrl}/Videos/${itemId}/${sourceId}/Subtitles/${subtitleStreamIndex}/Stream.${format}`);
|
|
1400
1412
|
if (token && useQueryToken) {
|
|
1413
|
+
url.searchParams.append("ApiKey", token);
|
|
1401
1414
|
url.searchParams.append("api_key", token);
|
|
1402
1415
|
}
|
|
1403
1416
|
if (startTimeTicks > 0) {
|
|
@@ -1471,6 +1484,7 @@ var MediaModule = class {
|
|
|
1471
1484
|
if (!serverUrl || !itemId) return "";
|
|
1472
1485
|
const url = new URL(`${serverUrl}/Items/${itemId}/Download`);
|
|
1473
1486
|
if (token && useQueryToken) {
|
|
1487
|
+
url.searchParams.append("ApiKey", token);
|
|
1474
1488
|
url.searchParams.append("api_key", token);
|
|
1475
1489
|
}
|
|
1476
1490
|
if (filename) {
|
|
@@ -1517,13 +1531,17 @@ var MediaModule = class {
|
|
|
1517
1531
|
/**
|
|
1518
1532
|
* Returns authentication headers for media streaming requests (e.g., configuring hls.js xhrSetup).
|
|
1519
1533
|
* Crucial for Jellyfin 12+ servers where query-based auth (?api_key=) is disabled.
|
|
1534
|
+
* Pass { legacy: false } to only send Authorization and avoid conflicting headers or reverse-proxy CORS rejections.
|
|
1520
1535
|
*/
|
|
1521
|
-
getStreamHeaders() {
|
|
1536
|
+
getStreamHeaders(options = {}) {
|
|
1522
1537
|
const authHeader = this.http.getAuthHeader();
|
|
1523
|
-
|
|
1524
|
-
Authorization: authHeader
|
|
1525
|
-
"X-Emby-Authorization": authHeader
|
|
1538
|
+
const headers = {
|
|
1539
|
+
Authorization: authHeader
|
|
1526
1540
|
};
|
|
1541
|
+
if (options.legacy ?? true) {
|
|
1542
|
+
headers["X-Emby-Authorization"] = authHeader;
|
|
1543
|
+
}
|
|
1544
|
+
return headers;
|
|
1527
1545
|
}
|
|
1528
1546
|
};
|
|
1529
1547
|
|
|
@@ -1660,7 +1678,7 @@ var OfflineStorageManager = class {
|
|
|
1660
1678
|
request.onerror = () => resolve(null);
|
|
1661
1679
|
});
|
|
1662
1680
|
} catch (err) {
|
|
1663
|
-
console.warn(
|
|
1681
|
+
console.warn("[Jellyfin Offline] getDownloadedRecord error for %s:", id, err);
|
|
1664
1682
|
return null;
|
|
1665
1683
|
}
|
|
1666
1684
|
}
|
|
@@ -2415,7 +2433,7 @@ var WebSocketModule = class {
|
|
|
2415
2433
|
try {
|
|
2416
2434
|
listener(...args);
|
|
2417
2435
|
} catch (e) {
|
|
2418
|
-
console.error(
|
|
2436
|
+
console.error("[Jellyfin SDK] WebSocket listener error on '%s':", event, e);
|
|
2419
2437
|
}
|
|
2420
2438
|
});
|
|
2421
2439
|
}
|
|
@@ -2855,6 +2873,7 @@ var TrickplayModule = class {
|
|
|
2855
2873
|
const { mediaSourceId, useQueryToken = true } = options;
|
|
2856
2874
|
const url = new URL(`${serverUrl}/Videos/${itemId}/Trickplay/${width}/tiles.m3u8`);
|
|
2857
2875
|
if (token && useQueryToken) {
|
|
2876
|
+
url.searchParams.append("ApiKey", token);
|
|
2858
2877
|
url.searchParams.append("api_key", token);
|
|
2859
2878
|
url.searchParams.append("X-Emby-Token", token);
|
|
2860
2879
|
}
|
|
@@ -2873,6 +2892,7 @@ var TrickplayModule = class {
|
|
|
2873
2892
|
const { mediaSourceId, useQueryToken = true } = options;
|
|
2874
2893
|
const url = new URL(`${serverUrl}/Videos/${itemId}/Trickplay/${width}/${index}.jpg`);
|
|
2875
2894
|
if (token && useQueryToken) {
|
|
2895
|
+
url.searchParams.append("ApiKey", token);
|
|
2876
2896
|
url.searchParams.append("api_key", token);
|
|
2877
2897
|
url.searchParams.append("X-Emby-Token", token);
|
|
2878
2898
|
}
|
|
@@ -3063,6 +3083,7 @@ var ChaptersModule = class {
|
|
|
3063
3083
|
} = options;
|
|
3064
3084
|
const url = new URL(`${serverUrl}/Items/${itemId}/Images/Chapter/${chapterIndex}`);
|
|
3065
3085
|
if (token && useQueryToken) {
|
|
3086
|
+
url.searchParams.append("ApiKey", token);
|
|
3066
3087
|
url.searchParams.append("api_key", token);
|
|
3067
3088
|
url.searchParams.append("X-Emby-Token", token);
|
|
3068
3089
|
}
|
|
@@ -3747,7 +3768,7 @@ var JellyfinClient = class {
|
|
|
3747
3768
|
this.cache = new MemoryCacheAdapter();
|
|
3748
3769
|
this.clientInfo = {
|
|
3749
3770
|
name: options.clientInfo?.name || "@francofantomius/jellyfin",
|
|
3750
|
-
version: options.clientInfo?.version || "0.4.
|
|
3771
|
+
version: options.clientInfo?.version || "0.4.2",
|
|
3751
3772
|
device: options.clientInfo?.device || (typeof window !== "undefined" ? "Web Browser" : "Node.js"),
|
|
3752
3773
|
deviceId: options.clientInfo?.deviceId || generateDeviceId()
|
|
3753
3774
|
};
|
|
@@ -3869,7 +3890,7 @@ var JellyfinClient = class {
|
|
|
3869
3890
|
try {
|
|
3870
3891
|
fn(...args);
|
|
3871
3892
|
} catch (e) {
|
|
3872
|
-
console.error(
|
|
3893
|
+
console.error("[Jellyfin SDK] Event handler error on '%s':", event, e);
|
|
3873
3894
|
}
|
|
3874
3895
|
});
|
|
3875
3896
|
}
|