Files
sell/middlelayer/utils/dataloaders.ts

90 lines
2.5 KiB
TypeScript

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<string, Product | null>(
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<string, Page | null>(
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<string, User | null>(
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<string, Product | null>;
page: DataLoader<string, Page | null>;
user: DataLoader<string, User | null>;
};
}
/**
* 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(),
},
};
};