diff --git a/src/entities/media/api/mediaManifestApi.ts b/src/entities/media/api/mediaManifestApi.ts index 9460f23..785704c 100644 --- a/src/entities/media/api/mediaManifestApi.ts +++ b/src/entities/media/api/mediaManifestApi.ts @@ -36,17 +36,26 @@ export const mediaManifestApi = { return DEFAULT_MEDIA_MANIFEST; } - const response = await fetch(MEDIA_MANIFEST_URL, { - method: 'GET', - cache: MEDIA_MANIFEST_FETCH_CACHE, - signal, - }); + try { + const response = await fetch(MEDIA_MANIFEST_URL, { + method: 'GET', + cache: MEDIA_MANIFEST_FETCH_CACHE, + signal, + }); - if (!response.ok) { - throw new Error(copy.media.manifestLoadFailed); + if (!response.ok) { + throw new Error(`${copy.media.manifestLoadFailed} (${response.status} at ${MEDIA_MANIFEST_URL})`); + } + + const payload = (await response.json()) as Partial; + return normalizeMediaManifest(payload); + } catch (error) { + if (error instanceof Error && error.name === 'AbortError') { + throw error; + } + throw new Error( + `${copy.media.manifestLoadFailed}: ${error instanceof Error ? error.message : String(error)} (URL: ${MEDIA_MANIFEST_URL})` + ); } - - const payload = (await response.json()) as Partial; - return normalizeMediaManifest(payload); }, }; diff --git a/src/entities/media/model/resolveMediaAsset.ts b/src/entities/media/model/resolveMediaAsset.ts index 96c41b6..bada8f8 100644 --- a/src/entities/media/model/resolveMediaAsset.ts +++ b/src/entities/media/model/resolveMediaAsset.ts @@ -99,18 +99,18 @@ const mergeSoundAssets = (manifest: MediaManifest) => { }; export const normalizeMediaManifest = (manifest: Partial | null | undefined): MediaManifest => { - const mergedManifest: MediaManifest = { + const baseManifest: MediaManifest = { version: manifest?.version ?? DEFAULT_MEDIA_MANIFEST.version, updatedAt: manifest?.updatedAt ?? DEFAULT_MEDIA_MANIFEST.updatedAt, cdnBaseUrl: manifest?.cdnBaseUrl ?? DEFAULT_MEDIA_MANIFEST.cdnBaseUrl, - scenes: manifest?.scenes ?? [], - sounds: manifest?.sounds ?? [], + scenes: manifest?.scenes ?? DEFAULT_MEDIA_MANIFEST.scenes, + sounds: manifest?.sounds ?? DEFAULT_MEDIA_MANIFEST.sounds, }; return { - ...mergedManifest, - scenes: mergeSceneAssets(mergedManifest), - sounds: mergeSoundAssets(mergedManifest), + ...baseManifest, + scenes: mergeSceneAssets(baseManifest), + sounds: mergeSoundAssets(baseManifest), }; }; diff --git a/src/entities/media/model/useMediaCatalog.ts b/src/entities/media/model/useMediaCatalog.ts index 290f83b..f79a9c4 100644 --- a/src/entities/media/model/useMediaCatalog.ts +++ b/src/entities/media/model/useMediaCatalog.ts @@ -40,10 +40,18 @@ const readMediaManifest = async (signal?: AbortSignal): Promise { - const nextError = error instanceof Error ? error.message : null; + // Only return abort errors up the chain if we're not using fallback + if (error instanceof Error && error.name === 'AbortError') { + throw error; + } + + const nextError = error instanceof Error ? error.message : String(error); + + // Explicitly use normalize with null to get a pure fallback manifest + const fallbackManifest = normalizeMediaManifest(null); return { - manifest: manifestCache, + manifest: fallbackManifest, error: nextError, usedFallbackManifest: true, };