@thorprovider/adapters 5.0.0 → 5.0.1
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.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +6 -0
- package/README.md +53 -631
- package/dist/index.d.mts +406 -194
- package/dist/index.d.ts +406 -194
- package/dist/index.js +3092 -604
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3081 -602
- package/dist/index.mjs.map +1 -1
- package/docs/RETRY_SOLUTION_SUMMARY.md +1 -1
- package/docs/authentication.md +0 -26
- package/docs/capabilities-system.md +66 -36
- package/docs/getting-started.md +1 -1
- package/docs/providers-overview.md +16 -13
- package/docs/update-documentation.md +10 -8
- package/package.json +6 -5
- package/quick-reference.md +0 -33
- package/src/backend/factory.ts +11 -1
- package/src/factory/index.ts +52 -74
- package/src/index.ts +17 -3
- package/src/providers/bigcommerce/bigcommerce.ts +6 -0
- package/src/providers/bigcommerce/index.ts +315 -0
- package/src/providers/bigcommerce/transforms.ts +227 -0
- package/src/providers/index.ts +16 -1
- package/src/providers/magento/index.ts +387 -0
- package/src/providers/magento/magento.ts +5 -0
- package/src/providers/magento/queries.ts +267 -0
- package/src/providers/magento/transforms.ts +249 -0
- package/src/providers/medusa/auth.test.ts +94 -92
- package/src/providers/medusa/auth.ts +72 -123
- package/src/providers/medusa/index.test.ts +392 -0
- package/src/providers/medusa/index.ts +1 -21
- package/src/providers/medusa/live-smoke.test.ts +412 -0
- package/src/providers/shopify/auth.ts +402 -0
- package/src/providers/shopify/index.ts +444 -0
- package/src/providers/shopify/mutations.ts +247 -0
- package/src/providers/shopify/queries.ts +324 -0
- package/src/providers/shopify/shopify.ts +7 -0
- package/src/providers/shopify/transforms.ts +275 -0
- package/src/providers/spree/index.ts +344 -0
- package/src/providers/spree/spree.ts +5 -0
- package/src/providers/spree/transforms.ts +254 -0
- package/src/providers/woocommerce/index.ts +310 -0
- package/src/providers/woocommerce/transforms.ts +254 -0
- package/src/providers/woocommerce/woocommerce.ts +5 -0
- package/src/types/capabilities.types.ts +250 -0
- package/vitest.live.config.ts +18 -0
|
@@ -17,7 +17,7 @@ Errores frecuentes `Failed to fetch products: fetch failed` en el V0 starter al
|
|
|
17
17
|
|
|
18
18
|
### 1. Módulo de Retry Logic (`fetch-utils.ts`)
|
|
19
19
|
- **Ubicación**: `packages/adapters/src/core/fetch-utils.ts`
|
|
20
|
-
- **Importación**: `import { fetchWithRetry } from '
|
|
20
|
+
- **Importación**: utilidad interna — no está re-exportada desde `@thorprovider/adapters`. Úsala dentro del paquete como `import { fetchWithRetry } from '../core/fetch-utils'`.
|
|
21
21
|
- **Funcionalidad**:
|
|
22
22
|
- Reintentos automáticos con exponential backoff
|
|
23
23
|
- Timeout configurable (10s por defecto)
|
package/docs/authentication.md
CHANGED
|
@@ -186,33 +186,7 @@ await commerce.auth.deleteAddress(address.id);
|
|
|
186
186
|
| Login works but profile fails | Ensure `commerce.auth.getCurrentCustomer()` is called after login |
|
|
187
187
|
| Infinite login loop | Check cookie path and domain settings on the backend |
|
|
188
188
|
|
|
189
|
-
## Multi-Tenant: Linking Customer to Sales Channel
|
|
190
|
-
|
|
191
|
-
After login or registration, call `linkCustomerToChannel()` to associate the customer with the storefront's sales channel. This is **required** for the customer to appear in the admin panel of the correct tenant and is idempotent.
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
if (!commerce.auth) throw new Error('Auth not available');
|
|
195
|
-
|
|
196
|
-
const { customer } = await commerce.auth.login({
|
|
197
|
-
email: 'user@example.com',
|
|
198
|
-
password: 'SecurePassword123!',
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
// Link the customer to the sales channel resolved from the publishable key
|
|
202
|
-
const { linked, reason } = await commerce.auth.linkCustomerToChannel();
|
|
203
|
-
// linked === true → new link created
|
|
204
|
-
// linked === true, reason === 'already_linked' → idempotent — no action needed
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
**Throws:**
|
|
208
|
-
- `ProviderAPIError('NOT_AUTHENTICATED', 401)` — login must succeed first
|
|
209
|
-
- `ProviderAPIError('CHANNEL_RESOLUTION_FAILED', 400)` — publishable key doesn't map to a channel
|
|
210
|
-
- `ProviderAPIError('CONFIGURATION_ERROR')` — provider instantiated without `baseUrl`/`publishableKey`
|
|
211
|
-
|
|
212
|
-
**Provider support:** Medusa only. Shopify and other stubs return `{ linked: false, reason: 'not_applicable' }`.
|
|
213
|
-
|
|
214
189
|
## Next Steps
|
|
215
190
|
|
|
216
191
|
- [Profile Management](profile-management.md)
|
|
217
192
|
- [Services Overview](services-overview.md)
|
|
218
|
-
- [Multi-Tenant Channel Scoping](multi-tenant-channel-scoping.md)
|
|
@@ -6,7 +6,7 @@ tags: [architecture, capabilities, backend, detection]
|
|
|
6
6
|
related:
|
|
7
7
|
- providers-overview.md
|
|
8
8
|
- services-overview.md
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-05-23
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# Capabilities System
|
|
@@ -37,27 +37,52 @@ if (commerce.capabilities.updateEmail) {
|
|
|
37
37
|
| `changePasswordViaEmail` | `boolean` | Supports `requestPasswordReset` method. |
|
|
38
38
|
| `deleteAccount` | `boolean` | Supports `deleteAccount` method. |
|
|
39
39
|
| `uploadAvatar` | `boolean` | Supports native file upload for avatars. |
|
|
40
|
+
| `avatarViaMetadata` | `boolean` | Can store avatar URL in customer metadata/attributes. |
|
|
41
|
+
| `customAttributes` | `boolean` | Supports custom customer attributes/metadata. |
|
|
40
42
|
|
|
41
|
-
###
|
|
43
|
+
### Order Management
|
|
42
44
|
|
|
43
45
|
| Capability | Type | Description |
|
|
44
46
|
|------------|------|-------------|
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `cartNotes` | `boolean` | Supports order/cart notes. |
|
|
48
|
-
| `cartCustomAttributes` | `boolean` | Supports metadata/attributes at cart level. |
|
|
47
|
+
| `fetchOrders` | `boolean` | Can fetch customer order history. |
|
|
48
|
+
| `cancelOrder` | `boolean` | Can cancel orders before fulfillment. |
|
|
49
49
|
|
|
50
|
-
###
|
|
50
|
+
### Address Management
|
|
51
51
|
|
|
52
52
|
| Capability | Type | Description |
|
|
53
53
|
|------------|------|-------------|
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `productInventory` | `boolean` | Real-time inventory tracking available. |
|
|
57
|
-
| `productDigital` | `boolean` | Supports digital/downloadable products. |
|
|
58
|
-
| `productReviews` | `boolean` | Native review system support. |
|
|
54
|
+
| `manageAddresses` | `boolean` | Can add/update/delete shipping addresses. |
|
|
55
|
+
| `defaultAddress` | `boolean` | Can set a default shipping address. |
|
|
59
56
|
|
|
60
|
-
|
|
57
|
+
### Cart & Checkout
|
|
58
|
+
|
|
59
|
+
| Capability | Type | Description |
|
|
60
|
+
|------------|------|-------------|
|
|
61
|
+
| `applyDiscounts` | `boolean` | Can apply discount codes to cart. |
|
|
62
|
+
| `shippingCalculation` | `boolean` | Can calculate shipping rates before checkout. |
|
|
63
|
+
| `guestCheckout` | `boolean` | Supports checkout without an account. |
|
|
64
|
+
| `savedPaymentMethods` | `boolean` | Can save payment methods for future use. |
|
|
65
|
+
| `listPaymentProviders` | `boolean` | Can list available payment providers dynamically. |
|
|
66
|
+
| `regionSpecificPayments` | `boolean` | Payment providers vary by region. |
|
|
67
|
+
|
|
68
|
+
### Discovery & Search
|
|
69
|
+
|
|
70
|
+
| Capability | Type | Description |
|
|
71
|
+
|------------|------|-------------|
|
|
72
|
+
| `advancedSearch` | `boolean` | Supports full-text / filtered product search. |
|
|
73
|
+
| `facetedFilters` | `boolean` | Supports faceted filtering by attributes. |
|
|
74
|
+
|
|
75
|
+
### Social & Loyalty
|
|
76
|
+
|
|
77
|
+
| Capability | Type | Description |
|
|
78
|
+
|------------|------|-------------|
|
|
79
|
+
| `productReviews` | `boolean` | Native product reviews/ratings system. |
|
|
80
|
+
| `wishlist` | `boolean` | Native wishlist/favorites feature. |
|
|
81
|
+
| `loyaltyProgram` | `boolean` | Native loyalty/rewards program. |
|
|
82
|
+
|
|
83
|
+
## Type Definition (source of truth)
|
|
84
|
+
|
|
85
|
+
> Canonical source: `packages/types/src/commerce-provider.ts` — `BackendCapabilities`
|
|
61
86
|
|
|
62
87
|
```typescript
|
|
63
88
|
export interface BackendCapabilities {
|
|
@@ -68,28 +93,33 @@ export interface BackendCapabilities {
|
|
|
68
93
|
changePasswordViaEmail: boolean;
|
|
69
94
|
deleteAccount: boolean;
|
|
70
95
|
uploadAvatar: boolean;
|
|
71
|
-
|
|
72
|
-
// Avatar Extensions
|
|
73
96
|
avatarViaMetadata: boolean;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
customAttributes: boolean;
|
|
98
|
+
|
|
99
|
+
// Orders
|
|
100
|
+
fetchOrders: boolean;
|
|
101
|
+
cancelOrder: boolean;
|
|
102
|
+
|
|
103
|
+
// Addresses
|
|
104
|
+
manageAddresses: boolean;
|
|
105
|
+
defaultAddress: boolean;
|
|
106
|
+
|
|
107
|
+
// Cart / Checkout
|
|
108
|
+
applyDiscounts: boolean;
|
|
109
|
+
shippingCalculation: boolean;
|
|
110
|
+
guestCheckout: boolean;
|
|
111
|
+
savedPaymentMethods: boolean;
|
|
112
|
+
listPaymentProviders: boolean;
|
|
113
|
+
regionSpecificPayments: boolean;
|
|
114
|
+
|
|
115
|
+
// Discovery
|
|
116
|
+
advancedSearch: boolean;
|
|
117
|
+
facetedFilters: boolean;
|
|
118
|
+
|
|
119
|
+
// Social / Loyalty
|
|
86
120
|
productReviews: boolean;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
authJWT: boolean;
|
|
90
|
-
authSession: boolean;
|
|
91
|
-
authOAuth: boolean;
|
|
92
|
-
authPasswordless: boolean;
|
|
121
|
+
wishlist: boolean;
|
|
122
|
+
loyaltyProgram: boolean;
|
|
93
123
|
}
|
|
94
124
|
```
|
|
95
125
|
|
|
@@ -111,15 +141,15 @@ return (
|
|
|
111
141
|
async function handleAvatarUpdate(file: File) {
|
|
112
142
|
if (caps.uploadAvatar) {
|
|
113
143
|
return await commerce.auth.uploadAvatar(file);
|
|
114
|
-
}
|
|
115
|
-
|
|
144
|
+
}
|
|
145
|
+
|
|
116
146
|
if (caps.avatarViaMetadata) {
|
|
117
147
|
const url = await externalUpload(file);
|
|
118
148
|
return await commerce.auth.updateCustomer({
|
|
119
149
|
metadata: { avatar_url: url }
|
|
120
150
|
});
|
|
121
151
|
}
|
|
122
|
-
|
|
152
|
+
|
|
123
153
|
throw new Error('Avatar updates not supported on this backend');
|
|
124
154
|
}
|
|
125
155
|
```
|
package/docs/getting-started.md
CHANGED
|
@@ -17,7 +17,7 @@ Quick setup guide for integrating Thor adapters into your project. Start with `m
|
|
|
17
17
|
## Prerequisites
|
|
18
18
|
|
|
19
19
|
- Node.js 18+
|
|
20
|
-
- Yarn 4+ (
|
|
20
|
+
- Yarn 4+ (this monorepo currently uses the `node-modules` linker)
|
|
21
21
|
- Optional: access to a Medusa.js v2 backend
|
|
22
22
|
- Optional: Medusa Publishable API Key
|
|
23
23
|
|
|
@@ -30,20 +30,26 @@ Thor Adapters eliminate these problems by wrapping the data layer in a consisten
|
|
|
30
30
|
|
|
31
31
|
## Current Support Matrix
|
|
32
32
|
|
|
33
|
+
The `createProvider` factory currently accepts these provider identifiers:
|
|
34
|
+
|
|
35
|
+
- `mock`
|
|
36
|
+
- `medusa`
|
|
37
|
+
- `stelorder`
|
|
38
|
+
- `shopify`
|
|
39
|
+
- `bigcommerce`
|
|
40
|
+
- `woocommerce`
|
|
41
|
+
- `spree`
|
|
42
|
+
- `magento`
|
|
43
|
+
|
|
44
|
+
The package docs explicitly describe these currently documented integrations:
|
|
45
|
+
|
|
33
46
|
### Mock
|
|
34
|
-
**Status:** ✅ Production Ready
|
|
35
47
|
Fixture-backed provider for local development, previews, design-mode storefront work, and backend-optional scaffolds.
|
|
36
48
|
|
|
37
|
-
### Medusa
|
|
38
|
-
|
|
39
|
-
Our primary integration, highly optimized for headless performance.
|
|
40
|
-
|
|
41
|
-
### Shopify
|
|
42
|
-
**Status:** 🚧 In Development (Phase 1)
|
|
43
|
-
Focusing on Storefront API integration for product discovery and cart.
|
|
49
|
+
### Medusa
|
|
50
|
+
Primary storefront integration used by the checked-in `@thorprovider/core` package.
|
|
44
51
|
|
|
45
52
|
### Stel Order
|
|
46
|
-
**Status:** ✅ ERP Adapter (v1)
|
|
47
53
|
Single-company ERP integration for catalog, categories, inventory visibility, customers (STEL clients), sales orders, and payment/delivery option listing.
|
|
48
54
|
|
|
49
55
|
**Scope & Limitations:**
|
|
@@ -54,9 +60,7 @@ Single-company ERP integration for catalog, categories, inventory visibility, cu
|
|
|
54
60
|
- **No variants:** STEL products are single-SKU; the adapter creates one synthetic variant per product
|
|
55
61
|
- **Client-side search:** STEL has no fulltext search; `getProducts({ query })` filters in-memory after fetch
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
**Status:** 🗓️ Planned
|
|
59
|
-
Targeting the REST API for hybrid headless setups.
|
|
63
|
+
For the other accepted provider identifiers, verify source-level capability coverage before treating them as production-ready.
|
|
60
64
|
|
|
61
65
|
## Conceptual Foundation
|
|
62
66
|
|
|
@@ -102,4 +106,3 @@ graph TD
|
|
|
102
106
|
|
|
103
107
|
- [Reference: Capabilities System](capabilities-system.md)
|
|
104
108
|
- [How-to: Getting Started](getting-started.md)
|
|
105
|
-
- [Workflow: Add New Provider](../../../docs/workflows/legacy/add-provider.md)
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
# Update Documentation
|
|
2
|
-
|
|
3
1
|
---
|
|
2
|
+
title: Update Documentation
|
|
3
|
+
purpose: Guidelines for updating @thorprovider/adapters documentation correctly
|
|
4
4
|
type: how-to
|
|
5
5
|
tags: [documentation, maintenance, adapters, standards, copilot]
|
|
6
6
|
related:
|
|
7
7
|
- ../../../docs/templates/README.md
|
|
8
|
-
- ../../../docs/
|
|
9
|
-
updated: 2026-
|
|
8
|
+
- ../../../docs/standards/documentation.md
|
|
9
|
+
updated: 2026-05-23
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
# Update Documentation
|
|
13
|
+
|
|
12
14
|
**Specific guidelines for updating @thorprovider/adapters documentation.**
|
|
13
15
|
|
|
14
|
-
Global guidelines: [docs/
|
|
16
|
+
Global guidelines: [docs/standards/documentation.md](../../../docs/standards/documentation.md)
|
|
15
17
|
|
|
16
18
|
## Prerequisites
|
|
17
19
|
|
|
18
|
-
- Read [global guidelines](../../../docs/
|
|
20
|
+
- Read [global guidelines](../../../docs/standards/documentation.md) for doc types and templates
|
|
19
21
|
- Understand the [Providers System](providers-overview.md) and [Capabilities System](capabilities-system.md)
|
|
20
|
-
- Ensure understanding of the [
|
|
22
|
+
- Ensure understanding of the [Architecture Overview](../../../docs/architecture/overview.md) (Strategy Pattern)
|
|
21
23
|
|
|
22
24
|
## Step-by-Step Process for Adapters
|
|
23
25
|
|
|
@@ -109,5 +111,5 @@ async function performTask() {
|
|
|
109
111
|
|
|
110
112
|
## Next Steps
|
|
111
113
|
|
|
112
|
-
- [global
|
|
114
|
+
- [global documentation standards](../../../docs/standards/documentation.md)
|
|
113
115
|
- [How-to: Getting Started](getting-started.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thorprovider/adapters",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "Framework-agnostic commerce adapters for Thor Commerce ecosystem - Multi-platform support with unified API",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org",
|
|
@@ -22,13 +22,14 @@
|
|
|
22
22
|
"dev": "tsup --watch",
|
|
23
23
|
"type-check": "tsc --noEmit",
|
|
24
24
|
"test": "vitest run --config vitest.config.ts",
|
|
25
|
-
"test:live": "vitest run --config vitest.config.ts src/providers/stelorder/live-smoke.test.ts",
|
|
25
|
+
"test:live": "vitest run --config vitest.live.config.ts src/providers/stelorder/live-smoke.test.ts",
|
|
26
|
+
"test:live:medusa": "vitest run --config vitest.live.config.ts src/providers/medusa/live-smoke.test.ts",
|
|
26
27
|
"generate:agent-index": "node ../../scripts/generate-package-agents-index.cjs packages/adapters @thorprovider/adapters"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
|
-
"@medusajs/js-sdk": "2.
|
|
30
|
-
"@medusajs/types": "2.
|
|
31
|
-
"@thorprovider/types": "^3.
|
|
30
|
+
"@medusajs/js-sdk": "2.16.0",
|
|
31
|
+
"@medusajs/types": "2.16.0",
|
|
32
|
+
"@thorprovider/types": "^3.14.4",
|
|
32
33
|
"bcryptjs": "^3.0.3",
|
|
33
34
|
"jose": "^6.2.2"
|
|
34
35
|
},
|
package/quick-reference.md
CHANGED
|
@@ -52,39 +52,6 @@ Framework-agnostic business logic SDK for e-commerce operations. Provides unifie
|
|
|
52
52
|
- **Collections**: Product collections/categories
|
|
53
53
|
- **Customer**: Authentication, profile management
|
|
54
54
|
- **Orders**: Order history, details, tracking
|
|
55
|
-
- **Auth — Multi-Tenant**: `linkCustomerToChannel()` — links authenticated customer to sales channel (Medusa only)
|
|
56
|
-
|
|
57
|
-
### Admin Client (Medusa only)
|
|
58
|
-
`provider.admin` — available when `adminConfig.apiKey` is set. Exposes 15 methods for the `/admin/thor/` endpoints:
|
|
59
|
-
```typescript
|
|
60
|
-
const commerce = createProvider({ provider: 'medusa', config: { ..., adminConfig: { apiKey: '...' } } })
|
|
61
|
-
if (!commerce.admin) throw new Error('Admin not configured')
|
|
62
|
-
|
|
63
|
-
// Sales Channel — Customers / API Keys / Categories
|
|
64
|
-
await commerce.admin.getChannelCustomers(salesChannelId, { limit, offset })
|
|
65
|
-
await commerce.admin.getChannelApiKeys(salesChannelId)
|
|
66
|
-
await commerce.admin.getChannelCategories(salesChannelId, { limit, offset, include_descendants })
|
|
67
|
-
|
|
68
|
-
// Category ↔ Sales Channel assignments
|
|
69
|
-
await commerce.admin.getCategorySalesChannels(categoryId)
|
|
70
|
-
await commerce.admin.assignCategoryToChannels(categoryId, { sales_channel_ids: [...] })
|
|
71
|
-
await commerce.admin.unassignCategoryFromChannels(categoryId, { sales_channel_ids: [...] })
|
|
72
|
-
|
|
73
|
-
// Collection ↔ Sales Channel assignments
|
|
74
|
-
await commerce.admin.getCollectionSalesChannels(collectionId)
|
|
75
|
-
await commerce.admin.assignCollectionToChannels(collectionId, { sales_channel_ids: [...] })
|
|
76
|
-
await commerce.admin.unassignCollectionFromChannels(collectionId, { sales_channel_ids: [...] })
|
|
77
|
-
|
|
78
|
-
// Storefront Config (visual theme, SEO defaults)
|
|
79
|
-
await commerce.admin.getStorefrontConfig(salesChannelId)
|
|
80
|
-
await commerce.admin.updateStorefrontConfig(salesChannelId, { theme_accent_color, logo_url, currency_code, seo_defaults })
|
|
81
|
-
|
|
82
|
-
// Site Designer Config (page builder config with history)
|
|
83
|
-
await commerce.admin.getSiteConfig(salesChannelId)
|
|
84
|
-
await commerce.admin.updateSiteConfig(salesChannelId, { config: { ... } })
|
|
85
|
-
await commerce.admin.getSiteConfigHistory(salesChannelId, { limit, offset })
|
|
86
|
-
await commerce.admin.restoreSiteConfig(salesChannelId, version)
|
|
87
|
-
```
|
|
88
55
|
|
|
89
56
|
### Provider Architecture
|
|
90
57
|
```
|
package/src/backend/factory.ts
CHANGED
|
@@ -93,5 +93,15 @@ export function createBackendMetadataAdapter(
|
|
|
93
93
|
return new MedusaMetadataAdapter(medusa);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
if (provider === 'shopify') {
|
|
97
|
+
// TODO: Implement Shopify metadata adapter
|
|
98
|
+
throw new Error('Shopify metadata adapter not yet implemented');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (provider === 'woocommerce') {
|
|
102
|
+
// TODO: Implement WooCommerce metadata adapter
|
|
103
|
+
throw new Error('WooCommerce metadata adapter not yet implemented');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
throw new Error(`Unsupported provider: ${provider}`);
|
|
97
107
|
}
|
package/src/factory/index.ts
CHANGED
|
@@ -1,93 +1,57 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @thorprovider/adapters
|
|
3
|
-
* Provider Factory -
|
|
2
|
+
* @thorprovider/adapters v2.0
|
|
3
|
+
* Provider Factory - Create commerce providers dynamically
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* This factory is bound to SupportedProviderType from @thorprovider/types (L1).
|
|
6
|
+
* When adding a new provider:
|
|
7
|
+
* 1. Update SupportedProviderType enum in packages/types/src/provider.ts
|
|
8
|
+
* 2. Add new discriminated union case here
|
|
9
|
+
* 3. Create packages/adapters/src/providers/[platform]/
|
|
10
|
+
* 4. Implement CommerceProvider interface
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
import type { CommerceProvider } from '../types';
|
|
13
14
|
import { MedusaProvider, type MedusaProviderConfig } from '../providers/medusa';
|
|
15
|
+
import { ShopifyProvider, type ShopifyProviderConfig } from '../providers/shopify';
|
|
16
|
+
import { BigCommerceProvider, type BigCommerceProviderConfig } from '../providers/bigcommerce';
|
|
17
|
+
import { WooCommerceProvider, type WooCommerceProviderConfig } from '../providers/woocommerce';
|
|
18
|
+
import { SpreeProvider, type SpreeProviderConfig } from '../providers/spree';
|
|
19
|
+
import { MagentoProvider, type MagentoProviderConfig } from '../providers/magento';
|
|
14
20
|
import { StelOrderProvider, type StelOrderProviderConfig } from '../providers/stelorder';
|
|
15
21
|
import { MockProvider, type MockProviderConfig } from '../providers/mock';
|
|
16
22
|
import { ProviderNotFoundError, ConfigurationError } from '../core/errors';
|
|
17
23
|
import type { ProviderTypeString } from '@thorprovider/types';
|
|
18
24
|
|
|
19
|
-
// ============================================
|
|
20
|
-
// Registry
|
|
21
|
-
// ============================================
|
|
22
|
-
|
|
23
|
-
type ProviderFactory = (config: any) => CommerceProvider;
|
|
24
|
-
|
|
25
|
-
const registry = new Map<string, ProviderFactory>();
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Register a provider factory for a given type string.
|
|
29
|
-
* Call this to make a provider available to `createProvider()`.
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```ts
|
|
33
|
-
* import { registerProvider } from '@thorprovider/adapters';
|
|
34
|
-
* import { MyProvider } from './my-provider';
|
|
35
|
-
*
|
|
36
|
-
* registerProvider('my-provider', (config) => new MyProvider(config));
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
export function registerProvider(type: string, factory: ProviderFactory): void {
|
|
40
|
-
registry.set(type, factory);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
25
|
/**
|
|
44
|
-
*
|
|
26
|
+
* Supported provider types (imported from @thorprovider/types L1)
|
|
27
|
+
* Kept for backward compatibility; prefer ProviderTypeString from @thorprovider/types
|
|
45
28
|
*/
|
|
46
|
-
export
|
|
47
|
-
return Array.from(registry.keys());
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ============================================
|
|
51
|
-
// Built-in registrations
|
|
52
|
-
// ============================================
|
|
53
|
-
|
|
54
|
-
registerProvider('mock', (config) => new MockProvider(config));
|
|
55
|
-
registerProvider('medusa', (config) => new MedusaProvider(config));
|
|
56
|
-
registerProvider('stelorder', (config) => new StelOrderProvider(config));
|
|
57
|
-
|
|
58
|
-
// ============================================
|
|
59
|
-
// Types
|
|
60
|
-
// ============================================
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Supported provider types
|
|
64
|
-
*/
|
|
65
|
-
export type ProviderType = ProviderTypeString | (string & {});
|
|
29
|
+
export type ProviderType = ProviderTypeString;
|
|
66
30
|
|
|
67
31
|
/**
|
|
68
|
-
* Provider configuration discriminated union
|
|
32
|
+
* Provider configuration discriminated union
|
|
69
33
|
*/
|
|
70
34
|
export type ProviderFactoryConfig =
|
|
71
35
|
| { provider: 'mock'; config: MockProviderConfig }
|
|
72
36
|
| { provider: 'medusa'; config: MedusaProviderConfig }
|
|
73
37
|
| { provider: 'stelorder'; config: StelOrderProviderConfig }
|
|
74
|
-
| { provider:
|
|
38
|
+
| { provider: 'shopify'; config: ShopifyProviderConfig }
|
|
39
|
+
| { provider: 'bigcommerce'; config: BigCommerceProviderConfig }
|
|
40
|
+
| { provider: 'woocommerce'; config: WooCommerceProviderConfig }
|
|
41
|
+
| { provider: 'spree'; config: SpreeProviderConfig }
|
|
42
|
+
| { provider: 'magento'; config: MagentoProviderConfig };
|
|
75
43
|
|
|
76
44
|
/**
|
|
77
|
-
* Runtime provider configuration (accepts any
|
|
45
|
+
* Runtime provider configuration (accepts any ProviderTypeString from env vars)
|
|
78
46
|
*/
|
|
79
47
|
export type RuntimeProviderConfig = {
|
|
80
|
-
provider:
|
|
48
|
+
provider: ProviderTypeString;
|
|
81
49
|
config: Record<string, unknown>;
|
|
82
50
|
};
|
|
83
51
|
|
|
84
|
-
// ============================================
|
|
85
|
-
// Factory
|
|
86
|
-
// ============================================
|
|
87
|
-
|
|
88
52
|
/**
|
|
89
|
-
* Create a commerce provider instance
|
|
90
|
-
*
|
|
53
|
+
* Create a commerce provider instance
|
|
54
|
+
*
|
|
91
55
|
* @example
|
|
92
56
|
* ```ts
|
|
93
57
|
* const commerce = createProvider({
|
|
@@ -97,28 +61,42 @@ export type RuntimeProviderConfig = {
|
|
|
97
61
|
* publishableKey: process.env.MEDUSA_PUBLISHABLE_KEY,
|
|
98
62
|
* }
|
|
99
63
|
* });
|
|
64
|
+
*
|
|
65
|
+
* const products = await commerce.getProducts();
|
|
100
66
|
* ```
|
|
101
67
|
*/
|
|
102
68
|
export function createProvider(options: ProviderFactoryConfig | RuntimeProviderConfig): CommerceProvider {
|
|
103
69
|
if (!options || !options.provider) {
|
|
104
70
|
throw new ConfigurationError('Provider type is required');
|
|
105
71
|
}
|
|
106
|
-
|
|
72
|
+
|
|
107
73
|
if (!options.config) {
|
|
108
74
|
throw new ConfigurationError('Provider configuration is required');
|
|
109
75
|
}
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
76
|
+
|
|
77
|
+
const config = options.config as any;
|
|
78
|
+
|
|
79
|
+
switch (options.provider) {
|
|
80
|
+
case 'mock':
|
|
81
|
+
return new MockProvider(config);
|
|
82
|
+
case 'medusa':
|
|
83
|
+
return new MedusaProvider(config);
|
|
84
|
+
case 'stelorder':
|
|
85
|
+
return new StelOrderProvider(config);
|
|
86
|
+
case 'shopify':
|
|
87
|
+
return new ShopifyProvider(config);
|
|
88
|
+
case 'bigcommerce':
|
|
89
|
+
return new BigCommerceProvider(config);
|
|
90
|
+
case 'woocommerce':
|
|
91
|
+
return new WooCommerceProvider(config);
|
|
92
|
+
case 'spree':
|
|
93
|
+
return new SpreeProvider(config);
|
|
94
|
+
case 'magento':
|
|
95
|
+
return new MagentoProvider(config);
|
|
96
|
+
|
|
97
|
+
default:
|
|
98
|
+
throw new ProviderNotFoundError(String((options as any).provider));
|
|
119
99
|
}
|
|
120
|
-
|
|
121
|
-
return factory(options.config);
|
|
122
100
|
}
|
|
123
101
|
|
|
124
102
|
/**
|
package/src/index.ts
CHANGED
|
@@ -41,6 +41,11 @@ export {
|
|
|
41
41
|
MOCK_CAPABILITIES,
|
|
42
42
|
MEDUSA_CAPABILITIES,
|
|
43
43
|
STELORDER_CAPABILITIES,
|
|
44
|
+
SHOPIFY_CAPABILITIES,
|
|
45
|
+
BIGCOMMERCE_CAPABILITIES,
|
|
46
|
+
WOOCOMMERCE_CAPABILITIES,
|
|
47
|
+
SPREE_CAPABILITIES,
|
|
48
|
+
MAGENTO_CAPABILITIES,
|
|
44
49
|
isBackendCapabilities,
|
|
45
50
|
getCapabilityDescription,
|
|
46
51
|
} from './types/capabilities.types';
|
|
@@ -54,9 +59,10 @@ export {
|
|
|
54
59
|
ConfigurationError,
|
|
55
60
|
ResourceNotFoundError,
|
|
56
61
|
ProviderAPIError,
|
|
62
|
+
extractErrorMessage,
|
|
57
63
|
createLogger,
|
|
58
64
|
fetchWithRetry,
|
|
59
|
-
|
|
65
|
+
createFetchWithRetry,
|
|
60
66
|
type Logger,
|
|
61
67
|
type LogLevel,
|
|
62
68
|
type RetryConfig,
|
|
@@ -181,8 +187,6 @@ export type {
|
|
|
181
187
|
// ============================================
|
|
182
188
|
export {
|
|
183
189
|
createProvider,
|
|
184
|
-
registerProvider,
|
|
185
|
-
getRegisteredProviders,
|
|
186
190
|
isProviderType,
|
|
187
191
|
type ProviderType,
|
|
188
192
|
type ProviderFactoryConfig,
|
|
@@ -198,4 +202,14 @@ export {
|
|
|
198
202
|
type StelOrderProviderConfig,
|
|
199
203
|
MockProvider,
|
|
200
204
|
type MockProviderConfig,
|
|
205
|
+
ShopifyProvider,
|
|
206
|
+
type ShopifyProviderConfig,
|
|
207
|
+
BigCommerceProvider,
|
|
208
|
+
type BigCommerceProviderConfig,
|
|
209
|
+
WooCommerceProvider,
|
|
210
|
+
type WooCommerceProviderConfig,
|
|
211
|
+
SpreeProvider,
|
|
212
|
+
type SpreeProviderConfig,
|
|
213
|
+
MagentoProvider,
|
|
214
|
+
type MagentoProviderConfig,
|
|
201
215
|
} from './providers';
|