diff --git a/package.json b/package.json index 47a4aea..fea8011 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "db:migrate": "prisma migrate dev", "db:seed": "ts-node -P tsconfig.seed.json prisma/seed.ts", "db:create-user": "ts-node -P tsconfig.seed.json scripts/create-user.ts", + "db:create-user:prod": "node scripts/create-user.js", "db:studio": "prisma studio" }, "prisma": { diff --git a/scripts/create-user.js b/scripts/create-user.js new file mode 100644 index 0000000..2e2413e --- /dev/null +++ b/scripts/create-user.js @@ -0,0 +1,67 @@ +const fs = require("fs"); +const path = require("path"); + +// Minimal .env loader (avoids depending on the `dotenv` package, which may +// not be installed in a production deployment that skipped devDependencies). +function loadEnvFile(file) { + if (!fs.existsSync(file)) return; + for (const line of fs.readFileSync(file, "utf8").split("\n")) { + const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/); + if (!match) continue; + const key = match[1]; + let value = (match[2] ?? "").trim(); + if (value.startsWith('"') && value.endsWith('"')) value = value.slice(1, -1); + else if (value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1); + if (!(key in process.env)) process.env[key] = value; + } +} +loadEnvFile(path.join(__dirname, "..", ".env")); + +const { PrismaClient } = require("@prisma/client"); +const { PrismaPg } = require("@prisma/adapter-pg"); +const bcrypt = require("bcryptjs"); + +const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }); +const prisma = new PrismaClient({ adapter }); + +async function main() { + const [, , email, password, name] = process.argv; + + if (!email || !password) { + console.error("Usage: node scripts/create-user.js [name]"); + process.exit(1); + } + + if (password.length < 8) { + console.error("Password must be at least 8 characters long."); + process.exit(1); + } + + const hashedPassword = await bcrypt.hash(password, 12); + const normalizedEmail = email.toLowerCase().trim(); + + const user = await prisma.user.upsert({ + where: { email: normalizedEmail }, + create: { + email: normalizedEmail, + password: hashedPassword, + name: name ?? null, + role: "ADMIN", + }, + update: { + password: hashedPassword, + ...(name ? { name } : {}), + }, + }); + + console.log(`✅ User ready: ${user.email} (role: ${user.role})`); +} + +main() + .catch((e) => { + console.error(e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + });