project setup with core files including configuration, package management, and basic structure. Added .gitignore, README, and various TypeScript types for CMS components. Implemented initial components and layouts for the application.

This commit is contained in:
Peter Meier
2025-12-13 23:26:13 +01:00
parent ea288a5bbc
commit b1a556dc6d
167 changed files with 19057 additions and 131 deletions

View File

@@ -0,0 +1,89 @@
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(),
},
};
};