new Cloudinary image logic - schema, validation,

This commit is contained in:
Matthieu Morin 2024-04-05 14:28:25 +02:00
parent c78de3ec28
commit 6ac2261cf1
6 changed files with 119 additions and 50 deletions

View File

@ -4,7 +4,9 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"validate": "node ./tests/ValidateServices.js", "validate:images": "node ./tests/validateImages.js",
"validate:services": "node ./tests/ValidateServices.js",
"validate": "pnpm run validate:services && validate:images",
"dev": "pnpm run validate && vite dev --mode development", "dev": "pnpm run validate && vite dev --mode development",
"build": "pnpm run validate && vite build", "build": "pnpm run validate && vite build",
"build-dev": "pnpm run validate && vite build --mode development", "build-dev": "pnpm run validate && vite build --mode development",

14
src/content/images.json Normal file
View File

@ -0,0 +1,14 @@
{
"example_image": {
"publicId": "example_image",
"transformations": [
{ "width": 1200, "height": 627, "crop": "fill", "quality": "auto", "format": "auto" }
]
},
"another_image": {
"publicId": "another_image",
"transformations": [
{ "width": 800, "height": 600, "crop": "fill", "quality": "auto", "format": "auto" }
]
}
}

View File

@ -1,49 +0,0 @@
{
"$schema": "../schema-categories.json",
"title": "Vakuslim 48 - zeštíhlující procedura",
"description": "A description of a description",
"id": "depilace",
"image": "",
"services": [
{
"title": "Ošetření horních končetin",
"description": "Diagnostika pleti, odlíčení tonizace",
"id": "vakuslim-48-zestihlujici-procedura-horni-koncetiny",
"image": "",
"price": 600,
"duration": 120
},
{
"title": "1 ošetření spodní části těla (břicho, boky, dolní končetiny)",
"description": "Diagnostika pleti, odlíčení tonizace",
"id": "vakuslim-48-zestihlujici-procedura-spodni-cast-tela",
"image": "",
"price": 800,
"duration": 120
},
{
"title": "1 ošetření komplet horní-dolní části",
"description": "Diagnostika pleti, odlíčení tonizace",
"id": "vakuslim-48-zestihlujici-procedura-komplet-horni-dolni-cast",
"image": "",
"price": 1200,
"duration": 120
},
{
"title": "6 ošetření předplatné kompet",
"description": "Diagnostika pleti, odlíčení tonizace",
"id": "vakuslim-48-zestihlujici-procedura-6-o-setreni-predplatne-kompet",
"image": "",
"price": 6600,
"duration": 120
},
{
"title": "12 ošetření předplatné komplet",
"description": "Diagnostika pleti, odlíčení tonizace",
"id": "vakuslim-48-zestihlujici-procedura-12-o-setreni-predplatne-komplet",
"image": "",
"price": 11000,
"duration": 120
}
]
}

View File

@ -0,0 +1,21 @@
// imageService.ts
import cloudinary from 'cloudinary';
import imagesData from '$content/images.json';
cloudinary.v2.config({
cloud_name: import.meta.env.VITE_CLOUDINARY_CLOUD_NAME,
});
export const getCloudinaryImageUrl = (publicId: string, options: cloudinary.UploadApiOptions = {}) => {
const imageData = imagesData[publicId];
if (!imageData) {
throw new Error(`Image with public ID ${publicId} not found in images.json`);
}
const transformationOptions = {
...options,
...imageData.transformations,
};
return cloudinary.v2.url(publicId, transformationOptions);
};

View File

@ -0,0 +1,49 @@
// uploadImages.ts
import fs from 'fs';
import path from 'path';
import cloudinary from 'cloudinary';
import matter from 'gray-matter';
cloudinary.v2.config({
cloud_name: import.meta.env.VITE_CLOUDINARY_CLOUD_NAME,
api_key: import.meta.env.VITE_CLOUDINARY_API_KEY,
api_secret: import.meta.env.VITE_CLOUDINARY_API_SECRET,
});
const contentDir = 'src/content';
const imagesJsonPath = 'src/content/images.json';
async function uploadImages() {
const imagesData = {};
// Read all Markdown files in the content directory
const mdFiles = fs.readdirSync(contentDir).filter((file) => file.endsWith('.md'));
for (const mdFile of mdFiles) {
const mdFilePath = path.join(contentDir, mdFile);
const mdContent = fs.readFileSync(mdFilePath, 'utf-8');
const { data, content } = matter(mdContent);
// Extract relative image paths from the Markdown content
const imagePaths = content.match(/\!\[.*?\]\((.*?)\)/g) || [];
for (const imagePath of imagePaths) {
const relativeImagePath = imagePath.match(/\((.*?)\)/)[1];
const imageFilePath = path.join(contentDir, relativeImagePath);
// Upload the image to Cloudinary
const uploadResult = await cloudinary.v2.uploader.upload(imageFilePath);
// Add the image metadata to the imagesData object
imagesData[uploadResult.public_id] = {
publicId: uploadResult.public_id,
// Add any desired transformation options here
};
}
}
// Write the imagesData to the images.json file
fs.writeFileSync(imagesJsonPath, JSON.stringify(imagesData, null, 2));
}
uploadImages();

32
tests/validateImages.js Normal file
View File

@ -0,0 +1,32 @@
import cloudinary from 'cloudinary';
import imagesData from '$content/images.json';
import { env } from '$env/dynamic/private';
cloudinary.v2.config({
cloud_name: env.CLOUDINARY_CLOUD_NAME,
api_key: env.CLOUDINARY_API_KEY,
api_secret: env.CLOUDINARY_API_SECRET,
});
async function validateImages() {
const invalidImages = [];
for (const publicId in imagesData) {
try {
// Check if the image exists on Cloudinary
await cloudinary.v2.api.resource(publicId);
} catch (error) {
invalidImages.push(publicId);
}
}
if (invalidImages.length > 0) {
console.error(`The following images are missing or invalid on Cloudinary: ${invalidImages.join(', ')}`);
process.exit(1);
} else {
console.log('All images are valid on Cloudinary.');
}
}
validateImages();