import { getJson, GetJsonError } from '../common'; import type { Metadata } from '../types'; import { getCacheSetting } from './get-cache-setting'; import { getMFEHasUniqueChunkNamespace } from './get-mfe-has-unique-chunk-namespace'; import { TtlCache } from './ttl-cache'; const MINUTE = 1000 * 60; type MetadataResponse = Awaited>; const metadataResponseCache = new TtlCache({ ttlMs: 15 * MINUTE }); interface GetMetadataProps { fallbackPackageUrl?: string; mainPackageUrl: string; onRequestError?: (error: GetJsonError) => void; signal?: AbortSignal; retries?: number; } async function getMetadata(props: GetMetadataProps) { const { fallbackPackageUrl, mainPackageUrl, onRequestError, retries, signal } = props; try { return await getJson(`${mainPackageUrl}/dist/metadata.json`, { cache: getCacheSetting(mainPackageUrl), retries: fallbackPackageUrl ? 0 : retries, onRequestError, signal, }); } catch (e) { if (!fallbackPackageUrl) { throw e; } return getJson(`${fallbackPackageUrl}/dist/metadata.json`, { retries, onRequestError, cache: getCacheSetting(fallbackPackageUrl), signal, }); } } export async function getCachedMetadata( props: GetMetadataProps & { cache: boolean | number } ): Promise { let cache = props.cache; const cacheKey = props.mainPackageUrl; const cachedResponse = cache ? metadataResponseCache.get(cacheKey) : undefined; if (cachedResponse) { return { ...cachedResponse, cacheHit: true }; } const metadataResponse = await getMetadata(props); const mfeHasUniqueChunkNamespace = getMFEHasUniqueChunkNamespace( metadataResponse.data.bundledWith ); if (cache === true && !mfeHasUniqueChunkNamespace) { cache = -1; } if (cache) { metadataResponseCache.set( cacheKey, metadataResponse, typeof cache === 'number' ? cache : undefined ); } return metadataResponse; }