@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.
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
@@ -0,0 +1,315 @@
1
+ /**
2
+ * @thorprovider/adapters — BigCommerce Provider
3
+ * Implements CommerceProvider for BigCommerce REST Storefront API
4
+ *
5
+ * Uses raw fetch against BigCommerce Storefront REST API.
6
+ * The official `@bigcommerce/storefront-data-hooks` is deprecated (3 years unmaintained).
7
+ */
8
+
9
+ import type {
10
+ Product,
11
+ GetProductsOptions,
12
+ Cart,
13
+ CartLineInput,
14
+ CartLineUpdate,
15
+ Collection,
16
+ CollectionProductsOptions,
17
+ GetCollectionsOptions,
18
+ ProductCategory,
19
+ GetCategoriesOptions,
20
+ Order,
21
+ GetOrdersOptions,
22
+ Customer,
23
+ Address,
24
+ PaymentMethod,
25
+ PaymentMethodsOptions,
26
+ ShippingMethod,
27
+ StockLocation,
28
+ InventoryLevel,
29
+ StockValidation,
30
+ FulfillmentOption,
31
+ StorefrontContext,
32
+ BackendCapabilities,
33
+ } from '@thorprovider/types';
34
+ import type { CommerceProvider, ProviderConfig } from '../../types/provider';
35
+ import { BIGCOMMERCE_CAPABILITIES } from '../../types/capabilities.types';
36
+ import { createLogger } from '../../core/logger';
37
+ import { ProviderAPIError } from '../../core/errors';
38
+ import {
39
+ transformProduct,
40
+ transformCart,
41
+ transformCollection,
42
+ transformCustomer,
43
+ transformOrder,
44
+ } from './transforms';
45
+
46
+ /**
47
+ * BigCommerce provider configuration
48
+ */
49
+ export interface BigCommerceProviderConfig extends ProviderConfig {
50
+ /** BigCommerce store hash */
51
+ storeHash: string;
52
+ /** Storefront API token (JWT) */
53
+ storefrontApiToken: string;
54
+ /** Storefront API URL (usually https://store-{hash}.mybigcommerce.com) */
55
+ storefrontApiUrl: string;
56
+ /** Channel ID */
57
+ channelId: string;
58
+ /** Default currency code (default: 'USD') */
59
+ currencyCode?: string;
60
+ }
61
+
62
+ export class BigCommerceProvider implements CommerceProvider {
63
+ readonly name = 'bigcommerce';
64
+ readonly version = '1.0.0';
65
+ readonly capabilities: BackendCapabilities = BIGCOMMERCE_CAPABILITIES;
66
+
67
+ private logger: ReturnType<typeof createLogger>;
68
+ private storefrontApiUrl: string;
69
+ private storeHash: string;
70
+ private channelId: string;
71
+ private currencyCode: string;
72
+ private headers: Record<string, string>;
73
+
74
+ constructor(config: BigCommerceProviderConfig) {
75
+ this.logger = createLogger('BigCommerceProvider', config.debug);
76
+ this.storefrontApiUrl = config.storefrontApiUrl.replace(/\/$/, '');
77
+ this.storeHash = config.storeHash;
78
+ this.channelId = config.channelId;
79
+ this.currencyCode = config.currencyCode ?? 'USD';
80
+ this.headers = {
81
+ 'Content-Type': 'application/json',
82
+ 'Authorization': `Bearer ${config.storefrontApiToken}`,
83
+ };
84
+ this.logger.info('Initializing BigCommerce Provider', { storeHash: this.storeHash, channelId: this.channelId });
85
+ }
86
+
87
+ private async fetchApi<T = any>(path: string, init?: RequestInit): Promise<T> {
88
+ const url = `${this.storefrontApiUrl}${path}`;
89
+ const response = await fetch(url, {
90
+ ...init,
91
+ headers: { ...this.headers, ...init?.headers },
92
+ });
93
+
94
+ if (!response.ok) {
95
+ throw new ProviderAPIError(
96
+ `BigCommerce API error: ${response.status} ${response.statusText}`,
97
+ 'BIGCOMMERCE_API_ERROR',
98
+ response.status,
99
+ );
100
+ }
101
+
102
+ return response.json() as Promise<T>;
103
+ }
104
+
105
+ // ============================================
106
+ // Product Operations
107
+ // ============================================
108
+
109
+ async getProduct(handle: string): Promise<Product | undefined> {
110
+ try {
111
+ const data = await this.fetchApi<{ data: any[] }>(`/api/storefront/products?include=variants,options,images&keyword=${encodeURIComponent(handle)}`);
112
+ const product = data.data?.[0];
113
+ return product ? transformProduct(product, this.currencyCode) : undefined;
114
+ } catch {
115
+ return undefined;
116
+ }
117
+ }
118
+
119
+ async getProducts(options?: GetProductsOptions): Promise<Product[]> {
120
+ const limit = options?.first ?? 20;
121
+ let path = `/api/storefront/products?include=variants,options,images&limit=${limit}`;
122
+ if (options?.query) path += `&keyword=${encodeURIComponent(options.query)}`;
123
+
124
+ const data = await this.fetchApi<{ data: any[] }>(path);
125
+ return (data.data ?? []).map((p) => transformProduct(p, this.currencyCode));
126
+ }
127
+
128
+ async getProductRecommendations(_productId: string): Promise<Product[]> {
129
+ return []; // BigCommerce doesn't have a Storefront recommendation API
130
+ }
131
+
132
+ // ============================================
133
+ // Collection Operations (BigCommerce Categories)
134
+ // ============================================
135
+
136
+ async getCollection(handle: string): Promise<Collection | undefined> {
137
+ try {
138
+ const data = await this.fetchApi<{ data: any[] }>(`/api/storefront/categories?url=/${handle}/`);
139
+ const cat = data.data?.[0];
140
+ return cat ? transformCollection(cat) : undefined;
141
+ } catch {
142
+ return undefined;
143
+ }
144
+ }
145
+
146
+ async getCollections(options?: GetCollectionsOptions): Promise<Collection[]> {
147
+ const limit = options?.limit ?? 50;
148
+ const data = await this.fetchApi<{ data: any[] }>(`/api/storefront/categories?limit=${limit}`);
149
+ return (data.data ?? []).map(transformCollection);
150
+ }
151
+
152
+ async getCollectionProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]> {
153
+ const limit = options?.first ?? 20;
154
+ const data = await this.fetchApi<{ data: any[] }>(
155
+ `/api/storefront/products?include=variants,options,images&categories:in=${handle}&limit=${limit}`,
156
+ );
157
+ return (data.data ?? []).map((p) => transformProduct(p, this.currencyCode));
158
+ }
159
+
160
+ // ============================================
161
+ // Category Operations
162
+ // ============================================
163
+
164
+ async getCategory(idOrHandle: string): Promise<ProductCategory | undefined> {
165
+ return this.getCollection(idOrHandle) as any;
166
+ }
167
+
168
+ async getCategories(options?: GetCategoriesOptions): Promise<ProductCategory[]> {
169
+ return this.getCollections(options) as any;
170
+ }
171
+
172
+ async getCategoryProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]> {
173
+ return this.getCollectionProducts(handle, options);
174
+ }
175
+
176
+ // ============================================
177
+ // Cart Operations
178
+ // ============================================
179
+
180
+ async createCart(): Promise<Cart> {
181
+ const data = await this.fetchApi<{ data: any }>('/api/storefront/carts', {
182
+ method: 'POST',
183
+ body: JSON.stringify({ line_items: [] }),
184
+ });
185
+ return transformCart(data.data ?? data, this.currencyCode);
186
+ }
187
+
188
+ async getCart(cartId: string): Promise<Cart | undefined> {
189
+ try {
190
+ const data = await this.fetchApi<{ data: any }>(`/api/storefront/carts/${cartId}?include=line_items.physical_items.options`);
191
+ return transformCart(data.data ?? data, this.currencyCode);
192
+ } catch {
193
+ return undefined;
194
+ }
195
+ }
196
+
197
+ async addToCart(cartId: string, lines: CartLineInput[]): Promise<Cart> {
198
+ const lineItems = lines.map((l) => ({
199
+ product_id: parseInt(l.merchandiseId, 10),
200
+ quantity: l.quantity,
201
+ }));
202
+
203
+ const data = await this.fetchApi<{ data: any }>(`/api/storefront/carts/${cartId}/items`, {
204
+ method: 'POST',
205
+ body: JSON.stringify({ line_items: lineItems }),
206
+ });
207
+
208
+ return transformCart(data.data ?? data, this.currencyCode);
209
+ }
210
+
211
+ async removeFromCart(cartId: string, lineIds: string[]): Promise<Cart> {
212
+ for (const lineId of lineIds) {
213
+ await this.fetchApi(`/api/storefront/carts/${cartId}/items/${lineId}`, { method: 'DELETE' });
214
+ }
215
+
216
+ const cart = await this.getCart(cartId);
217
+ if (!cart) throw new ProviderAPIError('Cart not found after removal', 'BIGCOMMERCE_CART_ERROR');
218
+ return cart;
219
+ }
220
+
221
+ async updateCart(cartId: string, lines: CartLineUpdate[]): Promise<Cart> {
222
+ for (const line of lines) {
223
+ await this.fetchApi(`/api/storefront/carts/${cartId}/items/${line.id}`, {
224
+ method: 'PUT',
225
+ body: JSON.stringify({ line_item: { quantity: line.quantity } }),
226
+ });
227
+ }
228
+
229
+ const cart = await this.getCart(cartId);
230
+ if (!cart) throw new ProviderAPIError('Cart not found after update', 'BIGCOMMERCE_CART_ERROR');
231
+ return cart;
232
+ }
233
+
234
+ // ============================================
235
+ // Checkout Operations (Hosted)
236
+ // ============================================
237
+
238
+ async completeCheckout(_cartId: string): Promise<Order> {
239
+ throw new ProviderAPIError(
240
+ 'BigCommerce uses Embedded Checkout. Redirect the buyer to cart.checkoutUrl.',
241
+ 'BIGCOMMERCE_HOSTED_CHECKOUT',
242
+ );
243
+ }
244
+
245
+ async getShippingMethods(_cartId: string): Promise<ShippingMethod[]> {
246
+ return [];
247
+ }
248
+
249
+ async getRegionCountries(): Promise<import('@thorprovider/types').Country[]> {
250
+ return [];
251
+ }
252
+
253
+ async addShippingMethod(_cartId: string, _methodId: string): Promise<Cart> {
254
+ throw new ProviderAPIError('BigCommerce handles shipping in Embedded Checkout.', 'BIGCOMMERCE_HOSTED_CHECKOUT');
255
+ }
256
+
257
+ async initiatePaymentSession(_cartId: string, _providerId: string): Promise<void> {
258
+ throw new ProviderAPIError('BigCommerce handles payment in Embedded Checkout.', 'BIGCOMMERCE_HOSTED_CHECKOUT');
259
+ }
260
+
261
+ async applyDiscountCode(cartId: string, code: string): Promise<Cart> {
262
+ const data = await this.fetchApi<{ data: any }>(`/api/storefront/carts/${cartId}/coupons`, {
263
+ method: 'POST',
264
+ body: JSON.stringify({ coupon_code: code }),
265
+ });
266
+ return transformCart(data.data ?? data, this.currencyCode);
267
+ }
268
+
269
+ async removeDiscountCode(cartId: string, code: string): Promise<Cart> {
270
+ await this.fetchApi(`/api/storefront/carts/${cartId}/coupons/${encodeURIComponent(code)}`, { method: 'DELETE' });
271
+ const cart = await this.getCart(cartId);
272
+ if (!cart) throw new ProviderAPIError('Cart not found after coupon removal', 'BIGCOMMERCE_CART_ERROR');
273
+ return cart;
274
+ }
275
+
276
+ // ============================================
277
+ // Customer, Order, Payment, Inventory, Admin
278
+ // ============================================
279
+
280
+ async getOrders(_options: GetOrdersOptions): Promise<Order[]> {
281
+ return [];
282
+ }
283
+
284
+ async getPaymentMethods(_options: PaymentMethodsOptions): Promise<PaymentMethod[]> {
285
+ return [];
286
+ }
287
+
288
+ async getStockLocations(): Promise<StockLocation[]> { return []; }
289
+ async checkInventoryLevels(): Promise<InventoryLevel[]> { return []; }
290
+ async validateCartStock(): Promise<StockValidation> { return { allAvailable: true, unavailableItems: [] }; }
291
+ async getFulfillmentOptions(): Promise<FulfillmentOption[]> { return []; }
292
+
293
+ async cancelOrder(_orderId: string): Promise<Order> {
294
+ throw new ProviderAPIError('Order cancellation requires BigCommerce Management API.', 'BIGCOMMERCE_ADMIN_REQUIRED');
295
+ }
296
+ async createFulfillment(_orderId: string): Promise<void> {
297
+ throw new ProviderAPIError('Fulfillment requires BigCommerce Management API.', 'BIGCOMMERCE_ADMIN_REQUIRED');
298
+ }
299
+ async createRefund(_orderId: string): Promise<void> {
300
+ throw new ProviderAPIError('Refunds require BigCommerce Management API.', 'BIGCOMMERCE_ADMIN_REQUIRED');
301
+ }
302
+ async getAdminOrders(): Promise<{ orders: Order[]; count: number }> { return { orders: [], count: 0 }; }
303
+
304
+ async getStorefrontContext(): Promise<StorefrontContext> {
305
+ return {
306
+ id: this.channelId,
307
+ name: `BigCommerce Store ${this.storeHash}`,
308
+ platformType: 'bigcommerce',
309
+ requiresProductScoping: false,
310
+ currencyCode: this.currencyCode,
311
+ };
312
+ }
313
+
314
+ isStorefrontRequired(): boolean { return false; }
315
+ }
@@ -0,0 +1,227 @@
1
+ /**
2
+ * @thorprovider/adapters — BigCommerce Provider
3
+ * Transform functions: BigCommerce REST API → @thorprovider/types
4
+ */
5
+
6
+ import type {
7
+ Product,
8
+ ProductVariant,
9
+ ProductOption,
10
+ Cart,
11
+ CartItem,
12
+ Collection,
13
+ Money,
14
+ Image,
15
+ Order,
16
+ OrderItem,
17
+ OrderStatus,
18
+ PaymentStatus,
19
+ FulfillmentStatus,
20
+ Customer,
21
+ Address,
22
+ } from '@thorprovider/types';
23
+
24
+ // ============================================
25
+ // Money & Image Transforms
26
+ // ============================================
27
+
28
+ function transformMoney(amount: number | string | null | undefined, currencyCode: string = 'USD'): Money {
29
+ const numAmount = typeof amount === 'string' ? parseFloat(amount) : (amount ?? 0);
30
+ return {
31
+ amount: numAmount.toFixed(2),
32
+ currencyCode: currencyCode.toUpperCase(),
33
+ };
34
+ }
35
+
36
+ function transformImage(url: string, alt: string = ''): Image {
37
+ return { url, altText: alt, width: 800, height: 800 };
38
+ }
39
+
40
+ // ============================================
41
+ // Product Transforms
42
+ // ============================================
43
+
44
+ export function transformProduct(raw: any, currencyCode: string = 'USD'): Product {
45
+ const images: Image[] = (raw.images ?? []).map((img: any) =>
46
+ transformImage(img.url_standard ?? img.url_thumbnail ?? '', img.description ?? ''),
47
+ );
48
+
49
+ const variants: ProductVariant[] = (raw.variants ?? []).map((v: any) => ({
50
+ id: String(v.id),
51
+ title: v.option_display_name ?? `Variant ${v.id}`,
52
+ availableForSale: (v.purchasing_disabled !== true),
53
+ price: transformMoney(v.price ?? raw.price, currencyCode),
54
+ compareAtPrice: v.sale_price ? transformMoney(v.sale_price, currencyCode) : undefined,
55
+ selectedOptions: (v.option_values ?? []).map((ov: any) => ({
56
+ name: ov.option_display_name ?? '',
57
+ value: ov.label ?? '',
58
+ })),
59
+ }));
60
+
61
+ const options: ProductOption[] = (raw.options ?? []).map((opt: any) => ({
62
+ id: String(opt.id),
63
+ name: opt.display_name ?? '',
64
+ values: (opt.option_values ?? []).map((val: any) => val.label ?? ''),
65
+ }));
66
+
67
+ const price = raw.price ?? raw.calculated_price?.as_entered ?? 0;
68
+
69
+ return {
70
+ id: String(raw.id),
71
+ handle: raw.custom_url?.url?.replace(/^\//, '').replace(/\/$/, '') ?? String(raw.id),
72
+ title: raw.name ?? '',
73
+ description: raw.plain_text_description ?? raw.description ?? '',
74
+ descriptionHtml: raw.description ?? '',
75
+ availableForSale: raw.availability === 'available' || raw.is_visible !== false,
76
+ featuredImage: images[0] ?? { url: '', altText: '', width: 800, height: 800 },
77
+ images,
78
+ options,
79
+ variants,
80
+ priceRange: {
81
+ minVariantPrice: transformMoney(price, currencyCode),
82
+ maxVariantPrice: transformMoney(price, currencyCode),
83
+ },
84
+ seo: {
85
+ title: raw.page_title ?? raw.name ?? '',
86
+ description: raw.meta_description ?? '',
87
+ },
88
+ tags: [],
89
+ createdAt: raw.date_created ?? new Date().toISOString(),
90
+ updatedAt: raw.date_modified ?? new Date().toISOString(),
91
+ };
92
+ }
93
+
94
+ // ============================================
95
+ // Collection Transforms (BigCommerce "Categories" or "Brands")
96
+ // ============================================
97
+
98
+ export function transformCollection(raw: any): Collection {
99
+ return {
100
+ id: String(raw.id ?? ''),
101
+ handle: raw.custom_url?.url?.replace(/^\//, '').replace(/\/$/, '') ?? String(raw.id),
102
+ title: raw.name ?? '',
103
+ description: raw.description ?? '',
104
+ seo: {
105
+ title: raw.page_title ?? raw.name ?? '',
106
+ description: raw.meta_description ?? '',
107
+ },
108
+ updatedAt: raw.date_modified ?? new Date().toISOString(),
109
+ path: `/collections/${raw.custom_url?.url?.replace(/^\//, '').replace(/\/$/, '') ?? raw.id}`,
110
+ };
111
+ }
112
+
113
+ // ============================================
114
+ // Cart Transforms
115
+ // ============================================
116
+
117
+ export function transformCart(raw: any, currencyCode: string = 'USD'): Cart {
118
+ const lineItems = Object.values(raw.line_items ?? {}).flat() as any[];
119
+
120
+ const lines: CartItem[] = lineItems.map((item: any) => ({
121
+ id: item.id,
122
+ quantity: item.quantity ?? 1,
123
+ cost: {
124
+ totalAmount: transformMoney(item.extended_sale_price ?? item.sale_price ?? 0, currencyCode),
125
+ },
126
+ merchandise: {
127
+ id: String(item.variant_id ?? item.product_id),
128
+ title: item.name ?? '',
129
+ selectedOptions: (item.options ?? []).map((opt: any) => ({
130
+ name: opt.name ?? '',
131
+ value: opt.value ?? '',
132
+ })),
133
+ product: {
134
+ id: String(item.product_id),
135
+ handle: String(item.product_id),
136
+ title: item.name ?? '',
137
+ featuredImage: item.image_url
138
+ ? transformImage(item.image_url)
139
+ : { url: '', altText: '', width: 800, height: 800 },
140
+ },
141
+ },
142
+ }));
143
+
144
+ return {
145
+ id: raw.id,
146
+ checkoutUrl: raw.redirect_urls?.checkout_url ?? '',
147
+ totalQuantity: lines.reduce((sum, l) => sum + l.quantity, 0),
148
+ cost: {
149
+ subtotalAmount: transformMoney(raw.base_amount ?? 0, currencyCode),
150
+ totalAmount: transformMoney(raw.cart_amount ?? 0, currencyCode),
151
+ },
152
+ lines,
153
+ };
154
+ }
155
+
156
+ // ============================================
157
+ // Customer Transforms
158
+ // ============================================
159
+
160
+ export function transformCustomer(raw: any): Customer {
161
+ return {
162
+ id: String(raw.id),
163
+ email: raw.email ?? '',
164
+ firstName: raw.first_name ?? '',
165
+ lastName: raw.last_name ?? '',
166
+ phone: raw.phone ?? '',
167
+ hasAccount: true,
168
+ };
169
+ }
170
+
171
+ export function transformAddress(raw: any): Address {
172
+ return {
173
+ id: String(raw.id ?? ''),
174
+ firstName: raw.first_name ?? '',
175
+ lastName: raw.last_name ?? '',
176
+ address1: raw.address1 ?? '',
177
+ address2: raw.address2 ?? '',
178
+ city: raw.city ?? '',
179
+ province: raw.state_or_province ?? '',
180
+ countryCode: raw.country_code ?? '',
181
+ postalCode: raw.postal_code ?? '',
182
+ phone: raw.phone ?? '',
183
+ company: raw.company ?? '',
184
+ };
185
+ }
186
+
187
+ // ============================================
188
+ // Order Transforms
189
+ // ============================================
190
+
191
+ export function transformOrder(raw: any, currencyCode: string = 'USD'): Order {
192
+ const items: OrderItem[] = (raw.products ?? []).map((p: any) => ({
193
+ id: String(p.id),
194
+ title: p.name ?? '',
195
+ variantTitle: p.sku ?? '',
196
+ quantity: p.quantity ?? 1,
197
+ price: transformMoney(p.base_price ?? 0, currencyCode),
198
+ total: transformMoney(p.base_total ?? 0, currencyCode),
199
+ productId: String(p.product_id),
200
+ }));
201
+
202
+ const statusMap: Record<string, OrderStatus> = {
203
+ 'Incomplete': 'pending',
204
+ 'Pending': 'pending',
205
+ 'Shipped': 'completed',
206
+ 'Partially Shipped': 'processing',
207
+ 'Refunded': 'refunded',
208
+ 'Cancelled': 'cancelled',
209
+ 'Completed': 'completed',
210
+ };
211
+
212
+ return {
213
+ id: String(raw.id),
214
+ orderNumber: String(raw.id),
215
+ email: raw.billing_address?.email ?? '',
216
+ status: statusMap[raw.status] ?? 'pending',
217
+ paymentStatus: raw.payment_status === 'paid' ? 'paid' : 'pending',
218
+ fulfillmentStatus: raw.status === 'Shipped' ? 'fulfilled' : 'unfulfilled',
219
+ items,
220
+ total: transformMoney(raw.total_inc_tax ?? 0, currencyCode),
221
+ subtotal: transformMoney(raw.subtotal_inc_tax ?? 0, currencyCode),
222
+ tax: transformMoney(raw.total_tax ?? 0, currencyCode),
223
+ shipping: transformMoney(raw.shipping_cost_inc_tax ?? 0, currencyCode),
224
+ createdAt: raw.date_created ?? new Date().toISOString(),
225
+ updatedAt: raw.date_modified ?? new Date().toISOString(),
226
+ };
227
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @thorprovider/adapters v5.0
2
+ * @thorprovider/adapters v2.0
3
3
  * Providers index
4
4
  */
5
5
 
@@ -9,5 +9,20 @@ export type { MedusaProviderConfig } from './medusa';
9
9
  export { StelOrderProvider } from './stelorder';
10
10
  export type { StelOrderProviderConfig } from './stelorder';
11
11
 
12
+ export { ShopifyProvider } from './shopify';
13
+ export type { ShopifyProviderConfig } from './shopify';
14
+
15
+ export { BigCommerceProvider } from './bigcommerce';
16
+ export type { BigCommerceProviderConfig } from './bigcommerce';
17
+
18
+ export { WooCommerceProvider } from './woocommerce';
19
+ export type { WooCommerceProviderConfig } from './woocommerce';
20
+
21
+ export { SpreeProvider } from './spree';
22
+ export type { SpreeProviderConfig } from './spree';
23
+
24
+ export { MagentoProvider } from './magento';
25
+ export type { MagentoProviderConfig } from './magento';
26
+
12
27
  export { MockProvider } from './mock';
13
28
  export type { MockProviderConfig } from './mock';