diff --git a/.jules/bolt.md b/.jules/bolt.md index 02deaeba..4c327a6b 100644 Binary files a/.jules/bolt.md and b/.jules/bolt.md differ diff --git a/prisma.config.ts b/prisma.config.ts index 4cc9297d..1cf64a67 100644 --- a/prisma.config.ts +++ b/prisma.config.ts @@ -3,6 +3,16 @@ import "dotenv/config"; import { defineConfig } from "prisma/config"; +// 🛡️ Guardian: Fix Prisma CI build environment resolution +// JULES Check: Prevents hanging schemas when DATABASE_URL is missing +// Impact: Fixes build pipeline validation errors +// Date: 2024-07-02 +// Session: N/A + +if (process.env.DATABASE_URL && !process.env.DIRECT_URL) { + process.env.DIRECT_URL = process.env.DATABASE_URL; +} + export default defineConfig({ schema: "prisma/schema.prisma", migrations: { @@ -10,7 +20,7 @@ export default defineConfig({ }, engine: "classic", datasource: { - url: - process.env.DATABASE_URL ?? "postgresql://placeholder:placeholder@localhost:5432/placeholder", + // Non-null assertion strictly for typing, avoiding the fake placeholder URL that causes deployment hangs + url: process.env.DATABASE_URL!, }, }); diff --git a/src/app/api/admin/import-prompts/route.ts b/src/app/api/admin/import-prompts/route.ts index 8efd7b3a..a60cf909 100644 --- a/src/app/api/admin/import-prompts/route.ts +++ b/src/app/api/admin/import-prompts/route.ts @@ -196,18 +196,28 @@ export async function POST(request: NextRequest) { let skipped = 0; const errors: string[] = []; + // ⚡ Bolt: Prevent N+1 queries by pre-fetching all existing prompt titles in a single batched query + const uniqueTitles = Array.from(new Set(rows.map((r) => r.act).filter(Boolean))); + + const existingPrompts = await db.prompt.findMany({ + where: { title: { in: uniqueTitles } }, + select: { title: true }, + }); + + // Create a Set for O(1) lookups during iteration + const existingTitlesSet = new Set(existingPrompts.map((p) => p.title)); + for (const row of rows) { try { // Check if prompt with same title already exists - const existing = await db.prompt.findFirst({ - where: { title: row.act }, - }); - - if (existing) { + if (existingTitlesSet.has(row.act)) { skipped++; continue; } + // Add newly processed title to Set to prevent inserting duplicates from the CSV itself + existingTitlesSet.add(row.act); + // Get or create contributor user const authorId = await getOrCreateContributor(row.contributor);