datacops-cms
Version:
A modern, extensible CMS built with Next.js and Prisma.
111 lines (97 loc) • 3.97 kB
text/typescript
import bcrypt from 'bcryptjs'
import { execSync } from 'child_process'
import * as fs from 'fs'
import { NextRequest, NextResponse } from 'next/server'
import path from 'path'
import { z } from 'zod'
// Zod schema for validating request
const installSchema = z.object({
dbType: z.enum(['sqlite', 'postgres', 'mysql']),
dbUrl: z.string().optional(),
name: z.string().min(1),
email: z.string().email(),
password: z.string().min(6),
})
export async function POST(req: NextRequest)
{
try {
const body = await req.json()
const { dbType, dbUrl = '', name, email, password } = installSchema.parse(body)
const envPath = path.resolve(process.cwd(), '.env')
const schemaPath = path.resolve(process.cwd(), 'prisma/schema.prisma')
// Determine the DB URL
let finalDbUrl = dbUrl
if (dbType === 'sqlite') {
// Default to a file in the prisma directory
finalDbUrl = 'file:./dev.db'
}
// ------------------------------
// 1. Update .env file
// ------------------------------
let originalEnv = ''
try {
originalEnv = fs.readFileSync(envPath, 'utf-8')
} catch {
originalEnv = ''
}
// Ensure IS_INSTALLED/DATABASE_TYPE/DATABASE_URL exist
let newEnv = originalEnv
if (!/IS_INSTALLED=/.test(originalEnv)) newEnv += '\nIS_INSTALLED=false'
if (!/DATABASE_TYPE=/.test(originalEnv)) newEnv += '\nDATABASE_TYPE="sqlite"'
if (!/DATABASE_URL=/.test(originalEnv)) newEnv += '\nDATABASE_URL="file:./dev.db"'
const updatedEnv = newEnv
.replace(/IS_INSTALLED=.*/g, 'IS_INSTALLED=true')
.replace(/DATABASE_TYPE=.*/g, `DATABASE_TYPE="${dbType}"`)
.replace(/DATABASE_URL=.*/g, `DATABASE_URL="${finalDbUrl}"`)
fs.writeFileSync(envPath, updatedEnv)
// ------------------------------
// 2. Update schema.prisma file
// ------------------------------
const schema = fs.readFileSync(schemaPath, 'utf-8')
const providerValue =
dbType === 'postgres'
? 'postgresql'
: dbType === 'sqlite'
? 'sqlite'
: dbType
// Replace ONLY the datasource provider line
const updatedSchema = schema.replace(
/(datasource\s+db\s+\{\s*provider\s*=\s*)".*?"(\s*)/,
`$1"${providerValue}"$2`
)
fs.writeFileSync(schemaPath, updatedSchema)
// ------------------------------
// 3. Generate & Push Schema
// ------------------------------
execSync('npx prisma generate', { stdio: 'inherit' })
execSync('npx prisma db push', { stdio: 'inherit' })
// ------------------------------
// 4. Dynamically import Prisma Client
// ------------------------------
const { PrismaClient } = await import('@prisma/client')
const prisma = new PrismaClient()
// ------------------------------
// 5. Create Super Admin User
// ------------------------------
const hashedPassword = await bcrypt.hash(password, 10)
await prisma.user.create({
data: {
name,
email,
password: hashedPassword,
role: 'SUPERADMIN',
},
})
return NextResponse.json({ success: true, message: 'Installation completed successfully.' })
} catch (error) {
console.error('[INSTALL ERROR]', error)
return NextResponse.json(
{
success: false,
message: 'Installation failed',
error: error instanceof Error ? error.message : String(error),
},
{ status: 400 }
)
}
}