/**
 * Favicon rasterization for browser tabs.
 *
 * Uploaded favicon sources (especially SVGs) often carry large intrinsic
 * dimensions, which makes browsers render an oversized tab icon. We always
 * serve a square PNG at the target pixel size from dedicated public routes.
 */
import { isAllowedStorageUrl } from '../api/route-helpers.js';
import { safeFetch } from '../security/safe-fetch.js';
import { FAVICON_PIXEL_SIZE, } from './favicon-paths.js';
export { APPLE_TOUCH_ICON_PATH, APPLE_TOUCH_PIXEL_SIZE, FAVICON_ICON_PATH, FAVICON_PIXEL_SIZE, } from './favicon-paths.js';
let _sharp = null;
async function getSharp() {
    if (!_sharp) {
        const mod = await import(/* webpackIgnore: true */ 'sharp');
        _sharp = (mod.default ?? mod);
    }
    return _sharp;
}
/** Max favicon source we'll pull into memory for rasterization. */
const MAX_SOURCE_BYTES = 2 * 1024 * 1024;
/**
 * Fit an image into a square transparent PNG canvas at `size`×`size` px.
 * SVG sources get a higher raster density so edges stay crisp at tab size.
 */
export async function rasterizeBrandIcon(input, size) {
    const sharp = await getSharp();
    const density = Math.max(72, Math.ceil((size / FAVICON_PIXEL_SIZE) * 288));
    return sharp(input, { density, animated: false })
        .resize(size, size, {
        fit: 'contain',
        background: { r: 0, g: 0, b: 0, alpha: 0 },
    })
        .png()
        .toBuffer();
}
/**
 * Load the configured favicon source from brand settings and rasterize it.
 * Returns null when no favicon is configured or the source cannot be fetched.
 */
export async function loadAndRasterizeFavicon(db, size) {
    const { brandAssetIds, gatherBrandAssets, getBrandSettings } = await import('./resolve.js');
    const brand = await getBrandSettings(db);
    const sourceId = brand.faviconSourceAssetId;
    if (!sourceId)
        return null;
    const assets = await gatherBrandAssets(db, brandAssetIds(brand));
    const source = assets.get(sourceId);
    const url = source?.publicUrl;
    if (!url || !isAllowedStorageUrl(url))
        return null;
    const resp = await safeFetch(url, { method: 'GET', timeoutMs: 8000 });
    if (!resp.ok)
        return null;
    const buffer = Buffer.from(await resp.arrayBuffer());
    if (buffer.length === 0 || buffer.length > MAX_SOURCE_BYTES)
        return null;
    try {
        return await rasterizeBrandIcon(buffer, size);
    }
    catch {
        return null;
    }
}
//# sourceMappingURL=favicon-icon.js.map