feat(saleor): Phase 1 - GraphQL Client Setup

- Add Apollo Client for Saleor GraphQL API
- Create GraphQL fragments (Product, Variant, Checkout)
- Create GraphQL queries (Products, Checkout)
- Create GraphQL mutations (Checkout operations)
- Add TypeScript types for Saleor entities
- Add product helper functions
- Install @apollo/client and graphql dependencies

Part of WordPress/WooCommerce → Saleor migration
This commit is contained in:
Unchained
2026-03-21 12:36:21 +02:00
parent db1914d69b
commit 7b94537670
27 changed files with 7879 additions and 3 deletions

302
infrastructure-overview.md Normal file
View File

@@ -0,0 +1,302 @@
# Infrastructure Overview: WordPress → Saleor Migration
## System Architecture
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ K3s Cluster │
│ │
│ ┌──────────────────────────┐ ┌─────────────────────────────────────────┐ │
│ │ manoonoils namespace │ │ saleor namespace │ │
│ │ (WordPress/WooCommerce)│ │ (Headless Commerce) │ │
│ │ │ │ │ │
│ │ ┌──────────────────┐ │ │ ┌──────────────────────────────────┐ │ │
│ │ │ WordPress │ │ │ │ Saleor API (Django) │ │ │
│ │ │ - WooCommerce │ │ │ │ - GraphQL endpoint │ │ │
│ │ │ - ADVMO Plugin │ │ │ │ - Product management │ │ │
│ │ └────────┬─────────┘ │ │ └────────┬─────────────────────────┘ │ │
│ │ │ │ │ │ │ │
│ │ ┌────────▼─────────┐ │ │ ┌────────▼──────────────────────────┐ │ │
│ │ │ Redis │ │ │ │ Redis │ │ │
│ │ │ (Object Cache) │ │ │ │ (Celery + Cache) │ │ │
│ │ └──────────────────┘ │ │ └───────────────────────────────────┘ │ │
│ │ │ │ │ │ │ │
│ │ ┌────────▼─────────┐ │ │ ┌────────▼──────────────────────────┐ │ │
│ │ │ MariaDB │ │ │ │ PostgreSQL │ │ │
│ │ │ (WP database) │ │ │ │ (Products, Orders, Users) │ │ │
│ │ └──────────────────┘ │ │ └───────────────────────────────────┘ │ │
│ │ │ │ │ │
│ └──────────────────────────┘ └─────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Shared Services │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ MinIO Object Storage │ │ │
│ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │
│ │ │ │ manoon-media │ │ saleor │ │ other │ │ │ │
│ │ │ │ (WP images) │ │ (Saleor │ │ buckets... │ │ │ │
│ │ │ │ │ │ images) │ │ │ │ │ │
│ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ Traefik Ingress │ │ │
│ │ │ │ │ │
│ │ │ manoonoils.com → WordPress │ │ │
│ │ │ dev.manoonoils.com → Next.js Storefront │ │ │
│ │ │ api.manoonoils.com → Saleor API │ │ │
│ │ │ dashboard.manoonoils.com → Saleor Dashboard │ │ │
│ │ │ minio-api.nodecrew.me → MinIO API │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
## Redis Usage
### WordPress Redis (manoonoils namespace)
```yaml
# WordPress uses Redis for:
# - Object caching (reduces DB queries)
# - Session storage
# - Transients cache
Service: redis.manoonoils.svc.cluster.local:6379
Purpose: WP Object Cache only
Data: Temporary cache (can be cleared)
Persistence: Not critical
```
**wp-config.php:**
```php
define( 'WP_REDIS_HOST', 'redis' );
define( 'WP_REDIS_PORT', 6379 );
```
### Saleor Redis (saleor namespace)
```yaml
# Saleor uses Redis for:
# - Celery task queue (background jobs)
# - Django cache framework
# - WebSocket channel layer (if using subscriptions)
Service: saleor-redis.saleor.svc.cluster.local:6379
Purpose: Task queue + Cache
Data: Task queue messages, cached data
Persistence: Not critical (tasks re-created if lost)
```
**Saleor environment:**
```bash
CELERY_BROKER_URL=redis://saleor-redis.saleor:6379/0
REDIS_URL=redis://saleor-redis.saleor:6379/0
```
### Key Point: Separate Redis Instances
| Component | Redis Instance | Purpose |
|-----------|----------------|---------|
| **WordPress** | `redis.manoonoils` | Object cache only |
| **Saleor** | `saleor-redis.saleor` | Celery + cache |
| **No sharing** | - | Each has its own |
## Media Storage Architecture
### MinIO Configuration
**Single MinIO instance serves both systems:**
```
MinIO Server (minio.manoonoils:9000)
├── manoon-media/ ← WordPress uploads (existing)
│ ├── wp-content/
│ │ └── uploads/
│ │ ├── 2024/
│ │ │ └── 01/
│ │ │ └── product-image.jpg
│ │ └── 2023/
│ └── assets/
│ └── logo.png
└── saleor/ ← Saleor media (new)
├── products/ ← Product images
├── assets/ ← Logos, favicons
└── exports/ ← Data exports
```
### WordPress Media Flow
```
1. User uploads image in WordPress
2. ADVMO plugin intercepts upload
3. Image saved to MinIO: manoon-media/wp-content/uploads/2024/01/image.jpg
4. WordPress stores URL: https://minio-api.nodecrew.me/manoon-media/wp-content/uploads/2024/01/image.jpg
5. Image served from MinIO
```
### Saleor Media Flow
```
1. User uploads image in Saleor Dashboard
2. Saleor API saves to MinIO: saleor/products/image.jpg
3. Saleor generates thumbnails
4. Image served via API: https://api.manoonoils.com/media/products/image.jpg
5. Or direct from MinIO: https://minio-api.nodecrew.me/saleor/products/image.jpg
```
## Image Migration Process
### Option 1: Copy Images (Recommended)
```bash
# 1. Access MinIO
kubectl exec -it deployment/minio -n manoonoils -- /bin/sh
# 2. Set up alias
mc alias set local http://localhost:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD
# 3. Create saleor bucket if not exists
mc mb local/saleor
# 4. Copy all WordPress images to Saleor bucket
mc cp --recursive local/manoon-media/wp-content/uploads/ local/saleor/products/
# 5. Copy assets
mc cp local/manoon-media/assets/logo.png local/saleor/assets/
```
**Result:**
- Original images stay in `manoon-media` (WordPress keeps working)
- Copies in `saleor` (for Saleor use)
- No downtime during migration
### Option 2: Move Images (After Full Migration)
```bash
# Only after WordPress is fully retired:
# 1. Move instead of copy
mc mv local/manoon-media/wp-content/uploads/ local/saleor/products/
# 2. Update any remaining references
# 3. Delete manoon-media bucket when confirmed safe
```
## Logo & Asset Strategy
### During Migration Period
**Keep logos in both places:**
```
MinIO:
├── manoon-media/assets/logo.png ← Used by WordPress
└── saleor/assets/logo.png ← Used by Saleor
```
**Next.js storefront:**
```typescript
// Use absolute URL to MinIO
const LOGO_URL = 'https://minio-api.nodecrew.me/saleor/assets/logo.png';
// Or use Next.js public folder
import logo from '@/public/logo.png';
```
### Post-Migration
**Option A: Keep in MinIO**
- Serve from `saleor/assets/`
- Update via MinIO console or API
- CDN-friendly
**Option B: Move to Next.js**
```
storefront/public/
├── logo.png
├── favicon.ico
└── assets/
└── hero-banner.jpg
```
**Access:** `https://dev.manoonoils.com/logo.png`
## Data Flow During Migration
### Phase 1: Parallel Running
```
Customer visits dev.manoonoils.com (Saleor storefront)
Products fetched from Saleor API
Product images loaded from:
- NEW products: saleor bucket
- OLD products: manoon-media bucket (mapped URL)
Checkout via Saleor checkout API
```
### Phase 2: Full Cutover
```
Customer visits dev.manoonoils.com
All products in Saleor
All images in saleor bucket
WordPress fully retired
```
## Backup Strategy
### What to Back Up
| Component | Backup Method | Frequency | Location |
|-----------|--------------|-----------|----------|
| **WordPress DB** | Kopia | Daily | StorageBox |
| **WordPress files** | Kopia | Daily | StorageBox |
| **MinIO buckets** | Kopia | Daily | StorageBox |
| **Saleor DB** | Kopia | Daily | StorageBox |
| **Saleor PVC** | Kopia | Daily | StorageBox |
### MinIO Backup Commands
```bash
# Backup specific bucket
kopia snapshot create /mnt/storagebox/kopia-backups
# Or use MinIO client for bucket backup
mc mirror local/saleor /backup/saleor-$(date +%Y%m%d)
```
## Summary
| Component | WordPress | Saleor | Relationship |
|-----------|-----------|--------|--------------|
| **Redis** | Separate instance | Separate instance | No sharing |
| **Database** | MariaDB | PostgreSQL | Separate |
| **Media** | manoon-media bucket | saleor bucket | Same MinIO |
| **Cache** | WP Object Cache | Django Cache | Separate |
| **Task Queue** | None (WP-Cron) | Celery + Redis | Saleor only |
**Key Takeaways:**
1. ✅ Saleor has its own Redis (no conflict with WordPress)
2. ✅ Both use same MinIO (easy image copying)
3. ✅ Copy images from `manoon-media` to `saleor` bucket
4. ✅ Keep logos in both places during transition
5. ✅ WordPress can stay running while Saleor is tested