import { Client } from "minio"; import sharp from "sharp" import {config} from "dotenv" config() // Retrieve MinIO details from environment variables const minioEndpoint = process.env["S3_ENDPOINT_URL"] || "your-minio-endpoint"; const minioAccessKey = process.env["S3_ACCESS_KEY"] || "your-access-key"; const minioSecretKey = process.env["S3_SECRET_ACCESS_KEY"] || "your-secret-key"; const minioBucketName = "silvester23"; const minioClient = new Client({ endPoint: minioEndpoint, accessKey: minioAccessKey, secretKey: minioSecretKey, }); const objects = []; const objectStream = minioClient.listObjects(minioBucketName); for await (const obj of objectStream) { objects.push(obj); } async function compressObject(pngBuffer, fileName, format) { const newFilePath = `${fileName.slice(0, -4)}.${format}`; let buffer; switch (format) { case "webp": buffer = await sharp(pngBuffer).webp({ quality: 80 }).toBuffer(); break; case "jpg": buffer = await sharp(pngBuffer).jpeg({ quality: 80 }).toBuffer(); break; case "avif": buffer = await sharp(pngBuffer).avif({ quality: 80 }).toBuffer(); break; default: throw new Error(`Unknown format ${format}`); } // Upload the JPG buffer back to the same MinIO bucket await minioClient.putObject(minioBucketName, newFilePath, buffer, { 'Content-Type': 'image/' + format, }); console.log(`Uploaded ${newFilePath} to MinIO`); } async function fetchBuffer(objectName) { const chunks = []; return new Promise((res, rej) => { minioClient.getObject(minioBucketName,objectName, function (err, dataStream) { if (err) { return console.log(err) } dataStream.on('data', function (chunk) { chunks.push(chunk); }) dataStream.on('end', function () { res(Buffer.concat(chunks)) }) dataStream.on('error', function (err) { console.log(err) rej(err) }) }) }) } const pngs = objects.filter((o) => o.name.endsWith(".png")); console.log(`Found ${pngs.length} PNGs`); for (const obj of pngs) { const pngFilePath = obj.name; const jpgFilePath = pngFilePath.slice(0, -4) + ".jpg"; const avifFilePath = pngFilePath.slice(0, -4) + ".avif"; const webpFilePath = pngFilePath.slice(0, -4) + ".webp"; const hasJpg = objects.some((o) => o.name === jpgFilePath); const hasAvif = objects.some((o) => o.name === avifFilePath); const hasWebp = objects.some((o) => o.name === webpFilePath); if(hasAvif && hasJpg && hasWebp) { continue; } const pngBuffer = await fetchBuffer(pngFilePath); if(!hasJpg) { await compressObject(pngBuffer, pngFilePath, "jpg"); } if(!hasAvif) { await compressObject(pngBuffer, pngFilePath, "avif"); } if(!hasWebp) { await compressObject(pngBuffer, pngFilePath, "webp"); } }