merge(stg): merge main into stg and resolve storage conflicts

This commit is contained in:
2026-04-23 13:48:26 +08:00
36 changed files with 17763 additions and 233 deletions

View File

@@ -0,0 +1,97 @@
/**
* Script migrasi: download semua file dari Seafile public share → upload ke MinIO
* Jalankan sekali: bun run prisma/migrate-seafile-to-minio.ts
*/
import { Client } from "minio";
import fileStorageData from "./data/file-storage.json";
const SEAFILE_BASE_URL = "https://cld-dkr-makuro-seafile.wibudev.com";
const SEAFILE_SHARE_TOKEN = "3a9a9ecb5e244f4da8ae";
const minio = new Client({
endPoint: process.env.MINIO_ENDPOINT!,
accessKey: process.env.MINIO_ACCESS_KEY!,
secretKey: process.env.MINIO_SECRET_KEY!,
useSSL: process.env.MINIO_USE_SSL === "true",
});
const BUCKET = process.env.MINIO_BUCKET!;
function buildSeafileUrl(fileName: string): string {
return `${SEAFILE_BASE_URL}/d/${SEAFILE_SHARE_TOKEN}/files/?p=${encodeURIComponent(fileName)}&raw=1`;
}
function guessMimeType(fileName: string): string {
const ext = fileName.split(".").pop()?.toLowerCase();
const map: Record<string, string> = {
webp: "image/webp",
jpg: "image/jpeg",
jpeg: "image/jpeg",
png: "image/png",
gif: "image/gif",
};
return map[ext ?? ""] ?? "application/octet-stream";
}
async function migrateFile(name: string): Promise<"ok" | "skip" | "error"> {
const objectName = `image/${name}`;
// Cek apakah sudah ada di MinIO — skip jika sudah
try {
await minio.statObject(BUCKET, objectName);
console.log(` ⏭ sudah ada, skip: ${name}`);
return "skip";
} catch {
// tidak ada, lanjut upload
}
const seafileUrl = buildSeafileUrl(name);
try {
const res = await fetch(seafileUrl);
if (!res.ok) {
console.error(` ✗ gagal download (HTTP ${res.status}): ${name}`);
return "error";
}
const buffer = Buffer.from(await res.arrayBuffer());
await minio.putObject(BUCKET, objectName, buffer, buffer.length, {
"Content-Type": guessMimeType(name),
});
console.log(`${name} (${(buffer.length / 1024).toFixed(1)} KB)`);
return "ok";
} catch (err) {
console.error(` ✗ error: ${name}`, err);
return "error";
}
}
async function main() {
console.log(`\n🚀 Migrasi Seafile → MinIO`);
console.log(` Bucket : ${BUCKET}`);
console.log(` Total : ${fileStorageData.length} file\n`);
let ok = 0, skip = 0, error = 0;
for (const item of fileStorageData) {
const result = await migrateFile(item.name);
if (result === "ok") ok++;
else if (result === "skip") skip++;
else error++;
}
console.log(`\n📊 Hasil:`);
console.log(` ✓ Berhasil : ${ok}`);
console.log(` ⏭ Dilewati : ${skip}`);
console.log(` ✗ Gagal : ${error}`);
if (error > 0) {
console.log(`\n⚠ Ada ${error} file yang gagal. Jalankan ulang script untuk retry.`);
process.exit(1);
} else {
console.log(`\n✅ Migrasi selesai!`);
}
}
main();