Files
sell/README.md

444 lines
11 KiB
Markdown

# GraphQL Middlelayer + Astro Frontend
Ein moderner, skalierbarer Onlineshop mit GraphQL-basiertem Middlelayer und Astro-Frontend. Der Middlelayer fungiert als flexible Abstraktionsschicht zwischen Frontend und verschiedenen Datenquellen.
## 🚀 Features
- **GraphQL API** mit Apollo Server v5
- **Astro Frontend** mit SSR und Client-Side Interaktivität
- **Adapter Pattern** für flexible Datenquellen (Mock, Headless CMS, Database)
- **Performance-Optimierungen**:
- Dataloader für Batch-Loading (verhindert N+1 Queries)
- Redis/In-Memory Caching
- Response Caching
- Query Complexity Limits
- **Monitoring & Observability**:
- Structured Logging (Winston)
- Prometheus Metrics
- Distributed Tracing
- **Type-Safe** mit TypeScript durchgängig
- **Modern UI** mit Tailwind CSS und Alpine.js
- **Internationalization (i18n)**:
- URL-basierte Locales (`/de`, `/en`)
- Übersetzungen aus Middlelayer (mit Default-Fallback)
- CMS-Inhalte mehrsprachig (vorbereitet für Contentful)
## 📋 Voraussetzungen
- Node.js 18+
- npm oder yarn
- (Optional) Redis für verteiltes Caching
## 🛠️ Installation
```bash
# Dependencies installieren
npm install
# (Optional) Redis installieren (macOS)
brew install redis
brew services start redis
```
## 🏃 Quick Start
```bash
# GraphQL Server + Astro Frontend starten
npm start
# Oder einzeln:
npm run mock:server # Nur GraphQL Server (Port 4000)
npm run dev # Nur Astro Frontend (Port 4321)
```
## 📁 Projektstruktur
```
/
├── middlelayer/ # GraphQL Middlelayer
│ ├── adapters/ # Datenquellen-Adapter (Mock, CMS, etc.)
│ ├── config/ # Konfiguration
│ ├── monitoring/ # Logging, Metrics, Tracing
│ ├── plugins/ # Apollo Server Plugins
│ ├── types/ # TypeScript Typen
│ ├── utils/ # Utilities (Cache, Dataloader, etc.)
│ ├── index.ts # Server Entry Point
│ ├── schema.ts # GraphQL Schema
│ └── resolvers.ts # GraphQL Resolvers
├── src/ # Astro Frontend
│ ├── components/ # Astro Komponenten
│ ├── layouts/ # Layout Templates
│ ├── lib/ # Utilities & GraphQL Client
│ ├── pages/ # Astro Pages
│ └── styles/ # Global Styles
└── docs/ # Dokumentation
```
## ⚙️ Konfiguration
### Environment Variables
Erstelle eine `.env` Datei im Root-Verzeichnis:
```env
# Server Ports
PORT=4000 # GraphQL Server Port
METRICS_PORT=9090 # Metrics Server Port
# Logging
LOG_LEVEL=info # debug, info, warn, error
NODE_ENV=development # development, production
# GraphQL
MAX_QUERY_COMPLEXITY=1000 # Query Complexity Limit
# Redis (Optional)
REDIS_ENABLED=true # Redis Cache aktivieren
REDIS_HOST=localhost # Redis Host
REDIS_PORT=6379 # Redis Port
REDIS_PASSWORD= # Optional: Redis Password
# Cache TTLs (in Millisekunden)
CACHE_PAGES_TTL=60000 # 60 Sekunden
CACHE_PAGE_SEO_TTL=300000 # 5 Minuten
CACHE_NAVIGATION_TTL=300000 # 5 Minuten
CACHE_PRODUCTS_TTL=30000 # 30 Sekunden
```
### Cache-Konfiguration
Cache-TTLs können über Environment Variables oder direkt in `middlelayer/config/cache.ts` konfiguriert werden.
## 🌐 Endpoints
| Service | URL | Beschreibung |
|---------|-----|--------------|
| GraphQL API | `http://localhost:4000` | GraphQL Endpoint & Playground |
| Metrics | `http://localhost:9090/metrics` | Prometheus Metrics |
| Health Check | `http://localhost:9090/health` | Service Health Status |
| Astro Frontend | `http://localhost:4321` | Frontend Application |
## 📊 GraphQL Schema
### Queries
```graphql
# Produkte
query {
products(limit: 4) {
id
name
price
originalPrice
promotion {
category
text
}
}
product(id: "prod-123") {
id
name
description
price
}
}
# CMS (mit Locale-Support)
query {
pageSeo(locale: "de") {
title
description
}
page(slug: "/about", locale: "de") {
headline
subheadline
}
pages(locale: "en") {
slug
name
}
navigation(locale: "de") {
links {
name
slug
}
}
}
# Übersetzungen
query {
translations(locale: "de", namespace: "auth") {
locale
translations {
key
value
}
}
}
}
page(slug: "/") {
slug
name
headline
}
navigation {
name
links {
name
url
}
}
}
```
## 🏗️ Architektur
### Middlelayer
Der Middlelayer verwendet das **Adapter Pattern** für flexible Datenquellen:
```
Frontend (Astro)
GraphQL API (Apollo Server)
DataService (Singleton)
DataAdapter (Interface)
┌─────────────┬──────────────┬─────────────┐
│ Mock Adapter│ CMS Adapter │ DB Adapter │
└─────────────┴──────────────┴─────────────┘
```
**Vorteile:**
- Einfaches Wechseln zwischen Datenquellen
- Testbarkeit durch Mock-Adapter
- Zentrale Logik im DataService
- Caching auf Service-Ebene
### Frontend
- **Astro** für Server-Side Rendering
- **Alpine.js** für Client-Side Interaktivität
- **Tailwind CSS** für Styling
- **GraphQL Client** für Datenabfragen
## 🔧 Entwicklung
### NPM Scripts
```bash
npm run mock:server # Startet GraphQL Server
npm run dev # Startet Astro Dev Server
npm start # Startet beide (concurrently)
npm run build # Production Build
npm run preview # Preview Production Build
```
### Neuen Adapter hinzufügen
1. Implementiere `DataAdapter` Interface:
```typescript
// middlelayer/adapters/myAdapter.ts
import type { DataAdapter } from './interface.js';
export class MyAdapter implements DataAdapter {
async getProducts(limit?: number): Promise<Product[]> {
// Implementierung
}
// ... weitere Methoden
}
```
2. In `middlelayer/adapters/config.ts` registrieren:
```typescript
export function createAdapter(): DataAdapter {
const adapterType = process.env.ADAPTER_TYPE || 'mock';
if (adapterType === 'myAdapter') {
return new MyAdapter();
}
// ...
}
```
## 📈 Monitoring
### Prometheus Metrics
Metriken sind verfügbar unter `http://localhost:9090/metrics`:
- `graphql_queries_total` - Anzahl der Queries
- `graphql_query_duration_seconds` - Query-Dauer
- `cache_hits_total` / `cache_misses_total` - Cache-Statistiken
- `dataservice_calls_total` - DataService-Aufrufe
- `errors_total` - Fehler-Anzahl
### Logging
Structured Logging mit Winston:
- Console Output (Development)
- JSON Logs (Production)
- Log-Level konfigurierbar
### Tracing
Automatische Trace-ID-Generierung für Request-Tracking.
## 🚀 Deployment
### Production Build
```bash
npm run build
```
### Docker (Beispiel)
```dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
RUN npm run build
CMD ["npm", "start"]
```
## 🧪 Testing
```bash
# GraphQL Query testen
curl -X POST http://localhost:4000 \
-H "Content-Type: application/json" \
-d '{"query":"{ products(limit: 4) { id name price } }"}'
# Health Check
curl http://localhost:9090/health
# Metrics
curl http://localhost:9090/metrics
```
## 📚 Weitere Dokumentation
- [Architektur & Skalierung](./docs/ARCHITECTURE_SCALING.md) - Detaillierte Architektur-Analyse
- [Redis Setup](./middlelayer/utils/REDIS_SETUP.md) - Redis Cache Konfiguration
- [Monitoring](./middlelayer/monitoring/README.md) - Monitoring & Observability
## 🐛 Bekannte Probleme
### Query Complexity Schema-Realm-Konflikt
**Problem:** `graphql-query-complexity` hat einen Schema-Realm-Konflikt mit Apollo Server.
**Workaround:** Das Plugin überspringt den Check bei Realm-Konflikten automatisch. Funktioniert, aber Complexity-Check wird manchmal übersprungen.
**Status:** Funktioniert, permanente Lösung in Arbeit.
## 🌍 Internationalization (i18n)
### URL-basierte Locales
Das System unterstützt URL-basierte Locales:
- `/de` - Deutsche Version
- `/en` - Englische Version
- `/` - Auto-Redirect zu Browser-Locale oder Cookie
### Übersetzungen
**Architektur:**
- **Defaults**: Fallback-Übersetzungen in `src/lib/i18n/defaults.ts`
- **Middlelayer**: Übersetzungen können vom GraphQL-Server geladen werden
- **Überschreibungen**: Middlelayer-Übersetzungen überschreiben Defaults
**Verwendung in React:**
```tsx
import { useI18n } from "../lib/i18n/useI18n.js";
function MyComponent() {
const { t } = useI18n("auth");
return <h1>{t("login.title")}</h1>;
}
```
**Verwendung in Alpine.js:**
```html
<div x-data="{ t: window.i18n?.t || ((key) => key) }">
<button x-text="t('nav.login')"></button>
</div>
```
### CMS-Locale-Support
**Contentful-Ansatz:**
Contentful verwendet ein Locale-System, bei dem:
- Jedes Content-Feld lokalisiert werden kann
- Standard-Locale wird definiert (z.B. `en-US`)
- Fallback-Locales können konfiguriert werden
- API-Aufrufe enthalten `locale`-Parameter: `fields.headline['en-US']`
**Unser System:**
- GraphQL-Schema unterstützt `locale`-Parameter für alle CMS-Queries
- Adapter-Interface ist vorbereitet für Locale-Parameter
- Mock-Adapter gibt aktuell alle Locales gleich zurück (TODO: Locale-spezifische Mock-Daten)
- Bei Contentful-Integration: Adapter würde `locale`-Parameter an Contentful API weitergeben
**Beispiel GraphQL Query:**
```graphql
query {
page(slug: "/about", locale: "de") {
headline # Deutsche Übersetzung
subheadline
}
page(slug: "/about", locale: "en") {
headline # Englische Übersetzung
subheadline
}
}
```
## 🔮 Roadmap
- [ ] Query Complexity Schema-Realm-Problem dauerhaft lösen
- [ ] Database Adapter (PostgreSQL, MySQL)
- [ ] Headless CMS Adapter (Contentful, Strapi)
- [ ] Locale-spezifische Inhalte implementieren
- [ ] Fallback-Locales konfigurieren
- [ ] Rate Limiting
- [ ] Authentication/Authorization ✅ (implementiert)
- [ ] GraphQL Subscriptions
- [ ] i18n: Weitere Sprachen hinzufügen
- [ ] i18n: Locale-spezifische Mock-Daten für CMS
- [ ] E2E Tests
## 🤝 Beitragen
1. Fork das Repository
2. Erstelle einen Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Committe deine Änderungen (`git commit -m 'Add some AmazingFeature'`)
4. Push zum Branch (`git push origin feature/AmazingFeature`)
5. Öffne einen Pull Request
## 📝 Lizenz
Dieses Projekt ist privat.
## 👥 Autoren
- Entwickelt mit ❤️ für moderne E-Commerce-Lösungen
---
**Hinweis:** Dieses Projekt ist in aktiver Entwicklung. Für Fragen oder Probleme öffne bitte ein Issue.