API Referansı ve GraphQL
REST endpoint'leri (api.*.ts), GraphQL Yoga, Better Auth kimlik doğrulama ve session yönetimi.
Achidemy’de REST API route’ları (api.*.ts), GraphQL (GraphQL Yoga) ve Better Auth ile kimlik doğrulama/session yönetimi kullanılır. Bu sayfa tüm api.* endpoint’lerinin görev ve parametrelerini, api.graphql.ts üzerinden şema ve client entegrasyonunu ve Better Auth hook’ları ile session yönetimini özetler. Her endpoint’in ne için ve nasıl kullanıldığı, istek/yanıt formatları ve örnek çağrılar için Platform API Referansı sayfasına bakın.
REST Endpoints — api.*.ts Görevleri ve Parametreleri
Section titled “REST Endpoints — api.*.ts Görevleri ve Parametreleri”Route tanımları app/routes.ts içindedir; dil prefix’i yok (/api/...).
| Endpoint | Dosya | Method | Görev | Parametreler / Gövde |
|---|---|---|---|---|
| POST /api/graphql | api.graphql.ts | GET/POST | GraphQL sorgu ve mutation; aşağıda ayrıca açıklanır. | Body: { query, variables } |
| /api/auth/ | api.auth.ts | * | Better Auth handler; giriş, kayıt, çıkış, OAuth, şifre sıfırlama, session. | Better Auth path’lerine göre (örn. sign-in/email, sign-up/email, sign-out, callback/google). |
| POST /api/stripe/webhook | api.stripe.webhook.ts | POST | Stripe webhook; checkout.session.completed, payment_intent.succeeded, subscription vb. | Stripe-Signature header; raw body imza doğrulaması. |
| POST /api/stripe/connect-onboarding | api.stripe.connect-onboarding.ts | POST | Stripe Connect Express onboarding; Account Link ile yönlendirme. | Form/cookie (session); redirect döner. |
| POST /api/moderate-text | api.moderate-text.ts | POST | Cloudflare AI ile metin moderasyonu; yorumlar, mesajlar ve Q&A için ortak AI filtresi. | JSON: { text: string } — dönüş: { isAllowed: boolean, reason: string }. |
| POST /api/instructor/update-manual-payout | api.instructor.update-manual-payout.ts | POST | TR eğitmeni: manuel ödeme bilgisi (IBAN/Payoneer) güncelleme. | FormData: details (string). Yetki: session + role instructor. |
| POST /api/lesson-resource-upload | api.lesson-resource-upload.ts | POST | Ders kaynağı (PDF vb.) yükleme; Bunny Storage. | FormData: lessonId, file. Yetki: eğitmen (kurs sahibi). Env: BUNNY_STORAGE_*. |
| POST /api/lesson/caption-upload | api.lesson.caption-upload.ts | POST | Video altyazısı (.vtt) yükleme; Bunny Stream + lesson_captions. | FormData: lessonId, captionFile, langCode, label. Env: BUNNY_LIBRARY_ID, BUNNY_API_KEY / BUNNY_STREAM_API_KEY. |
| POST /api/lesson/caption-delete | api.lesson.caption-delete.ts | POST | Video altyazısı silme; Bunny Stream + lesson_captions. | FormData: captionId. Env: BUNNY_LIBRARY_ID, BUNNY_API_KEY / BUNNY_STREAM_API_KEY. |
| POST /api/chat-image-upload | api.chat-image-upload.ts | POST | Mesajda görsel yükleme; Bunny Storage. | FormData: file (image/jpeg,png,gif,webp). Dönüş: { url }. Env: BUNNY_STORAGE_*, BUNNY_PULL_ZONE_URL. |
| GET /api/certificate/:id/download | api.certificate.$id.download.ts | GET | Sertifika PDF indirme. | Path: id (sertifika UUID). Yetki: session; sertifika userId eşleşmeli. |
| GET /api/certificates/:id/download | (aynı dosya) | GET | Aynı; plural URL (geriye dönük uyumluluk). | Aynı. |
| GET /api/invoice/:enrollmentId/download | api.invoice.$enrollmentId.download.ts | GET | Satın alma faturası PDF indirme. | Path: enrollmentId. Yetki: session; enrollment userId eşleşmeli. |
| GET /api/admin/activities | api.admin.activities.ts | GET | Admin “Tüm bildirimler” modalı; ödeme talepleri + kurs onayları. | Yetki: session + role admin. Dönüş: { activities } (JSON). |
| POST /api/video-telemetry | api.video-telemetry.ts | POST | Video telemetri heartbeat (15 sn blok); watch_time_logs insert + daily_activities upsert + subscription_watch_logs upsert + streak tetikleme + Enterprise anti‑cheat (payout koruması). | JSON: courseId, lessonId, durationSeconds (genelde 15), timestamp?. Session zorunlu. |
| POST /api/update-progress | api.update-progress.ts | POST | (Legacy) Video izleme ilerlemesi (saniye) kaydı; user_lessons_progress, daily_activities, subscription_watch_logs. | JSON: userId, lessonId, courseId, instructorId, secondsWatched, isSubscription. |
| GET /api/algolia-sync | api.algolia-sync.ts | GET | Tüm yayındaki kursları Algolia arama index’ine toplu senkronize eder; index ayarlarını (searchableAttributes, typoTolerance) yapılandırır. Tek seferlik başlangıç verisi aktarımı için. | Parametre yok. Env: VITE_ALGOLIA_APP_ID, ALGOLIA_ADMIN_KEY. Dönüş: { settings, sync: { synced }, totalPublished }. |
Not: api.exercise-resource-upload.ts ve api.quiz-resource-upload.ts projede dosya olarak vardır; routes.ts içinde route tanımı yoksa doğrudan /api/... ile erişilmez (iç kullanım veya farklı mount edilmiş olabilir). Dokümante edilen liste routes.ts’teki API route’larına göredir.
Veri için route loader, form/mutation için action kullanılır.
GraphQL Yoga — api.graphql.ts ve Şema
Section titled “GraphQL Yoga — api.graphql.ts ve Şema”Dosya: app/routes/api.graphql.ts
Endpoint: POST /api/graphql (GET de desteklenir; Yoga varsayılanı).
Akış:
context.cloudflare.envvegetDbUrl(env)ile DB bağlantısı;initAuth(dbUrl, env, context.cloudflare?.ctx)ile Better Auth (Cloudflarectx.waitUntilile arka plan e-posta gönderimi desteklenir).auth.api.getSession({ headers: request.headers })ile oturum alınır.- createYoga (graphql-yoga) ile Yoga instance:
schema(app/graphql/schema.ts),graphqlEndpoint: "/api/graphql",contextfonksiyonudb,request,user(session?.user + role),cloudflare(bölgesel fiyat/ülke için) döner. yoga.handleRequest(request)ile istek işlenir; GET (GraphiQL/playground) ve POST (sorgu) desteklenir.
Performans notu: GraphQL şeması içinde ağır sorgular (ör.
categoryTree,adminStats,enrolledCourses) N+1 sorgu problemi olmadan, toplu SQL (group by) ve in‑memory cache ile optimize edilmiştir. Cloudflare Workers üzerinde global scope değişkenleri (Map) ardışık istekler arasında RAM’de tutulur; bu sayedecategoryTreesonucu 1 saatlik TTL ile bellekte saklanır, admin istatistikleri ve öğrenci kurs listesi ise tek seferde toplu sorgular ile hesaplanır.
Şema tanımları: app/graphql/schema.ts
- createSchema (graphql-yoga) ile tek bir şema:
typeDefs(SDL string) +resolvers(Query, Mutation, tipler). - GraphQLContext:
{ db, request?, user?, cloudflare? }— resolver’laruserile yetkilendirme,requestile cookie/header,cloudflareilerequest.cf(ülke) kullanır. - Tipler: User, Course, Enrollment, Review, Certificate, PayoutRequest, CartItem, CourseBundle vb.
- Query örnekleri: courses, courseBySlug, me, myCertificates, conversationMessages, unreadMessagesCount, admin için listeler vb.
- Mutation örnekleri: createCourse, updateCourse, toggleLessonCompletion, recordLearningActivity, requestPayout, createStripeCheckoutSession, addBundleToCart, createBundleCheckoutSession, addToCart, createReview, reportCourse (kurs şikayet sistemi; DMCA / içerik ihlali) vb. Paket checkout ve vitrin: Kurs ve Paket Vitrin Sayfaları.
Client entegrasyonu: Uygulama içinde fetch("/api/graphql", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query, variables }) }) ile sorgu/mutation atılır; cookie ile session gönderilir (credentials: “include”). Dil prefix’i yok; base URL’e göre /api/graphql kullanılır.
Kurs Şikayet Mutasyonu — reportCourse
Section titled “Kurs Şikayet Mutasyonu — reportCourse”- SDL:
input ReportCourseInput { courseId: ID!, reason: String!, description: String }reportCourse(input: ReportCourseInput!): Boolean
- Amaç: Öğrencilerin kursları DMCA / içerik ihlali / spam gibi sebeplerle şikayet etmesini sağlamak.
- Yetki: Sadece giriş yapmış kullanıcılar; anonim kullanıcılar için resolver
"Şikayet oluşturmak için giriş yapmalısınız."hatası üretir. - Veritabanı:
course_reportstablosuna insert;courseId,reporterId,reason,description,status="pending"vecreatedAtalanları doldurulur. - Otomatik kalkan: Pending şikayet sayısı 5’e ulaştığında kurs otomatik
pending_reviewyapılır ve eğitmene bildirim gönderilir. - Kullanım:
ReportCourseModalbileşeni (app/components/courses/ReportCourseModal.tsx), kurs detay sayfasında/api/graphqlüzerinden bu mutasyonu çağırır.
AI Şikayet Analizi — analyzeCourseReports
Section titled “AI Şikayet Analizi — analyzeCourseReports”- SDL:
analyzeCourseReports(courseId: ID!): AIReportAnalysis - Dönüş:
{ summary, commonReasons, extractedLinks, criticalityScore, recommendation } - Yetki: Sadece admin.
- Amaç: Bir kursa gelen tüm şikayetleri Cloudflare AI (Llama 3.1 8B) ile özetlemek; ortak nedenler, linkler ve kritiklik skoru üretir.
- Kullanım:
/admin/reports/:courseIdsayfasında AIReportAnalyzer bileşeni.
AI Kurs Kalite Ön İncelemesi — analyzeCourseContentForAdmin
Section titled “AI Kurs Kalite Ön İncelemesi — analyzeCourseContentForAdmin”- SDL:
analyzeCourseContentForAdmin(courseId: ID!): AICourseAnalysis - Dönüş:
{ summary, contentIssues, missingAssets, profanityDetected, qualityScore, recommendation } - Yetki: Sadece admin.
- Amaç: Kurs başlığı, açıklaması, müfredatı, fiyatı ve eksik asset’leri (kapak, tanıtım videosu) Cloudflare AI ile analiz etmek.
- Kullanım:
/admin/course/:slug/previewsayfasında AICourseReviewer bileşeni (app/components/admin/AICourseReviewer.tsx).
Detaylı açıklama için Yapay Zeka Destekli Moderasyon sayfasına bakın.
Better Auth — Kimlik Doğrulama Hook’ları ve Session Yönetimi
Section titled “Better Auth — Kimlik Doğrulama Hook’ları ve Session Yönetimi”Base path: /api/auth
Dosya: app/routes/api.auth.ts — tüm istekler auth.handler(request) ile Better Auth’a iletilir.
Konfigürasyon: app/lib/auth.ts — betterAuth({ ... })
- basePath:
/api/auth - baseURL: env
BASE_URLveya localhost - database: Drizzle adapter (PostgreSQL);
user,session,account,verificationtabloları. - socialProviders: Google (clientId, clientSecret; overrideUserInfoOnSignIn: true).
- emailAndPassword: enabled; sendResetPassword (şifre sıfırlama linki, dil destekli URL); onPasswordReset; resetPasswordTokenExpiresIn: 3600.
- emailVerification: enabled; sendOnSignUp: true; sendVerificationEmail (dil destekli verify-email URL); afterEmailVerification.
- user.additionalFields: role (string, default “student”), onboardingCompleted (boolean), stripeCustomerId (string).
- databaseHooks:
- user.create.after: OAuth ile oluşturmada
image→googleImagegüncellemesi; emailVerified ise hoş geldin e-postası (sendWelcomeEmail). - user.update.after: Google ile giriş/güncellemede
image→googleImagesenkronizasyonu.
- user.create.after: OAuth ile oluşturmada
Session yönetimi: Better Auth, cookie tabanlı session kullanır. auth.api.getSession({ headers: request.headers }) ile mevcut oturum okunur; resolver’lar ve API route’ları bu session’a göre user ve yetki kontrolü yapar. Çıkış: /api/auth/sign-out (Better Auth endpoint’i).
Kullanım: Login/register sayfaları Better Auth client (örn. signIn.email, signUp.email) ile /api/auth path’lerini tetikler; callback ve redirect’ler BASE_URL ve dil path’ine göre yapılandırılır.
| Konu | Açıklama |
|---|---|
| REST api.* | routes.ts’te tanımlı endpoint’ler: graphql, auth/*, stripe/webhook, stripe/connect-onboarding, moderate-text, instructor/update-manual-payout, lesson-resource-upload, lesson/caption-upload, lesson/caption-delete, chat-image-upload, certificate(s)/:id/download, invoice/:enrollmentId/download, admin/activities, video-telemetry (heartbeat), update-progress (legacy). |
| GraphQL | POST /api/graphql; Yoga + schema (typeDefs + resolvers); context: db, request, user, cloudflare. Client: fetch + credentials. |
| Better Auth | /api/auth/* → auth.handler; Drizzle + Google + email/password + verification + reset; databaseHooks (user create/update); session cookie ile getSession. |
İlgili mimari: Checkout & Webhooks (Stripe webhook), Stripe Connect (connect-onboarding), TR Payout (update-manual-payout), Video Altyazıları (caption-upload, caption-delete), Öğrenme Deneyimi (video-telemetry), Kurs ve Paket Vitrin Sayfaları (bundle checkout), İletişim (chat-image-upload).
İlgili Dosyalar
Section titled “İlgili Dosyalar”app/routes/api.graphql.ts— GraphQL Yoga endpoint; şema ve context.app/routes/api.auth.ts— Better Auth handler (tüm /api/auth/*).app/graphql/schema.ts— GraphQL typeDefs ve resolvers.app/lib/auth.ts— Better Auth yapılandırması.app/lib/graphql-client.ts— Uygulama içi GraphQL istemcisi.