@thorprovider/adapters 4.2.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/PROVIDER_IMPLEMENTATION_ANALYSIS.md +659 -0
  2. package/dist/index.d.mts +160 -1
  3. package/dist/index.d.ts +160 -1
  4. package/dist/index.js +384 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +384 -2
  7. package/dist/index.mjs.map +1 -1
  8. package/docs/RETRY_SOLUTION_SUMMARY.md +26 -11
  9. package/docs/authentication.md +115 -62
  10. package/docs/capabilities-system.md +4 -2
  11. package/docs/category-customization.md +37 -29
  12. package/docs/fetch-reliability-solution.md +127 -278
  13. package/docs/getting-started.md +43 -29
  14. package/docs/profile-management.md +68 -38
  15. package/docs/services-overview.md +4 -2
  16. package/package.json +1 -1
  17. package/quick-reference.md +33 -0
  18. package/src/providers/medusa/admin.test.ts +404 -0
  19. package/src/providers/medusa/admin.ts +442 -0
  20. package/src/providers/medusa/auth.test.ts +137 -0
  21. package/src/providers/medusa/auth.ts +96 -1
  22. package/src/providers/medusa/index.ts +21 -1
  23. package/src/providers/shopify/auth.ts +6 -0
  24. package/src/resilience/README.md +70 -48
  25. package/src/core/errors.js +0 -161
  26. package/src/core/fetch-utils.js +0 -240
  27. package/src/core/logger.js +0 -63
  28. package/src/metadata/channel-scope-validation.js +0 -136
  29. package/src/metadata/channel-scope.js +0 -174
  30. package/src/metadata/index.js +0 -31
  31. package/src/providers/medusa/auth.js +0 -601
  32. package/src/providers/medusa/index.js +0 -2485
  33. package/src/providers/medusa/payment.js +0 -265
  34. package/src/providers/medusa/transforms.js +0 -505
  35. package/src/types/capabilities.types.js +0 -141
  36. package/src/types/provider.js +0 -9
  37. package/src/utils/payment-utils.js +0 -152
@@ -1,14 +1,26 @@
1
- # Solución a Errores Frecuentes de "Failed to fetch products"
1
+ ---
2
+ title: Fetch Reliability Solution
3
+ purpose: Documents the retry and circuit breaker patterns implemented for robust backend communication
4
+ type: reference
5
+ tags: [resilience, retry, circuit-breaker, fetch, network, medusa]
6
+ related:
7
+ - RETRY_SOLUTION_SUMMARY.md
8
+ - providers-overview.md
9
+ - ../src/resilience/README.md
10
+ updated: 2026-05-03
11
+ ---
12
+
13
+ # Fetch Reliability Solution
2
14
 
3
- **Problema identificado**: Febrero 10, 2026
4
- **Estado**: ✅ Resuelto
5
- **Severidad**: Alta (afectaba experiencia de usuario con fallos intermitentes)
15
+ **Problem identified**: February 10, 2026
16
+ **Status**: ✅ Resolved + Extended with Circuit Breaker
17
+ **Severity**: High (intermittent user-facing failures)
6
18
 
7
19
  ---
8
20
 
9
- ## 🔴 Problema Original
21
+ ## 🔴 Original Problem
10
22
 
11
- El error `ProviderAPIError: Failed to fetch products: fetch failed` ocurría con frecuencia en el V0 starter, interrumpiendo la carga de productos desde el backend de Medusa.
23
+ The error `ProviderAPIError: Failed to fetch products: fetch failed` occurred intermittently in the V0 starter when loading products from the Medusa backend.
12
24
 
13
25
  ```
14
26
  ⨯ Error [ProviderAPIError]: Failed to fetch products: fetch failed
@@ -18,80 +30,55 @@ El error `ProviderAPIError: Failed to fetch products: fetch failed` ocurría con
18
30
  provider: 'medusa',
19
31
  ```
20
32
 
21
- **Características del problema**:
22
- - Ocurría cada cierto tiempo sin patrón predecible
23
- - El backend funcionaba con normalidad cuando se probaba directamente
24
- - El error era `fetch failed` sin más detalles
25
- - No había información de qué causaba el fallo
33
+ **Characteristics:**
34
+ - Occurred without a predictable pattern
35
+ - Backend was healthy when tested directly
36
+ - Error was `fetch failed` with no further detail
37
+ - No information about the root cause
26
38
 
27
39
  ---
28
40
 
29
- ## 🔍 Causas Identificadas
41
+ ## 🔍 Root Causes
30
42
 
31
- ### 1. **Ausencia de Retry Logic**
32
- - **Problema**: Cualquier fallo temporal de red causaba error inmediato
33
- - **Impacto**: Fallos transitorios (picos de latencia, pérdida momentánea de paquetes) causaban errores visibles al usuario
34
- - **Solución**: Implementar reintentos automáticos con exponential backoff
43
+ ### 1. No Retry Logic
44
+ Any transient network failure caused an immediate error. Spikes in latency or momentary packet loss were visible to the user.
35
45
 
36
- ### 2. **Sin Timeout Configurado**
37
- - **Problema**: Requests sin límite de tiempo, podían quedarse colgadas indefinidamente
38
- - **Impacto**: Requests lentos bloqueaban la aplicación sin dar feedback
39
- - **Solución**: Timeout de 10 segundos por request
46
+ ### 2. No Timeout
47
+ Requests had no time limit and could hang indefinitely.
40
48
 
41
- ### 3. **Falta de Keep-Alive en Conexiones HTTP**
42
- - **Problema**: Cada request creaba nueva conexión TCP (handshake completo cada vez)
43
- - **Impacto**: Mayor latencia, mayor probabilidad de fallos de conexión
44
- - **Solución**: Implementada implícitamente en el SDK de Medusa (reutiliza conexiones)
49
+ ### 3. No Keep-Alive
50
+ Each request created a new TCP connection (full handshake every time), increasing latency and failure probability.
45
51
 
46
- ### 4. **Sin Manejo de Errores de Red Específico**
47
- - **Problema**: Error genérico "fetch failed" sin información útil
48
- - **Impacto**: Difícil diagnosticar la causa raíz
49
- - **Solución**: Logging detallado con contexto de reintentos
50
-
51
- ### 5. **Configuración de URL del Backend**
52
- - **Observación**: URL con trailing slash `https://erpthor.com/`
53
- - **Riesgo potencial**: Redirecciones innecesarias dependiendo de la configuración del servidor
54
- - **Recomendación**: Verificar que el backend esté bien configurado para manejar trailing slashes
52
+ ### 4. Generic Error Messages
53
+ `fetch failed` with no context made root-cause diagnosis difficult.
55
54
 
56
55
  ---
57
56
 
58
- ## ✅ Soluciones Implementadas
59
-
60
- ### 1. Nuevo Módulo `fetch-utils.ts` (`@thorprovider/adapters/core`)
57
+ ## ✅ Solutions Implemented
61
58
 
62
- Creamos utilidades centralizadas para manejo robusto de requests HTTP:
59
+ ### 1. Retry Logic with Exponential Backoff (`fetch-utils.ts`)
63
60
 
64
- **Características**:
65
- - ✅ **Retry automático con exponential backoff**
66
- - 3 reintentos por defecto (4 intentos totales)
67
- - Delay inicial: 300ms
68
- - Backoff multiplicador: 2x (300ms → 600ms → 1200ms)
69
- - Delay máximo: 5 segundos
61
+ Located at `packages/adapters/src/core/fetch-utils.ts`. Exported from the main package entry point:
70
62
 
71
- - ✅ **Timeout configurable**
72
- - 10 segundos por defecto
73
- - Usa `AbortController` nativo
74
- - Timeout independiente por cada intento
63
+ ```typescript
64
+ import { fetchWithRetry, createFetchWithRetry } from '@thorprovider/adapters';
65
+ ```
75
66
 
76
- - ✅ **Detección inteligente de errores retryables**
77
- - Network errors (fetch failed, connection refused)
78
- - Timeout errors
79
- - HTTP status codes específicos: 408, 429, 500, 502, 503, 504
67
+ > ⚠️ **Note:** `@thorprovider/adapters` does not expose subpath exports (e.g. `@thorprovider/adapters/core/fetch-utils`). Always import from the main entry point.
80
68
 
81
- - ✅ **Logging detallado**
82
- - Debug info de cada intento
83
- - Warnings en reintentos con tiempo restante
84
- - Errors con contexto completo
69
+ **Features:**
70
+ - ✅ Automatic retry with exponential backoff (3 retries by default, 4 total attempts)
71
+ - ✅ Configurable timeout via `AbortController` (10s default)
72
+ - ✅ Smart retryable error detection: network errors, timeouts, HTTP 408/429/500/502/503/504
73
+ - ✅ Detailed logging per attempt
85
74
 
86
- **API**:
75
+ **API:**
87
76
 
88
77
  ```typescript
89
- // Uso básico
90
- import { fetchWithRetry } from '@thorprovider/adapters/core/fetch-utils';
91
-
78
+ // Basic usage
92
79
  const response = await fetchWithRetry('https://api.example.com/products');
93
80
 
94
- // Configuración personalizada
81
+ // Custom configuration
95
82
  const response = await fetchWithRetry(
96
83
  'https://api.example.com/products',
97
84
  { method: 'POST', body: JSON.stringify(data) },
@@ -102,298 +89,160 @@ const response = await fetchWithRetry(
102
89
  }
103
90
  );
104
91
 
105
- // Factory para crear fetch personalizado
106
- import { createFetchWithRetry } from '@thorprovider/adapters/core/fetch-utils';
107
-
92
+ // Factory for a reusable configured fetch
108
93
  const customFetch = createFetchWithRetry({ maxRetries: 5 });
109
94
  const response = await customFetch(url);
110
95
  ```
111
96
 
112
- ### 2. Actualización del `MedusaProvider`
97
+ ### 2. MedusaProvider Integration
113
98
 
114
- **Cambios**:
115
-
116
- 1. **Import de fetch utilities**:
117
- ```typescript
118
- import { createFetchWithRetry, type RetryConfig } from '../../core/fetch-utils';
119
- ```
120
-
121
- 2. **Nueva propiedad en `MedusaProviderConfig`**:
122
- ```typescript
123
- export interface MedusaProviderConfig extends ProviderConfig {
124
- // ... propiedades existentes
125
-
126
- /**
127
- * Retry configuration for fetch requests (optional)
128
- */
129
- retry?: RetryConfig;
130
- }
131
- ```
132
-
133
- 3. **Inyección de fetch personalizado en el constructor**:
134
- ```typescript
135
- constructor(config: MedusaProviderConfig) {
136
- // ... código existente
137
-
138
- // Create fetch with retry logic
139
- const fetchWithRetry = createFetchWithRetry(config.retry);
140
-
141
- this.sdk = new Medusa({
142
- baseUrl: config.baseUrl,
143
- publishableKey: config.publishableKey,
144
- fetch: fetchWithRetry as any, // ← Custom fetch with retries!
145
- // ... resto de configuración
146
- });
147
- }
148
- ```
149
-
150
- ### 3. Configuración por Defecto en V0 Starter
151
-
152
- Actualizamos `/packages/core/lib/commerce.ts`:
99
+ The `MedusaProviderConfig` accepts an optional `retry` field:
153
100
 
154
101
  ```typescript
155
102
  export const commerce = createProvider({
156
- provider: providerType,
103
+ provider: 'medusa',
157
104
  config: {
158
- baseUrl: NEXT_PUBLIC_COMMERCE_API_URL,
159
- publishableKey: NEXT_PUBLIC_COMMERCE_API_KEY,
160
-
161
- // ✨ Nueva configuración de retry
105
+ baseUrl: process.env.NEXT_PUBLIC_COMMERCE_API_URL!,
106
+ publishableKey: process.env.NEXT_PUBLIC_COMMERCE_API_KEY!,
162
107
  retry: {
163
- maxRetries: 3, // 4 intentos totales
164
- timeoutMs: 10000, // 10 segundos por request
165
- initialDelayMs: 300, // Delay inicial 300ms
166
- backoffMultiplier: 2, // Exponential backoff (2x cada vez)
167
- maxDelayMs: 5000, // Cap en 5 segundos
108
+ maxRetries: 3, // 4 total attempts
109
+ timeoutMs: 10000, // 10s per request
110
+ initialDelayMs: 300, // Initial delay
111
+ backoffMultiplier: 2, // Exponential backoff (2x each retry)
112
+ maxDelayMs: 5000, // Cap at 5s
168
113
  },
169
-
170
- // ... resto de configuración
171
114
  },
172
115
  });
173
116
  ```
174
117
 
175
- ---
118
+ ### 3. Circuit Breaker Pattern
176
119
 
177
- ## 📊 Impacto Esperado
120
+ The Circuit Breaker is **fully implemented** in `packages/adapters/src/resilience/`. It prevents cascading failures when the backend is consistently unavailable.
178
121
 
179
- ### Antes (Sin Retry Logic)
180
- ```
181
- Request 1 → Network glitch → ❌ FAIL → Error al usuario
182
- Probabilidad de fallo visible: ~5-10% en condiciones normales
183
- ```
122
+ ```typescript
123
+ import { CircuitBreaker, backendCircuitBreaker } from '@thorprovider/adapters';
184
124
 
185
- ### Después (Con Retry Logic)
186
- ```
187
- Request 1 → Network glitch → ⏳ Retry 1 (300ms) → ⏳ Retry 2 (600ms) → ✅ SUCCESS
188
- Probabilidad de fallo visible: ~0.1-0.5% (reducción de 90-98%)
125
+ // Use the pre-configured global instance
126
+ const products = await backendCircuitBreaker.execute(
127
+ () => commerce.getProducts(),
128
+ [] // Fallback: return empty array if circuit is open
129
+ );
130
+
131
+ // Or create a custom instance
132
+ const breaker = new CircuitBreaker({
133
+ failureThreshold: 5,
134
+ resetTimeout: 60000,
135
+ name: 'medusa-api',
136
+ });
189
137
  ```
190
138
 
191
- **Beneficios cuantificables**:
192
- - ✅ **90-98% reducción en errores visibles** al usuario
193
- - ✅ **Mejor experiencia de usuario** sin interrupciones
194
- - ✅ **Resiliencia ante problemas de red transitorios**
195
- - ✅ **Mejor observabilidad** con logs detallados
196
- - ✅ **Configuración flexible** por entorno (dev/staging/prod)
139
+ See [resilience/README.md](../src/resilience/README.md) for full Circuit Breaker documentation.
197
140
 
198
141
  ---
199
142
 
200
- ## 🧪 Testing
201
-
202
- ### Escenarios de Prueba
203
-
204
- 1. **Backend funcionando normalmente**
205
- - ✅ Debe funcionar igual que antes
206
- - ✅ Sin delays innecesarios
207
- - ✅ Log: "Fetch successful" en primer intento
208
-
209
- 2. **Backend lento (respuesta > 10s)**
210
- - ✅ Timeout después de 10 segundos
211
- - ✅ Retry automático
212
- - ✅ Log: "Request timeout", luego reintento
213
-
214
- 3. **Backend temporalmente caído**
215
- - ✅ 4 intentos totales (1 original + 3 retries)
216
- - ✅ Delays: 300ms, 600ms, 1200ms
217
- - ✅ Log: "Fetch failed after all retries"
218
-
219
- 4. **Red intermitente**
220
- - ✅ Recovery automático en siguiente intento exitoso
221
- - ✅ Sin error visible al usuario si se recupera antes del 4º intento
143
+ ## 📊 Expected Impact
222
144
 
223
- ### Comandos de Testing
224
-
225
- ```bash
226
- # Build y verificar que compila sin errores
227
- yarn build
228
-
229
- # Verificar tipos
230
- yarn type-check
231
-
232
- # Correr tests (cuando existan)
233
- yarn test
145
+ ### Before (No Retry Logic)
146
+ ```
147
+ Request → Network glitch → ❌ FAIL → Error shown to user
148
+ Visible failure rate: ~5-10% under normal conditions
149
+ ```
234
150
 
235
- # Dev mode para probar en navegador
236
- yarn dev:showcase # Puerto 3002
237
- yarn workspace @thorprovider/core dev # Puerto 3000
151
+ ### After (With Retry Logic)
152
+ ```
153
+ Request → Network glitch → ⏳ Retry 1 (300ms) → ⏳ Retry 2 (600ms) → ✅ SUCCESS
154
+ Visible failure rate: ~0.1-0.5% (90-98% reduction)
238
155
  ```
239
156
 
240
157
  ---
241
158
 
242
- ## 🎛️ Configuración por Entorno
159
+ ## 🎛️ Configuration by Environment
243
160
 
244
- ### Development (más agresivo con timeouts)
161
+ ### Development (fast feedback)
245
162
  ```typescript
246
163
  retry: {
247
- maxRetries: 2, // Menos reintentos para feedback rápido
248
- timeoutMs: 5000, // 5 segundos (más estricto)
164
+ maxRetries: 2,
165
+ timeoutMs: 5000,
249
166
  initialDelayMs: 200,
250
167
  }
251
168
  ```
252
169
 
253
- ### Production (más tolerante)
170
+ ### Production (maximum availability)
254
171
  ```typescript
255
172
  retry: {
256
- maxRetries: 5, // Más reintentos para máxima disponibilidad
257
- timeoutMs: 15000, // 15 segundos (más tolerante)
173
+ maxRetries: 5,
174
+ timeoutMs: 15000,
258
175
  initialDelayMs: 500,
259
176
  maxDelayMs: 10000,
260
177
  }
261
178
  ```
262
179
 
263
- ### Testing/CI (sin reintentos)
180
+ ### Testing / CI (fail fast)
264
181
  ```typescript
265
182
  retry: {
266
- maxRetries: 0, // Sin reintentos, fallar rápido
267
- timeoutMs: 3000, // 3 segundos máximo
183
+ maxRetries: 0,
184
+ timeoutMs: 3000,
268
185
  }
269
186
  ```
270
187
 
271
188
  ---
272
189
 
273
- ## 📝 Logging y Monitoreo
274
-
275
- ### Logs Generados
190
+ ## 📝 Logging
276
191
 
277
- **Nivel DEBUG** (solo en development):
192
+ **DEBUG** (development only):
278
193
  ```
279
194
  [FetchUtils] Fetch attempt { url, attempt: 1, maxAttempts: 4, timeout: 10000 }
280
195
  [FetchUtils] Fetch successful { url, attempt: 1 }
281
196
  ```
282
197
 
283
- **Nivel WARN** (retry attempts):
198
+ **WARN** (retry attempts):
284
199
  ```
285
- [FetchUtils] Fetch failed, retrying... {
286
- url,
287
- attempt: 2,
288
- maxAttempts: 4,
289
- nextRetryIn: '600ms',
290
- error: 'fetch failed'
291
- }
200
+ [FetchUtils] Fetch failed, retrying... { url, attempt: 2, maxAttempts: 4, nextRetryIn: '600ms', error: 'fetch failed' }
292
201
  ```
293
202
 
294
- **Nivel ERROR** (failure final):
203
+ **ERROR** (all retries exhausted):
295
204
  ```
296
- [FetchUtils] Fetch failed after all retries {
297
- url,
298
- totalAttempts: 4,
299
- error: 'fetch failed'
300
- }
205
+ [FetchUtils] Fetch failed after all retries { url, totalAttempts: 4, error: 'fetch failed' }
301
206
  [MedusaProvider] Failed to fetch products { error: 'fetch failed' }
302
207
  ```
303
208
 
304
- ### Métricas Recomendadas (Future Work)
305
-
306
- Para producción, considerar agregar:
307
- - ✅ Contador de reintentos exitosos vs fallidos
308
- - ✅ Latencia promedio de requests
309
- - ✅ Rate de timeout por endpoint
310
- - ✅ Alertas cuando retry rate > 10%
311
-
312
209
  ---
313
210
 
314
- ## 🚀 Próximos Pasos (Opcional - Future Work)
315
-
316
- ### 1. Circuit Breaker Pattern
317
- Si el backend está completamente caído, evitar reintentos innecesarios:
318
-
319
- ```typescript
320
- // Después de N fallos consecutivos, "abrir el circuito"
321
- // y fallar rápido por X segundos antes de intentar de nuevo
322
- ```
323
-
324
- ### 2. Cache Layer
325
- Para reducir dependencia en el backend:
326
-
327
- ```typescript
328
- // Cache en memoria/Redis de productos frecuentes
329
- // Fallback a cache si backend falla
330
- ```
331
-
332
- ### 3. Health Check Endpoint
333
- Endpoint ligero para verificar salud del backend:
211
+ ## 🧪 Testing
334
212
 
335
- ```typescript
336
- // GET /health
337
- // Si falla, skip productos complejos y usar cache
338
- ```
213
+ ```bash
214
+ # Run adapter unit tests (includes fetch-utils and circuit breaker)
215
+ yarn workspace @thorprovider/adapters test
339
216
 
340
- ### 4. Retry Budget
341
- Limitar % de requests totales que pueden hacer retry:
217
+ # Type check
218
+ yarn workspace @thorprovider/adapters type-check
342
219
 
343
- ```typescript
344
- // Protección contra thundering herd cuando backend se cae
220
+ # Build
221
+ yarn workspace @thorprovider/adapters build
345
222
  ```
346
223
 
347
224
  ---
348
225
 
349
- ## 🔗 Referencias
350
-
351
- ### Archivos Modificados
352
-
353
- 1. **`packages/adapters/src/core/fetch-utils.ts`** (NUEVO)
354
- - Utilidades de retry y timeout
226
+ ## ✅ Validation Checklist
355
227
 
356
- 2. **`packages/adapters/src/core/index.ts`**
357
- - Export de fetch-utils
358
-
359
- 3. **`packages/adapters/src/providers/medusa/index.ts`**
360
- - Import fetch-utils
361
- - Actualización de `MedusaProviderConfig`
362
- - Inyección de custom fetch en constructor
363
-
364
- 4. **`packages/core/lib/commerce.ts`**
365
- - Configuración por defecto de retry
366
-
367
- ### Documentación Relacionada
368
-
369
- - `packages/adapters/README.md` - Arquitectura de adapters
370
- - `packages/adapters/docs/providers-overview.md` - Providers overview
371
- - `.github/copilot-instructions.md` - Copilot patterns
372
-
373
- ### Patrones Implementados
374
-
375
- - ✅ **Retry Pattern** con Exponential Backoff
376
- - ✅ **Timeout Pattern** con AbortController
377
- - ✅ **Strategy Pattern** (configurable retry strategies)
378
- - ✅ **Dependency Injection** (custom fetch en SDK)
228
+ - [x] Code compiles without TypeScript errors
229
+ - [x] Exports updated in `core/index.ts`
230
+ - [x] Default retry config added in V0 starter
231
+ - [x] Logging implemented at appropriate levels
232
+ - [x] Backward compatible (`retry` is optional)
233
+ - [x] Unit tests added (vitest)
234
+ - [x] Circuit Breaker implemented and exported
235
+ - [ ] Validation in staging environment (TODO)
236
+ - [ ] Production metrics baseline (TODO)
379
237
 
380
238
  ---
381
239
 
382
- ## ✅ Checklist de Validación
383
-
384
- - [x] Código compila sin errores TypeScript
385
- - [x] Exports actualizados en `core/index.ts`
386
- - [x] Configuración por defecto agregada en V0 starter
387
- - [x] Logging implementado en niveles apropiados
388
- - [x] Documentación completa creada
389
- - [x] Backward compatible (retry es opcional)
390
- - [ ] Tests unitarios agregados (TODO)
391
- - [ ] Tests de integración con backend real (TODO)
392
- - [ ] Validación en entorno de staging (TODO)
393
- - [ ] Deploy a producción (TODO)
394
-
395
- ---
240
+ ## 🔗 Related Files
396
241
 
397
- **Autor**: GitHub Copilot (Claude Sonnet 4.5)
398
- **Fecha**: Febrero 10, 2026
399
- **Versión**: 1.0
242
+ | File | Purpose |
243
+ |------|---------|
244
+ | `packages/adapters/src/core/fetch-utils.ts` | Retry + timeout utilities |
245
+ | `packages/adapters/src/core/index.ts` | Core exports |
246
+ | `packages/adapters/src/resilience/` | Circuit Breaker implementation |
247
+ | `packages/adapters/src/providers/medusa/index.ts` | MedusaProvider with retry injection |
248
+ | `packages/core/lib/commerce.ts` | Default retry config in V0 starter |
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Getting started"
3
3
  purpose: "Provide a quick setup guide for integrating Thor adapters in mock or live backend mode"
4
- lastReviewed: "2026-05-01"
4
+ lastReviewed: "2026-05-03"
5
5
  type: how-to
6
6
  tags: [setup, installation, adapters, medusa, configuration]
7
7
  related:
@@ -12,7 +12,7 @@ related:
12
12
 
13
13
  # Getting Started
14
14
 
15
- Quick setup guide for integrating Thor adapters into our project. Start with `mock` for backend-optional development, or configure a real backend immediately.
15
+ Quick setup guide for integrating Thor adapters into your project. Start with `mock` for backend-optional development, or configure a real backend immediately.
16
16
 
17
17
  ## Prerequisites
18
18
 
@@ -42,7 +42,7 @@ const liveCommerce = createProvider({
42
42
  },
43
43
  });
44
44
 
45
- // Fetch products
45
+ // Fetch products (framework-agnostic)
46
46
  const products = await commerce.getProducts({ first: 10 });
47
47
  ```
48
48
 
@@ -56,7 +56,7 @@ yarn add @thorprovider/adapters
56
56
 
57
57
  ### Step 2: Initialize the Provider
58
58
 
59
- Create a shared instance for our application.
59
+ Create a shared singleton instance for your application.
60
60
 
61
61
  ```typescript
62
62
  // lib/commerce.ts
@@ -95,30 +95,60 @@ NEXT_PUBLIC_COMMERCE_API_URL=http://localhost:9000
95
95
  NEXT_PUBLIC_COMMERCE_API_KEY=your_publishable_key_here
96
96
  ```
97
97
 
98
- ### Step 4: Use in Server Components (Next.js)
98
+ ### Step 4: Use in Your Application
99
+
100
+ The adapters are framework-agnostic. Use them in any server or client context:
101
+
102
+ ```typescript
103
+ // Pure TypeScript / Node.js
104
+ import { commerce } from './lib/commerce';
105
+
106
+ const products = await commerce.getProducts();
107
+ console.log(products.map(p => p.title));
108
+ ```
109
+
110
+ #### Framework Integration Example (Next.js App Router)
99
111
 
100
112
  ```typescript
101
- // app/products/page.tsx
113
+ // app/products/page.tsx ← This is framework code, NOT adapter code
102
114
  import { commerce } from '@/lib/commerce';
103
115
 
104
116
  export default async function ProductsPage() {
105
117
  const products = await commerce.getProducts();
106
-
118
+
107
119
  return (
108
- <div>
120
+ <ul>
109
121
  {products.map(product => (
110
- <div key={product.id}>{product.title}</div>
122
+ <li key={product.id}>{product.title}</li>
111
123
  ))}
112
- </div>
124
+ </ul>
113
125
  );
114
126
  }
115
127
  ```
116
128
 
129
+ > ℹ️ The adapter (`commerce`) is framework-agnostic. Only the page component is Next.js-specific.
130
+
131
+ ## Capability Checks
132
+
133
+ Before calling optional features, always check the provider's capabilities:
134
+
135
+ ```typescript
136
+ // ✅ Correct: check capability before calling
137
+ if (commerce.capabilities.advancedSearch && commerce.searchProductsAdvanced) {
138
+ const result = await commerce.searchProductsAdvanced({ query: 'laptop' });
139
+ }
140
+
141
+ // ✅ Correct: check auth availability before calling auth methods
142
+ if (commerce.auth) {
143
+ const customer = await commerce.auth.getCurrentCustomer();
144
+ }
145
+ ```
146
+
117
147
  ## ✅ DO's
118
148
 
119
149
  1. **Use Singleton Pattern:** Create one instance of the provider and export it.
120
150
  2. **Handle Environment Variables:** Require `baseUrl` only for real backends.
121
- 3. **Prefer Server-Side:** Fetch data in Server Components whenever possible.
151
+ 3. **Check Capabilities:** Use `commerce.capabilities.featureName` before calling optional methods.
122
152
  4. **Use TypeScript Types:** Leverage the exported types from `@thorprovider/adapters` for better DX.
123
153
  5. **Configure Debug Mode:** Enable `debug: true` during development to trace API issues.
124
154
 
@@ -127,16 +157,8 @@ export default async function ProductsPage() {
127
157
  1. **Don't hardcode credentials:** Never put URLs or API keys directly in the code.
128
158
  2. **Don't create multiple instances:** Creating providers inside components causes memory leaks and inconsistent state.
129
159
  3. **Don't expose Secret Keys:** Only use Publishable Keys in frontend code.
130
- 4. **Don't ignore Capability checks:** Use `commerce.can('feature')` before calling optional methods.
131
- 5. **Don't import React in Adapters:** Keep adapters framework-agnostic.
132
-
133
- ## Common Patterns
134
-
135
- ### Shared Client and Server Instance
136
- Using a single file to export the provider ensure both SSR and Client-side transitions use the same configuration.
137
-
138
- ### Dynamic Backend Switching
139
- You can switch providers (e.g., from 'medusa' to 'mock') for testing purposes by changing the configuration.
160
+ 4. **Don't import React or Next.js in adapter code:** Keep adapters framework-agnostic.
161
+ 5. **Don't call optional methods without checking:** `commerce.auth`, `commerce.searchProductsAdvanced`, etc. may be undefined.
140
162
 
141
163
  ## Common Errors & Solutions
142
164
 
@@ -152,14 +174,6 @@ You can switch providers (e.g., from 'medusa' to 'mock') for testing purposes by
152
174
  **Cause:** Backend doesn't allow the frontend origin.
153
175
  **Solution:** Add your frontend URL to Medusa server configuration.
154
176
 
155
- ## Common Pitfalls
156
-
157
- > ⚠️ **Pitfall 1: Mixing Session and JWT**
158
- > Ensure you consistently use one authentication method. JWT is preferred for headless setups.
159
-
160
- > ⚠️ **Pitfall 2: Forgetting to regenerate types**
161
- > If the backend data structure changes, ensure your adapter matches the expected interface.
162
-
163
177
  ## Troubleshooting
164
178
 
165
179
  | Issue | Solution |