first commit
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
enum Role {
|
||||
ADMIN
|
||||
USER
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
name String?
|
||||
email String @unique
|
||||
password String?
|
||||
role Role @default(USER)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
accounts Account[]
|
||||
sessions Session[]
|
||||
}
|
||||
|
||||
model Account {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
type String
|
||||
provider String
|
||||
providerAccountId String
|
||||
refresh_token String? @db.Text
|
||||
access_token String? @db.Text
|
||||
expires_at Int?
|
||||
token_type String?
|
||||
scope String?
|
||||
id_token String? @db.Text
|
||||
session_state String?
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([provider, providerAccountId])
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @default(cuid())
|
||||
sessionToken String @unique
|
||||
userId String
|
||||
expires DateTime
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model VerificationToken {
|
||||
identifier String
|
||||
token String @unique
|
||||
expires DateTime
|
||||
|
||||
@@unique([identifier, token])
|
||||
}
|
||||
|
||||
model Category {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
slug String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Lesson {
|
||||
id String @id @default(cuid())
|
||||
slug String @unique
|
||||
title String
|
||||
youtubeId String
|
||||
youtubeUrl String
|
||||
thumbnailUrl String
|
||||
duration String
|
||||
publishDate DateTime @default(now())
|
||||
category String
|
||||
tags String[]
|
||||
viewsCount Int @default(0)
|
||||
downloadCount Int @default(0)
|
||||
likesCount Int @default(0)
|
||||
summary String @db.Text
|
||||
notesMarkdown String[]
|
||||
isFeatured Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
codeSnippets CodeSnippet[]
|
||||
downloads ResourceDownload[]
|
||||
chapters VideoChapter[]
|
||||
}
|
||||
|
||||
model CodeSnippet {
|
||||
id String @id @default(cuid())
|
||||
fileName String
|
||||
language String
|
||||
code String @db.Text
|
||||
description String?
|
||||
lessonId String
|
||||
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model ResourceDownload {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
type String // zip, github, pdf, link
|
||||
url String
|
||||
size String?
|
||||
lessonId String
|
||||
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model VideoChapter {
|
||||
id String @id @default(cuid())
|
||||
time String
|
||||
seconds Int
|
||||
title String
|
||||
lessonId String
|
||||
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model Cheatsheet {
|
||||
id String @id @default(cuid())
|
||||
slug String @unique
|
||||
title String
|
||||
category String
|
||||
description String @db.Text
|
||||
tags String[]
|
||||
lastUpdated DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
items CheatsheetItem[]
|
||||
}
|
||||
|
||||
model CheatsheetItem {
|
||||
id String @id @default(cuid())
|
||||
command String
|
||||
description String
|
||||
example String?
|
||||
cheatsheetId String
|
||||
cheatsheet Cheatsheet @relation(fields: [cheatsheetId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model ContactMessage {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
email String
|
||||
subject String
|
||||
message String @db.Text
|
||||
isRead Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model Setting {
|
||||
id String @id @default(cuid())
|
||||
key String @unique
|
||||
value String @db.Text
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
import { Pool } from 'pg';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const connectionString = process.env.DATABASE_URL || 'postgres://postgres:mBTWE2cDKGExtpktguD3HPe8y9Xr9kWFYdxV4WHQKISLLGoBAS4UdtfSCfXwvPpq@65.109.236.58:37298/postgres';
|
||||
|
||||
const pool = new Pool({ connectionString });
|
||||
const adapter = new PrismaPg(pool);
|
||||
const db = new PrismaClient({ adapter });
|
||||
|
||||
async function main() {
|
||||
console.log('Seeding PostgreSQL database...');
|
||||
|
||||
// Clear existing records
|
||||
await db.videoChapter.deleteMany();
|
||||
await db.resourceDownload.deleteMany();
|
||||
await db.codeSnippet.deleteMany();
|
||||
await db.lesson.deleteMany();
|
||||
await db.cheatsheetItem.deleteMany();
|
||||
await db.cheatsheet.deleteMany();
|
||||
|
||||
// Create Lessons
|
||||
await db.lesson.create({
|
||||
data: {
|
||||
slug: 'nextjs-16-app-router-full-course',
|
||||
title: 'Next.js 16 App Router & Server Actions Complete Masterclass (Code & Project)',
|
||||
youtubeId: 'dQw4w9WgXcQ',
|
||||
youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
||||
thumbnailUrl: 'https://images.unsplash.com/photo-1618401471353-b98afee0b2eb?w=800&auto=format&fit=crop&q=80',
|
||||
duration: '42:15',
|
||||
category: 'Next.js',
|
||||
tags: ['Next.js 16', 'App Router', 'Server Actions', 'TypeScript', 'Tailwind CSS v4'],
|
||||
viewsCount: 24500,
|
||||
downloadCount: 4120,
|
||||
likesCount: 1890,
|
||||
isFeatured: true,
|
||||
summary: 'In this tutorial, we build a full-stack Next.js 16 application from scratch covering App Router architecture, proxy.ts middleware, Server Actions, and PostgreSQL integration.',
|
||||
notesMarkdown: [
|
||||
'In Next.js 16, using proxy.ts is recommended over deprecated middleware.ts.',
|
||||
'Server Actions functions are declared with "use server" directive and can be invoked directly from client components.',
|
||||
'Data fetching revalidation uses revalidatePath or revalidateTag helpers.',
|
||||
'Form handling UX is significantly improved using useActionState and useFormStatus hooks.'
|
||||
],
|
||||
codeSnippets: {
|
||||
create: [
|
||||
{
|
||||
fileName: 'app/actions.ts',
|
||||
language: 'typescript',
|
||||
description: 'Server Action function handling form submission',
|
||||
code: `'use server'\n\nimport { revalidatePath } from 'next/cache';\n\nexport async function submitProjectIdea(formData: FormData) {\n const title = formData.get('title') as string;\n const description = formData.get('description') as string;\n\n if (!title || title.length < 3) {\n return { success: false, error: 'Title must be at least 3 characters long.' };\n }\n\n // Database insertion simulation\n console.log('Saved Idea:', { title, description });\n\n revalidatePath('/ideas');\n return { success: true, message: 'Your idea was submitted successfully!' };\n}`
|
||||
},
|
||||
{
|
||||
fileName: 'proxy.ts',
|
||||
language: 'typescript',
|
||||
description: 'Next.js 16 proxy configuration (middleware alternative)',
|
||||
code: `import { NextRequest, NextResponse } from 'next/server';\nimport createMiddleware from 'next-intl/middleware';\nimport { routing } from '@/i18n/routing';\n\nconst intlMiddleware = createMiddleware(routing);\n\nexport async function proxy(request: NextRequest) {\n if (request.nextUrl.pathname.includes('/admin')) {\n // Auth check logic\n }\n return intlMiddleware(request);\n}\n\nexport const config = {\n matcher: ['/((?!api|_next|_vercel|.*\\\\..*).*)']\n};`
|
||||
},
|
||||
{
|
||||
fileName: 'components/IdeaForm.tsx',
|
||||
language: 'tsx',
|
||||
description: 'Client Form component using useActionState',
|
||||
code: `'use client';\n\nimport { useActionState } from 'react';\nimport { submitProjectIdea } from '@/app/actions';\n\nexport function IdeaForm() {\n const [state, formAction, isPending] = useActionState(submitProjectIdea, null);\n\n return (\n <form action={formAction} className="space-y-4 max-w-md p-6 bg-slate-900 rounded-xl border border-slate-800">\n <h3 className="text-xl font-bold text-white">Add New Idea</h3>\n \n <div>\n <label className="block text-sm text-slate-400 mb-1">Idea Title</label>\n <input name="title" required className="w-full px-3 py-2 bg-slate-800 border border-slate-700 rounded-lg text-white" />\n </div>\n\n <button disabled={isPending} className="w-full py-2.5 bg-red-600 hover:bg-red-500 text-white rounded-lg font-medium">\n {isPending ? 'Submitting...' : 'Share Idea'}\n </button>\n\n {state?.error && <p className="text-red-400 text-sm">{state.error}</p>}\n {state?.success && <p className="text-emerald-400 text-sm">{state.message}</p>}\n </form>\n );\n}`
|
||||
}
|
||||
]
|
||||
},
|
||||
downloads: {
|
||||
create: [
|
||||
{
|
||||
title: 'Full Project Source Code (Starter Pack)',
|
||||
type: 'zip',
|
||||
url: 'https://github.com/ayrisdev/nextjs-16-starter/archive/refs/heads/main.zip',
|
||||
size: '4.2 MB'
|
||||
},
|
||||
{
|
||||
title: 'GitHub Repository',
|
||||
type: 'github',
|
||||
url: 'https://github.com/ayrisdev/nextjs-16-starter'
|
||||
},
|
||||
{
|
||||
title: 'Lesson Notes & Architecture (PDF Document)',
|
||||
type: 'pdf',
|
||||
url: '#',
|
||||
size: '1.8 MB'
|
||||
}
|
||||
]
|
||||
},
|
||||
chapters: {
|
||||
create: [
|
||||
{ time: '00:00', seconds: 0, title: 'Introduction & Demo' },
|
||||
{ time: '04:15', seconds: 255, title: 'Next.js 16 Project Setup & Structure' },
|
||||
{ time: '11:30', seconds: 690, title: 'Routing & Middleware with proxy.ts' },
|
||||
{ time: '21:00', seconds: 1260, title: 'Form Handling via Server Actions' },
|
||||
{ time: '32:45', seconds: 1965, title: 'PostgreSQL & Prisma Integration' },
|
||||
{ time: '40:00', seconds: 2400, title: 'Deployment & Summary' }
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await db.lesson.create({
|
||||
data: {
|
||||
slug: 'python-ai-agent-automation',
|
||||
title: 'Building Autonomous AI Agents with Python (CrewAI & Gemini API)',
|
||||
youtubeId: 'dQw4w9WgXcQ',
|
||||
youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
||||
thumbnailUrl: 'https://images.unsplash.com/photo-1526374965328-7f61d4dc18c5?w=800&auto=format&fit=crop&q=80',
|
||||
duration: '28:50',
|
||||
category: 'Python & AI',
|
||||
tags: ['Python', 'CrewAI', 'Gemini API', 'AI Agents', 'Automation'],
|
||||
viewsCount: 18200,
|
||||
downloadCount: 3200,
|
||||
likesCount: 1450,
|
||||
summary: 'Build an autonomous AI agent in Python that crawls web data, summarizes tech news, and generates structured reports automatically.',
|
||||
notesMarkdown: [
|
||||
'🤖 AI agents are configured with role, goal, and backstory.',
|
||||
'🤖 Equip agents with real-time web search using Serper API or Tavily.',
|
||||
'🤖 Gemini 1.5 Flash provides high token throughput with minimal latency.'
|
||||
],
|
||||
codeSnippets: {
|
||||
create: [
|
||||
{
|
||||
fileName: 'agent.py',
|
||||
language: 'python',
|
||||
description: 'CrewAI Agent Definition',
|
||||
code: `from crewai import Agent, Task, Crew, Process\nfrom langchain_google_genai import ChatGoogleGenerativeAI\nimport os\n\nllm = ChatGoogleGenerativeAI(\n model="gemini-1.5-flash",\n google_api_key=os.getenv("GEMINI_API_KEY")\n)\n\nresearcher = Agent(\n role='Tech Researcher',\n goal='Discover top AI trends from the past 24 hours',\n backstory='You are an expert technology journalist following AI developments.',\n verbose=True,\n llm=llm\n)\n\ntask1 = Task(\n description='Summarize 2026 AI trends in 5 bullet points.',\n expected_output='A markdown list with 5 key takeaways.',\n agent=researcher\n)\n\ncrew = Crew(\n agents=[researcher],\n tasks=[task1],\n process=Process.sequential\n)\n\nresult = crew.kickoff()\nprint(result)`
|
||||
}
|
||||
]
|
||||
},
|
||||
downloads: {
|
||||
create: [
|
||||
{
|
||||
title: 'Python AI Agent Project Files',
|
||||
type: 'zip',
|
||||
url: '#',
|
||||
size: '2.1 MB'
|
||||
},
|
||||
{
|
||||
title: 'GitHub Repository',
|
||||
type: 'github',
|
||||
url: 'https://github.com/ayrisdev/python-ai-agent'
|
||||
}
|
||||
]
|
||||
},
|
||||
chapters: {
|
||||
create: [
|
||||
{ time: '00:00', seconds: 0, title: 'Introduction & What is an AI Agent?' },
|
||||
{ time: '05:20', seconds: 320, title: 'Installing Dependencies (CrewAI & Gemini)' },
|
||||
{ time: '14:10', seconds: 850, title: 'Agent & Task Coding' },
|
||||
{ time: '24:00', seconds: 1440, title: 'Testing & Output Review' }
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await db.lesson.create({
|
||||
data: {
|
||||
slug: 'tailwind-css-v4-tricks-and-setup',
|
||||
title: 'Modern UI Design with Tailwind CSS v4: Tricks, Themes & Components',
|
||||
youtubeId: 'dQw4w9WgXcQ',
|
||||
youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
||||
thumbnailUrl: 'https://images.unsplash.com/photo-1507238691740-187a5b1d37b8?w=800&auto=format&fit=crop&q=80',
|
||||
duration: '35:10',
|
||||
category: 'Tailwind CSS',
|
||||
tags: ['Tailwind CSS v4', 'OKLCH', 'CSS Grid', 'UI Design', 'Shadcn'],
|
||||
viewsCount: 31000,
|
||||
downloadCount: 5400,
|
||||
likesCount: 2600,
|
||||
summary: 'Learn CSS-first configuration in Tailwind CSS v4 using @import "tailwindcss";, OKLCH color spaces, and advanced glassmorphism component design.',
|
||||
notesMarkdown: [
|
||||
'🎨 In Tailwind v4, @theme directive in globals.css replaces tailwind.config.js.',
|
||||
'🎨 OKLCH color space ensures consistent perceived contrast across light and dark modes.',
|
||||
'🎨 @custom-variant dark provides flexible dark mode scoping.'
|
||||
],
|
||||
codeSnippets: {
|
||||
create: [
|
||||
{
|
||||
fileName: 'globals.css',
|
||||
language: 'css',
|
||||
description: 'Tailwind CSS v4 Theme Configuration',
|
||||
code: `@import "tailwindcss";\n\n@theme inline {\n --color-primary: oklch(0.65 0.22 260);\n --color-accent: oklch(0.72 0.19 145);\n --radius-lg: 1rem;\n}\n\n:root {\n --background: oklch(0.98 0.01 250);\n --foreground: oklch(0.15 0.02 250);\n}`
|
||||
}
|
||||
]
|
||||
},
|
||||
downloads: {
|
||||
create: [
|
||||
{
|
||||
title: 'Tailwind v4 UI Starter Pack',
|
||||
type: 'zip',
|
||||
url: '#',
|
||||
size: '1.2 MB'
|
||||
}
|
||||
]
|
||||
},
|
||||
chapters: {
|
||||
create: [
|
||||
{ time: '00:00', seconds: 0, title: "What's New in Tailwind v4" },
|
||||
{ time: '08:30', seconds: 510, title: 'Defining Color Palettes with @theme' },
|
||||
{ time: '20:15', seconds: 1215, title: 'Building Glassmorphism Cards' }
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create Cheatsheets
|
||||
await db.cheatsheet.create({
|
||||
data: {
|
||||
slug: 'git-komutlari-hizli-rehber',
|
||||
title: 'Essential Git & GitHub Commands Cheatsheet',
|
||||
category: 'DevOps & Tooling',
|
||||
description: 'Handy reference for daily Git workflow, branching, and conflict resolution commands.',
|
||||
tags: ['Git', 'GitHub', 'Terminal'],
|
||||
items: {
|
||||
create: [
|
||||
{ command: 'git checkout -b feature/new-feature', description: 'Creates a new branch and switches to it.' },
|
||||
{ command: 'git status', description: 'Lists modified and untracked files.' },
|
||||
{ command: 'git commit -m "feat: add new page"', description: 'Saves changes with a descriptive commit message.' },
|
||||
{ command: 'git push origin feature/new-feature', description: 'Pushes the branch to remote repository.' },
|
||||
{ command: 'git log --oneline -n 5', description: 'Displays last 5 commits in clean single line format.' }
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await db.cheatsheet.create({
|
||||
data: {
|
||||
slug: 'nextjs-app-router-cheatsheet',
|
||||
title: 'Next.js App Router File Structure & Route Handlers',
|
||||
category: 'Next.js',
|
||||
description: 'Special file conventions (page, layout, loading, error) and their responsibilities.',
|
||||
tags: ['Next.js', 'App Router', 'React'],
|
||||
items: {
|
||||
create: [
|
||||
{ command: 'app/[locale]/page.tsx', description: 'Main page component for the route.' },
|
||||
{ command: 'app/layout.tsx', description: 'Root layout component wrapping all pages.' },
|
||||
{ command: 'app/loading.tsx', description: 'Suspense fallback displayed while page loads.' },
|
||||
{ command: 'app/error.tsx', description: 'Client-side Error Boundary component.' },
|
||||
{ command: 'app/api/route.ts', description: 'REST API Endpoint handlers (GET, POST, PUT, DELETE).' }
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Seeding completed successfully!');
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('Seed error:', e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await db.$disconnect();
|
||||
await pool.end();
|
||||
});
|
||||
Reference in New Issue
Block a user