@npio/internals
Version:
A free visual website editor, powered with your own SolidJS components.
146 lines (131 loc) • 3.45 kB
text/typescript
import { parseMultipartFormData } from "@npio/filesystem";
import { decode } from "decode-formdata";
import { FontFaceFile } from "../../../types";
import { getFontFormat } from "../../string";
import { useFilesystemDriver } from "../filesystem";
import { useDatabase } from "../prisma";
import { extractFontMeta, faceKey, fontPath } from "./util";
export const uploadFonts = async function () {
const db = useDatabase();
const prepare = async function (id: string) {
const font = await db.nitroFont.findUniqueOrThrow({
include: {
faces: true,
},
where: {
id,
},
});
return {
font,
};
};
let preparePromise: ReturnType<typeof prepare> = undefined!;
type File = {
filename: string;
contentType: string;
format: string;
};
const result = decode<Record<string, any> & { files: (File | undefined)[] }>(
await parseMultipartFormData<Promise<File | undefined>>({
async handleFile(info, fields) {
const format = getFontFormat(info.contentType);
if (!format) {
return;
}
if (!preparePromise) {
const id = fields.find(([name]: any) => name === "id")![1];
if (typeof id !== "string") throw new Error("Invalid font id");
preparePromise = prepare(id);
}
const { font } = await preparePromise;
const driver = useFilesystemDriver(font.driver);
try {
await driver.put({
name: fontPath(font, info.filename),
stream: info.body,
contentType: info.contentType,
});
const { body, name, ...rest } = info;
return { ...rest, format };
} catch (err) {
console.log("Error while uploading a font", err);
}
},
}),
{
arrays: ["files"],
},
);
const files = result.files.filter((file) => file != null) as File[];
if (!files.length || !preparePromise) {
return;
}
const { font } = await preparePromise;
await db.nitroFont.update({
data: {
cdn: null,
},
where: {
id: font.id,
},
});
const faces: Record<
string,
{
id?: string;
weight: any;
style: any;
files: FontFaceFile[];
}
> = {};
for (const face of font.faces) {
const key = faceKey(face.weight!, face.style);
faces[key] = {
id: face.id,
weight: face.weight,
style: face.style,
files: JSON.parse(face.files),
};
}
for (const file of files) {
const meta = extractFontMeta(file.filename);
const face = (faces[meta.key] = faces[meta.key] || {
weight: meta.weight,
style: meta.style,
files: [],
});
if (!face.files.find((f) => f.name == file.filename)) {
face.files.push({
format: file.format,
name: file.filename,
mime: file.contentType,
});
}
}
for (const face of Object.values(faces)) {
if (!face.id) {
await db.nitroFontFace.create({
data: {
style: face.style,
weight: face.weight,
files: JSON.stringify(face.files),
font: {
connect: {
id: font.id,
},
},
},
});
} else {
await db.nitroFontFace.update({
data: {
files: JSON.stringify(face.files),
},
where: {
id: face.id,
},
});
}
}
};