import DataLoader from "dataloader"; import type { Product, Page } from "../types/index.js"; import type { User } from "../types/user.js"; import { dataService } from "../dataService.js"; import { userService } from "../auth/userService.js"; /** * Dataloader für Batch-Loading von Produkten * Verhindert N+1 Queries, wenn mehrere Produkte in einer Query abgefragt werden */ export const createProductLoader = () => { return new DataLoader( async (ids: readonly string[]) => { // Batch-Loading: Lade alle Produkte in einem Batch const products = await Promise.all( ids.map((id) => dataService.getProduct(id)) ); // Stelle sicher, dass die Reihenfolge mit den IDs übereinstimmt return products; } ); }; /** * Dataloader für Batch-Loading von Seiten * Unterstützt Locale im Key-Format: "slug:locale" oder "slug" */ export const createPageLoader = () => { return new DataLoader( async (keys: readonly string[]) => { const pages = await Promise.all( keys.map((key) => { // Parse Key: Format kann "slug:locale" oder "slug" sein const parts = key.split(":"); const slug = parts[0] ?? ""; const locale = parts.length > 1 ? parts[1] : undefined; return dataService.getPage(slug, locale); }) ); return pages; } ); }; /** * Dataloader für Batch-Loading von Usern */ export const createUserLoader = () => { return new DataLoader( async (userIds: readonly string[]) => { const users = await Promise.all( userIds.map((id) => userService.getUserById(id)) ); return users; } ); }; /** * Context für GraphQL Resolver * Enthält Dataloader-Instanzen und User-Informationen * * Der Context wird für jeden GraphQL Request erstellt und enthält: * - `user`: Aktueller authentifizierter User (oder null) * - `loaders`: Dataloader-Instanzen für Batch-Loading (verhindert N+1 Queries) */ export interface GraphQLContext { user: User | null; loaders: { product: DataLoader; page: DataLoader; user: DataLoader; }; } /** * Erstellt einen neuen Context mit Dataloadern und User */ export const createContext = (user: User | null = null): GraphQLContext => { return { user, loaders: { product: createProductLoader(), page: createPageLoader(), user: createUserLoader(), }, }; };