UNPKG

@npio/internals

Version:

A free visual website editor, powered with your own SolidJS components.

111 lines (96 loc) 3.19 kB
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; };