@npio/internals
Version:
A free visual website editor, powered with your own SolidJS components.
111 lines (96 loc) • 3.19 kB
text/typescript
import { parseMultipartFormData } from "@npio/filesystem";
import { createId } from "@paralleldrive/cuid2";
import { NitroMedia } from "@prisma/client";
import { decode } from "decode-formdata";
import { basename, extname } from "path";
import { rgbVal } from "../../color";
import { useFilesystem, useFilesystemDriver } from "../filesystem";
import { useDatabase } from "../prisma";
import { processImageUpload } from "./image";
import { joinMediaUrl } from "./util";
export const uploadMedia = async () => {
const db = useDatabase();
const prepare = async function (id: string) {
const project = await db.nitroProject.findUniqueOrThrow({
where: {
id,
},
});
return {
project,
};
};
let preparePromise: ReturnType<typeof prepare> = undefined!;
const fs = useFilesystem();
const driverName = fs.default;
const driver = useFilesystemDriver(driverName);
type File = {
filename: string;
contentType: string;
media: NitroMedia;
};
const result = decode<Record<string, any> & { files: (File | undefined)[] }>(
await parseMultipartFormData<Promise<File | undefined>>({
async handleFile(info, fields) {
if (!preparePromise) {
const id = fields.find(([name]: any) => name === "projectId")![1];
if (typeof id !== "string") throw new Error("Invalid project id");
preparePromise = prepare(id);
}
const { project } = await preparePromise;
let publicId = createId();
const extension = extname(info.filename).slice(1);
const rawFile = publicId + "." + extension;
const { stream, info: imageInfo_ } = processImageUpload({
contentType: info.contentType,
stream: info.body,
})!;
try {
await driver.put({
name: joinMediaUrl(rawFile),
stream,
contentType: info.contentType,
});
const imageInfo = await imageInfo_;
const originalName = basename(
info.unsanitizedFilename,
"." + extension,
);
const media = await db.nitroMedia.create({
data: {
project: {
connect: {
id: project.id,
},
},
publicId,
name: originalName,
file: rawFile,
extension,
mime: info.contentType,
driver: driverName,
...(imageInfo
? {
color: rgbVal(imageInfo.stats.dominant),
width: imageInfo.meta.width,
height: imageInfo.meta.height,
blurhash: imageInfo.blurhash,
dataUrl: imageInfo.dataUrl,
}
: {}),
},
});
const { body, name, ...rest } = info;
return { ...rest, media };
} catch (err) {
console.log("Error while uploading an image", err);
}
},
}),
{
arrays: ["files"],
},
);
const ids = result.files.filter((f) => f != null).map((f) => f.media.id);
return ids;
};