From c2ad5153663f3f73d9c448a34f3c9c1993f0e419 Mon Sep 17 00:00:00 2001 From: nico Date: Tue, 27 Jan 2026 10:50:33 +0800 Subject: [PATCH] Fix Seed Image 27 Jan --- bun.lockb | Bin 424350 -> 427009 bytes package.json | 2 + prisma/resolveImageByName.ts | 87 +- prisma/safeSeedMany.ts | 45 ++ prisma/safeseedUnique.ts | 87 +- prisma/seed.ts | 2 +- prisma/seed_assets.ts | 756 +++++++++++------- .../(pages)/desa/galery/video/[id]/page.tsx | 10 +- 8 files changed, 676 insertions(+), 313 deletions(-) create mode 100644 prisma/safeSeedMany.ts diff --git a/bun.lockb b/bun.lockb index 14f3d9e9c553e8c6ef5d3af125a851b747a3e886..afa73367054fd4c567f7f3ee08d6856f71413675 100755 GIT binary patch delta 80538 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 delta 78602 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 YXz$&lU39xXTSHseo-aJLZieaq2XO##n*aa+ diff --git a/package.json b/package.json index cfab3f92..2cfb90fb 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "bun": "^1.2.2", "chart.js": "^4.4.8", "classnames": "^2.5.1", + "cli-progress": "^3.12.0", "colors": "^1.4.0", "date-fns": "^4.1.0", "dayjs": "^1.11.13", @@ -104,6 +105,7 @@ }, "devDependencies": { "@eslint/eslintrc": "^3", + "@types/cli-progress": "^3.11.6", "@types/jsonwebtoken": "^9.0.10", "@types/node": "^20", "@types/react": "^19", diff --git a/prisma/resolveImageByName.ts b/prisma/resolveImageByName.ts index 0d9e0cff..e105eef3 100644 --- a/prisma/resolveImageByName.ts +++ b/prisma/resolveImageByName.ts @@ -1,25 +1,78 @@ +// import prisma from "@/lib/prisma"; + +// // Ganti nama fungsi dan logikanya +// export default async function resolveImageById( +// imageId?: string | null +// ): Promise { +// if (!imageId) return null; + +// const image = await prisma.fileStorage.findFirst({ +// where: { +// id: imageId, // ← cari berdasarkan ID +// category: "image", +// isActive: true, +// deletedAt: null, +// }, +// select: { id: true }, +// }); + +// if (!image) { +// console.warn(`⚠️ Image with ID ${imageId} not found`); +// return null; +// } + +// return image.id; +// } + import prisma from "@/lib/prisma"; -// Ganti nama fungsi dan logikanya -export default async function resolveImageById( - imageId?: string | null -): Promise { +/** + * Resolve image ID by checking multiple possible names + * @param imageId - The ID from JSON (could be filename or actual ID) + * @returns The actual database ID or null + */ +export default async function resolveImageById(imageId: string | null): Promise { if (!imageId) return null; - const image = await prisma.fileStorage.findFirst({ - where: { - id: imageId, // ← cari berdasarkan ID - category: "image", - isActive: true, - deletedAt: null, - }, - select: { id: true }, - }); + try { + // 1. Coba cari berdasarkan ID langsung + const byId = await prisma.fileStorage.findUnique({ + where: { id: imageId }, + select: { id: true }, + }); + if (byId) return byId.id; - if (!image) { - console.warn(`⚠️ Image with ID ${imageId} not found`); + // 2. Coba cari berdasarkan name (exact match) + const byName = await prisma.fileStorage.findUnique({ + where: { name: imageId }, + select: { id: true }, + }); + if (byName) return byName.id; + + // 3. Coba cari berdasarkan realName + const byRealName = await prisma.fileStorage.findFirst({ + where: { realName: imageId }, + select: { id: true }, + }); + if (byRealName) return byRealName.id; + + // 4. Coba dengan menambahkan ekstensi .webp + const withWebp = `${imageId.replace(/\.(jpg|jpeg|png)$/i, '')}.webp`; + const byWebp = await prisma.fileStorage.findFirst({ + where: { + OR: [ + { name: withWebp }, + { name: { contains: imageId.split('.')[0] } }, + ], + }, + select: { id: true }, + }); + if (byWebp) return byWebp.id; + + console.warn(`⚠️ Image not found for: ${imageId}`); + return null; + } catch (error) { + console.error(`❌ Error resolving image ${imageId}:`, error); return null; } - - return image.id; } \ No newline at end of file diff --git a/prisma/safeSeedMany.ts b/prisma/safeSeedMany.ts new file mode 100644 index 00000000..d909bb2c --- /dev/null +++ b/prisma/safeSeedMany.ts @@ -0,0 +1,45 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { PrismaClient } from "@prisma/client"; +import { safeSeedUnique } from "./safeseedUnique"; +import cliProgress from 'cli-progress'; + +type SafeSeedOptions = { + skipUpdate?: boolean; + silent?: boolean; // Opsional: untuk suppress log +}; + +/** + * Batch upsert with progress logging + */ +export async function safeSeedMany( + model: T, + items: Array<{ where: Record; data: Record }>, + options: SafeSeedOptions = {} +) { + const bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic); + bar.start(items.length, 0); + + let success = 0; + let failed = 0; + let skipped = 0; + + for (const [index, item] of items.entries()) { + try { + const result = await safeSeedUnique(model, item.where, item.data, { + ...options, + silent: true, + }); + if (result) success++; + else skipped++; + } catch (err) { + failed++; + } + bar.update(index + 1); + } + + bar.stop(); + console.log(`✅ ${String(model)}: ${success} seeded, ${skipped} skipped, ${failed} failed`); + + return { success, skipped, failed }; +} \ No newline at end of file diff --git a/prisma/safeseedUnique.ts b/prisma/safeseedUnique.ts index 75f942dd..e0ea0d52 100644 --- a/prisma/safeseedUnique.ts +++ b/prisma/safeseedUnique.ts @@ -4,9 +4,16 @@ import { PrismaClient } from "@prisma/client"; type SafeSeedOptions = { skipUpdate?: boolean; + silent?: boolean; // Opsional: untuk suppress log }; -// prisma/safeseedUnique.ts +/** + * Safely upsert data with error handling + * @param model - Prisma model name + * @param where - Unique identifier(s) + * @param data - Full data object (will be used for create) + * @param options - Additional options + */ export async function safeSeedUnique( model: T, where: Record, @@ -14,23 +21,87 @@ export async function safeSeedUnique( options: SafeSeedOptions = {} ) { const m = prisma[model] as any; - if (!m) throw new Error(`Model ${String(model)} tidak ditemukan`); + + if (!m) { + throw new Error(`❌ Model ${String(model)} tidak ditemukan di Prisma Client`); + } try { - // Pastikan `where` berisi field yang benar-benar unique (misal: `id`) const result = await m.upsert({ where, update: options.skipUpdate ? {} : data, - create: data, // ✅ Jangan duplikasi `where` ke `create` + create: data, }); - console.log(`✅ Seed ${String(model)}:`, where); + + if (!options.silent) { + console.log(`✅ Seeded ${String(model)}:`, where); + } + return result; - } catch (err) { - console.error(`❌ Gagal seed ${String(model)}:`, where, err); - throw err; // ✅ Rethrow agar seeding berhenti jika kritis + } catch (err: any) { + // Handle specific Prisma errors + if (err.code === "P2002") { + console.warn(`⚠️ Duplicate ${String(model)} (skipped):`, where); + return null; + } + + if (err.code === "P2003") { + console.error(`❌ Foreign key constraint failed for ${String(model)}:`, where); + console.error(" Missing relation:", err.meta?.field_name); + throw err; + } + + if (err.code === "P2025") { + console.error(`❌ Record not found for ${String(model)}:`, where); + throw err; + } + + // Log unexpected errors with full details + console.error(`❌ Failed to seed ${String(model)}:`, where); + console.error(" Error:", err.message); + console.error(" Code:", err.code); + + throw err; } } + + +//ini yang bener pertama + +// /* eslint-disable @typescript-eslint/no-explicit-any */ +// import prisma from "@/lib/prisma"; +// import { PrismaClient } from "@prisma/client"; + +// type SafeSeedOptions = { +// skipUpdate?: boolean; +// }; + +// // prisma/safeseedUnique.ts +// export async function safeSeedUnique( +// model: T, +// where: Record, +// data: Record, +// options: SafeSeedOptions = {} +// ) { +// const m = prisma[model] as any; +// if (!m) throw new Error(`Model ${String(model)} tidak ditemukan`); + +// try { +// // Pastikan `where` berisi field yang benar-benar unique (misal: `id`) +// const result = await m.upsert({ +// where, +// update: options.skipUpdate ? {} : data, +// create: data, // ✅ Jangan duplikasi `where` ke `create` +// }); +// console.log(`✅ Seed ${String(model)}:`, where); +// return result; +// } catch (err) { +// console.error(`❌ Gagal seed ${String(model)}:`, where, err); +// throw err; // ✅ Rethrow agar seeding berhenti jika kritis +// } +// } + // /* eslint-disable @typescript-eslint/no-explicit-any */ // import { PrismaClient } from "@prisma/client"; diff --git a/prisma/seed.ts b/prisma/seed.ts index 3772fb42..129643d5 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -3018,6 +3018,7 @@ import resolveImageById from "./resolveImageByName"; } console.log("✅ Data perpustakaan seeded successfully"); + // =========== SUBMENU DATA PENDIDIKAN ===================== console.log("🔄 Seeding Data pendidikan..."); for (const k of dataPendidikan) { await prisma.dataPendidikan.upsert({ @@ -3037,7 +3038,6 @@ import resolveImageById from "./resolveImageByName"; } console.log("✅ Data pendidikan seeded successfully"); - // =========== SUBMENU DATA PENDIDIKAN ===================== })() .then(() => prisma.$disconnect()) .catch((e) => { diff --git a/prisma/seed_assets.ts b/prisma/seed_assets.ts index 1565c034..1bc230da 100644 --- a/prisma/seed_assets.ts +++ b/prisma/seed_assets.ts @@ -1,218 +1,27 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -// prisma/seedAssets.ts -import prisma from "@/lib/prisma"; -import AdmZip from "adm-zip"; -import fs from "fs/promises"; -import path from "path"; -import sharp from "sharp"; -import fetchWithRetry from "./data/fetchWithRetry"; - -const UPLOADS_DIR = path.resolve(process.env.WIBU_UPLOAD_DIR || "uploads"); - -// --- Helper: deteksi kategori file --- -function detectCategory(filename: string): "image" | "document" | "other" { - const ext = path.extname(filename).toLowerCase(); - if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image"; - if ([".pdf", ".doc", ".docx"].includes(ext)) return "document"; - return "other"; -} - -// --- Helper: recursive walk dir --- -async function walkDir( - dir: string, - fileList: string[] = [], -): Promise { - const entries = await fs.readdir(dir, { withFileTypes: true }); - - for (const entry of entries) { - const fullPath = path.join(dir, entry.name); - - if (entry.isDirectory()) { - if (entry.name === "__MACOSX") continue; // skip folder sampah - await walkDir(fullPath, fileList); - } else { - if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; // skip file sampah - fileList.push(fullPath); - } - } - - return fileList; -} - -export default async function seedAssets() { - console.log("🚀 Seeding assets..."); - console.log("📁 Upload dir:", UPLOADS_DIR); - - await fs.mkdir(UPLOADS_DIR, { recursive: true }); - - // 1. Download zip - const url = - "https://cld-dkr-makuro-seafile.wibudev.com/f/03be4043989e4caeb36b/?dl=1"; - const res = await fetchWithRetry(url, 3, 20000); - - // Validasi content-type - const contentType = res.headers.get("content-type"); - if (!contentType?.includes("zip")) { - throw new Error(`Invalid content-type (${contentType}). Expected ZIP file`); - } - - const buffer = Buffer.from(await res.arrayBuffer()); - - // Validasi ukuran file - if (buffer.length < 100) { - throw new Error("Downloaded ZIP is empty or corrupted"); - } - - // Validasi signature ZIP ("PK") - if (buffer.toString("utf8", 0, 2) !== "PK") { - throw new Error("Invalid ZIP signature (PK not found)"); - } - - // 2. Extract zip ke folder tmp - const extractDir = path.join(process.cwd(), "tmp_assets"); - await fs.rm(extractDir, { recursive: true, force: true }); - await fs.mkdir(extractDir, { recursive: true }); - - let zip: AdmZip; - - try { - zip = new AdmZip(buffer); - } catch (err) { - throw new Error("Failed to parse ZIP file (corrupted or invalid)"); - } - - try { - zip.extractAllTo(extractDir, true); - } catch (err) { - throw new Error("Failed to extract ZIP contents"); - } - - // 3. Cari semua file valid (recursive) - const files = await walkDir(extractDir); - - // 4. Loop tiap file & simpan - for (const filePath of files) { - const entryName = path.basename(filePath); - const category = detectCategory(entryName); - - let finalName = entryName; - let mimeType = "application/octet-stream"; - let targetPath = ""; - - if (category === "image") { - const fileBaseName = path.parse(entryName).name; - finalName = `${fileBaseName}.webp`; - targetPath = path.join(UPLOADS_DIR, "images", finalName); - await fs.mkdir(path.dirname(targetPath), { recursive: true }); - await sharp(filePath).webp({ quality: 80 }).toFile(targetPath); - mimeType = "image/webp"; - } else if (category === "document") { - targetPath = path.join(UPLOADS_DIR, "documents", entryName); - await fs.mkdir(path.dirname(targetPath), { recursive: true }); - await fs.copyFile(filePath, targetPath); - mimeType = "application/pdf"; - } else { - targetPath = path.join(UPLOADS_DIR, "other", entryName); - await fs.mkdir(path.dirname(targetPath), { recursive: true }); - await fs.copyFile(filePath, targetPath); - } - - const existing = await prisma.fileStorage.findUnique({ - where: { name: finalName }, - }); - - if (existing) { - // Restore kalau soft deleted - await prisma.fileStorage.update({ - where: { name: finalName }, - data: { - path: targetPath, - realName: entryName, - mimeType, - link: `/uploads/${category}/${finalName}`, - category, - deletedAt: null, - isActive: true, - }, - }); - - console.log(`♻️ restored: ${category}/${finalName}`); - } else { - await prisma.fileStorage.create({ - data: { - name: finalName, - realName: entryName, - path: targetPath, - mimeType, - link: `/uploads/${category}/${finalName}`, - category, - }, - }); - - console.log(`📂 created: ${category}/${finalName}`); - } - - console.log(`📂 saved: ${category}/${finalName}`); - } - - // 6. Cleanup - await fs.rm(extractDir, { recursive: true, force: true }); - - console.log("✅ Selesai seed assets!"); - console.log("DB URL (asset):", process.env.DATABASE_URL); -} - -// --- Auto run kalau dipanggil langsung --- -if (import.meta.main) { - seedAssets() - .catch((err) => { - console.error("❌ Error seeding assets:", err); - process.exit(1); - }) - .finally(async () => { - await prisma.$disconnect(); - }); -} - -// prisma/seedAssets.ts +// /* eslint-disable @typescript-eslint/no-unused-vars */ +// // prisma/seedAssets.ts // import prisma from "@/lib/prisma"; // import AdmZip from "adm-zip"; // import fs from "fs/promises"; // import path from "path"; // import sharp from "sharp"; -// import mime from "mime-types"; // import fetchWithRetry from "./data/fetchWithRetry"; -// /* ========================= -// * CONFIG -// * ========================= */ -// const UPLOADS_DIR = path.resolve( -// process.env.WIBU_UPLOAD_DIR || "uploads" -// ); +// const UPLOADS_DIR = path.resolve(process.env.WIBU_UPLOAD_DIR || "uploads"); -// const TMP_DIR = path.join(process.cwd(), "tmp_assets"); - -// const CATEGORY_DIR: Record = { -// image: "images", -// document: "documents", -// other: "other", -// }; - -// type FileCategory = "image" | "document" | "other"; - -// /* ========================= -// * HELPERS -// * ========================= */ -// function detectCategory(filename: string): FileCategory { +// // --- Helper: deteksi kategori file --- +// function detectCategory(filename: string): "image" | "document" | "other" { // const ext = path.extname(filename).toLowerCase(); // if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image"; -// if ([".pdf", ".doc", ".docx", ".txt"].includes(ext)) return "document"; +// if ([".pdf", ".doc", ".docx"].includes(ext)) return "document"; // return "other"; // } +// // --- Helper: recursive walk dir --- // async function walkDir( // dir: string, -// result: string[] = [] +// fileList: string[] = [], // ): Promise { // const entries = await fs.readdir(dir, { withFileTypes: true }); @@ -220,139 +29,141 @@ if (import.meta.main) { // const fullPath = path.join(dir, entry.name); // if (entry.isDirectory()) { -// if (entry.name === "__MACOSX") continue; -// await walkDir(fullPath, result); +// if (entry.name === "__MACOSX") continue; // skip folder sampah +// await walkDir(fullPath, fileList); // } else { -// if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; -// result.push(fullPath); +// if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; // skip file sampah +// fileList.push(fullPath); // } // } -// return result; +// return fileList; // } -// async function ensureDir(dir: string) { -// await fs.mkdir(dir, { recursive: true }); -// } - -// /* ========================= -// * FILE PROCESSORS -// * ========================= */ -// async function processImage(filePath: string, entryName: string) { -// const baseName = path.parse(entryName).name; -// const finalName = `${baseName}.webp`; -// const targetDir = path.join(UPLOADS_DIR, CATEGORY_DIR.image); -// const targetPath = path.join(targetDir, finalName); - -// await ensureDir(targetDir); -// await sharp(filePath).webp({ quality: 80 }).toFile(targetPath); - -// return { -// finalName, -// targetPath, -// mimeType: "image/webp", -// }; -// } - -// async function processNonImage( -// filePath: string, -// entryName: string, -// category: FileCategory -// ) { -// const targetDir = path.join(UPLOADS_DIR, CATEGORY_DIR[category]); -// const targetPath = path.join(targetDir, entryName); - -// await ensureDir(targetDir); -// await fs.copyFile(filePath, targetPath); - -// return { -// finalName: entryName, -// targetPath, -// mimeType: mime.lookup(entryName) || "application/octet-stream", -// }; -// } - -// /* ========================= -// * MAIN -// * ========================= */ // export default async function seedAssets() { // console.log("🚀 Seeding assets..."); // console.log("📁 Upload dir:", UPLOADS_DIR); -// await ensureDir(UPLOADS_DIR); +// await fs.mkdir(UPLOADS_DIR, { recursive: true }); -// /* ===== Download ZIP ===== */ +// // 1. Download zip // const url = -// "https://cld-dkr-makuro-seafile.wibudev.com/f/e13d5429785640c098ae/?dl=1"; +// "https://cld-dkr-makuro-seafile.wibudev.com/f/03be4043989e4caeb36b/?dl=1"; // const res = await fetchWithRetry(url, 3, 20000); -// if (!res.headers.get("content-type")?.includes("zip")) { -// throw new Error("Invalid ZIP content-type"); +// // Validasi content-type +// const contentType = res.headers.get("content-type"); +// if (!contentType?.includes("zip")) { +// throw new Error(`Invalid content-type (${contentType}). Expected ZIP file`); // } // const buffer = Buffer.from(await res.arrayBuffer()); -// if (buffer.length < 100 || buffer.toString("utf8", 0, 2) !== "PK") { -// throw new Error("Corrupted ZIP file"); + +// // Validasi ukuran file +// if (buffer.length < 100) { +// throw new Error("Downloaded ZIP is empty or corrupted"); // } -// /* ===== Extract ===== */ -// await fs.rm(TMP_DIR, { recursive: true, force: true }); -// await ensureDir(TMP_DIR); +// // Validasi signature ZIP ("PK") +// if (buffer.toString("utf8", 0, 2) !== "PK") { +// throw new Error("Invalid ZIP signature (PK not found)"); +// } -// const zip = new AdmZip(buffer); -// zip.extractAllTo(TMP_DIR, true); +// // 2. Extract zip ke folder tmp +// const extractDir = path.join(process.cwd(), "tmp_assets"); +// await fs.rm(extractDir, { recursive: true, force: true }); +// await fs.mkdir(extractDir, { recursive: true }); -// /* ===== Process Files ===== */ -// const files = await walkDir(TMP_DIR); +// let zip: AdmZip; +// try { +// zip = new AdmZip(buffer); +// } catch (err) { +// throw new Error("Failed to parse ZIP file (corrupted or invalid)"); +// } + +// try { +// zip.extractAllTo(extractDir, true); +// } catch (err) { +// throw new Error("Failed to extract ZIP contents"); +// } + +// // 3. Cari semua file valid (recursive) +// const files = await walkDir(extractDir); + +// // 4. Loop tiap file & simpan // for (const filePath of files) { // const entryName = path.basename(filePath); // const category = detectCategory(entryName); -// let result; +// let finalName = entryName; +// let mimeType = "application/octet-stream"; +// let targetPath = ""; // if (category === "image") { -// result = await processImage(filePath, entryName); +// const fileBaseName = path.parse(entryName).name; +// finalName = `${fileBaseName}.webp`; +// targetPath = path.join(UPLOADS_DIR, "images", finalName); +// await fs.mkdir(path.dirname(targetPath), { recursive: true }); +// await sharp(filePath).webp({ quality: 80 }).toFile(targetPath); +// mimeType = "image/webp"; +// } else if (category === "document") { +// targetPath = path.join(UPLOADS_DIR, "documents", entryName); +// await fs.mkdir(path.dirname(targetPath), { recursive: true }); +// await fs.copyFile(filePath, targetPath); +// mimeType = "application/pdf"; // } else { -// result = await processNonImage(filePath, entryName, category); +// targetPath = path.join(UPLOADS_DIR, "other", entryName); +// await fs.mkdir(path.dirname(targetPath), { recursive: true }); +// await fs.copyFile(filePath, targetPath); // } -// const { finalName, targetPath, mimeType } = result; - // const existing = await prisma.fileStorage.findUnique({ // where: { name: finalName }, // }); -// const data = { -// name: finalName, -// realName: entryName, -// path: targetPath, -// mimeType, -// link: `/uploads/${CATEGORY_DIR[category]}/${finalName}`, -// category, -// deletedAt: null, -// isActive: true, -// }; - // if (existing) { +// // Restore kalau soft deleted // await prisma.fileStorage.update({ // where: { name: finalName }, -// data, +// data: { +// path: targetPath, +// realName: entryName, +// mimeType, +// link: `/uploads/${category}/${finalName}`, +// category, +// deletedAt: null, +// isActive: true, +// }, // }); + // console.log(`♻️ restored: ${category}/${finalName}`); // } else { -// await prisma.fileStorage.create({ data }); +// await prisma.fileStorage.create({ +// data: { +// name: finalName, +// realName: entryName, +// path: targetPath, +// mimeType, +// link: `/uploads/${category}/${finalName}`, +// category, +// }, +// }); + // console.log(`📂 created: ${category}/${finalName}`); // } + +// console.log(`📂 saved: ${category}/${finalName}`); // } -// /* ===== Cleanup ===== */ -// await fs.rm(TMP_DIR, { recursive: true, force: true }); +// // 6. Cleanup +// await fs.rm(extractDir, { recursive: true, force: true }); // console.log("✅ Selesai seed assets!"); +// console.log("DB URL (asset):", process.env.DATABASE_URL); // } -// /* ===== Auto Run ===== */ +// // --- Auto run kalau dipanggil langsung --- // if (import.meta.main) { // seedAssets() // .catch((err) => { @@ -363,3 +174,382 @@ if (import.meta.main) { // await prisma.$disconnect(); // }); // } + +// // prisma/seedAssets.ts +// // import prisma from "@/lib/prisma"; +// // import AdmZip from "adm-zip"; +// // import fs from "fs/promises"; +// // import path from "path"; +// // import sharp from "sharp"; +// // import mime from "mime-types"; +// // import fetchWithRetry from "./data/fetchWithRetry"; + +// // /* ========================= +// // * CONFIG +// // * ========================= */ +// // const UPLOADS_DIR = path.resolve( +// // process.env.WIBU_UPLOAD_DIR || "uploads" +// // ); + +// // const TMP_DIR = path.join(process.cwd(), "tmp_assets"); + +// // const CATEGORY_DIR: Record = { +// // image: "images", +// // document: "documents", +// // other: "other", +// // }; + +// // type FileCategory = "image" | "document" | "other"; + +// // /* ========================= +// // * HELPERS +// // * ========================= */ +// // function detectCategory(filename: string): FileCategory { +// // const ext = path.extname(filename).toLowerCase(); +// // if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image"; +// // if ([".pdf", ".doc", ".docx", ".txt"].includes(ext)) return "document"; +// // return "other"; +// // } + +// // async function walkDir( +// // dir: string, +// // result: string[] = [] +// // ): Promise { +// // const entries = await fs.readdir(dir, { withFileTypes: true }); + +// // for (const entry of entries) { +// // const fullPath = path.join(dir, entry.name); + +// // if (entry.isDirectory()) { +// // if (entry.name === "__MACOSX") continue; +// // await walkDir(fullPath, result); +// // } else { +// // if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; +// // result.push(fullPath); +// // } +// // } + +// // return result; +// // } + +// // async function ensureDir(dir: string) { +// // await fs.mkdir(dir, { recursive: true }); +// // } + +// // /* ========================= +// // * FILE PROCESSORS +// // * ========================= */ +// // async function processImage(filePath: string, entryName: string) { +// // const baseName = path.parse(entryName).name; +// // const finalName = `${baseName}.webp`; +// // const targetDir = path.join(UPLOADS_DIR, CATEGORY_DIR.image); +// // const targetPath = path.join(targetDir, finalName); + +// // await ensureDir(targetDir); +// // await sharp(filePath).webp({ quality: 80 }).toFile(targetPath); + +// // return { +// // finalName, +// // targetPath, +// // mimeType: "image/webp", +// // }; +// // } + +// // async function processNonImage( +// // filePath: string, +// // entryName: string, +// // category: FileCategory +// // ) { +// // const targetDir = path.join(UPLOADS_DIR, CATEGORY_DIR[category]); +// // const targetPath = path.join(targetDir, entryName); + +// // await ensureDir(targetDir); +// // await fs.copyFile(filePath, targetPath); + +// // return { +// // finalName: entryName, +// // targetPath, +// // mimeType: mime.lookup(entryName) || "application/octet-stream", +// // }; +// // } + +// // /* ========================= +// // * MAIN +// // * ========================= */ +// // export default async function seedAssets() { +// // console.log("🚀 Seeding assets..."); +// // console.log("📁 Upload dir:", UPLOADS_DIR); + +// // await ensureDir(UPLOADS_DIR); + +// // /* ===== Download ZIP ===== */ +// // const url = +// // "https://cld-dkr-makuro-seafile.wibudev.com/f/e13d5429785640c098ae/?dl=1"; +// // const res = await fetchWithRetry(url, 3, 20000); + +// // if (!res.headers.get("content-type")?.includes("zip")) { +// // throw new Error("Invalid ZIP content-type"); +// // } + +// // const buffer = Buffer.from(await res.arrayBuffer()); +// // if (buffer.length < 100 || buffer.toString("utf8", 0, 2) !== "PK") { +// // throw new Error("Corrupted ZIP file"); +// // } + +// // /* ===== Extract ===== */ +// // await fs.rm(TMP_DIR, { recursive: true, force: true }); +// // await ensureDir(TMP_DIR); + +// // const zip = new AdmZip(buffer); +// // zip.extractAllTo(TMP_DIR, true); + +// // /* ===== Process Files ===== */ +// // const files = await walkDir(TMP_DIR); + +// // for (const filePath of files) { +// // const entryName = path.basename(filePath); +// // const category = detectCategory(entryName); + +// // let result; + +// // if (category === "image") { +// // result = await processImage(filePath, entryName); +// // } else { +// // result = await processNonImage(filePath, entryName, category); +// // } + +// // const { finalName, targetPath, mimeType } = result; + +// // const existing = await prisma.fileStorage.findUnique({ +// // where: { name: finalName }, +// // }); + +// // const data = { +// // name: finalName, +// // realName: entryName, +// // path: targetPath, +// // mimeType, +// // link: `/uploads/${CATEGORY_DIR[category]}/${finalName}`, +// // category, +// // deletedAt: null, +// // isActive: true, +// // }; + +// // if (existing) { +// // await prisma.fileStorage.update({ +// // where: { name: finalName }, +// // data, +// // }); +// // console.log(`♻️ restored: ${category}/${finalName}`); +// // } else { +// // await prisma.fileStorage.create({ data }); +// // console.log(`📂 created: ${category}/${finalName}`); +// // } +// // } + +// // /* ===== Cleanup ===== */ +// // await fs.rm(TMP_DIR, { recursive: true, force: true }); + +// // console.log("✅ Selesai seed assets!"); +// // } + +// // /* ===== Auto Run ===== */ +// // if (import.meta.main) { +// // seedAssets() +// // .catch((err) => { +// // console.error("❌ Error seeding assets:", err); +// // process.exit(1); +// // }) +// // .finally(async () => { +// // await prisma.$disconnect(); +// // }); +// // } + +import prisma from "@/lib/prisma"; +import AdmZip from "adm-zip"; +import fs from "fs/promises"; +import path from "path"; +import sharp from "sharp"; +import fetchWithRetry from "./data/fetchWithRetry"; +import { constants } from "fs"; + +// ✅ Gunakan env variable dengan fallback +const UPLOADS_DIR = path.join(process.cwd(), process.env.WIBU_UPLOAD_DIR || "uploads"); + + +function detectCategory(filename: string): "image" | "document" | "other" { + const ext = path.extname(filename).toLowerCase(); + if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image"; + if ([".pdf", ".doc", ".docx"].includes(ext)) return "document"; + return "other"; +} + +async function walkDir( + dir: string, + fileList: string[] = [], +): Promise { + const entries = await fs.readdir(dir, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + if (entry.name === "__MACOSX") continue; + await walkDir(fullPath, fileList); + } else { + if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; + fileList.push(fullPath); + } + } + return fileList; +} + +export default async function seedAssets() { + console.log("🚀 Seeding assets..."); + console.log("📁 Upload dir:", UPLOADS_DIR); + + try { + await fs.access(UPLOADS_DIR, fs.constants.W_OK); + } catch (err) { + console.error("❌ Upload directory is not writable:", UPLOADS_DIR); + throw new Error( + `UPLOADS_DIR not writable: ${UPLOADS_DIR}. Check Docker volume or permissions` + ); + } + + // ✅ Pastikan folder exist + await fs.mkdir(UPLOADS_DIR, { recursive: true }); + try { + await fs.access(UPLOADS_DIR, constants.W_OK); +} catch { + throw new Error( + `UPLOADS_DIR not writable: ${UPLOADS_DIR}. Check Docker volume or permissions` + ); +} + await fs.mkdir(path.join(UPLOADS_DIR, "images"), { recursive: true }); + await fs.mkdir(path.join(UPLOADS_DIR, "documents"), { recursive: true }); + await fs.mkdir(path.join(UPLOADS_DIR, "other"), { recursive: true }); + + const url = + "https://cld-dkr-makuro-seafile.wibudev.com/f/8e9e42e9f3e94c80919e/?dl=1"; + + let buffer: Buffer; + try { + console.log("⬇️ Downloading ZIP from:", url); + const res = await fetchWithRetry(url, 3, 20000); + + const contentType = res.headers.get("content-type"); + if ( + !contentType?.includes("zip") && + !contentType?.includes("octet-stream") + ) { + throw new Error( + `Invalid content-type (${contentType}). Expected ZIP file`, + ); + } + + buffer = Buffer.from(await res.arrayBuffer()); + + if (buffer.length < 100) { + throw new Error("Downloaded ZIP is empty or corrupted"); + } + + if (buffer.toString("utf8", 0, 2) !== "PK") { + throw new Error("Invalid ZIP signature (PK not found)"); + } + + console.log(`✅ Downloaded ${(buffer.length / 1024 / 1024).toFixed(2)} MB`); + } catch (err) { + console.error("❌ Failed to download ZIP:", err); + throw err; + } + + // Extract ZIP + const extractDir = path.join(process.cwd(), "tmp_assets"); + await fs.rm(extractDir, { recursive: true, force: true }); + await fs.mkdir(extractDir, { recursive: true }); + + let zip: AdmZip; + try { + zip = new AdmZip(buffer); + zip.extractAllTo(extractDir, true); + console.log("✅ ZIP extracted successfully"); + } catch (err) { + console.error("❌ Failed to extract ZIP:", err); + throw err; + } + + const files = await walkDir(extractDir); + console.log(`📦 Found ${files.length} files to process`); + + // Process files + for (const filePath of files) { + const entryName = path.basename(filePath); + const category = detectCategory(entryName); + + let finalName = entryName; + let mimeType = "application/octet-stream"; + let targetPath = ""; + + try { + if (category === "image") { + const fileBaseName = path.parse(entryName).name; + finalName = `${fileBaseName}.webp`; + targetPath = path.join(UPLOADS_DIR, "images", finalName); + + await fs.mkdir(path.dirname(targetPath), { recursive: true }); + await sharp(filePath).webp({ quality: 80 }).toFile(targetPath); + mimeType = "image/webp"; + } else if (category === "document") { + targetPath = path.join(UPLOADS_DIR, "documents", entryName); + await fs.mkdir(path.dirname(targetPath), { recursive: true }); + await fs.copyFile(filePath, targetPath); + mimeType = "application/pdf"; + } else { + targetPath = path.join(UPLOADS_DIR, "other", entryName); + await fs.mkdir(path.dirname(targetPath), { recursive: true }); + await fs.copyFile(filePath, targetPath); + } + + // ✅ Upsert ke database + await prisma.fileStorage.upsert({ + where: { name: finalName }, + update: { + path: path.dirname(targetPath), + realName: entryName, + mimeType, + link: `/api/fileStorage/findUnique/${finalName}`, + category, + deletedAt: null, + isActive: true, + }, + create: { + name: finalName, + realName: entryName, + path: path.dirname(targetPath), + mimeType, + link: `/api/fileStorage/findUnique/${finalName}`, + category, + }, + }); + + console.log(`✅ Processed: ${category}/${finalName}`); + } catch (err) { + console.error(`❌ Failed to process ${entryName}`, err); + throw err; // ⛔ penting + } + } + + // Cleanup + await fs.rm(extractDir, { recursive: true, force: true }); + console.log("✅ Asset seeding completed!"); +} + +if (import.meta.main) { + seedAssets() + .catch((err) => { + console.error("❌ Error seeding assets:", err); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + }); +} diff --git a/src/app/darmasaba/(pages)/desa/galery/video/[id]/page.tsx b/src/app/darmasaba/(pages)/desa/galery/video/[id]/page.tsx index 2e65b465..8b3fa242 100644 --- a/src/app/darmasaba/(pages)/desa/galery/video/[id]/page.tsx +++ b/src/app/darmasaba/(pages)/desa/galery/video/[id]/page.tsx @@ -1,7 +1,9 @@ 'use client'; +import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery'; import colors from '@/con/colors'; import { + ActionIcon, Alert, Box, Button, @@ -15,12 +17,10 @@ import { Title, } from '@mantine/core'; import { useShallowEffect } from '@mantine/hooks'; -import { IconArrowBack, IconInfoCircle, IconVideo } from '@tabler/icons-react'; +import { IconArrowBack, IconArrowLeft, IconInfoCircle, IconVideo } from '@tabler/icons-react'; import { useParams, useRouter } from 'next/navigation'; import { useState } from 'react'; import { useProxy } from 'valtio/utils'; -import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery'; -import BackButton from '../../../layanan/_com/BackButto'; function convertToEmbedUrl(youtubeUrl: string): string { @@ -95,7 +95,9 @@ export default function DetailVideoUser() { {/* Tombol Kembali */} - + router.push('/darmasaba/desa/galery/video')}> + + {/* Header - Dijadikan Title */}