PronounsPage/server/imageCopy.ts
Valentyne Stigloher 10180aa6a3 (refactor) use #shared alias instead of ~~/shared
the #shared alias used by Nuxt cannot be easily disabled and to prevent breackage with jiti, we make use of it
2025-08-17 18:56:02 +02:00

58 lines
1.8 KiB
TypeScript

import { loadImage, createCanvas } from 'canvas';
import { newDate, sha256 } from '#shared/helpers.ts';
import { s3, s3BucketParams } from '~~/server/cloudServices.ts';
const convertToPng = async (original: Buffer): Promise<Buffer> => {
const image = await loadImage(original);
const canvas = createCanvas(image.width, image.height);
canvas.getContext('2d').drawImage(image, 0, 0);
return canvas.toBuffer('image/png');
};
export default async (prefix: string, url: string, ttlDays: number | null = null): Promise<string | null> => {
if (!url) {
return null;
}
const isSvg = url.toLowerCase().replace(/\?.*$/, '').endsWith('.svg') || url.startsWith('data:image/svg+xml');
const key = `${prefix}/${await sha256(url)}.${isSvg ? 'svg' : 'png'}`;
try {
const metadata = await s3.headObject({ Key: key, ...s3BucketParams });
if (
ttlDays !== null &&
metadata.LastModified! < new Date(
newDate().setDate(newDate().getDate() - ttlDays),
)
) {
throw 'force refresh';
}
return `${process.env.NUXT_PUBLIC_CLOUDFRONT}/${key}`;
} catch {
try {
const originalBuffer = Buffer.from(await (await fetch(url)).arrayBuffer());
await s3.putObject({
Key: key,
Body: isSvg
? originalBuffer
: await convertToPng(originalBuffer),
ContentType: isSvg
? 'image/svg+xml'
: 'image/png',
ACL: 'public-read',
...s3BucketParams,
});
return `${process.env.NUXT_PUBLIC_CLOUDFRONT}/${key}`;
} catch (e) {
return null;
}
}
};