Merge pull request 'Fix uploads -1' (#52) from nico/21-jan-26 into staggingweb
Reviewed-on: http://wibugit.wibudev.com/wibu/desa-darmasaba/pulls/52
This commit is contained in:
@@ -45,6 +45,7 @@
|
|||||||
"@types/bun": "^1.2.2",
|
"@types/bun": "^1.2.2",
|
||||||
"@types/leaflet": "^1.9.20",
|
"@types/leaflet": "^1.9.20",
|
||||||
"@types/lodash": "^4.17.16",
|
"@types/lodash": "^4.17.16",
|
||||||
|
"@types/mime-types": "^3.0.1",
|
||||||
"@types/nodemailer": "^7.0.2",
|
"@types/nodemailer": "^7.0.2",
|
||||||
"add": "^2.0.6",
|
"add": "^2.0.6",
|
||||||
"adm-zip": "^0.5.16",
|
"adm-zip": "^0.5.16",
|
||||||
@@ -72,6 +73,7 @@
|
|||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"list": "^2.0.19",
|
"list": "^2.0.19",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"mime-types": "^3.0.2",
|
||||||
"motion": "^12.4.1",
|
"motion": "^12.4.1",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.5",
|
||||||
"next": "^15.5.2",
|
"next": "^15.5.2",
|
||||||
|
|||||||
@@ -1,27 +1,222 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
// /* 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<string[]> {
|
||||||
|
// 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/eadd52c5bd654ec789a3/?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
|
// prisma/seedAssets.ts
|
||||||
import prisma from "@/lib/prisma";
|
import prisma from "@/lib/prisma";
|
||||||
import AdmZip from "adm-zip";
|
import AdmZip from "adm-zip";
|
||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
|
import mime from "mime-types";
|
||||||
import fetchWithRetry from "./data/fetchWithRetry";
|
import fetchWithRetry from "./data/fetchWithRetry";
|
||||||
|
|
||||||
const UPLOADS_DIR =
|
/* =========================
|
||||||
process.env.WIBU_UPLOAD_DIR || path.join(process.cwd(), "uploads");
|
* CONFIG
|
||||||
|
* ========================= */
|
||||||
|
const UPLOADS_DIR = path.resolve(
|
||||||
|
process.env.WIBU_UPLOAD_DIR || "uploads"
|
||||||
|
);
|
||||||
|
|
||||||
// --- Helper: deteksi kategori file ---
|
const TMP_DIR = path.join(process.cwd(), "tmp_assets");
|
||||||
function detectCategory(filename: string): "image" | "document" | "other" {
|
|
||||||
|
const CATEGORY_DIR: Record<FileCategory, string> = {
|
||||||
|
image: "images",
|
||||||
|
document: "documents",
|
||||||
|
other: "other",
|
||||||
|
};
|
||||||
|
|
||||||
|
type FileCategory = "image" | "document" | "other";
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
* HELPERS
|
||||||
|
* ========================= */
|
||||||
|
function detectCategory(filename: string): FileCategory {
|
||||||
const ext = path.extname(filename).toLowerCase();
|
const ext = path.extname(filename).toLowerCase();
|
||||||
if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image";
|
if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image";
|
||||||
if ([".pdf", ".doc", ".docx"].includes(ext)) return "document";
|
if ([".pdf", ".doc", ".docx", ".txt"].includes(ext)) return "document";
|
||||||
return "other";
|
return "other";
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Helper: recursive walk dir ---
|
|
||||||
async function walkDir(
|
async function walkDir(
|
||||||
dir: string,
|
dir: string,
|
||||||
fileList: string[] = []
|
result: string[] = []
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
@@ -29,139 +224,139 @@ async function walkDir(
|
|||||||
const fullPath = path.join(dir, entry.name);
|
const fullPath = path.join(dir, entry.name);
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
if (entry.name === "__MACOSX") continue; // skip folder sampah
|
if (entry.name === "__MACOSX") continue;
|
||||||
await walkDir(fullPath, fileList);
|
await walkDir(fullPath, result);
|
||||||
} else {
|
} else {
|
||||||
if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; // skip file sampah
|
if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue;
|
||||||
fileList.push(fullPath);
|
result.push(fullPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileList;
|
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() {
|
export default async function seedAssets() {
|
||||||
console.log("🚀 Seeding assets...");
|
console.log("🚀 Seeding assets...");
|
||||||
|
console.log("📁 Upload dir:", UPLOADS_DIR);
|
||||||
|
|
||||||
// 1. Download zip
|
await ensureDir(UPLOADS_DIR);
|
||||||
|
|
||||||
|
/* ===== Download ZIP ===== */
|
||||||
const url =
|
const url =
|
||||||
"https://cld-dkr-makuro-seafile.wibudev.com/f/eadd52c5bd654ec789a3/?dl=1";
|
"https://cld-dkr-makuro-seafile.wibudev.com/f/eadd52c5bd654ec789a3/?dl=1";
|
||||||
const res = await fetchWithRetry(url, 3, 20000);
|
const res = await fetchWithRetry(url, 3, 20000);
|
||||||
|
|
||||||
// Validasi content-type
|
if (!res.headers.get("content-type")?.includes("zip")) {
|
||||||
const contentType = res.headers.get("content-type");
|
throw new Error("Invalid ZIP content-type");
|
||||||
if (!contentType?.includes("zip")) {
|
|
||||||
throw new Error(`Invalid content-type (${contentType}). Expected ZIP file`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.from(await res.arrayBuffer());
|
const buffer = Buffer.from(await res.arrayBuffer());
|
||||||
|
if (buffer.length < 100 || buffer.toString("utf8", 0, 2) !== "PK") {
|
||||||
// Validasi ukuran file
|
throw new Error("Corrupted ZIP file");
|
||||||
if (buffer.length < 100) {
|
|
||||||
throw new Error("Downloaded ZIP is empty or corrupted");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validasi signature ZIP ("PK")
|
/* ===== Extract ===== */
|
||||||
if (buffer.toString("utf8", 0, 2) !== "PK") {
|
await fs.rm(TMP_DIR, { recursive: true, force: true });
|
||||||
throw new Error("Invalid ZIP signature (PK not found)");
|
await ensureDir(TMP_DIR);
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Extract zip ke folder tmp
|
const zip = new AdmZip(buffer);
|
||||||
const extractDir = path.join(process.cwd(), "tmp_assets");
|
zip.extractAllTo(TMP_DIR, true);
|
||||||
await fs.rm(extractDir, { recursive: true, force: true });
|
|
||||||
await fs.mkdir(extractDir, { recursive: true });
|
|
||||||
|
|
||||||
let zip: AdmZip;
|
/* ===== Process Files ===== */
|
||||||
|
const files = await walkDir(TMP_DIR);
|
||||||
|
|
||||||
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) {
|
for (const filePath of files) {
|
||||||
const entryName = path.basename(filePath);
|
const entryName = path.basename(filePath);
|
||||||
const category = detectCategory(entryName);
|
const category = detectCategory(entryName);
|
||||||
|
|
||||||
let finalName = entryName;
|
let result;
|
||||||
let mimeType = "application/octet-stream";
|
|
||||||
let targetPath = "";
|
|
||||||
|
|
||||||
if (category === "image") {
|
if (category === "image") {
|
||||||
const fileBaseName = path.parse(entryName).name;
|
result = await processImage(filePath, entryName);
|
||||||
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 {
|
} else {
|
||||||
targetPath = path.join(UPLOADS_DIR, "other", entryName);
|
result = await processNonImage(filePath, entryName, category);
|
||||||
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
||||||
await fs.copyFile(filePath, targetPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { finalName, targetPath, mimeType } = result;
|
||||||
|
|
||||||
const existing = await prisma.fileStorage.findUnique({
|
const existing = await prisma.fileStorage.findUnique({
|
||||||
where: { name: finalName },
|
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) {
|
if (existing) {
|
||||||
// Restore kalau soft deleted
|
|
||||||
await prisma.fileStorage.update({
|
await prisma.fileStorage.update({
|
||||||
where: { name: finalName },
|
where: { name: finalName },
|
||||||
data: {
|
data,
|
||||||
path: targetPath,
|
|
||||||
realName: entryName,
|
|
||||||
mimeType,
|
|
||||||
link: `/uploads/${category}/${finalName}`,
|
|
||||||
category,
|
|
||||||
deletedAt: null,
|
|
||||||
isActive: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`♻️ restored: ${category}/${finalName}`);
|
console.log(`♻️ restored: ${category}/${finalName}`);
|
||||||
} else {
|
} else {
|
||||||
await prisma.fileStorage.create({
|
await prisma.fileStorage.create({ data });
|
||||||
data: {
|
|
||||||
name: finalName,
|
|
||||||
realName: entryName,
|
|
||||||
path: targetPath,
|
|
||||||
mimeType,
|
|
||||||
link: `/uploads/${category}/${finalName}`,
|
|
||||||
category,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`📂 created: ${category}/${finalName}`);
|
console.log(`📂 created: ${category}/${finalName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`📂 saved: ${category}/${finalName}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Cleanup
|
/* ===== Cleanup ===== */
|
||||||
await fs.rm(extractDir, { recursive: true, force: true });
|
await fs.rm(TMP_DIR, { recursive: true, force: true });
|
||||||
|
|
||||||
console.log("✅ Selesai seed assets!");
|
console.log("✅ Selesai seed assets!");
|
||||||
console.log("DB URL (asset):", process.env.DATABASE_URL);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Auto run kalau dipanggil langsung ---
|
/* ===== Auto Run ===== */
|
||||||
if (import.meta.main) {
|
if (import.meta.main) {
|
||||||
seedAssets()
|
seedAssets()
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const Utils = new Elysia({
|
|||||||
}).get("/version", async () => {
|
}).get("/version", async () => {
|
||||||
const packageJson = await fs.readFile(
|
const packageJson = await fs.readFile(
|
||||||
path.join(ROOT, "package.json"),
|
path.join(ROOT, "package.json"),
|
||||||
"utf-8"
|
"utf-8",
|
||||||
);
|
);
|
||||||
const version = JSON.parse(packageJson).version;
|
const version = JSON.parse(packageJson).version;
|
||||||
return { version };
|
return { version };
|
||||||
@@ -78,9 +78,9 @@ const ApiServer = new Elysia()
|
|||||||
.use(swagger({ path: "/api/docs" }))
|
.use(swagger({ path: "/api/docs" }))
|
||||||
.use(
|
.use(
|
||||||
staticPlugin({
|
staticPlugin({
|
||||||
assets: process.env.WIBU_UPLOAD_DIR,
|
assets: UPLOAD_DIR,
|
||||||
prefix: "/uploads",
|
prefix: "/uploads",
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
.use(cors(corsConfig))
|
.use(cors(corsConfig))
|
||||||
.use(Utils)
|
.use(Utils)
|
||||||
@@ -127,9 +127,9 @@ const ApiServer = new Elysia()
|
|||||||
query: t.Optional(
|
query: t.Optional(
|
||||||
t.Object({
|
t.Object({
|
||||||
size: t.Optional(t.Number()),
|
size: t.Optional(t.Number()),
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.delete(
|
.delete(
|
||||||
"/img/:name",
|
"/img/:name",
|
||||||
@@ -143,7 +143,7 @@ const ApiServer = new Elysia()
|
|||||||
params: t.Object({
|
params: t.Object({
|
||||||
name: t.String(),
|
name: t.String(),
|
||||||
}),
|
}),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/imgs",
|
"/imgs",
|
||||||
@@ -161,9 +161,9 @@ const ApiServer = new Elysia()
|
|||||||
page: t.Number({ default: 1 }),
|
page: t.Number({ default: 1 }),
|
||||||
count: t.Number({ default: 10 }),
|
count: t.Number({ default: 10 }),
|
||||||
search: t.String({ default: "" }),
|
search: t.String({ default: "" }),
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/upl-img",
|
"/upl-img",
|
||||||
@@ -176,7 +176,7 @@ const ApiServer = new Elysia()
|
|||||||
title: t.String(),
|
title: t.String(),
|
||||||
files: t.Files({ multiple: true }),
|
files: t.Files({ multiple: true }),
|
||||||
}),
|
}),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/upl-img-single",
|
"/upl-img-single",
|
||||||
@@ -192,7 +192,7 @@ const ApiServer = new Elysia()
|
|||||||
name: t.String(),
|
name: t.String(),
|
||||||
file: t.File(),
|
file: t.File(),
|
||||||
}),
|
}),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/upl-csv-single",
|
"/upl-csv-single",
|
||||||
@@ -204,7 +204,7 @@ const ApiServer = new Elysia()
|
|||||||
name: t.String(),
|
name: t.String(),
|
||||||
file: t.File(),
|
file: t.File(),
|
||||||
}),
|
}),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/upl-csv",
|
"/upl-csv",
|
||||||
@@ -215,8 +215,8 @@ const ApiServer = new Elysia()
|
|||||||
body: t.Object({
|
body: t.Object({
|
||||||
files: t.Files(),
|
files: t.Files(),
|
||||||
}),
|
}),
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const GET = ApiServer.handle;
|
export const GET = ApiServer.handle;
|
||||||
|
|||||||
Reference in New Issue
Block a user