datacops-cms
Version:
A modern, extensible CMS built with Next.js and Prisma.
78 lines (66 loc) • 2.58 kB
text/typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
import fs from "fs"
import { NextRequest, NextResponse } from "next/server"
import path from "path"
import { z } from "zod"
import { ensurePermissionForType } from "../../permissions/route"
const RelationSchema = z.object({
target: z.string(),
relationType: z.enum(["one-one", "one-many", "many-many"]),
})
const FieldSchema = z.object({
name: z.string(),
label: z.string(),
type: z.string(),
required: z.boolean(),
options: z.array(z.object({
label: z.string(),
value: z.string(),
})).optional(),
description: z.string().optional(),
relation: RelationSchema.optional(),
slugSource: z.string().optional(), // <--- Add if you support slug fields
})
const ContentTypeSchema = z.object({
name: z.string().min(1),
label: z.string().min(1),
fields: z.array(FieldSchema),
})
function safeFieldName(name: string)
{
return name.trim().replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, '').toLowerCase()
}
export async function POST(req: NextRequest)
{
try {
const data = await req.json()
const parsed = ContentTypeSchema.parse(data)
// Sanitize type name (no spaces, lowercase, etc.)
const safeName = safeFieldName(parsed.name)
const safeFields = parsed.fields.map(f => ({
...f,
name: safeFieldName(f.name),
}));
const folder = path.resolve(process.cwd(), "content-types")
if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true })
const filePath = path.join(folder, `${safeName}.json`)
if (fs.existsSync(filePath)) {
return NextResponse.json({ error: "Content type already exists" }, { status: 400 })
}
// Save the parsed schema (with safe field names)
try {
fs.writeFileSync(
filePath,
JSON.stringify({ ...parsed, name: safeName, fields: safeFields }, null, 2),
"utf-8"
)
// ⬇️ Add this line right after file creation
ensurePermissionForType(safeName);
} catch (err: any) {
return NextResponse.json({ error: "Failed to write schema file. " + err.message }, { status: 500 });
}
return NextResponse.json({ success: true, message: "Content type schema saved.", name: safeName })
} catch (e: any) {
return NextResponse.json({ error: e.message }, { status: 400 })
}
}