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:
443
README.md
443
README.md
@@ -1,2 +1,443 @@
|
||||
# sell
|
||||
# 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.
|
||||
|
||||
Reference in New Issue
Block a user