104 lines
3.5 KiB
TypeScript
104 lines
3.5 KiB
TypeScript
import { Body, Controller, Get, Path, Post, Put, Query, Route, SuccessResponse } from "tsoa";
|
|
import { replaceIllegalChars } from "../utils/minio";
|
|
import minioClient from "../minio";
|
|
import HttpStatusCode from "../interfaces/http-status";
|
|
import HttpError from "../interfaces/http-error";
|
|
|
|
const DEFAULT_BUCKET = process.env.MINIO_BUCKET;
|
|
const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX;
|
|
|
|
if (!DEFAULT_BUCKET) throw Error("Default MinIO bucket must be specified.");
|
|
if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified.");
|
|
|
|
@Route("/storage/d")
|
|
export class StorageController extends Controller {
|
|
@Get()
|
|
@SuccessResponse(HttpStatusCode.OK, "Success")
|
|
public async getFolder(@Query() path: string, @Query() bucket?: string) {
|
|
const list = await new Promise<{ pathname: string; name: string }[]>((resolve, reject) => {
|
|
const item: { pathname: string; name: string }[] = [];
|
|
|
|
const stream = minioClient.listObjectsV2(bucket ?? DEFAULT_BUCKET!, path);
|
|
stream.on("data", (v) => {
|
|
if (v && v.prefix) {
|
|
item.push({
|
|
pathname: v.prefix,
|
|
name: v.prefix.slice(path?.length).split("/")[0],
|
|
});
|
|
}
|
|
});
|
|
stream.on("end", () => resolve(item));
|
|
stream.on("error", () => reject(new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์")));
|
|
});
|
|
|
|
return list;
|
|
}
|
|
|
|
@Post()
|
|
@SuccessResponse(HttpStatusCode.CREATED, "Success")
|
|
public async createFolder(@Query() path: string, @Query() bucket?: string) {
|
|
const fragments = path.split("/").filter(Boolean);
|
|
|
|
await Promise.all(
|
|
fragments.map(async (_, i, a) => {
|
|
const path = [...a.slice(0, i + 1)].map((x) => replaceIllegalChars(x)).join("/");
|
|
const created = await minioClient
|
|
.putObject(bucket ?? DEFAULT_BUCKET!, `${path}/.keep`, "", 0)
|
|
.catch((e) => console.error(e));
|
|
if (!created) throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์");
|
|
}),
|
|
);
|
|
|
|
return this.setStatus(HttpStatusCode.CREATED);
|
|
}
|
|
|
|
@Put()
|
|
@SuccessResponse(HttpStatusCode.NO_CONTENT, "Success")
|
|
public async updateFolder(
|
|
@Body()
|
|
body: {
|
|
from: {
|
|
bucket: string;
|
|
path: string;
|
|
};
|
|
to: {
|
|
bucket: string;
|
|
path: string;
|
|
};
|
|
},
|
|
) {
|
|
const src = body.from.path.split("/").filter(Boolean).join("/");
|
|
const dst = body.to.path.split("/").filter(Boolean).join("/");
|
|
|
|
if (
|
|
!Boolean(
|
|
await minioClient
|
|
.statObject(DEFAULT_BUCKET!, `${dst.replace(/^\/|\/$/g, "")}/.keep`)
|
|
.catch((e) => {
|
|
if (e.code === "NotFound") return false;
|
|
throw new Error(`Minio Error: ${e}`);
|
|
}),
|
|
)
|
|
)
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "Destination Not Found");
|
|
|
|
const list = await new Promise<{ pathname: string; name: string }[]>((resolve, reject) => {
|
|
const item: { pathname: string; name: string }[] = [];
|
|
|
|
const stream = minioClient.listObjectsV2(body.from.bucket, src);
|
|
|
|
stream.on("data", (v) => {
|
|
if (v && v.prefix) {
|
|
item.push({
|
|
pathname: v.prefix,
|
|
name: v.prefix.slice(src.length).split("/")[0],
|
|
});
|
|
}
|
|
});
|
|
stream.on("error", (e) => reject(new Error(`Minio Error: ${e}`)));
|
|
stream.on("end", () => resolve(item));
|
|
});
|
|
|
|
return this.setStatus(HttpStatusCode.NO_CONTENT);
|
|
}
|
|
}
|