/** * Zet de dienst-foto's écht in de mediabibliotheek (R2 + `media`-tabel) en koppelt ze aan * de 25 beeldvelden van de 5 diensten (nav/hero + 3 resultaat-slots). Eén media-rij per * unieke bronfoto (13), meerdere velden mogen dezelfde foto delen. * Lokaal provider: storage_key == R2-objectkey; src wordt op displaytijd afgeleid. * Print UPLOAD-regels (storageKey + bronbestand) voor de PowerShell-uploadstap. */ import { ulid } from "ulidx"; import { writeFileSync, mkdirSync } from "node:fs"; // 13 unieke bronfoto's (variant gekozen op formaat: -1280 voor hero/cards, werk-basis voor galerij). const IMAGES = { "dienst-gevel": { file: "dienst-gevelreiniging-1280.webp", w: 1280, h: 956, size: 223140, alt: "Bakstenen gevel halverwege de reiniging" }, "dienst-voeg": { file: "dienst-voegwerk-1280.webp", w: 1280, h: 956, size: 158522, alt: "Strak nieuw voegwerk tussen rode bakstenen" }, "dienst-dak": { file: "dienst-dakreiniging-1280.webp", w: 1280, h: 956, size: 147566, alt: "Schoon dakpannendak na reiniging en coating" }, "dienst-schoorsteen": { file: "dienst-schoorsteen-1280.webp", w: 1280, h: 956, size: 141238, alt: "Herstelde schoorsteen met nieuw voegwerk op een dak" }, "dienst-algemeen": { file: "dienst-algemeen-1280.webp", w: 1280, h: 956, size: 283500, alt: "Vers gereinigd terras en bestrating" }, "hero-after": { file: "hero-after-1280.webp", w: 1280, h: 714, size: 158222, alt: "Schone bakstenen gevel na reiniging" }, "hero-gevel": { file: "hero-gevel-1280.webp", w: 1280, h: 714, size: 192040, alt: "Verzorgde, schone gevel van een woonhuis" }, "werk-1": { file: "werk-1.webp", w: 1200, h: 1600, size: 376578, alt: "Schoorsteen met nieuw aangebracht loodwerk op een dak" }, "werk-2": { file: "werk-2.webp", w: 1600, h: 1200, size: 341744, alt: "Schone tuinmuur en bestrating na reiniging" }, "werk-3": { file: "werk-3.webp", w: 738, h: 1600, size: 181398, alt: "Strak nieuw voegwerk tussen de bakstenen van een gevel" }, "werk-4": { file: "werk-4.webp", w: 1200, h: 1600, size: 614486, alt: "Dakpannendak vol mos voor de reiniging" }, "werk-5": { file: "werk-5.webp", w: 1200, h: 1600, size: 428016, alt: "Dak wordt op hoogte gereinigd" }, "werk-6": { file: "werk-6.webp", w: 1200, h: 1600, size: 293814, alt: "Hersteld metsel- en voegwerk aan een tuinmuur met trap" }, }; // Veld -> foto per dienst (nav==hero per dienst; resultaat = de 3 galerij-foto's). const MAP = { "gevelreiniging": { nav_image: "dienst-gevel", hero_image: "dienst-gevel", result_1_image: "hero-after", result_2_image: "dienst-voeg", result_3_image: "hero-gevel" }, "voegwerk": { nav_image: "dienst-voeg", hero_image: "dienst-voeg", result_1_image: "werk-3", result_2_image: "werk-6", result_3_image: "hero-gevel" }, "dakreiniging-coating": { nav_image: "dienst-dak", hero_image: "dienst-dak", result_1_image: "werk-4", result_2_image: "werk-5", result_3_image: "dienst-dak" }, "schoorsteen-voegwerk": { nav_image: "dienst-schoorsteen", hero_image: "dienst-schoorsteen", result_1_image: "werk-1", result_2_image: "werk-6", result_3_image: "dienst-schoorsteen" }, "algemeen-reinigen": { nav_image: "dienst-algemeen", hero_image: "dienst-algemeen", result_1_image: "werk-2", result_2_image: "werk-6", result_3_image: "dienst-algemeen" }, }; const q = (s) => "'" + String(s).replace(/'/g, "''") + "'"; // Wijs elke unieke foto een ULID + storageKey toe. for (const k of Object.keys(IMAGES)) { const id = ulid(); IMAGES[k].id = id; IMAGES[k].storageKey = id + ".webp"; } function fieldJson(img) { return JSON.stringify({ id: img.id, provider: "local", filename: img.file, mimeType: "image/webp", width: img.w, height: img.h, alt: img.alt, meta: { storageKey: img.storageKey }, }); } const lines = ["-- Diensten: foto's in de mediabibliotheek + gekoppeld aan de 25 beeldvelden."]; lines.push("INSERT OR REPLACE INTO media (id, filename, mime_type, size, width, height, alt, storage_key, status, created_at) VALUES"); const mediaRows = Object.values(IMAGES).map( (img) => ` (${q(img.id)}, ${q(img.file)}, 'image/webp', ${img.size}, ${img.w}, ${img.h}, ${q(img.alt)}, ${q(img.storageKey)}, 'ready', datetime('now'))`, ); lines.push(mediaRows.join(",\n") + ";"); for (const [slug, fields] of Object.entries(MAP)) { for (const [field, imgKey] of Object.entries(fields)) { lines.push(`UPDATE ec_diensten SET ${field}=${q(fieldJson(IMAGES[imgKey]))} WHERE slug=${q(slug)};`); } } mkdirSync("migrations", { recursive: true }); writeFileSync("migrations/0010_diensten_media.sql", lines.join("\n") + "\n", "utf8"); // Print de upload-mapping (uniek per bronbestand) voor de R2-stap. for (const img of Object.values(IMAGES)) { console.log(`UPLOAD|public/images/${img.file}|${img.storageKey}`); } console.log("geschreven: migrations/0010_diensten_media.sql");