import fs from 'fs/promises' import yaml from 'js-yaml' import fetch from 'node-fetch' import path from 'path' export const loadViteManifests = (() => { let cache let lastCacheTime return async function loadViteManifests ({ useCache = true } = {}) { const CACHE_TTL = parseInt(process.env.CACHE_TTL) if (!cache || useCache === false || +new Date() > lastCacheTime + CACHE_TTL) { const urlsSource = await fs.readFile('./config/manifests/urls.yaml', 'utf8') const urls = yaml.load(urlsSource).manifests // vite manifests contains a set of objects with the vite-manifests // from the corresponding registered services const viteManifests = await Promise.all(urls.map(async url => { // fetch the manifests const result = await fetch(url) if (!result.ok) throw new Error(`Failed to load manifest for url ${result.url} (Status: ${result.status}: ${result.statusText})`) try { return result.json() } catch (err) { throw new Error(`Failed to load manifest for url ${result.url}: ${err}`) } })) // combine all manifests by keys. With duplicates, last wins const viteManifest = viteManifests.reduce((memo, manifest) => Object.assign(memo, manifest), {}) // only update that object if it really changed to prevent any further parsing from being triggered if (!cache || JSON.stringify(viteManifest) !== JSON.stringify(cache)) { cache = viteManifest } lastCacheTime = +new Date() } return cache } })() export function viteToOxManifest (viteManifests) { const deps = viteManifestToDeps(viteManifests) return Object.values(viteManifests) .filter(manifest => Array.isArray(manifest?.meta?.manifests)) .map(manifest => manifest.meta.manifests.map(oxManifest => { const dependencies = deps[manifest.file] const data = { ...oxManifest, path: manifest.file.slice(0, -path.parse(manifest.file).ext.length) } if (dependencies?.length > 0) data.dependencies = dependencies return data }) ) .flat() } export const getOxManifests = (() => { let prevViteManifest let oxManifestCache return async function getOxManifests () { const viteManifest = await loadViteManifests() if (viteManifest !== prevViteManifest) { oxManifestCache = viteToOxManifest(viteManifest) prevViteManifest = viteManifest } return oxManifestCache } })() export function viteManifestToDeps (viteManifest) { const deps = {} for (const { file, imports, css, assets } of Object.values(viteManifest)) { deps[file] = [] .concat(imports?.map(path => viteManifest[path].file)) .concat(css) .concat(assets) .filter(Boolean) } return deps } export const getDependencies = (() => { let prevViteManifest let depCache return async function getDependencies () { const viteManifest = await loadViteManifests() console.log('viteManifests', Object.keys(viteManifest).length) if (viteManifest !== prevViteManifest) { depCache = viteManifestToDeps(viteManifest) prevViteManifest = viteManifest } return depCache } })()