polymech-astro/packages/imagetools/api/utils/getImage.js
2025-08-16 11:49:45 +02:00

125 lines
3.2 KiB
JavaScript

// @ts-check
import crypto from "node:crypto";
import objectHash from "object-hash";
import getImageSources from "./getImageSources.js";
import getProcessedImage from "./getProcessedImage.js";
import getArtDirectedImages from "./getArtDirectedImages.js";
import pMap from "p-map";
import { get_cached_object, set_cached_object } from '@polymech/cache';
const imagesData = new Map();
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default async function ({
src,
type,
sizes: imagesizes,
format,
breakpoints,
placeholder,
fallbackFormat,
includeSourceFormat,
formatOptions,
artDirectives,
transformConfigs,
}) {
try {
const args = Array.from(arguments);
const hash = objectHash(args);
// Check in-memory cache first
if (imagesData.has(hash)) {
return imagesData.get(hash);
}
// Check persistent cache
const cacheKey = { src, type, imagesizes, format, breakpoints, placeholder, fallbackFormat, includeSourceFormat, formatOptions, artDirectives, transformConfigs };
const cachedResult = await get_cached_object(cacheKey, 'astro-imagetools');
if (cachedResult) {
console.log(`Cache hit for ${type} at ${src}`);
imagesData.set(hash, cachedResult);
return cachedResult;
}
const start = performance.now();
const { path, base, rest, image, imageWidth, imageHeight, imageFormat } =
await getProcessedImage(src, transformConfigs);
src = path;
rest.aspect = `${imageWidth / imageHeight}`;
if (!fallbackFormat) {
fallbackFormat = imageFormat;
}
// Fetch both image sources and art-directed images
const [mainImage, artDirectedImages] = await pMap(
[
async () =>
await getImageSources(
src,
base,
image,
format,
imageWidth,
imagesizes,
breakpoints,
placeholder,
imageFormat,
formatOptions,
fallbackFormat,
includeSourceFormat,
rest
),
async () => {
return await getArtDirectedImages(
artDirectives,
placeholder,
format,
imagesizes,
breakpoints,
fallbackFormat,
includeSourceFormat,
formatOptions,
rest
);
},
],
async (task) => await task(),
{ concurrency: 1 }
);
// Ensure artDirectedImages is an array
const images = Array.isArray(artDirectedImages) ? [...artDirectedImages, mainImage] : [mainImage];
const uuid = crypto.randomBytes(4).toString("hex").toUpperCase();
const returnObject = {
uuid,
images,
};
// Cache both in memory and persistently
imagesData.set(hash, returnObject);
await set_cached_object(cacheKey, 'astro-imagetools', returnObject, {
src: args[0].src,
type,
timestamp: Date.now()
});
const end = performance.now();
console.log(
`Responsive Image sets generated for ${type} at ${args[0].src} in ${end - start}ms`
);
return returnObject;
} catch (error) {
console.error("Error processing images:", error);
throw error;
}
}