UNPKG

@premieroctet/next-admin

Version:

Next-Admin provides a customizable and turnkey admin dashboard for applications built with Next.js and powered by the Prisma ORM. It aims to simplify the development process by providing a turnkey admin system that can be easily integrated into your proje

123 lines (122 loc) 5.22 kB
import { PrismaClientKnownRequestError, PrismaClientValidationError } from "@prisma/client/runtime/library"; import { Permission } from "../types.mjs"; import { hasPermission } from "../utils/permissions.mjs"; import { getDataItem } from "../utils/prisma.mjs"; import { formatId, formattedFormData, getModelIdProperty, parseFormData } from "../utils/server.mjs"; import { uncapitalize } from "../utils/tools.mjs"; import { validate } from "../utils/validator.mjs"; const deleteResource = async ({ prisma, resource, body, modelOptions })=>{ const modelIdProperty = getModelIdProperty(resource); if (modelOptions?.middlewares?.delete) { const resources = await prisma[uncapitalize(resource)].findMany({ where: { [modelIdProperty]: { in: body.map((id)=>formatId(resource, id.toString())) } } }); const middlewareExec = await Promise.allSettled(resources.map(async (res)=>{ const isSuccessDelete = await modelOptions?.middlewares?.delete?.(res); return isSuccessDelete; })); if (middlewareExec.some((exec)=>"rejected" === exec.status || false === exec.value)) return false; } return prisma[uncapitalize(resource)].deleteMany({ where: { [modelIdProperty]: { in: body.map((id)=>formatId(resource, id.toString())) } } }); }; const submitResource = async ({ prisma, resource, body, id, options, schema })=>{ const { __admin_redirect: redirect, ...formValues } = body; const schemaDefinition = schema.definitions[resource]; const parsedFormData = parseFormData(formValues, schemaDefinition, options?.model?.[resource]?.edit?.fields); const resourceIdField = getModelIdProperty(resource); const fields = options?.model?.[resource]?.edit?.fields; try { validate(parsedFormData, fields); const { formattedData, complementaryFormattedData, errors } = await formattedFormData(formValues, schema, resource, id, fields, prisma); if (errors.length) return { error: options?.model?.[resource]?.edit?.submissionErrorMessage ?? "Submission error", validation: errors.map((error)=>({ property: error.field, message: error.message })) }; if (!!id) { if (!hasPermission(options?.model?.[resource], Permission.EDIT)) return { error: "Unable to update items of this model" }; await prisma.$transaction(async (client)=>{ let canEdit = true; if (options?.model?.[resource]?.middlewares?.edit) { const currentData = await prisma[uncapitalize(resource)].findUniqueOrThrow({ where: { [resourceIdField]: formatId(resource, id.toString()) } }); canEdit = await options?.model?.[resource]?.middlewares?.edit(formattedData, currentData); } if (!canEdit) throw new Error("Unable to edit this item"); await prisma[resource].update({ where: { [resourceIdField]: id }, data: formattedData }); }); const { data, relationshipsRawData } = await getDataItem({ prisma, resource, resourceId: id, options }); return { updated: true, data, redirect: "list" === redirect, relationshipsRawData }; } if (!hasPermission(options?.model?.[resource], Permission.CREATE)) return { error: "Unable to create items of this model" }; const data = await prisma[resource].create({ data: formattedData }); await prisma[resource].update({ where: { [resourceIdField]: data[resourceIdField] }, data: complementaryFormattedData }); const { data: responseData, relationshipsRawData } = await getDataItem({ prisma, resource, resourceId: data[resourceIdField], options }); return { created: true, createdId: data[resourceIdField], data: responseData, redirect: "list" === redirect, relationshipsRawData }; } catch (error) { if (error.constructor.name === PrismaClientValidationError.name || error.constructor.name === PrismaClientKnownRequestError.name || "ValidationError" === error.name) { let data = parsedFormData; if ("ValidationError" === error.name) error.errors.map((error)=>{ data[error.property] = formValues[error.property]; }); return { error: error.message, validation: error.errors }; } throw error; } }; export { deleteResource, submitResource };