From e4686cb9eefc322628c4f99ebe8c4e9196b2b10e Mon Sep 17 00:00:00 2001 From: Aldo Jimenez Date: Sun, 29 Mar 2026 19:10:49 -0400 Subject: [PATCH] fix: seed script fails due to missing content field The seed script fetches from /prompts.json without the ?full_content=true parameter. The API only returns contentPreview by default, so the content field is undefined, causing PrismaClientValidationError for every prompt. Changes: - Add ?full_content=true to the fetch URL - Make content optional in RemotePrompt interface - Skip prompts without content instead of failing Before: Created 0 prompts (1595 skipped) with validation errors After: Created 1576 prompts (19 skipped - no content) --- prisma/seed.ts | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/prisma/seed.ts b/prisma/seed.ts index d4ffc705..7931a65d 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -3,14 +3,15 @@ import bcrypt from "bcryptjs"; const prisma = new PrismaClient(); -const PROMPTS_JSON_URL = "https://prompts.chat/prompts.json"; +const PROMPTS_JSON_URL = "https://prompts.chat/prompts.json?full_content=true"; -interface RemotePrompt { +/** Raw shape returned by the remote API — content may be absent. */ +interface RemotePromptRaw { id: string; title: string; slug: string; description: string | null; - content: string; + content?: string; type: string; structuredFormat: string | null; mediaUrl: string | null; @@ -52,11 +53,20 @@ interface RemotePrompt { }>; } -interface RemotePromptsResponse { - count: number; - prompts: RemotePrompt[]; +/** Validated prompt with required content field. */ +type RemotePrompt = RemotePromptRaw & { content: string }; + +/** Type guard that narrows a raw API prompt to a validated RemotePrompt. */ +function hasContent(prompt: RemotePromptRaw): prompt is RemotePrompt { + return typeof prompt.content === "string" && prompt.content.length > 0; } +interface RemotePromptsResponse { + count: number; + prompts: RemotePromptRaw[]; +} + +/** Fetches all prompts from the remote prompts.chat API with full content. */ async function fetchPrompts(): Promise { console.log(`šŸ“” Fetching prompts from ${PROMPTS_JSON_URL}...`); const response = await fetch(PROMPTS_JSON_URL); @@ -68,12 +78,13 @@ async function fetchPrompts(): Promise { return data; } +/** Seeds the database with users, categories, tags, and prompts from prompts.chat. */ async function main() { console.log("🌱 Seeding database from prompts.chat..."); // Create admin user for assigning prompts const password = await bcrypt.hash("password123", 12); - + const admin = await prisma.user.upsert({ where: { email: "admin@prompts.chat" }, update: {}, @@ -174,7 +185,7 @@ async function main() { userIdMap.set(username, admin.id); continue; } - + const user = await prisma.user.upsert({ where: { username }, update: { name: author.name, avatar: author.avatar }, @@ -225,6 +236,13 @@ async function main() { }; const structuredFormat = remotePrompt.structuredFormat ? formatMap[remotePrompt.structuredFormat] : null; + // Skip prompts without content + if (!hasContent(remotePrompt)) { + console.warn(`⚠ Skipping prompt "${remotePrompt.title}" - no content`); + promptsSkipped++; + continue; + } + // Check if prompt already exists const existingPrompt = await prisma.prompt.findFirst({ where: { slug: remotePrompt.slug }, @@ -280,6 +298,16 @@ async function main() { } console.log(`āœ… Created ${promptsCreated} prompts (${promptsSkipped} skipped)`); + + // Fail-fast if no prompts were created — likely an upstream API regression + const total = promptsCreated + promptsSkipped; + if (total > 0 && promptsCreated === 0) { + throw new Error( + `Seeding failed: 0 prompts created out of ${total} (${promptsSkipped} skipped). ` + + `This likely indicates an upstream API regression — check that ${PROMPTS_JSON_URL} returns content.` + ); + } + console.log("\nšŸŽ‰ Seeding complete!"); console.log("\nšŸ“‹ Test credentials (password: password123):"); console.log(" Admin: admin@prompts.chat");