@thorprovider/adapters 5.0.0 → 5.0.2

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 (47) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +53 -631
  4. package/dist/index.d.mts +406 -194
  5. package/dist/index.d.ts +406 -194
  6. package/dist/index.js +3092 -604
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +3081 -602
  9. package/dist/index.mjs.map +1 -1
  10. package/docs/RETRY_SOLUTION_SUMMARY.md +1 -1
  11. package/docs/authentication.md +0 -26
  12. package/docs/capabilities-system.md +66 -36
  13. package/docs/getting-started.md +1 -1
  14. package/docs/providers-overview.md +16 -13
  15. package/docs/update-documentation.md +10 -8
  16. package/package.json +6 -5
  17. package/quick-reference.md +0 -33
  18. package/src/backend/factory.ts +11 -1
  19. package/src/factory/index.ts +52 -74
  20. package/src/index.ts +17 -3
  21. package/src/providers/bigcommerce/bigcommerce.ts +6 -0
  22. package/src/providers/bigcommerce/index.ts +315 -0
  23. package/src/providers/bigcommerce/transforms.ts +227 -0
  24. package/src/providers/index.ts +16 -1
  25. package/src/providers/magento/index.ts +387 -0
  26. package/src/providers/magento/magento.ts +5 -0
  27. package/src/providers/magento/queries.ts +267 -0
  28. package/src/providers/magento/transforms.ts +249 -0
  29. package/src/providers/medusa/auth.test.ts +94 -92
  30. package/src/providers/medusa/auth.ts +72 -123
  31. package/src/providers/medusa/index.test.ts +392 -0
  32. package/src/providers/medusa/index.ts +1 -21
  33. package/src/providers/medusa/live-smoke.test.ts +412 -0
  34. package/src/providers/shopify/auth.ts +402 -0
  35. package/src/providers/shopify/index.ts +444 -0
  36. package/src/providers/shopify/mutations.ts +247 -0
  37. package/src/providers/shopify/queries.ts +324 -0
  38. package/src/providers/shopify/shopify.ts +7 -0
  39. package/src/providers/shopify/transforms.ts +275 -0
  40. package/src/providers/spree/index.ts +344 -0
  41. package/src/providers/spree/spree.ts +5 -0
  42. package/src/providers/spree/transforms.ts +254 -0
  43. package/src/providers/woocommerce/index.ts +310 -0
  44. package/src/providers/woocommerce/transforms.ts +254 -0
  45. package/src/providers/woocommerce/woocommerce.ts +5 -0
  46. package/src/types/capabilities.types.ts +250 -0
  47. package/vitest.live.config.ts +18 -0
package/README.md CHANGED
@@ -1,668 +1,90 @@
1
1
  ---
2
2
  title: "@thorprovider/adapters"
3
- purpose: "Explain the adapter package, its value proposition, and how to use the unified commerce provider layer"
4
- lastReviewed: "2026-05-01"
3
+ purpose: "Verified entry point for the framework-agnostic commerce adapter package"
4
+ lastReviewed: "2026-05-28"
5
5
  ---
6
6
 
7
- # @thorprovider/adapters v2.0
7
+ # @thorprovider/adapters
8
8
 
9
- **Unified commerce adapters for Thor Commerce ecosystem**
9
+ Framework-agnostic commerce adapter package for Thor Commerce.
10
10
 
11
- Framework-agnostic TypeScript library providing a unified interface for multiple e-commerce platforms (Medusa, Shopify, WooCommerce, etc.).
11
+ ## Verified facts
12
12
 
13
- ---
14
-
15
- ## 🎯 Why This Package Exists
16
-
17
- **Problem**: Direct backend integration leads to:
18
- - ❌ Vendor lock-in (Medusa code in 50+ files → impossible to switch to Shopify)
19
- - ❌ Inconsistent data structures (Medusa Product ≠ Shopify Product ≠ WooCommerce Product)
20
- - ❌ Duplicate business logic (cart logic in 10 apps = 10x maintenance)
21
- - ❌ Framework coupling (Medusa SDK tied to Next.js server actions)
22
-
23
- **Solution**: @thorprovider/adapters provides:
24
- - ✅ **Unified Interface**: One API for all backends (switch provider with 1 line change)
25
- - ✅ **Bidirectional Compatibility Layer**: Full read **and** write support — Backend responses → `@thorprovider/types` (inbound) and `@thorprovider/types` → Backend API payloads (outbound). Mutations (cart, orders, customers, addresses) are fully abstracted.
26
- - ✅ **Framework Agnostic**: Works with Next.js, Remix, Astro, or vanilla JS
27
- - ✅ **Capability Detection**: 21 capabilities for adaptive UIs (does backend support X?)
28
-
29
- **Inspired by**: Vercel Commerce (multi-provider), Stripe SDK (unified payments), Auth.js (multi-auth-provider)
30
-
31
- ---
32
-
33
- ## 💰 ROI / Value Proposition
34
-
35
- ### Backend Migration Cost Reduction
36
- ```typescript
37
- // Without @thorprovider/adapters (direct Medusa integration)
38
- Migration from Medusa → Shopify:
39
- 1. Find all Medusa SDK calls: 200+ files
40
- 2. Rewrite each call to Shopify API: 40 hours
41
- 3. Transform data structures: 20 hours
42
- 4. Update tests: 10 hours
43
- 5. Fix bugs from migration: 20 hours
44
- = 90 hours per app × $100/hour = $9,000 per app
45
-
46
- For 10 apps: $90,000 migration cost
47
-
48
- // With @thorprovider/adapters
49
- 1. Change provider in config: 1 line
50
- createProvider({ provider: 'shopify' }) // was 'medusa'
51
- 2. Verify transforms work: 2 hours
52
- 3. Update env variables: 1 hour
53
- = 3 hours × $100/hour = $300 per app
54
-
55
- For 10 apps: $3,000 migration cost
56
-
57
- // ROI: $90,000 - $3,000 = $87,000 saved (97% cost reduction)
58
- ```
59
-
60
- ### Development Speed
61
- ```typescript
62
- // Traditional approach (per feature)
63
- 1. Learn Medusa SDK: 4 hours
64
- 2. Implement getProducts(): 2 hours
65
- 3. Handle errors: 1 hour
66
- 4. Add retry logic: 2 hours
67
- 5. Write tests: 2 hours
68
- = 11 hours per feature
69
-
70
- // With @thorprovider/adapters
71
- 1. const products = await commerce.getProducts();
72
- 2. Already has: types, errors, retries, tests
73
- = 10 minutes per feature
74
-
75
- // Speed improvement: 66x faster
76
- ```
77
-
78
- ### Multi-Tenant Platforms
79
- ```typescript
80
- // Scenario: Platform with 100 clients
81
- // 50 clients use Medusa, 30 use Shopify, 20 use WooCommerce
82
-
83
- // Without adapters:
84
- - Maintain 3 separate codebases
85
- - 3x development cost
86
- - 3x bug surface area
87
-
88
- // With @thorprovider/adapters:
89
- - Single codebase
90
- - Provider selected per client: clientConfig.provider
91
- - 1x development, 1x maintenance
92
-
93
- // ROI: 67% cost reduction for multi-backend platforms
94
- ```
95
-
96
- ---
97
-
98
- ## 🤖 AI Agent Decision Framework
99
-
100
- ### When to Use @thorprovider/adapters
101
- ✅ Integrating with e-commerce backends (Medusa, Shopify, custom APIs)
102
- ✅ Building multi-tenant platforms (different backends per client)
103
- ✅ Need to switch backends in the future (reduce vendor lock-in)
104
- ✅ Framework-agnostic apps (Next.js, Remix, Astro, etc.)
105
- ✅ Want standardized data shapes across backends
106
-
107
- ### When NOT to Use
108
- ❌ Single backend forever + never migrating (direct SDK might be simpler)
109
- ❌ Need 100% of platform-specific features (use native SDK)
110
- ❌ Non-commerce application (no products/carts/orders)
111
- ❌ Backend has no JS SDK (need REST/GraphQL client first)
112
-
113
- ### Decision Tree
114
- ```
115
- Need e-commerce backend integration?
116
- ├─ YES → Multiple backends OR might switch?
117
- │ ├─ YES → Use @thorprovider/adapters (future-proof)
118
- │ └─ NO → Single backend forever?
119
- │ ├─ Need framework flexibility → Use @thorprovider/adapters
120
- │ └─ Tight coupling OK → Use native SDK
121
- └─ NO → Use generic HTTP client (fetch/axios)
122
- ```
123
-
124
- ### Key Rules for AI Agents
125
- 1. **NEVER import React/Next.js** in adapters code (framework-agnostic layer)
126
- 2. **ALWAYS transform to @thorprovider/types** (don't expose backend-specific types)
127
- 3. **ALWAYS use try/catch** with proper error handling (CommerceError)
128
- 4. **DOCUMENT capabilities** when adding new backends (updateCapabilities())
129
- 5. **WRITE transform functions** for each data type (transformProduct, transformCart)
130
-
131
- ### Supported Providers
132
-
133
- Currently implemented:
134
- - ✅ **Mock** — Fixture-backed provider for local development, previews, and backend-optional storefront bootstrapping
135
- - ✅ **Medusa JS** (v2) — Full implementation with multi-tenant support
136
- - ✅ **Stel Order** — ERP adapter (v1): catalog, categories, inventory, customers, orders, payment/delivery listing. No cart/checkout/auth (single-company ERP).
137
-
138
- Planned (Phase 2–3):
139
- - 🟡 **Shopify** — In progress
140
- - 🟡 **BigCommerce** — Planned
141
- - 🟡 **WooCommerce** — Planned
142
- - 🟡 **Spree** — Planned
143
- - 🟡 **Magento** — Planned
144
-
145
- ### Provider Selection
146
-
147
- ```typescript
148
- // Mock provider (safe default for preview / development)
149
- const mockCommerce = createProvider({
150
- provider: 'mock',
151
- config: {
152
- currencyCode: 'USD',
153
- }
154
- });
155
-
156
- // Medusa backend
157
- const commerce = createProvider({
158
- provider: 'medusa',
159
- config: {
160
- baseUrl: process.env.NEXT_PUBLIC_COMMERCE_API_URL,
161
- publishableKey: process.env.NEXT_PUBLIC_COMMERCE_API_KEY,
162
- currencyCode: 'USD',
163
- }
164
- });
13
+ - Package name: `@thorprovider/adapters`
14
+ - Current package version: `4.2.2`
15
+ - This package should not import React or `next/*`
16
+ - Public factory: `createProvider(...)`
17
+ - Public types are re-exported from both local adapter modules and `@thorprovider/types`
165
18
 
166
- // Stel Order ERP (catalog + CRM read/write, no cart/checkout)
167
- const stelCommerce = createProvider({
168
- provider: 'stelorder',
169
- config: {
170
- baseUrl: 'https://your-company.stelorder.com/app',
171
- apiKey: process.env.STEL_ORDER_API_KEY,
172
- currencyCode: 'EUR',
173
- companyName: 'My Company',
174
- }
175
- });
176
-
177
- const products = await commerce.getProducts();
178
- ```
179
-
180
- ### 🔒 Multi-Tenant Data Isolation: Sales Channel Filtering
181
-
182
- **Design Principle**: Every product query in `@thorprovider/adapters` includes explicit **sales channel filtering** to ensure one storefront instance never sees another tenant's products.
183
-
184
- #### The 1:1 Relationship
19
+ ## Provider identifiers accepted by `createProvider`
185
20
 
186
- ```
187
- V0 Starter Instance (Storefront)
188
- ↓
189
- NEXT_PUBLIC_SALES_CHANNEL_ID = "sc_01KJJY1..."
190
- ↓
191
- All product queries automatically filter:
192
- {
193
- sales_channel_id: [process.env.NEXT_PUBLIC_SALES_CHANNEL_ID],
194
- ...
195
- }
196
- ↓
197
- Backend returns products linked to THIS channel ONLY
198
- ↓
199
- Result: Multi-tenant isolation at data layer
200
- ```
201
-
202
- #### Implementation (Medusa Provider)
203
-
204
- All product retrieval methods filter by sales channel (updated 2026-03-26):
205
-
206
- ```typescript
207
- // Example: getProducts() in src/providers/medusa/index.ts
208
- async getProducts(options = {}) {
209
- const salesChannelId = process.env.NEXT_PUBLIC_SALES_CHANNEL_ID;
210
-
211
- const queryParams = {
212
- q: options.query,
213
- limit: options.first ?? 100,
214
- // ... other params
215
- };
216
-
217
- // CRITICAL: Apply sales channel filter
218
- if (salesChannelId) {
219
- queryParams.sales_channel_id = [salesChannelId];
220
- }
221
-
222
- const { products } = await this.sdk.store.product.list(queryParams);
223
- return products.map(p => transformProduct(p));
224
- }
225
- ```
21
+ The current factory union in `src/factory/index.ts` accepts these provider identifiers:
226
22
 
227
- **Methods implementing this pattern**:
228
- - ✅ `getProducts()` — Main product listing
229
- - ✅ `getProduct()` — Single product by handle
230
- - ✅ `getCollectionProducts()` — Products in collection
231
- - ✅ `getCategoryProducts()` — Products in category
232
- - ✅ `createLineItem()` — Pre-check variant validation
23
+ - `mock`
24
+ - `medusa`
25
+ - `stelorder`
26
+ - `shopify`
27
+ - `bigcommerce`
28
+ - `woocommerce`
29
+ - `spree`
30
+ - `magento`
233
31
 
234
- #### Why Explicit Filtering?
32
+ Implementation depth differs by provider. Use `commerce.capabilities` and optional method checks instead of assuming every provider supports every feature.
235
33
 
236
- > **Question**: Medusa's publishable API key already restricts unauthorized endpoints. Why add `sales_channel_id` parameter?
237
- >
238
- > **Answer**: **Defense-in-depth + Future-proofing**
239
- > 1. **API Key**: Prevents unauthorized endpoint access (✅)
240
- > 2. **sales_channel_id parameter**: Prevents data leakage within store endpoints (✅)
241
- > 3. **Together**: Best practice for multi-tenant SaaS platforms
34
+ ## Quick start
242
35
 
243
- #### Configuration (Per Platform)
36
+ ```ts
37
+ import { createProvider } from '@thorprovider/adapters'
244
38
 
245
- ```typescript
246
- // Medusa (REQUIRED for multi-tenant)
247
39
  const commerce = createProvider({
248
- provider: 'medusa',
40
+ provider: 'mock',
249
41
  config: {
250
- baseUrl: process.env.NEXT_PUBLIC_COMMERCE_API_URL,
251
- publishableKey: process.env.NEXT_PUBLIC_COMMERCE_API_KEY,
252
42
  currencyCode: 'USD',
253
- // CRITICAL: Derived from env, used in every product query
254
- // salesChannelId: process.env.NEXT_PUBLIC_SALES_CHANNEL_ID,
255
- }
256
- });
257
-
258
- // Shopify (when implemented — optional parameter, uses default if not set)
259
- // NEXT_PUBLIC_SHOPIFY_STOREFRONT_ID = '...'
260
-
261
- // WooCommerce (optional — uses default site)
262
- // NEXT_PUBLIC_WOOCOMMERCE_SITE_ID = '1'
263
- ```
264
-
265
- **Learn more**: [packages/core/docs/storefront-sales-channel-mapping.md](../core/docs/storefront-sales-channel-mapping.md) for platform-specific implementation details and multi-brand deployment patterns.
266
-
267
- ### Adding a New Provider
268
-
269
- To implement Shopify, BigCommerce, or another platform:
270
-
271
- 1. **Read the standardized guide**: [.development-guides/add-new-provider.md](../../.development-guides/add-new-provider.md)
272
- 2. **Follow 11-step checklist**: Registration in L1, implementation in L2, factory updates, tests, docs
273
- 3. **Use transform pattern**: Convert platform-specific types to `@thorprovider/types`
274
-
275
- Example checklist item:
276
- - [ ] Update `SupportedProviderType` enum in `packages/types/src/provider.ts`
277
- - [ ] Create `packages/adapters/src/providers/[platform]/index.ts`
278
- - [ ] Implement `CommerceProvider` interface
279
- - [ ] Add discriminated union case to factory
280
- - [ ] Write tests
281
- - [ ] Update documentation
282
-
283
-
284
- ### Transform Function Pattern
285
- ```typescript
286
- // ALWAYS follow this pattern when adding new providers
287
- export function transformProduct(backendProduct: any): Product {
288
- return {
289
- id: backendProduct.id,
290
- handle: backendProduct.slug,
291
- title: backendProduct.name,
292
- // ... transform all fields to @thorprovider/types shape
293
- };
294
- }
295
- ```
296
-
297
- ### Imbricación Principle: No Downstream Transformations
298
-
299
- **@thorprovider/adapters is the ONLY transformation layer** in the Thor Stack architecture.
300
-
301
- ```
302
- Backend (Medusa/Shopify) → Adapter.transform() → @thorprovider/types → Elements → Starters
303
- ↑ ONLY transformation point
304
- ```
305
-
306
- **Key Rules**:
307
- 1. **Adapters transform ONCE**: Backend-specific format → `@thorprovider/types` unified format
308
- 2. **Elements consume directly**: Import types from `@thorprovider/types`, never create local copies
309
- 3. **Starters pass through**: Use `@thorprovider/types` directly, no UI-specific transformations
310
- 4. **Single source of truth**: `@thorprovider/types` defines the contract for entire system
311
-
312
- **Why this matters**:
313
- - Changes to `@thorprovider/types` propagate instantly (no intermediate layers to update)
314
- - Zero duplicate type definitions (DRY principle)
315
- - 78× faster development (1 change vs 78 files)
316
-
317
- **Example: Order Management**
318
- ```typescript
319
- // ✅ CORRECT: Adapter transforms backend → @thorprovider/types
320
- // File: src/providers/medusa/transforms.ts
321
- export function transformOrder(medusaOrder: any): Order {
322
- return {
323
- id: medusaOrder.id,
324
- orderNumber: medusaOrder.display_id,
325
- status: transformOrderStatus(medusaOrder.status),
326
- createdAt: medusaOrder.created_at,
327
- items: medusaOrder.items.map(transformOrderItem),
328
- total: { amount: medusaOrder.total.toString(), currencyCode: 'USD' },
329
- // ... all fields mapped to @thorprovider/types Order
330
- }
331
- }
332
-
333
- // ✅ CORRECT: Elements import from @thorprovider/types
334
- // File: packages/components/src/patterns/modules/profile/ProfileModule.props.ts
335
- import type { Order } from '@thorprovider/types'
336
- export interface ProfileModuleProps {
337
- orders?: Order[] // Uses @thorprovider/types directly
338
- }
339
-
340
- // ✅ CORRECT: Starters pass through
341
- // File: packages/core/app/[locale]/profile/page.tsx
342
- const orders = await commerce.getOrders(customerId)
343
- <ProfileModule orders={orders} /> // No transformation!
344
-
345
- // ❌ WRONG: Creating intermediate types in L5
346
- interface UIOrder { // ← Duplicates @thorprovider/types Order
347
- id: string
348
- date: string // ← Different field name (vs createdAt)
349
- total: number // ← Different structure (vs Money object)
350
- }
351
- function transformOrderForUI(order: Order): UIOrder { ... } // ← Unnecessary layer
352
- ```
353
-
354
- **Reference**: See commits c3d5efd2 and cbaa83ef for real-world refactoring that eliminated an unnecessary transformer by making ProfileModule use `@thorprovider/types` directly.
355
-
356
- ---
357
-
358
- ## Quick Start
359
-
360
- ```bash
361
- yarn add @thorprovider/adapters
362
- ```
363
-
364
- ```typescript
365
- import { createProvider } from '@thorprovider/adapters';
366
-
367
- const commerce = createProvider({
368
- provider: 'medusa',
369
- config: {
370
- baseUrl: process.env.NEXT_PUBLIC_COMMERCE_API_URL!,
371
- publishableKey: process.env.NEXT_PUBLIC_COMMERCE_API_KEY!,
372
43
  },
373
- });
44
+ })
374
45
 
375
- // Use unified API
376
- const products = await commerce.getProducts();
377
- const cart = await commerce.createCart();
46
+ const products = await commerce.getProducts({ first: 10 })
378
47
  ```
379
48
 
380
- ---
381
-
382
- ## Features
383
-
384
- ✅ **Multi-platform** - Single API for Medusa, Shopify, WooCommerce, etc.
385
- ✅ **Type-safe** - Full TypeScript support with strict types
386
- ✅ **Framework agnostic** - Works with Next.js, Remix, Astro, or any JS framework
387
- ✅ **Easy swapping** - Change backends with minimal code changes
388
- ✅ **Capability Detection** - 21 backend capabilities for adaptive UIs (NEW in v2.0)
389
- ✅ **Authentication** - Built-in JWT and session-based auth
390
- ✅ **Auto-refresh** - Automatic token refresh for JWT
391
- ✅ **Profile Management** - Complete customer operations with capability awareness
392
-
393
- ---
394
-
395
- ## Core Concepts
49
+ Example with a Medusa backend:
396
50
 
397
- ### Unified Interface
398
-
399
- All providers implement the same interface:
400
-
401
- ```typescript
402
- interface CommerceProvider {
403
- readonly name: string;
404
- readonly version: string;
405
- readonly capabilities: BackendCapabilities; // NEW!
406
-
407
- // Products
408
- getProduct(handle: string): Promise<Product | undefined>;
409
- getProducts(options?: GetProductsOptions): Promise<Product[]>;
410
-
411
- // Collections
412
- getCollection(handle: string): Promise<Collection | undefined>;
413
- getCollections(): Promise<Collection[]>;
414
-
415
- // Cart
416
- createCart(): Promise<Cart>;
417
- addToCart(cartId: string, lines: CartLineInput[]): Promise<Cart>;
418
-
419
- // Auth (optional)
420
- auth?: AuthService;
421
- }
422
- ```
423
-
424
- ### Capabilities System (v2.0)
425
-
426
- Check backend support before attempting operations:
427
-
428
- ```typescript
429
- // Check if backend supports email updates
430
- if (commerce.capabilities.updateEmail) {
431
- // Show email field as editable
432
- } else {
433
- // Show as disabled with info message
434
- }
435
- ```
436
-
437
- **21 Capabilities** across 5 categories:
438
- - Profile: updateProfile, updateEmail, changePassword, deleteAccount, etc.
439
- - Avatar: uploadAvatar, avatarViaMetadata
440
- - Cart: promoCode, giftCards, notes, customAttributes
441
- - Products: variants, categories, inventory, digital, reviews
442
- - Auth: JWT, session, OAuth, passwordless
443
-
444
- **See**: [Capabilities System](./docs/capabilities-system.md)
445
-
446
- ---
51
+ ```ts
52
+ import { createProvider } from '@thorprovider/adapters'
447
53
 
448
- ## Supported Platforms
449
-
450
- | Platform | Status | Documentation |
451
- |----------|--------|---------------|
452
- | **Medusa v2** | ✅ Production Ready | [Medusa Docs](https://docs.medusajs.com/) |
453
- | **Stel Order** | ✅ ERP Adapter (v1) | Catalog, CRM, orders — no cart/checkout/auth |
454
- | **Shopify** | 🚧 Planned | [Shopify API](https://shopify.dev/api/storefront) |
455
- | **WooCommerce** | 🗓️ Roadmap | [WooCommerce API](https://woocommerce.github.io/woocommerce-rest-api-docs/) |
456
- | **BigCommerce** | 🗓️ Roadmap | [BigCommerce API](https://developer.bigcommerce.com/) |
457
- | **Local (Mock)** | ✅ Production Ready | For testing, previews, and backend-optional storefronts |
458
-
459
- **See**: [Providers Overview](./docs/providers-overview.md)
460
-
461
- ---
462
-
463
- ## Documentation
464
-
465
- ### Getting Started
466
- - [Installation & Quick Start](./docs/getting-started.md)
467
- - [Services Overview](./docs/services-overview.md) - Available operations
468
- - [Providers Overview](./docs/providers-overview.md) - Supported platforms
469
-
470
- ### Key Features
471
- - [Capabilities System](./docs/capabilities-system.md) - Feature detection (NEW!)
472
- - [Authentication](./docs/authentication.md) - JWT and session auth
473
- - [Profile Management](./docs/profile-management.md) - Customer operations
474
- - [Category Customization & Inheritance](./docs/category-customization.md) - Personalize inherited categories (NEW!)
475
-
476
- ### Advanced
477
- - [Add New Provider](../../docs/workflows/legacy/add-provider.md) - Step-by-step workflow
478
- - [Add New Service](../../docs/workflows/legacy/add-adapter-service.md) - Service workflow
479
- - [Type Definitions](./src/types/) - Full TypeScript types
480
-
481
- ### Testing
482
- - Unit/integration tests: `yarn workspace @thorprovider/adapters test`
483
- - Optional live Stel smoke test: `STEL_ORDER_SMOKE_TEST=1 STEL_ORDER_BASE_URL=... STEL_ORDER_API_KEY=... yarn workspace @thorprovider/adapters test:live`
484
- - Live smoke stays read-only unless `STEL_ORDER_TEST_CUSTOMER_ID` is explicitly set
485
-
486
- ---
487
-
488
- ## Examples
489
-
490
- ### Next.js Integration
491
-
492
- ```typescript
493
- // lib/commerce.ts
494
- import { createProvider } from '@thorprovider/adapters';
495
-
496
- export const commerce = createProvider({
54
+ const commerce = createProvider({
497
55
  provider: 'medusa',
498
56
  config: {
499
57
  baseUrl: process.env.NEXT_PUBLIC_COMMERCE_API_URL!,
500
58
  publishableKey: process.env.NEXT_PUBLIC_COMMERCE_API_KEY!,
501
- auth: {
502
- method: 'jwt',
503
- storage: 'localStorage',
504
- },
59
+ currencyCode: process.env.NEXT_PUBLIC_DEFAULT_CURRENCY || 'USD',
505
60
  },
506
- });
507
-
508
- // app/products/page.tsx
509
- import { commerce } from '@/lib/commerce';
510
-
511
- export default async function ProductsPage() {
512
- const products = await commerce.getProducts();
513
- return <ProductList products={products} />;
514
- }
61
+ })
515
62
  ```
516
63
 
517
- ### Authentication
518
-
519
- ```typescript
520
- // Login
521
- const { customer, token } = await commerce.auth.login({
522
- email: 'user@example.com',
523
- password: 'password123',
524
- });
525
-
526
- // Register
527
- const { customer } = await commerce.auth.register({
528
- email: 'user@example.com',
529
- password: 'password123',
530
- first_name: 'John',
531
- last_name: 'Doe',
532
- });
64
+ ## Package role
533
65
 
534
- // Get current customer
535
- const customer = await commerce.auth.getCurrentCustomer();
536
-
537
- // Update profile (capability-aware)
538
- if (commerce.capabilities.updateProfile) {
539
- await commerce.auth.updateCustomer({
540
- first_name: 'Jane',
541
- phone: '+1234567890',
542
- });
543
- }
544
- ```
66
+ This package centralizes:
545
67
 
546
- ### Cart Management
68
+ - Provider creation
69
+ - Capability detection
70
+ - Response and payload transforms
71
+ - Shared commerce errors and resilience utilities
72
+ - Framework-agnostic business logic used by Next.js and non-Next.js consumers
547
73
 
548
- ```typescript
549
- // Create cart
550
- const cart = await commerce.createCart();
74
+ ## Workspace commands
551
75
 
552
- // Add items
553
- const updated = await commerce.addToCart(cart.id!, [
554
- { merchandiseId: 'variant_123', quantity: 2 },
555
- ]);
556
-
557
- // Update quantities
558
- await commerce.updateCart(cart.id!, [
559
- { id: 'line_1', quantity: 3 },
560
- ]);
561
-
562
- // Remove items
563
- await commerce.removeFromCart(cart.id!, ['line_2']);
564
- ```
565
-
566
- ---
567
-
568
- ## Switching Providers
569
-
570
- Change platforms with minimal code changes:
571
-
572
- ```typescript
573
- // From Medusa
574
- const commerce = createProvider({
575
- provider: 'medusa',
576
- config: { /* ... */ }
577
- });
578
-
579
- // To Shopify (when available)
580
- const commerce = createProvider({
581
- provider: 'shopify',
582
- config: { /* ... */ }
583
- });
584
-
585
- // ✅ Rest of your code stays the same!
586
- const products = await commerce.getProducts();
587
- ```
588
-
589
- ---
590
-
591
- ## Architecture
592
-
593
- ```
594
- @thorprovider/adapters/
595
- ├── docs/ # Modular documentation
596
- │ ├── getting-started.md
597
- │ ├── services-overview.md
598
- │ ├── providers-overview.md
599
- │ ├── capabilities-system.md
600
- │ ├── authentication.md
601
- │ └── profile-management.md
602
- ├── types/ # Unified types (Product, Cart, etc.)
603
- ├── providers/ # Provider implementations
604
- │ ├── medusa/ # Medusa v2 provider
605
- │ ├── stelorder/ # Stel Order ERP adapter
606
- │ └── shopify/ # (coming soon)
607
- ├── core/ # Core utilities (errors, logger)
608
- └── factory/ # Provider factory
76
+ ```bash
77
+ yarn workspace @thorprovider/adapters dev
78
+ yarn workspace @thorprovider/adapters build
79
+ yarn workspace @thorprovider/adapters type-check
80
+ yarn workspace @thorprovider/adapters test
609
81
  ```
610
82
 
611
- ---
612
-
613
- ## Design Principles
614
-
615
- 1. **Provider Pattern** - One adapter per platform
616
- 2. **Interface First** - Unified API defined by shared types
617
- 3. **Framework Agnostic** - Zero dependencies on React/Next.js
618
- 4. **TypeScript Strict** - Strong types for all operations
619
- 5. **Composable** - Providers can be easily swapped
620
- 6. **Capability-Aware** - Build adaptive UIs that work across backends
621
-
622
- ---
623
-
624
- ## Contributing
625
-
626
- Contributions welcome! See [CONTRIBUTING.md](../../CONTRIBUTING.md).
627
-
628
- ### Adding a Provider
629
-
630
- 1. Define capabilities in `capabilities.ts`
631
- 2. Implement API client
632
- 3. Implement core services (Products, Cart, Auth)
633
- 4. Map responses to unified types
634
- 5. Write integration tests
635
- 6. Update factory and documentation
636
-
637
- **See**: [Add Provider Workflow](../../docs/workflows/legacy/add-provider.md)
638
-
639
-
640
- ---
641
-
642
- ## Version
643
-
644
- **Current**: v2.0 - Production Ready ✅
645
-
646
- **New in v2.0**:
647
- - ✅ Capabilities system (21 backend capabilities)
648
- - ✅ Profile management with capability awareness
649
- - ✅ Auto token refresh
650
- - ✅ Comprehensive TypeScript types
651
- - ✅ Modular documentation
652
-
653
- **See**: [CHANGELOG.md](./CHANGELOG.md)
654
-
655
- ---
656
-
657
- ## Resources
658
-
659
- - [Medusa Documentation](https://docs.medusajs.com/)
660
- - [TypeScript Handbook](https://www.typescriptlang.org/docs/)
661
- - [Examples](./examples/) - Code samples
662
- - [Thor Commerce](../../README.md) - Monorepo overview
663
-
664
- ---
665
-
666
- ## License
83
+ ## Related docs
667
84
 
668
- MIT
85
+ - [docs/getting-started.md](./docs/getting-started.md)
86
+ - [docs/providers-overview.md](./docs/providers-overview.md)
87
+ - [docs/services-overview.md](./docs/services-overview.md)
88
+ - [docs/capabilities-system.md](./docs/capabilities-system.md)
89
+ - [docs/authentication.md](./docs/authentication.md)
90
+ - [docs/multi-tenant-channel-scoping.md](./docs/multi-tenant-channel-scoping.md)