@thorprovider/adapters 3.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.
- package/.turbo/turbo-build.log +18 -0
- package/.turbo/turbo-test.log +1 -0
- package/.turbo/turbo-type-check.log +0 -0
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +271 -0
- package/README.md +634 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.mts +2524 -0
- package/dist/index.d.ts +2524 -0
- package/dist/index.js +8136 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8045 -0
- package/dist/index.mjs.map +1 -0
- package/docs/RETRY_SOLUTION_SUMMARY.md +55 -0
- package/docs/authentication.md +165 -0
- package/docs/capabilities-system.md +143 -0
- package/docs/category-customization.md +309 -0
- package/docs/fetch-reliability-solution.md +399 -0
- package/docs/getting-started.md +154 -0
- package/docs/multi-tenant-channel-scoping.md +225 -0
- package/docs/profile-management.md +147 -0
- package/docs/providers-overview.md +85 -0
- package/docs/services-overview.md +135 -0
- package/docs/update-documentation.md +113 -0
- package/package.json +43 -0
- package/publish.log +93 -0
- package/quick-reference.md +169 -0
- package/src/admin/AdminAuthService.ts +88 -0
- package/src/admin/AdminSessionService.ts +91 -0
- package/src/admin/MetricsService.ts +145 -0
- package/src/admin/index.ts +13 -0
- package/src/backend/BackendMetadataAdapter.ts +88 -0
- package/src/backend/factory.ts +107 -0
- package/src/backend/index.ts +12 -0
- package/src/backend/medusa/MedusaMetadataAdapter.ts +139 -0
- package/src/core/errors.js +161 -0
- package/src/core/errors.ts +132 -0
- package/src/core/fetch-utils.js +240 -0
- package/src/core/fetch-utils.ts +227 -0
- package/src/core/index.ts +8 -0
- package/src/core/logger.js +63 -0
- package/src/core/logger.ts +37 -0
- package/src/factory/index.ts +102 -0
- package/src/index.ts +205 -0
- package/src/lib/money-transform.ts +80 -0
- package/src/metadata/channel-scope-validation.js +136 -0
- package/src/metadata/channel-scope-validation.ts +151 -0
- package/src/metadata/channel-scope.js +174 -0
- package/src/metadata/channel-scope.ts +215 -0
- package/src/metadata/index.js +31 -0
- package/src/metadata/index.ts +37 -0
- 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 +22 -0
- 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.js +601 -0
- package/src/providers/medusa/auth.ts +496 -0
- package/src/providers/medusa/fulfillment-planner.ts +225 -0
- package/src/providers/medusa/index.js +2485 -0
- package/src/providers/medusa/index.ts +4239 -0
- package/src/providers/medusa/medusa.ts +8 -0
- package/src/providers/medusa/payment.js +265 -0
- package/src/providers/medusa/payment.ts +269 -0
- package/src/providers/medusa/transforms.js +505 -0
- package/src/providers/medusa/transforms.ts +625 -0
- package/src/providers/shopify/index.ts +444 -0
- package/src/providers/shopify/mutations.ts +102 -0
- package/src/providers/shopify/queries.ts +324 -0
- package/src/providers/shopify/shopify.ts +7 -0
- package/src/providers/shopify/transforms.ts +270 -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/resilience/README.md +299 -0
- package/src/resilience/circuit-breaker.ts +222 -0
- package/src/resilience/index.ts +10 -0
- package/src/types/capabilities.types.js +141 -0
- package/src/types/capabilities.types.ts +366 -0
- package/src/types/index.ts +24 -0
- package/src/types/provider.js +9 -0
- package/src/types/provider.ts +9 -0
- package/src/types/ui-responses.ts +261 -0
- package/src/utils/city-coordinates.ts +40 -0
- package/src/utils/geolocation.ts +52 -0
- package/src/utils/payment-utils.js +152 -0
- package/src/utils/payment-utils.ts +203 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +14 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2524 @@
|
|
|
1
|
+
import * as _thorprovider_types from '@thorprovider/types';
|
|
2
|
+
import { BackendCapabilities, Money, PaymentMethod, FulfillmentOption, CartItem, StockLocation, InventoryLevel, StorefrontConfig, DashboardMetrics, ProviderTypeString, CommerceProvider, AuthProvider, ProviderConfig, AuthConfig, Product, GetProductsOptions, AdvancedSearchProductsOptions, SearchResultMeta, FilterConfig, Collection, GetCollectionsOptions, CollectionProductsOptions, ProductCategory, GetCategoriesOptions, Cart, CartLineInput, CartLineUpdate, GetOrdersOptions, Order, GetCustomersOptions, Customer, Address, Region, AdminProduct, PaymentMethodsOptions, StockValidation, StorefrontContext, DesignerConfig, DesignerHistoryEntry, ShippingMethod } from '@thorprovider/types';
|
|
3
|
+
export * from '@thorprovider/types';
|
|
4
|
+
export { BackendCapabilities, CommerceProvider, DesignerConfig, DesignerHistoryEntry, DesignerNavItem, DesignerThemeConfig, DesignerThemePreset, ProviderConfig, StorefrontConfig, StorefrontConfigError, StorefrontContext, StorefrontPlatformType, StorefrontSeoDefaults } from '@thorprovider/types';
|
|
5
|
+
import Medusa from '@medusajs/js-sdk';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @thorprovider/adapters
|
|
9
|
+
* UI-ready response types
|
|
10
|
+
*
|
|
11
|
+
* These types extend domain types from @thorprovider/types (L1) but with transformations
|
|
12
|
+
* applied for direct UI consumption. This is where Money→number conversions happen.
|
|
13
|
+
*
|
|
14
|
+
* L3 (@thorprovider/components) should import these types, not the raw domain types.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* UI-ready cart item with prices as numbers
|
|
19
|
+
*
|
|
20
|
+
* Simplified cart item for UI consumption with prices in major currency units (e.g., dollars, euros).
|
|
21
|
+
* Transformed from domain CartItem by adapter services.
|
|
22
|
+
* Values come from Money.amount (decimal string in major units) parsed to number.
|
|
23
|
+
*
|
|
24
|
+
* This is a flattened structure optimized for UI display, unlike the nested
|
|
25
|
+
* domain CartItem which follows the Shopify/Medusa structure.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const uiItem: UICartItem = {
|
|
30
|
+
* id: 'item_123',
|
|
31
|
+
* productId: 'prod_abc',
|
|
32
|
+
* variantId: 'var_xyz',
|
|
33
|
+
* name: 'T-Shirt',
|
|
34
|
+
* variant: 'Red / Large',
|
|
35
|
+
* image: 'https://...',
|
|
36
|
+
* price: 19.99, // $19.99 in major units
|
|
37
|
+
* quantity: 2,
|
|
38
|
+
* total: 39.98, // $39.98 in major units
|
|
39
|
+
* isAvailable: true
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
interface UICartItem {
|
|
44
|
+
/** Unique item identifier */
|
|
45
|
+
id: string;
|
|
46
|
+
/** Product ID */
|
|
47
|
+
productId: string;
|
|
48
|
+
/** Variant ID */
|
|
49
|
+
variantId: string;
|
|
50
|
+
/** Product name */
|
|
51
|
+
name: string;
|
|
52
|
+
/** Product description (optional) */
|
|
53
|
+
description?: string;
|
|
54
|
+
/** Variant description (e.g., 'Red / Large') */
|
|
55
|
+
variant: string;
|
|
56
|
+
/** Product image URL */
|
|
57
|
+
image: string;
|
|
58
|
+
/** Unit price in major currency units (e.g., dollars, euros) */
|
|
59
|
+
price: number;
|
|
60
|
+
/** Quantity in cart */
|
|
61
|
+
quantity: number;
|
|
62
|
+
/** Total price (price × quantity) in major currency units */
|
|
63
|
+
total: number;
|
|
64
|
+
/** Whether item is available for purchase */
|
|
65
|
+
isAvailable?: boolean;
|
|
66
|
+
/** Maximum quantity available in stock */
|
|
67
|
+
maxQuantity?: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* UI-ready cart totals with amounts as numbers
|
|
71
|
+
*
|
|
72
|
+
* All monetary values are in major currency units (e.g., dollars, euros).
|
|
73
|
+
* Values come from Money.amount (decimal string in major units) parsed to number.
|
|
74
|
+
* Transformed from domain CartCost by adapter services.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const totals: UICartTotals = {
|
|
79
|
+
* subtotal: 59.97, // $59.97
|
|
80
|
+
* discount: 10.00, // $10.00
|
|
81
|
+
* shipping: 5.00, // $5.00
|
|
82
|
+
* tax: 5.39, // $5.39
|
|
83
|
+
* total: 60.36, // $60.36
|
|
84
|
+
* currency: 'USD',
|
|
85
|
+
* itemCount: 3
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
interface UICartTotals {
|
|
90
|
+
/** Subtotal before discounts/shipping/tax (in major currency units) */
|
|
91
|
+
subtotal: number;
|
|
92
|
+
/** Discount amount if any (in major currency units) */
|
|
93
|
+
discount?: number;
|
|
94
|
+
/** Discount code applied */
|
|
95
|
+
discountCode?: string;
|
|
96
|
+
/** Shipping cost (in major currency units) */
|
|
97
|
+
shipping?: number;
|
|
98
|
+
/** Tax amount (in major currency units) */
|
|
99
|
+
tax?: number;
|
|
100
|
+
/** Final total amount (in major currency units) */
|
|
101
|
+
total: number;
|
|
102
|
+
/** Currency code (ISO 4217, e.g., 'USD', 'EUR') */
|
|
103
|
+
currency: string;
|
|
104
|
+
/** Total number of items in cart */
|
|
105
|
+
itemCount: number;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* UI-ready shipping method with price as number
|
|
109
|
+
*
|
|
110
|
+
* Price is in the currency's smallest unit.
|
|
111
|
+
* Transformed from domain ShippingMethod by adapter services.
|
|
112
|
+
*
|
|
113
|
+
* Includes alias fields for compatibility with existing checkout components.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const method: UIShippingMethod = {
|
|
118
|
+
* id: 'ship_standard',
|
|
119
|
+
* methodId: 'ship_standard', // alias for id
|
|
120
|
+
* name: 'Standard Shipping',
|
|
121
|
+
* price: 500, // $5.00 as 500 cents
|
|
122
|
+
* amount: 500, // alias for price
|
|
123
|
+
* estimatedDays: '3-5 business days'
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
interface UIShippingMethod {
|
|
128
|
+
/** Unique identifier */
|
|
129
|
+
id: string;
|
|
130
|
+
/** Alias for id (for compatibility with checkout components) */
|
|
131
|
+
methodId: string;
|
|
132
|
+
/** Display name */
|
|
133
|
+
name: string;
|
|
134
|
+
/** Shipping price in smallest currency unit */
|
|
135
|
+
price: number;
|
|
136
|
+
/** Alias for price (for compatibility with checkout components) */
|
|
137
|
+
amount: number;
|
|
138
|
+
/** Optional description */
|
|
139
|
+
description?: string;
|
|
140
|
+
/** Estimated delivery time (human-readable string) */
|
|
141
|
+
estimatedDays?: string;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* UI-ready discount code with value as number
|
|
145
|
+
*
|
|
146
|
+
* Transformed from domain DiscountCode by adapter services.
|
|
147
|
+
* Value is in the currency's smallest unit for fixed discounts,
|
|
148
|
+
* or a percentage (0-100) for percentage discounts.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* // Fixed discount
|
|
153
|
+
* const fixedDiscount: UIDiscountCode = {
|
|
154
|
+
* code: 'SAVE10',
|
|
155
|
+
* value: 1000, // $10.00 as 1000 cents
|
|
156
|
+
* isPercentage: false,
|
|
157
|
+
* description: 'Save $10 on your order'
|
|
158
|
+
* }
|
|
159
|
+
*
|
|
160
|
+
* // Percentage discount
|
|
161
|
+
* const percentDiscount: UIDiscountCode = {
|
|
162
|
+
* code: 'SAVE20',
|
|
163
|
+
* value: 20, // 20%
|
|
164
|
+
* isPercentage: true,
|
|
165
|
+
* description: 'Save 20% on your order'
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
interface UIDiscountCode {
|
|
170
|
+
/** Discount code */
|
|
171
|
+
code: string;
|
|
172
|
+
/** Discount value - either amount in smallest currency unit or percentage (0-100) */
|
|
173
|
+
value: number;
|
|
174
|
+
/** Whether value is a percentage (true) or fixed amount (false) */
|
|
175
|
+
isPercentage: boolean;
|
|
176
|
+
/** Human-readable description of the discount */
|
|
177
|
+
description?: string;
|
|
178
|
+
/** Minimum purchase amount required (in smallest currency unit) */
|
|
179
|
+
minimumAmount?: number;
|
|
180
|
+
/** Expiration date */
|
|
181
|
+
expiresAt?: Date;
|
|
182
|
+
/** Maximum number of uses allowed */
|
|
183
|
+
maxUses?: number;
|
|
184
|
+
/** Current usage count */
|
|
185
|
+
usageCount?: number;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* UI-ready payment method for checkout selection
|
|
189
|
+
*
|
|
190
|
+
* Simplified version of domain PaymentMethod with additional
|
|
191
|
+
* providerId field for backend-specific provider identification.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const payment: UIPaymentMethod = {
|
|
196
|
+
* id: 'pp_stripe_stripe',
|
|
197
|
+
* providerId: 'stripe',
|
|
198
|
+
* name: 'Credit Card',
|
|
199
|
+
* description: 'Visa, Mastercard, American Express'
|
|
200
|
+
* }
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
interface UIPaymentMethod {
|
|
204
|
+
/** Unique identifier */
|
|
205
|
+
id: string;
|
|
206
|
+
/** Provider identifier (e.g., 'stripe', 'paypal', 'manual') */
|
|
207
|
+
providerId: string;
|
|
208
|
+
/** Display name for UI */
|
|
209
|
+
name: string;
|
|
210
|
+
/** Optional description */
|
|
211
|
+
description?: string;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @thorprovider/adapters v2.0
|
|
216
|
+
* Backend Capabilities System
|
|
217
|
+
*
|
|
218
|
+
* Defines what operations each backend platform supports.
|
|
219
|
+
* This is a compile-time capability detection system, NOT runtime feature flags.
|
|
220
|
+
*
|
|
221
|
+
* NOTE: BackendCapabilities interface is defined in @thorprovider/types (L1: Foundation).
|
|
222
|
+
* This file re-exports it and provides platform-specific implementations.
|
|
223
|
+
*
|
|
224
|
+
* @see packages/core/docs/BACKEND_CAPABILITIES_ANALYSIS.md
|
|
225
|
+
* @see packages/core/docs/COMMERCE_PROVIDER_ARCHITECTURE.md
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Medusa backend capabilities
|
|
230
|
+
*
|
|
231
|
+
* @see https://docs.medusajs.com/api/store
|
|
232
|
+
*/
|
|
233
|
+
declare const MEDUSA_CAPABILITIES: Readonly<BackendCapabilities>;
|
|
234
|
+
/**
|
|
235
|
+
* Shopify backend capabilities
|
|
236
|
+
*
|
|
237
|
+
* @see https://shopify.dev/docs/api/storefront
|
|
238
|
+
*/
|
|
239
|
+
declare const SHOPIFY_CAPABILITIES: Readonly<BackendCapabilities>;
|
|
240
|
+
/**
|
|
241
|
+
* BigCommerce backend capabilities
|
|
242
|
+
*
|
|
243
|
+
* @see https://developer.bigcommerce.com/docs/rest-storefront
|
|
244
|
+
*/
|
|
245
|
+
declare const BIGCOMMERCE_CAPABILITIES: Readonly<BackendCapabilities>;
|
|
246
|
+
/**
|
|
247
|
+
* WooCommerce backend capabilities
|
|
248
|
+
*
|
|
249
|
+
* @see https://developer.woocommerce.com/docs/apis/store-api
|
|
250
|
+
*/
|
|
251
|
+
declare const WOOCOMMERCE_CAPABILITIES: Readonly<BackendCapabilities>;
|
|
252
|
+
/**
|
|
253
|
+
* Spree Commerce backend capabilities
|
|
254
|
+
*
|
|
255
|
+
* @see https://docs.spreecommerce.org/api-reference
|
|
256
|
+
*/
|
|
257
|
+
declare const SPREE_CAPABILITIES: Readonly<BackendCapabilities>;
|
|
258
|
+
/**
|
|
259
|
+
* Adobe Commerce / Magento backend capabilities
|
|
260
|
+
*
|
|
261
|
+
* @see https://developer.adobe.com/commerce/webapi/graphql/
|
|
262
|
+
*/
|
|
263
|
+
declare const MAGENTO_CAPABILITIES: Readonly<BackendCapabilities>;
|
|
264
|
+
/**
|
|
265
|
+
* Type guard to check if an object is a valid BackendCapabilities
|
|
266
|
+
*/
|
|
267
|
+
declare function isBackendCapabilities(obj: unknown): obj is BackendCapabilities;
|
|
268
|
+
/**
|
|
269
|
+
* Get capability description for UI display
|
|
270
|
+
*/
|
|
271
|
+
declare function getCapabilityDescription(capability: keyof BackendCapabilities): string;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* @thorprovider/adapters v2.0
|
|
275
|
+
* Core errors
|
|
276
|
+
*/
|
|
277
|
+
/**
|
|
278
|
+
* Base error class for commerce providers
|
|
279
|
+
*/
|
|
280
|
+
declare class CommerceError extends Error {
|
|
281
|
+
readonly code?: string | undefined;
|
|
282
|
+
readonly status?: number | undefined;
|
|
283
|
+
constructor(message: string, code?: string | undefined, status?: number | undefined);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Provider not found error
|
|
287
|
+
*/
|
|
288
|
+
declare class ProviderNotFoundError extends CommerceError {
|
|
289
|
+
constructor(providerName: string);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Configuration error
|
|
293
|
+
*/
|
|
294
|
+
declare class ConfigurationError extends CommerceError {
|
|
295
|
+
constructor(message: string);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Resource not found error
|
|
299
|
+
*/
|
|
300
|
+
declare class ResourceNotFoundError extends CommerceError {
|
|
301
|
+
constructor(resource: string, identifier: string);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* API error from provider
|
|
305
|
+
*/
|
|
306
|
+
declare class ProviderAPIError extends CommerceError {
|
|
307
|
+
readonly provider: string;
|
|
308
|
+
constructor(message: string, provider: string, status?: number);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @thorprovider/adapters v2.0
|
|
313
|
+
* Core logger utility
|
|
314
|
+
*/
|
|
315
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
316
|
+
interface Logger {
|
|
317
|
+
debug(message: string, ...args: any[]): void;
|
|
318
|
+
info(message: string, ...args: any[]): void;
|
|
319
|
+
warn(message: string, ...args: any[]): void;
|
|
320
|
+
error(message: string, ...args: any[]): void;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Create a logger instance
|
|
324
|
+
*/
|
|
325
|
+
declare function createLogger(namespace: string, enabled?: boolean): Logger;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* @thorprovider/adapters v2.0
|
|
329
|
+
* Fetch Utilities - Retry logic, timeouts, and error handling
|
|
330
|
+
*
|
|
331
|
+
* This module provides enhanced fetch capabilities with:
|
|
332
|
+
* - Automatic retries with exponential backoff
|
|
333
|
+
* - Configurable timeouts
|
|
334
|
+
* - Better error handling for network failures
|
|
335
|
+
*/
|
|
336
|
+
/**
|
|
337
|
+
* Configuration for fetch retry behavior
|
|
338
|
+
*/
|
|
339
|
+
interface RetryConfig {
|
|
340
|
+
/**
|
|
341
|
+
* Maximum number of retry attempts (default: 3)
|
|
342
|
+
*/
|
|
343
|
+
maxRetries?: number;
|
|
344
|
+
/**
|
|
345
|
+
* Initial delay in milliseconds before first retry (default: 300ms)
|
|
346
|
+
*/
|
|
347
|
+
initialDelayMs?: number;
|
|
348
|
+
/**
|
|
349
|
+
* Multiplier for exponential backoff (default: 2)
|
|
350
|
+
*/
|
|
351
|
+
backoffMultiplier?: number;
|
|
352
|
+
/**
|
|
353
|
+
* Maximum delay between retries in milliseconds (default: 5000ms)
|
|
354
|
+
*/
|
|
355
|
+
maxDelayMs?: number;
|
|
356
|
+
/**
|
|
357
|
+
* Timeout for each fetch attempt in milliseconds (default: 10000ms - 10 seconds)
|
|
358
|
+
*/
|
|
359
|
+
timeoutMs?: number;
|
|
360
|
+
/**
|
|
361
|
+
* HTTP status codes that should trigger a retry (default: [408, 429, 500, 502, 503, 504])
|
|
362
|
+
*/
|
|
363
|
+
retryableStatusCodes?: number[];
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Circuit Breaker Pattern Implementation
|
|
368
|
+
*
|
|
369
|
+
* Prevents cascading failures when the backend is unavailable.
|
|
370
|
+
* Implements the Circuit Breaker pattern as described by Martin Fowler.
|
|
371
|
+
*
|
|
372
|
+
* States:
|
|
373
|
+
* - CLOSED: Normal operation, requests pass through
|
|
374
|
+
* - OPEN: Too many failures, requests fail fast
|
|
375
|
+
* - HALF_OPEN: Testing if backend has recovered
|
|
376
|
+
*
|
|
377
|
+
* @see https://martinfowler.com/bliki/CircuitBreaker.html
|
|
378
|
+
*/
|
|
379
|
+
type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
|
|
380
|
+
interface CircuitBreakerConfig {
|
|
381
|
+
/** Number of failures before opening circuit */
|
|
382
|
+
failureThreshold: number;
|
|
383
|
+
/** Time in ms to wait before attempting recovery */
|
|
384
|
+
resetTimeout: number;
|
|
385
|
+
/** Name for logging/monitoring */
|
|
386
|
+
name?: string;
|
|
387
|
+
}
|
|
388
|
+
interface CircuitBreakerStats {
|
|
389
|
+
state: CircuitState;
|
|
390
|
+
failureCount: number;
|
|
391
|
+
lastFailureTime: number | null;
|
|
392
|
+
totalRequests: number;
|
|
393
|
+
totalFailures: number;
|
|
394
|
+
totalSuccesses: number;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Circuit Breaker Class
|
|
398
|
+
*
|
|
399
|
+
* Monitors backend calls and prevents cascading failures by
|
|
400
|
+
* failing fast when the backend is unhealthy.
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```ts
|
|
404
|
+
* const breaker = new CircuitBreaker({
|
|
405
|
+
* failureThreshold: 3,
|
|
406
|
+
* resetTimeout: 60000, // 1 minute
|
|
407
|
+
* name: 'backend-api'
|
|
408
|
+
* });
|
|
409
|
+
*
|
|
410
|
+
* const result = await breaker.execute(
|
|
411
|
+
* () => fetch('/api/data'),
|
|
412
|
+
* fallbackData
|
|
413
|
+
* );
|
|
414
|
+
* ```
|
|
415
|
+
*/
|
|
416
|
+
declare class CircuitBreaker {
|
|
417
|
+
private config;
|
|
418
|
+
private failureCount;
|
|
419
|
+
private lastFailureTime;
|
|
420
|
+
private totalRequests;
|
|
421
|
+
private totalFailures;
|
|
422
|
+
private totalSuccesses;
|
|
423
|
+
constructor(config: CircuitBreakerConfig);
|
|
424
|
+
/**
|
|
425
|
+
* Get current circuit state
|
|
426
|
+
*/
|
|
427
|
+
get state(): CircuitState;
|
|
428
|
+
/**
|
|
429
|
+
* Get circuit breaker statistics
|
|
430
|
+
*/
|
|
431
|
+
get stats(): CircuitBreakerStats;
|
|
432
|
+
/**
|
|
433
|
+
* Execute a function with circuit breaker protection
|
|
434
|
+
*
|
|
435
|
+
* @param fn - Function to execute
|
|
436
|
+
* @param fallback - Fallback value if circuit is open
|
|
437
|
+
* @returns Result from fn or fallback
|
|
438
|
+
*/
|
|
439
|
+
execute<T>(fn: () => Promise<T>, fallback?: T): Promise<T>;
|
|
440
|
+
/**
|
|
441
|
+
* Check if circuit should attempt to reset
|
|
442
|
+
*/
|
|
443
|
+
private shouldAttemptReset;
|
|
444
|
+
/**
|
|
445
|
+
* Record a successful call
|
|
446
|
+
*/
|
|
447
|
+
private onSuccess;
|
|
448
|
+
/**
|
|
449
|
+
* Record a failed call
|
|
450
|
+
*/
|
|
451
|
+
private onFailure;
|
|
452
|
+
/**
|
|
453
|
+
* Reset circuit to CLOSED state
|
|
454
|
+
*/
|
|
455
|
+
private reset;
|
|
456
|
+
/**
|
|
457
|
+
* Manually reset the circuit breaker
|
|
458
|
+
*/
|
|
459
|
+
manualReset(): void;
|
|
460
|
+
/**
|
|
461
|
+
* Log messages (only in development)
|
|
462
|
+
*/
|
|
463
|
+
private log;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Custom error for when circuit is open
|
|
467
|
+
*/
|
|
468
|
+
declare class CircuitBreakerOpenError extends Error {
|
|
469
|
+
constructor(message: string);
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Global circuit breaker instance for backend API calls
|
|
473
|
+
*
|
|
474
|
+
* Can be imported and used throughout the application
|
|
475
|
+
*/
|
|
476
|
+
declare const backendCircuitBreaker: CircuitBreaker;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* @thorprovider/adapters
|
|
480
|
+
* Money transformation utilities
|
|
481
|
+
*
|
|
482
|
+
* Handles conversion between domain Money types (string decimals) and
|
|
483
|
+
* UI-ready number representations (smallest currency unit, e.g., cents).
|
|
484
|
+
*/
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Converts Money object to number in smallest currency unit
|
|
488
|
+
*
|
|
489
|
+
* Money.amount is a decimal string (e.g., "45.99").
|
|
490
|
+
* This function converts it to smallest unit (e.g., 4599 cents).
|
|
491
|
+
*
|
|
492
|
+
* @param money - Money object with decimal string amount
|
|
493
|
+
* @returns Amount in smallest currency unit (e.g., cents for USD)
|
|
494
|
+
*
|
|
495
|
+
* @example
|
|
496
|
+
* ```typescript
|
|
497
|
+
* moneyToNumber({ amount: "45.99", currencyCode: "USD" }) // => 4599
|
|
498
|
+
* moneyToNumber({ amount: "100.00", currencyCode: "EUR" }) // => 10000
|
|
499
|
+
* moneyToNumber({ amount: "0.50", currencyCode: "USD" }) // => 50
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
declare function moneyToNumber(money: Money): number;
|
|
503
|
+
/**
|
|
504
|
+
* Converts number (smallest unit) to Money object
|
|
505
|
+
*
|
|
506
|
+
* Takes an amount in smallest currency unit (e.g., cents) and
|
|
507
|
+
* converts it to a Money object with decimal string amount.
|
|
508
|
+
*
|
|
509
|
+
* @param amount - Amount in smallest currency unit (e.g., cents)
|
|
510
|
+
* @param currency - ISO 4217 currency code (e.g., 'USD', 'EUR')
|
|
511
|
+
* @returns Money object with decimal string amount
|
|
512
|
+
*
|
|
513
|
+
* @example
|
|
514
|
+
* ```typescript
|
|
515
|
+
* numberToMoney(4599, 'USD') // => { amount: "45.99", currencyCode: "USD" }
|
|
516
|
+
* numberToMoney(10000, 'EUR') // => { amount: "100.00", currencyCode: "EUR" }
|
|
517
|
+
* numberToMoney(50, 'USD') // => { amount: "0.50", currencyCode: "USD" }
|
|
518
|
+
* ```
|
|
519
|
+
*/
|
|
520
|
+
declare function numberToMoney(amount: number, currency: string): Money;
|
|
521
|
+
/**
|
|
522
|
+
* Safely converts Money to number, returning 0 for null/undefined
|
|
523
|
+
*
|
|
524
|
+
* Useful for optional Money fields that might not always be present.
|
|
525
|
+
*
|
|
526
|
+
* @param money - Money object or null/undefined
|
|
527
|
+
* @returns Amount in smallest unit, or 0 if money is null/undefined
|
|
528
|
+
*
|
|
529
|
+
* @example
|
|
530
|
+
* ```typescript
|
|
531
|
+
* moneyToNumberSafe({ amount: "10.00", currencyCode: "USD" }) // => 1000
|
|
532
|
+
* moneyToNumberSafe(undefined) // => 0
|
|
533
|
+
* moneyToNumberSafe(null) // => 0
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
declare function moneyToNumberSafe(money: Money | null | undefined): number;
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* @thorprovider/adapters - Payment Utilities
|
|
540
|
+
*
|
|
541
|
+
* Backend-agnostic utilities for extracting backend provider IDs from
|
|
542
|
+
* normalized PaymentMethod objects using metadata.
|
|
543
|
+
*
|
|
544
|
+
* This solves the problem of losing backend-specific provider IDs during
|
|
545
|
+
* transformation to frontend-friendly formats.
|
|
546
|
+
*
|
|
547
|
+
* @module payment-utils
|
|
548
|
+
* @since 2.0.0
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Backend mapping metadata stored in PaymentMethod.metadata
|
|
553
|
+
*
|
|
554
|
+
* This metadata is added during payment method transformation
|
|
555
|
+
* to preserve the original backend-specific identifier.
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* ```typescript
|
|
559
|
+
* const metadata = {
|
|
560
|
+
* _backendMapping: {
|
|
561
|
+
* backend: 'medusa',
|
|
562
|
+
* originalId: 'pp_stripe_stripe',
|
|
563
|
+
* normalizedType: 'card'
|
|
564
|
+
* }
|
|
565
|
+
* };
|
|
566
|
+
* ```
|
|
567
|
+
*/
|
|
568
|
+
interface BackendMapping {
|
|
569
|
+
/**
|
|
570
|
+
* Backend type (e.g., 'medusa', 'shopify', 'woocommerce')
|
|
571
|
+
*/
|
|
572
|
+
backend: string;
|
|
573
|
+
/**
|
|
574
|
+
* Original backend-specific provider ID
|
|
575
|
+
*
|
|
576
|
+
* Examples:
|
|
577
|
+
* - Medusa: 'pp_stripe_stripe', 'pp_paypal_paypal', 'pp_system_default'
|
|
578
|
+
* - Shopify: 'shopify_payments', 'paypal_express'
|
|
579
|
+
* - WooCommerce: 'stripe', 'paypal', 'cod'
|
|
580
|
+
*/
|
|
581
|
+
originalId: string;
|
|
582
|
+
/**
|
|
583
|
+
* Normalized payment method type
|
|
584
|
+
*
|
|
585
|
+
* The frontend-friendly type we inferred from the backend ID
|
|
586
|
+
* (e.g., 'card', 'wallet', 'bank_transfer', 'cash_on_delivery')
|
|
587
|
+
*/
|
|
588
|
+
normalizedType: string;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Extract backend provider ID from PaymentMethod
|
|
592
|
+
*
|
|
593
|
+
* Uses the `_backendMapping` metadata to retrieve the original
|
|
594
|
+
* backend-specific provider ID that should be sent to API calls.
|
|
595
|
+
*
|
|
596
|
+
* **Why this exists:**
|
|
597
|
+
* During transformation, we normalize backend IDs to friendly types:
|
|
598
|
+
* - Backend: 'pp_stripe_stripe' → Frontend: type 'card'
|
|
599
|
+
* - Backend: 'pp_system_default' → Frontend: type 'cash_on_delivery'
|
|
600
|
+
*
|
|
601
|
+
* But when making API calls, we need the ORIGINAL backend ID, not the type.
|
|
602
|
+
* This function extracts it from metadata.
|
|
603
|
+
*
|
|
604
|
+
* @param method - PaymentMethod with _backendMapping metadata
|
|
605
|
+
* @returns Backend provider ID (e.g., 'pp_stripe_stripe', 'pp_system_default')
|
|
606
|
+
* @throws {Error} If _backendMapping metadata is missing or invalid
|
|
607
|
+
*
|
|
608
|
+
* @example
|
|
609
|
+
* ```typescript
|
|
610
|
+
* // PaymentMethod from backend with metadata
|
|
611
|
+
* const method = {
|
|
612
|
+
* id: 'pp_system_default',
|
|
613
|
+
* type: 'cash_on_delivery',
|
|
614
|
+
* name: 'Cash on Delivery',
|
|
615
|
+
* metadata: {
|
|
616
|
+
* _backendMapping: {
|
|
617
|
+
* backend: 'medusa',
|
|
618
|
+
* originalId: 'pp_system_default',
|
|
619
|
+
* normalizedType: 'cash_on_delivery'
|
|
620
|
+
* }
|
|
621
|
+
* }
|
|
622
|
+
* };
|
|
623
|
+
*
|
|
624
|
+
* const providerId = getBackendProviderId(method);
|
|
625
|
+
* // Returns: 'pp_system_default'
|
|
626
|
+
*
|
|
627
|
+
* // Now safe to use with backend API:
|
|
628
|
+
* await commerce.initiatePaymentSession(cartId, providerId);
|
|
629
|
+
* ```
|
|
630
|
+
*
|
|
631
|
+
* @example
|
|
632
|
+
* ```typescript
|
|
633
|
+
* // Handling missing metadata
|
|
634
|
+
* try {
|
|
635
|
+
* const providerId = getBackendProviderId(methodWithoutMetadata);
|
|
636
|
+
* } catch (error) {
|
|
637
|
+
* console.error('Payment method missing backend mapping:', error.message);
|
|
638
|
+
* // Error: PaymentMethod 'stripe' is missing _backendMapping metadata.
|
|
639
|
+
* // This is required to extract the backend provider ID.
|
|
640
|
+
* }
|
|
641
|
+
* ```
|
|
642
|
+
*/
|
|
643
|
+
declare function getBackendProviderId(method: PaymentMethod): string;
|
|
644
|
+
/**
|
|
645
|
+
* Validate payment provider ID format
|
|
646
|
+
*
|
|
647
|
+
* Checks if the provider ID is a valid backend-specific identifier,
|
|
648
|
+
* not a normalized type like 'card', 'wallet', etc.
|
|
649
|
+
*
|
|
650
|
+
* **Why this exists:**
|
|
651
|
+
* Common bug: Accidentally sending normalized types to backend APIs:
|
|
652
|
+
* ❌ `initiatePaymentSession(cartId, 'card')` → Backend error
|
|
653
|
+
* ✅ `initiatePaymentSession(cartId, 'pp_stripe_stripe')` → Success
|
|
654
|
+
*
|
|
655
|
+
* This validation catches the bug at runtime with a helpful error message.
|
|
656
|
+
*
|
|
657
|
+
* @param id - Provider ID to validate
|
|
658
|
+
* @throws {Error} If ID appears to be a normalized type instead of backend ID
|
|
659
|
+
*
|
|
660
|
+
* @example
|
|
661
|
+
* ```typescript
|
|
662
|
+
* // Valid backend IDs - pass validation:
|
|
663
|
+
* validatePaymentId('pp_stripe_stripe'); // ✅ OK (Medusa)
|
|
664
|
+
* validatePaymentId('pp_system_default'); // ✅ OK (Medusa)
|
|
665
|
+
* validatePaymentId('shopify_payments'); // ✅ OK (Shopify)
|
|
666
|
+
* validatePaymentId('stripe'); // ✅ OK (WooCommerce)
|
|
667
|
+
* validatePaymentId('paypal_express'); // ✅ OK (generic)
|
|
668
|
+
*
|
|
669
|
+
* // Invalid (normalized types) - throw error:
|
|
670
|
+
* validatePaymentId('card'); // ❌ Throws error
|
|
671
|
+
* validatePaymentId('wallet'); // ❌ Throws error
|
|
672
|
+
* validatePaymentId('cash_on_delivery'); // ❌ Throws error
|
|
673
|
+
* ```
|
|
674
|
+
*
|
|
675
|
+
* @example
|
|
676
|
+
* ```typescript
|
|
677
|
+
* // Use before API calls:
|
|
678
|
+
* async function initiatePayment(cartId: string, providerId: string) {
|
|
679
|
+
* // Validate before sending to backend
|
|
680
|
+
* validatePaymentId(providerId);
|
|
681
|
+
*
|
|
682
|
+
* return await sdk.payment.initiatePaymentSession(cart, {
|
|
683
|
+
* provider_id: providerId
|
|
684
|
+
* });
|
|
685
|
+
* }
|
|
686
|
+
*
|
|
687
|
+
* // Catches bugs early:
|
|
688
|
+
* await initiatePayment(cartId, 'card');
|
|
689
|
+
* // ❌ Error: Invalid payment provider ID: 'card'.
|
|
690
|
+
* // This appears to be a normalized payment type, not a backend provider ID.
|
|
691
|
+
* // Use getBackendProviderId() to extract the correct backend ID from PaymentMethod.
|
|
692
|
+
* ```
|
|
693
|
+
*/
|
|
694
|
+
declare function validatePaymentId(id: string): void;
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Geolocation utilities
|
|
698
|
+
*
|
|
699
|
+
* Framework-agnostic helpers for proximity-based fulfillment.
|
|
700
|
+
*/
|
|
701
|
+
interface Coordinates {
|
|
702
|
+
lat: number;
|
|
703
|
+
lng: number;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Calculate distance between two coordinates using the Haversine formula.
|
|
707
|
+
* @returns Distance in kilometers
|
|
708
|
+
*/
|
|
709
|
+
declare function calculateDistance(from: Coordinates, to: Coordinates): number;
|
|
710
|
+
/**
|
|
711
|
+
* Geocode an address to coordinates.
|
|
712
|
+
*
|
|
713
|
+
* This is intentionally a best-effort approximation (city + country lookup).
|
|
714
|
+
* For production-grade accuracy, integrate a real geocoding provider.
|
|
715
|
+
*/
|
|
716
|
+
declare function geocodeAddress(address: {
|
|
717
|
+
city?: string;
|
|
718
|
+
countryCode?: string;
|
|
719
|
+
postalCode?: string;
|
|
720
|
+
}): Promise<Coordinates | null>;
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Fulfillment planner
|
|
724
|
+
*
|
|
725
|
+
* Plans an optimal fulfillment strategy for cart items given:
|
|
726
|
+
* - available stock locations
|
|
727
|
+
* - inventory levels per variant
|
|
728
|
+
* - an optional shipping address (for proximity sorting)
|
|
729
|
+
*/
|
|
730
|
+
|
|
731
|
+
interface FulfillmentGroup {
|
|
732
|
+
locationId: string;
|
|
733
|
+
locationName: string;
|
|
734
|
+
items: Array<{
|
|
735
|
+
variantId: string;
|
|
736
|
+
quantity: number;
|
|
737
|
+
productName: string;
|
|
738
|
+
}>;
|
|
739
|
+
shippingOptions: FulfillmentOption[];
|
|
740
|
+
}
|
|
741
|
+
interface FulfillmentPlan {
|
|
742
|
+
canFulfill: boolean;
|
|
743
|
+
groups: FulfillmentGroup[];
|
|
744
|
+
shippingAddress?: Coordinates;
|
|
745
|
+
}
|
|
746
|
+
interface PlanFulfillmentShippingAddress {
|
|
747
|
+
city?: string;
|
|
748
|
+
countryCode?: string;
|
|
749
|
+
postalCode?: string;
|
|
750
|
+
}
|
|
751
|
+
interface InventoryMap {
|
|
752
|
+
[variantId: string]: InventoryLevel[];
|
|
753
|
+
}
|
|
754
|
+
declare function planFulfillment(cartItems: CartItem[], stockLocations: StockLocation[], inventoryLevels: InventoryMap, shippingAddress?: PlanFulfillmentShippingAddress): Promise<FulfillmentPlan>;
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* @thorprovider/adapters v2.0
|
|
758
|
+
* Medusa Provider - Transform functions
|
|
759
|
+
*
|
|
760
|
+
* These functions convert Medusa-specific types to our unified types
|
|
761
|
+
*/
|
|
762
|
+
|
|
763
|
+
declare function transformStockLocation(raw: any): StockLocation;
|
|
764
|
+
declare function transformInventoryLevel(raw: any, locationName: string): InventoryLevel;
|
|
765
|
+
declare function transformFulfillmentOption(shippingOption: any, location: StockLocation, currencyCode: string): FulfillmentOption;
|
|
766
|
+
/**
|
|
767
|
+
* Transform backend `storefront_config` (snake_case) to `StorefrontConfig` (camelCase).
|
|
768
|
+
*
|
|
769
|
+
* Backend response shape:
|
|
770
|
+
* ```json
|
|
771
|
+
* {
|
|
772
|
+
* "id": "sfc_01J...",
|
|
773
|
+
* "sales_channel_id": "sc_01J...",
|
|
774
|
+
* "theme_accent_color": "indigo",
|
|
775
|
+
* "logo_url": "https://...",
|
|
776
|
+
* "currency_code": "EUR",
|
|
777
|
+
* "seo_defaults": { "title": "...", "description": "...", "ogImage": "..." },
|
|
778
|
+
* "created_at": "...",
|
|
779
|
+
* "updated_at": "..."
|
|
780
|
+
* }
|
|
781
|
+
* ```
|
|
782
|
+
*/
|
|
783
|
+
declare function transformStorefrontConfig(raw: any): StorefrontConfig;
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Admin Authentication Service
|
|
787
|
+
*
|
|
788
|
+
* Framework-agnostic authentication logic for admin dashboard.
|
|
789
|
+
* Uses bcryptjs for password hashing and jose for JWT operations.
|
|
790
|
+
*
|
|
791
|
+
* @remarks
|
|
792
|
+
* - L2: No Next.js imports, no env var access
|
|
793
|
+
* - Edge-compatible JWT via jose library
|
|
794
|
+
* - Password verification via bcryptjs
|
|
795
|
+
*
|
|
796
|
+
* @module admin/AdminAuthService
|
|
797
|
+
*/
|
|
798
|
+
/**
|
|
799
|
+
* Admin Auth Service
|
|
800
|
+
*
|
|
801
|
+
* Provides password verification and JWT management for admin authentication.
|
|
802
|
+
* All methods are framework-agnostic and can be used in any runtime.
|
|
803
|
+
*/
|
|
804
|
+
declare class AdminAuthService {
|
|
805
|
+
/**
|
|
806
|
+
* Verify password against bcrypt hash
|
|
807
|
+
*
|
|
808
|
+
* @param password - Plain text password from login form
|
|
809
|
+
* @param hash - Bcrypt hash stored in environment
|
|
810
|
+
* @returns true if password matches hash
|
|
811
|
+
*/
|
|
812
|
+
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
813
|
+
/**
|
|
814
|
+
* Generate a bcrypt hash for a password
|
|
815
|
+
*
|
|
816
|
+
* @param password - Plain text password
|
|
817
|
+
* @param rounds - Bcrypt cost factor (default: 10)
|
|
818
|
+
* @returns Bcrypt hash string
|
|
819
|
+
*/
|
|
820
|
+
hashPassword(password: string, rounds?: number): Promise<string>;
|
|
821
|
+
/**
|
|
822
|
+
* Generate JWT token (Edge-compatible via jose)
|
|
823
|
+
*
|
|
824
|
+
* @param payload - Token payload data
|
|
825
|
+
* @param secret - JWT secret string (min 32 chars recommended)
|
|
826
|
+
* @param expiresIn - Token expiration (default: '8h')
|
|
827
|
+
* @returns Signed JWT token string
|
|
828
|
+
*/
|
|
829
|
+
generateJWT(payload: Record<string, unknown>, secret: string, expiresIn?: string): Promise<string>;
|
|
830
|
+
/**
|
|
831
|
+
* Verify JWT token (Edge-compatible via jose)
|
|
832
|
+
*
|
|
833
|
+
* @param token - JWT token string
|
|
834
|
+
* @param secret - JWT secret string
|
|
835
|
+
* @returns Decoded payload or null if invalid/expired
|
|
836
|
+
*/
|
|
837
|
+
verifyJWT(token: string, secret: string): Promise<Record<string, unknown> | null>;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* Admin Session Service
|
|
842
|
+
*
|
|
843
|
+
* Framework-agnostic session verification for admin routes.
|
|
844
|
+
* Extracts and verifies JWT tokens from HTTP requests.
|
|
845
|
+
*
|
|
846
|
+
* @remarks
|
|
847
|
+
* - L2: No Next.js imports, no env var access
|
|
848
|
+
* - Uses standard Request API (works in Edge, Node.js, etc.)
|
|
849
|
+
* - JWT secret injected via constructor (no env var reading)
|
|
850
|
+
*
|
|
851
|
+
* @module admin/AdminSessionService
|
|
852
|
+
*/
|
|
853
|
+
/**
|
|
854
|
+
* Admin Session payload decoded from JWT
|
|
855
|
+
*/
|
|
856
|
+
interface AdminSession {
|
|
857
|
+
/** Admin user identifier */
|
|
858
|
+
adminId: string;
|
|
859
|
+
/** Token type (always 'admin') */
|
|
860
|
+
type: 'admin';
|
|
861
|
+
/** Issued at timestamp */
|
|
862
|
+
iat: number;
|
|
863
|
+
/** Expiration timestamp */
|
|
864
|
+
exp: number;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Admin Session Service
|
|
868
|
+
*
|
|
869
|
+
* Verifies admin sessions by extracting and validating JWT tokens
|
|
870
|
+
* from HTTP request cookies or Authorization headers.
|
|
871
|
+
*/
|
|
872
|
+
declare class AdminSessionService {
|
|
873
|
+
private jwtSecret;
|
|
874
|
+
private authService;
|
|
875
|
+
/**
|
|
876
|
+
* @param jwtSecret - JWT secret for token verification
|
|
877
|
+
*/
|
|
878
|
+
constructor(jwtSecret: string);
|
|
879
|
+
/**
|
|
880
|
+
* Verify admin session from HTTP request
|
|
881
|
+
*
|
|
882
|
+
* Checks for JWT token in:
|
|
883
|
+
* 1. `admin_token` cookie
|
|
884
|
+
* 2. `Authorization: Bearer <token>` header
|
|
885
|
+
*
|
|
886
|
+
* @param request - Standard HTTP Request object
|
|
887
|
+
* @returns AdminSession if valid, null otherwise
|
|
888
|
+
*/
|
|
889
|
+
verifySession(request: Request): Promise<AdminSession | null>;
|
|
890
|
+
/**
|
|
891
|
+
* Extract JWT token from request (cookie or Authorization header)
|
|
892
|
+
*/
|
|
893
|
+
private extractToken;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Metrics Calculation Service
|
|
898
|
+
*
|
|
899
|
+
* Framework-agnostic business logic for calculating dashboard metrics
|
|
900
|
+
* from raw order and product data.
|
|
901
|
+
*
|
|
902
|
+
* @remarks
|
|
903
|
+
* - L2: Pure business logic, no framework dependencies
|
|
904
|
+
* - Works with @thorprovider/types Order and Product interfaces
|
|
905
|
+
* - Stateless static methods for easy testing
|
|
906
|
+
*
|
|
907
|
+
* @module admin/MetricsService
|
|
908
|
+
*/
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Raw order data for metrics calculation
|
|
912
|
+
*
|
|
913
|
+
* @remarks
|
|
914
|
+
* Minimal interface to avoid coupling to specific Order type fields.
|
|
915
|
+
* Accepts the common fields available across all commerce providers.
|
|
916
|
+
*/
|
|
917
|
+
interface MetricsOrderInput {
|
|
918
|
+
total?: number;
|
|
919
|
+
status?: string;
|
|
920
|
+
created_at?: string;
|
|
921
|
+
createdAt?: string;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Raw product data for metrics calculation
|
|
925
|
+
*/
|
|
926
|
+
interface MetricsProductInput {
|
|
927
|
+
id: string;
|
|
928
|
+
variants?: Array<{
|
|
929
|
+
quantityAvailable?: number;
|
|
930
|
+
}>;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Metrics Service
|
|
934
|
+
*
|
|
935
|
+
* Calculates dashboard analytics from raw commerce data.
|
|
936
|
+
* All methods are static and pure (no side effects).
|
|
937
|
+
*/
|
|
938
|
+
declare class MetricsService {
|
|
939
|
+
/** Threshold for low stock alerts */
|
|
940
|
+
static readonly LOW_STOCK_THRESHOLD = 10;
|
|
941
|
+
/**
|
|
942
|
+
* Calculate complete dashboard metrics from orders and products
|
|
943
|
+
*
|
|
944
|
+
* @param orders - Array of order data
|
|
945
|
+
* @param products - Array of product data
|
|
946
|
+
* @returns Calculated DashboardMetrics
|
|
947
|
+
*/
|
|
948
|
+
static calculate(orders: MetricsOrderInput[], products: MetricsProductInput[]): DashboardMetrics;
|
|
949
|
+
/**
|
|
950
|
+
* Generate chart data for the last 7 days
|
|
951
|
+
*/
|
|
952
|
+
private static generateChartData;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* Backend Metadata Adapter Interface
|
|
957
|
+
*
|
|
958
|
+
* Framework-agnostic interface for storing configuration in backend metadata fields.
|
|
959
|
+
* This replaces the need for a separate database (SQLite/Supabase).
|
|
960
|
+
*
|
|
961
|
+
* Each backend (Medusa, Shopify, WordPress) implements this interface
|
|
962
|
+
* using their native metadata/metafields/postmeta capabilities.
|
|
963
|
+
*
|
|
964
|
+
* @module backend/BackendMetadataAdapter
|
|
965
|
+
*/
|
|
966
|
+
/**
|
|
967
|
+
* Backend Metadata Adapter
|
|
968
|
+
*
|
|
969
|
+
* @remarks
|
|
970
|
+
* Supported resource types by backend:
|
|
971
|
+
* - Medusa: `'sales_channel'`, `'customer'`, `'order'` (via admin API)
|
|
972
|
+
* - Shopify: Uses metafields API (TBD)
|
|
973
|
+
* - WordPress: Uses post_meta or user_meta (TBD)
|
|
974
|
+
*
|
|
975
|
+
* Multi-tenant channel scoping:
|
|
976
|
+
* Use with `'customer'` / `'order'` resource types and the well-known key
|
|
977
|
+
* `'sales_channel_id'` to tag entities to a specific sales channel.
|
|
978
|
+
* See `@thorprovider/adapters/metadata/channel-scope` for helper utilities.
|
|
979
|
+
*
|
|
980
|
+
* @example
|
|
981
|
+
* ```typescript
|
|
982
|
+
* // Store site configuration in Medusa sales channel metadata
|
|
983
|
+
* await adapter.setMetadata(
|
|
984
|
+
* 'sales_channel',
|
|
985
|
+
* 'sc_01HXXX',
|
|
986
|
+
* 'site_config',
|
|
987
|
+
* { version: '2026-03-25', config: {...} }
|
|
988
|
+
* );
|
|
989
|
+
*
|
|
990
|
+
* // Tag a customer to a sales channel (multi-tenant)
|
|
991
|
+
* await adapter.setMetadata(
|
|
992
|
+
* 'customer',
|
|
993
|
+
* 'cus_01HXXX',
|
|
994
|
+
* 'sales_channel_id',
|
|
995
|
+
* 'sc_01HXXX'
|
|
996
|
+
* );
|
|
997
|
+
* ```
|
|
998
|
+
*/
|
|
999
|
+
interface BackendMetadataAdapter {
|
|
1000
|
+
/**
|
|
1001
|
+
* Get metadata value from backend resource
|
|
1002
|
+
*
|
|
1003
|
+
* @param resourceType - Type of resource (`'sales_channel'` | `'customer'` | `'order'` | `'store'`)
|
|
1004
|
+
* @param resourceId - ID of the resource
|
|
1005
|
+
* @param key - Metadata key (e.g., `'site_config'`, `'sales_channel_id'`)
|
|
1006
|
+
* @returns Metadata value or null if not found
|
|
1007
|
+
*/
|
|
1008
|
+
getMetadata(resourceType: string, resourceId: string, key: string): Promise<any | null>;
|
|
1009
|
+
/**
|
|
1010
|
+
* Set metadata value on backend resource
|
|
1011
|
+
*
|
|
1012
|
+
* @param resourceType - Type of resource
|
|
1013
|
+
* @param resourceId - ID of the resource
|
|
1014
|
+
* @param key - Metadata key
|
|
1015
|
+
* @param value - Metadata value (will be JSON serialized)
|
|
1016
|
+
*/
|
|
1017
|
+
setMetadata(resourceType: string, resourceId: string, key: string, value: any): Promise<void>;
|
|
1018
|
+
/**
|
|
1019
|
+
* Delete metadata key from backend resource
|
|
1020
|
+
*
|
|
1021
|
+
* @param resourceType - Type of resource
|
|
1022
|
+
* @param resourceId - ID of the resource
|
|
1023
|
+
* @param key - Metadata key
|
|
1024
|
+
*/
|
|
1025
|
+
deleteMetadata(resourceType: string, resourceId: string, key: string): Promise<void>;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Backend Metadata Adapter Factory
|
|
1030
|
+
*
|
|
1031
|
+
* Framework-agnostic factory to create backend metadata adapters for admin/dashboard.
|
|
1032
|
+
* Keeps vendor-specific code in L2, prevents lock-in in L5.
|
|
1033
|
+
*
|
|
1034
|
+
* @remarks
|
|
1035
|
+
* This factory is distinct from the main provider factory (createProvider).
|
|
1036
|
+
* It's used for admin operations that require metadata/catalog access.
|
|
1037
|
+
* Provider types are imported from @thorprovider/types (L1) to maintain sync.
|
|
1038
|
+
*
|
|
1039
|
+
* @module backend/factory
|
|
1040
|
+
*/
|
|
1041
|
+
|
|
1042
|
+
/**
|
|
1043
|
+
* Configuration for creating a backend metadata adapter
|
|
1044
|
+
*
|
|
1045
|
+
* @remarks
|
|
1046
|
+
* Currently only 'medusa' is implemented. When adding Shopify/WooCommerce metadata adapters:
|
|
1047
|
+
* 1. Uncomment the provider type in packages/types/src/provider.ts
|
|
1048
|
+
* 2. Update this interface to accept the new provider type
|
|
1049
|
+
* 3. Implement ShopifyMetadataAdapter, WooCommerceMetadataAdapter
|
|
1050
|
+
* 4. Add cases to createBackendMetadataAdapter() switch
|
|
1051
|
+
*/
|
|
1052
|
+
interface BackendMetadataAdapterConfig {
|
|
1053
|
+
/** Backend provider type (from @thorprovider/types L1) */
|
|
1054
|
+
provider: ProviderTypeString;
|
|
1055
|
+
/** Backend base URL */
|
|
1056
|
+
baseUrl: string;
|
|
1057
|
+
/** Publishable API key (for storefront access) */
|
|
1058
|
+
publishableKey?: string;
|
|
1059
|
+
/** Enable debug logging */
|
|
1060
|
+
debug?: boolean;
|
|
1061
|
+
/**
|
|
1062
|
+
* Secret admin API key (from COMMERCE_ADMIN_API_KEY).
|
|
1063
|
+
* When provided, the metadata adapter SDK instance will send
|
|
1064
|
+
* `x-medusa-access-token` header on all admin requests.
|
|
1065
|
+
* Required for getMetadata/setMetadata to work after removing email/password auth.
|
|
1066
|
+
*/
|
|
1067
|
+
adminApiKey?: string;
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Create a backend metadata adapter (Factory Pattern)
|
|
1071
|
+
*
|
|
1072
|
+
* Keeps vendor-specific code in L2, prevents lock-in in L5.
|
|
1073
|
+
* L5 only provides configuration from env vars.
|
|
1074
|
+
*
|
|
1075
|
+
* @param config - Adapter configuration
|
|
1076
|
+
* @returns BackendMetadataAdapter instance
|
|
1077
|
+
*
|
|
1078
|
+
* @example
|
|
1079
|
+
* ```typescript
|
|
1080
|
+
* // In L5 (starters)
|
|
1081
|
+
* import { createBackendMetadataAdapter } from '@thorprovider/adapters';
|
|
1082
|
+
*
|
|
1083
|
+
* export const metadataAdapter = createBackendMetadataAdapter({
|
|
1084
|
+
* provider: process.env.NEXT_PUBLIC_COMMERCE_PROVIDER as any,
|
|
1085
|
+
* baseUrl: process.env.NEXT_PUBLIC_COMMERCE_API_URL!,
|
|
1086
|
+
* publishableKey: process.env.NEXT_PUBLIC_COMMERCE_API_KEY!,
|
|
1087
|
+
* });
|
|
1088
|
+
* ```
|
|
1089
|
+
*
|
|
1090
|
+
* @throws {Error} If provider is not supported
|
|
1091
|
+
*/
|
|
1092
|
+
declare function createBackendMetadataAdapter(config: BackendMetadataAdapterConfig): BackendMetadataAdapter;
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* Medusa Metadata Adapter
|
|
1096
|
+
*
|
|
1097
|
+
* Implementation of BackendMetadataAdapter for Medusa.js v2.
|
|
1098
|
+
* Uses Medusa's native metadata fields on sales_channel, customer, and order resources.
|
|
1099
|
+
*
|
|
1100
|
+
* Supported resource types:
|
|
1101
|
+
* - `'sales_channel'` — site config, channel-level settings
|
|
1102
|
+
* - `'customer'` — multi-tenant scoping (`sales_channel_id` key)
|
|
1103
|
+
* - `'order'` — multi-tenant scoping (`sales_channel_id` key)
|
|
1104
|
+
*
|
|
1105
|
+
* All operations require admin-level JWT authentication.
|
|
1106
|
+
*
|
|
1107
|
+
* @module backend/medusa/MedusaMetadataAdapter
|
|
1108
|
+
*/
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* Medusa Metadata Adapter
|
|
1112
|
+
*
|
|
1113
|
+
* @remarks
|
|
1114
|
+
* - Supports 'sales_channel' and 'store' resource types
|
|
1115
|
+
* - Uses Medusa admin API (requires admin token)
|
|
1116
|
+
* - Metadata is stored as JSON in the metadata field
|
|
1117
|
+
*
|
|
1118
|
+
* @example
|
|
1119
|
+
* ```typescript
|
|
1120
|
+
* const adapter = new MedusaMetadataAdapter(medusaClient);
|
|
1121
|
+
*
|
|
1122
|
+
* // Store site configuration
|
|
1123
|
+
* await adapter.setMetadata(
|
|
1124
|
+
* 'sales_channel',
|
|
1125
|
+
* 'sc_01HXXX',
|
|
1126
|
+
* 'site_config',
|
|
1127
|
+
* { version: '2026-03-25', config: {...} }
|
|
1128
|
+
* );
|
|
1129
|
+
* ```
|
|
1130
|
+
*/
|
|
1131
|
+
declare class MedusaMetadataAdapter implements BackendMetadataAdapter {
|
|
1132
|
+
private sdk;
|
|
1133
|
+
constructor(sdk: Medusa);
|
|
1134
|
+
/**
|
|
1135
|
+
* Get metadata value from Medusa resource
|
|
1136
|
+
*/
|
|
1137
|
+
getMetadata(resourceType: string, resourceId: string, key: string): Promise<any | null>;
|
|
1138
|
+
/**
|
|
1139
|
+
* Set metadata value on Medusa resource
|
|
1140
|
+
*/
|
|
1141
|
+
setMetadata(resourceType: string, resourceId: string, key: string, value: any): Promise<void>;
|
|
1142
|
+
/**
|
|
1143
|
+
* Delete metadata key from Medusa resource
|
|
1144
|
+
*
|
|
1145
|
+
* @remarks
|
|
1146
|
+
* Medusa deletes metadata keys by setting them to undefined or null
|
|
1147
|
+
*/
|
|
1148
|
+
deleteMetadata(resourceType: string, resourceId: string, key: string): Promise<void>;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Channel Scope — Backend-Agnostic Multi-Tenant Helpers
|
|
1153
|
+
*
|
|
1154
|
+
* Provides utilities for tagging, reading and filtering entity metadata by
|
|
1155
|
+
* sales-channel (or any future tenant key). Works with any backend that
|
|
1156
|
+
* exposes a writable `metadata: Record<string, unknown>` field on its
|
|
1157
|
+
* entities (Medusa, Shopify metafields, WooCommerce meta, etc.).
|
|
1158
|
+
*
|
|
1159
|
+
* ## Design decisions
|
|
1160
|
+
*
|
|
1161
|
+
* | Decision | Rationale |
|
|
1162
|
+
* |----------|-----------|
|
|
1163
|
+
* | Flat key (`sales_channel_id`) | Simpler queries, no prefix parsing required |
|
|
1164
|
+
* | Metadata, not custom fields | Zero DB migrations; works across backends |
|
|
1165
|
+
* | Pure functions | No side effects → easily testable; usable in any layer |
|
|
1166
|
+
* | `assigned_at` timestamp | Audit trail for dropshipper / admin assignment |
|
|
1167
|
+
*
|
|
1168
|
+
* @module metadata/channel-scope
|
|
1169
|
+
*/
|
|
1170
|
+
/**
|
|
1171
|
+
* Well-known metadata key used to store the owning sales-channel on any
|
|
1172
|
+
* entity that Medusa (or the backend) does not natively scope.
|
|
1173
|
+
*
|
|
1174
|
+
* Convention: every entity whose metadata contains this key is
|
|
1175
|
+
* considered "owned" by the referenced channel. Entities without it
|
|
1176
|
+
* are global / unscoped.
|
|
1177
|
+
*/
|
|
1178
|
+
declare const CHANNEL_SCOPE_KEY: "sales_channel_id";
|
|
1179
|
+
/**
|
|
1180
|
+
* Optional audit key — ISO-8601 timestamp of when the channel was assigned.
|
|
1181
|
+
*/
|
|
1182
|
+
declare const CHANNEL_ASSIGNED_AT_KEY: "channel_assigned_at";
|
|
1183
|
+
/**
|
|
1184
|
+
* Optional audit key — who assigned the entity to the channel.
|
|
1185
|
+
* Value is a free-form string (admin email, user id, "system", etc.).
|
|
1186
|
+
*/
|
|
1187
|
+
declare const CHANNEL_ASSIGNED_BY_KEY: "channel_assigned_by";
|
|
1188
|
+
/**
|
|
1189
|
+
* Minimal shape any entity must satisfy in order to participate in
|
|
1190
|
+
* channel-scope filtering. Compatible with @thorprovider/types Customer,
|
|
1191
|
+
* Order, ProductCategory, etc.
|
|
1192
|
+
*/
|
|
1193
|
+
interface ChannelScopeable {
|
|
1194
|
+
id: string;
|
|
1195
|
+
metadata?: Record<string, unknown>;
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Payload produced by `buildChannelScopeMetadata()`.
|
|
1199
|
+
* Can be spread directly into an `updateCustomer` / `updateOrder` call.
|
|
1200
|
+
*/
|
|
1201
|
+
interface ChannelScopeMetadata {
|
|
1202
|
+
[CHANNEL_SCOPE_KEY]: string;
|
|
1203
|
+
[CHANNEL_ASSIGNED_AT_KEY]: string;
|
|
1204
|
+
[CHANNEL_ASSIGNED_BY_KEY]?: string;
|
|
1205
|
+
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Build channel-scope metadata payload.
|
|
1208
|
+
*
|
|
1209
|
+
* The returned object should be **merged** into the entity's existing
|
|
1210
|
+
* `metadata` field when calling `updateCustomer`, `updateOrder`, etc.
|
|
1211
|
+
*
|
|
1212
|
+
* @param channelId - Sales-channel ID (e.g. `"sc_01HXXX"`)
|
|
1213
|
+
* @param assignedBy - Optional identifier of who performed the assignment
|
|
1214
|
+
* @returns Metadata fragment ready to spread into an update payload
|
|
1215
|
+
*
|
|
1216
|
+
* @example
|
|
1217
|
+
* ```typescript
|
|
1218
|
+
* const scope = buildChannelScopeMetadata('sc_01HXXX', 'admin@store.com');
|
|
1219
|
+
* await commerce.updateCustomer(customerId, {
|
|
1220
|
+
* metadata: { ...existingMeta, ...scope },
|
|
1221
|
+
* });
|
|
1222
|
+
* ```
|
|
1223
|
+
*/
|
|
1224
|
+
declare function buildChannelScopeMetadata(channelId: string, assignedBy?: string): ChannelScopeMetadata;
|
|
1225
|
+
/**
|
|
1226
|
+
* Read the channel-scope value from an entity's metadata.
|
|
1227
|
+
*
|
|
1228
|
+
* @returns The channel ID string, or `null` if the entity has no scope set.
|
|
1229
|
+
*/
|
|
1230
|
+
declare function getChannelScope(entity: ChannelScopeable): string | null;
|
|
1231
|
+
/**
|
|
1232
|
+
* Check if an entity is scoped to a specific channel.
|
|
1233
|
+
*
|
|
1234
|
+
* @param entity - Any entity with optional `metadata`
|
|
1235
|
+
* @param channelId - Channel ID to match against
|
|
1236
|
+
* @returns `true` if entity's metadata contains a matching scope key
|
|
1237
|
+
*/
|
|
1238
|
+
declare function isScopedToChannel(entity: ChannelScopeable, channelId: string): boolean;
|
|
1239
|
+
/**
|
|
1240
|
+
* Check if an entity has **no** channel scope (i.e. it is "global").
|
|
1241
|
+
*/
|
|
1242
|
+
declare function isGlobalEntity(entity: ChannelScopeable): boolean;
|
|
1243
|
+
/**
|
|
1244
|
+
* Filter an array of entities to only those belonging to a channel.
|
|
1245
|
+
*
|
|
1246
|
+
* If `channelId` is `undefined` or empty, returns the full array unfiltered.
|
|
1247
|
+
* This preserves backward compatibility for admin views that intentionally
|
|
1248
|
+
* list all entities regardless of tenant.
|
|
1249
|
+
*
|
|
1250
|
+
* @param entities - Array of channel-scopeable entities
|
|
1251
|
+
* @param channelId - Optional channel ID to filter by
|
|
1252
|
+
* @returns Filtered (or unfiltered) array
|
|
1253
|
+
*
|
|
1254
|
+
* @example
|
|
1255
|
+
* ```typescript
|
|
1256
|
+
* const allCustomers = await commerce.getCustomers();
|
|
1257
|
+
* const myCustomers = filterByChannel(allCustomers, salesChannelId);
|
|
1258
|
+
* ```
|
|
1259
|
+
*/
|
|
1260
|
+
declare function filterByChannel<T extends ChannelScopeable>(entities: T[], channelId?: string): T[];
|
|
1261
|
+
/**
|
|
1262
|
+
* Filter an array of entities to only those that are global (unscoped).
|
|
1263
|
+
*
|
|
1264
|
+
* Useful for admin views that want to list entities not yet assigned to
|
|
1265
|
+
* any channel.
|
|
1266
|
+
*/
|
|
1267
|
+
declare function filterGlobalOnly<T extends ChannelScopeable>(entities: T[]): T[];
|
|
1268
|
+
/**
|
|
1269
|
+
* Partition entities into `{ scoped, global }` groups.
|
|
1270
|
+
*
|
|
1271
|
+
* @param entities - Array of channel-scopeable entities
|
|
1272
|
+
* @param channelId - Channel ID to partition against
|
|
1273
|
+
* @returns Object with `scoped` (matching channel) and `global` (no scope) arrays
|
|
1274
|
+
*
|
|
1275
|
+
* @example
|
|
1276
|
+
* ```typescript
|
|
1277
|
+
* const { scoped, global } = partitionByChannel(customers, 'sc_123');
|
|
1278
|
+
* // scoped → customers assigned to sc_123
|
|
1279
|
+
* // global → customers not assigned to any channel
|
|
1280
|
+
* ```
|
|
1281
|
+
*/
|
|
1282
|
+
declare function partitionByChannel<T extends ChannelScopeable>(entities: T[], channelId: string): {
|
|
1283
|
+
scoped: T[];
|
|
1284
|
+
global: T[];
|
|
1285
|
+
};
|
|
1286
|
+
|
|
1287
|
+
/**
|
|
1288
|
+
* Channel Scope Validation — Pure TypeScript (no external deps)
|
|
1289
|
+
*
|
|
1290
|
+
* Validates channel-scope metadata before it is written to the backend.
|
|
1291
|
+
* Keeps all validation logic in L2 so that L5 starters don't duplicate checks.
|
|
1292
|
+
*
|
|
1293
|
+
* @module metadata/channel-scope-validation
|
|
1294
|
+
*/
|
|
1295
|
+
|
|
1296
|
+
/**
|
|
1297
|
+
* Thrown when channel-scope validation fails.
|
|
1298
|
+
*
|
|
1299
|
+
* Consumers can catch this specific type to provide user-friendly feedback
|
|
1300
|
+
* without leaking internal details.
|
|
1301
|
+
*/
|
|
1302
|
+
declare class ChannelScopeValidationError extends Error {
|
|
1303
|
+
readonly field: string;
|
|
1304
|
+
readonly value: unknown;
|
|
1305
|
+
constructor(message: string, field: string, value?: unknown);
|
|
1306
|
+
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Validate that a channel ID is a non-empty string.
|
|
1309
|
+
*
|
|
1310
|
+
* Does **not** enforce a specific prefix (e.g. `"sc_"`) because different
|
|
1311
|
+
* backends use different conventions:
|
|
1312
|
+
* - Medusa: `"sc_01HXXX"`
|
|
1313
|
+
* - Shopify: `"gid://shopify/Channel/789"`
|
|
1314
|
+
* - WooCommerce: `"1"` (numeric string)
|
|
1315
|
+
*
|
|
1316
|
+
* @throws {ChannelScopeValidationError}
|
|
1317
|
+
*/
|
|
1318
|
+
declare function validateChannelId(channelId: unknown): asserts channelId is string;
|
|
1319
|
+
/**
|
|
1320
|
+
* Validate that an entity ID is a non-empty string.
|
|
1321
|
+
*
|
|
1322
|
+
* @throws {ChannelScopeValidationError}
|
|
1323
|
+
*/
|
|
1324
|
+
declare function validateEntityId(entityId: unknown, label?: string): asserts entityId is string;
|
|
1325
|
+
/**
|
|
1326
|
+
* Validate that the `assignedBy` value (if provided) is a reasonable string.
|
|
1327
|
+
*
|
|
1328
|
+
* @throws {ChannelScopeValidationError}
|
|
1329
|
+
*/
|
|
1330
|
+
declare function validateAssignedBy(assignedBy: unknown): asserts assignedBy is string | undefined;
|
|
1331
|
+
/**
|
|
1332
|
+
* Full validation for a channel-scope assignment operation.
|
|
1333
|
+
*
|
|
1334
|
+
* Call before writing channel scope metadata to any entity.
|
|
1335
|
+
*
|
|
1336
|
+
* @throws {ChannelScopeValidationError} with descriptive field + value
|
|
1337
|
+
*
|
|
1338
|
+
* @example
|
|
1339
|
+
* ```typescript
|
|
1340
|
+
* validateChannelScopeAssignment('cus_123', 'sc_01HXXX', 'admin@store.com');
|
|
1341
|
+
* // If no error, safe to proceed
|
|
1342
|
+
* ```
|
|
1343
|
+
*/
|
|
1344
|
+
declare function validateChannelScopeAssignment(entityId: string, channelId: string, assignedBy?: string): void;
|
|
1345
|
+
/**
|
|
1346
|
+
* Validate that an entity is currently scoped to the expected channel.
|
|
1347
|
+
*
|
|
1348
|
+
* Useful as a guard before performing operations that should only
|
|
1349
|
+
* affect entities within the caller's channel (e.g. a dropshipper editing
|
|
1350
|
+
* a customer that must belong to their channel).
|
|
1351
|
+
*
|
|
1352
|
+
* @throws {ChannelScopeValidationError} if entity does not belong to expectedChannelId
|
|
1353
|
+
*/
|
|
1354
|
+
declare function assertEntityBelongsToChannel(entity: ChannelScopeable, expectedChannelId: string): void;
|
|
1355
|
+
|
|
1356
|
+
/**
|
|
1357
|
+
* Medusa provider configuration
|
|
1358
|
+
*/
|
|
1359
|
+
interface MedusaProviderConfig extends ProviderConfig {
|
|
1360
|
+
/**
|
|
1361
|
+
* Medusa backend URL
|
|
1362
|
+
*/
|
|
1363
|
+
baseUrl: string;
|
|
1364
|
+
/**
|
|
1365
|
+
* Publishable API key (for storefront access)
|
|
1366
|
+
*/
|
|
1367
|
+
publishableKey: string;
|
|
1368
|
+
/**
|
|
1369
|
+
* Default currency code (default: USD)
|
|
1370
|
+
*/
|
|
1371
|
+
/**
|
|
1372
|
+
* Default currency code (default: USD)
|
|
1373
|
+
*/
|
|
1374
|
+
currencyCode?: string;
|
|
1375
|
+
/**
|
|
1376
|
+
* Region ID (optional, will use default region if not provided)
|
|
1377
|
+
*/
|
|
1378
|
+
regionId?: string;
|
|
1379
|
+
/**
|
|
1380
|
+
* Authentication configuration (optional)
|
|
1381
|
+
* If not provided, auth methods will not be available
|
|
1382
|
+
*/
|
|
1383
|
+
auth?: AuthConfig;
|
|
1384
|
+
/**
|
|
1385
|
+
* Retry configuration for fetch requests (optional)
|
|
1386
|
+
* Configure automatic retries, timeouts, and backoff strategy
|
|
1387
|
+
*
|
|
1388
|
+
* @example
|
|
1389
|
+
* ```typescript
|
|
1390
|
+
* {
|
|
1391
|
+
* maxRetries: 3, // Retry up to 3 times
|
|
1392
|
+
* timeoutMs: 10000, // 10 second timeout per request
|
|
1393
|
+
* initialDelayMs: 300, // Start with 300ms delay
|
|
1394
|
+
* }
|
|
1395
|
+
* ```
|
|
1396
|
+
*/
|
|
1397
|
+
retry?: RetryConfig;
|
|
1398
|
+
/**
|
|
1399
|
+
* Admin API configuration (optional).
|
|
1400
|
+
* Required for inventory operations (stock locations, inventory levels).
|
|
1401
|
+
* When not provided, admin-only methods will throw with a descriptive error.
|
|
1402
|
+
*/
|
|
1403
|
+
adminConfig?: {
|
|
1404
|
+
/**
|
|
1405
|
+
* Secret API key created in Medusa Admin → Settings → API Keys → Secret.
|
|
1406
|
+
* Sent as `x-medusa-access-token` on every request of the dedicated admin SDK instance.
|
|
1407
|
+
* Never use a Publishable key here.
|
|
1408
|
+
*/
|
|
1409
|
+
apiKey: string;
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
/**
|
|
1413
|
+
* Medusa commerce provider
|
|
1414
|
+
*
|
|
1415
|
+
* Implements CommerceProvider interface for Medusa.js v2
|
|
1416
|
+
*/
|
|
1417
|
+
declare class MedusaProvider implements CommerceProvider {
|
|
1418
|
+
readonly name = "medusa";
|
|
1419
|
+
readonly version = "2.0.0";
|
|
1420
|
+
/**
|
|
1421
|
+
* Medusa backend capabilities.
|
|
1422
|
+
* Starts with static defaults, replaced by dynamic values from
|
|
1423
|
+
* `GET /store/thor/capabilities` once the fetch completes.
|
|
1424
|
+
*/
|
|
1425
|
+
private _dynamicCapabilities;
|
|
1426
|
+
/** Promise that resolves when capabilities fetch completes (success or failure) */
|
|
1427
|
+
private _capabilitiesPromise;
|
|
1428
|
+
/**
|
|
1429
|
+
* Getter returns dynamic capabilities if available, otherwise static fallback.
|
|
1430
|
+
*/
|
|
1431
|
+
get capabilities(): BackendCapabilities;
|
|
1432
|
+
private sdk;
|
|
1433
|
+
private logger;
|
|
1434
|
+
private currencyCode;
|
|
1435
|
+
private retryConfig;
|
|
1436
|
+
private baseUrl;
|
|
1437
|
+
private publishableKey;
|
|
1438
|
+
/** Secret API key for admin operations (if configured). */
|
|
1439
|
+
private adminApiKey?;
|
|
1440
|
+
/**
|
|
1441
|
+
* Dedicated SDK instance for admin calls.
|
|
1442
|
+
* Separate from `this.sdk` to prevent the admin API key from being overwritten
|
|
1443
|
+
* by customer JWT tokens set during storefront authentication.
|
|
1444
|
+
* Only created when adminConfig.apiKey is provided.
|
|
1445
|
+
*/
|
|
1446
|
+
private sdkAdmin?;
|
|
1447
|
+
/** Cached distinct product status values — rarely changes, cached for process lifetime */
|
|
1448
|
+
private _cachedProductStatuses;
|
|
1449
|
+
/**
|
|
1450
|
+
* In-memory cache for region countries
|
|
1451
|
+
* Structure: Map<regionId, { countries: Country[], expiresAt: number }>
|
|
1452
|
+
*/
|
|
1453
|
+
private regionCountriesCache;
|
|
1454
|
+
/**
|
|
1455
|
+
* Cache TTL for region countries (5 minutes)
|
|
1456
|
+
*/
|
|
1457
|
+
private readonly REGION_COUNTRIES_CACHE_TTL;
|
|
1458
|
+
/**
|
|
1459
|
+
* In-memory cache for storefront context (60 second TTL)
|
|
1460
|
+
*/
|
|
1461
|
+
private storefrontContextCache;
|
|
1462
|
+
/**
|
|
1463
|
+
* Cache TTL for storefront context (60 seconds)
|
|
1464
|
+
*/
|
|
1465
|
+
private readonly STOREFRONT_CONTEXT_CACHE_TTL;
|
|
1466
|
+
/**
|
|
1467
|
+
* Authentication provider (available if auth config is provided)
|
|
1468
|
+
*/
|
|
1469
|
+
readonly auth?: AuthProvider;
|
|
1470
|
+
private retrieveCartWithLineDetails;
|
|
1471
|
+
constructor(config: MedusaProviderConfig);
|
|
1472
|
+
/**
|
|
1473
|
+
* Fetch capabilities dynamically from `GET /store/thor/capabilities`.
|
|
1474
|
+
* Non-blocking — called in constructor. On failure, static fallback is used.
|
|
1475
|
+
* Cache: process-lifetime (per provider instance).
|
|
1476
|
+
*/
|
|
1477
|
+
private _fetchCapabilities;
|
|
1478
|
+
/**
|
|
1479
|
+
* Wrapper for SDK calls with retry logic
|
|
1480
|
+
* Handles network failures and temporary backend issues
|
|
1481
|
+
*/
|
|
1482
|
+
private withRetry;
|
|
1483
|
+
getProduct(handle: string, options?: {
|
|
1484
|
+
regionId?: string;
|
|
1485
|
+
}): Promise<Product | undefined>;
|
|
1486
|
+
getProducts(options?: GetProductsOptions & {
|
|
1487
|
+
regionId?: string;
|
|
1488
|
+
}): Promise<Product[]>;
|
|
1489
|
+
getProductRecommendations(productId: string): Promise<Product[]>;
|
|
1490
|
+
/**
|
|
1491
|
+
* Advanced product search using /store/search endpoint
|
|
1492
|
+
*
|
|
1493
|
+
* Uses hybrid MeiliSearch + Qdrant search with advanced filtering:
|
|
1494
|
+
* - Price range filtering
|
|
1495
|
+
* - Stock availability
|
|
1496
|
+
* - Custom product attributes
|
|
1497
|
+
*
|
|
1498
|
+
* Falls back to getProducts() if advanced search fails
|
|
1499
|
+
*/
|
|
1500
|
+
searchProductsAdvanced(options?: AdvancedSearchProductsOptions): Promise<{
|
|
1501
|
+
products: Product[];
|
|
1502
|
+
meta?: SearchResultMeta;
|
|
1503
|
+
}>;
|
|
1504
|
+
/**
|
|
1505
|
+
* Get available filter options for product filtering
|
|
1506
|
+
*
|
|
1507
|
+
* Aggregates filters from:
|
|
1508
|
+
* - Basic filters: categories, collections (always available)
|
|
1509
|
+
* - Advanced filters: price range, stock (if useAdvancedSearch=true)
|
|
1510
|
+
* - Custom attributes: category-specific attributes from backend
|
|
1511
|
+
*
|
|
1512
|
+
* Returns empty array if backend doesn't support dynamic filters
|
|
1513
|
+
*/
|
|
1514
|
+
getAvailableFilters(options: {
|
|
1515
|
+
categoryId?: string;
|
|
1516
|
+
useAdvancedSearch?: boolean;
|
|
1517
|
+
includeBasicFilters?: boolean;
|
|
1518
|
+
includeFacetCounts?: boolean;
|
|
1519
|
+
}): Promise<FilterConfig[]>;
|
|
1520
|
+
/**
|
|
1521
|
+
* Convert a human-readable string to a URL-safe slug.
|
|
1522
|
+
* Used to produce SEO-friendly filter values (option.value) that go into the URL.
|
|
1523
|
+
*
|
|
1524
|
+
* Examples:
|
|
1525
|
+
* "8GB RAM" → "8gb-ram"
|
|
1526
|
+
* "Red Color" → "red-color"
|
|
1527
|
+
* "16 GB" → "16-gb"
|
|
1528
|
+
*/
|
|
1529
|
+
private toSlug;
|
|
1530
|
+
/**
|
|
1531
|
+
* Map backend attribute type to filter type
|
|
1532
|
+
*/
|
|
1533
|
+
private mapAttributeTypeToFilterType;
|
|
1534
|
+
getCollection(handle: string): Promise<Collection | undefined>;
|
|
1535
|
+
getCollections(options?: GetCollectionsOptions): Promise<Collection[]>;
|
|
1536
|
+
getCollectionProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
1537
|
+
getCategory(idOrHandle: string): Promise<ProductCategory | undefined>;
|
|
1538
|
+
/**
|
|
1539
|
+
* Returns the set of product-category IDs that have at least one product
|
|
1540
|
+
* available in the given sales channel.
|
|
1541
|
+
*
|
|
1542
|
+
* Because Medusa's store/product-categories endpoint does not accept a
|
|
1543
|
+
* `sales_channel_id` filter, we derive the active category IDs by querying
|
|
1544
|
+
* store/products with the sales-channel scope and collecting the category
|
|
1545
|
+
* relations from the response. Pagination is handled internally so the
|
|
1546
|
+
* result is always complete regardless of catalog size.
|
|
1547
|
+
*
|
|
1548
|
+
* @deprecated Use `_getChannelCategories()` instead (backed by Thor Commerce plugin).
|
|
1549
|
+
* Kept as fallback for backends without the plugin installed.
|
|
1550
|
+
*/
|
|
1551
|
+
private _getActiveCategoryIds;
|
|
1552
|
+
/**
|
|
1553
|
+
* Fetch channel-scoped categories from Thor Commerce plugin.
|
|
1554
|
+
* Uses `GET /store/thor/categories` — a single indexed query.
|
|
1555
|
+
* Falls back to `_getActiveCategoryIds()` if the plugin is not available.
|
|
1556
|
+
*/
|
|
1557
|
+
private _getChannelCategories;
|
|
1558
|
+
getCategories(options?: GetCategoriesOptions): Promise<ProductCategory[]>;
|
|
1559
|
+
getCategoryProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
1560
|
+
createCart(options?: {
|
|
1561
|
+
regionId?: string;
|
|
1562
|
+
}): Promise<Cart>;
|
|
1563
|
+
getCart(cartId: string): Promise<Cart | undefined>;
|
|
1564
|
+
addToCart(cartId: string, lines: CartLineInput[]): Promise<Cart>;
|
|
1565
|
+
removeFromCart(cartId: string, lineIds: string[]): Promise<Cart>;
|
|
1566
|
+
updateCart(cartId: string, lines: CartLineUpdate[]): Promise<Cart>;
|
|
1567
|
+
/**
|
|
1568
|
+
* Get available regions from Medusa
|
|
1569
|
+
* Returns region information including id, name, and currency
|
|
1570
|
+
*/
|
|
1571
|
+
getRegions(): Promise<Array<{
|
|
1572
|
+
id: string;
|
|
1573
|
+
name: string;
|
|
1574
|
+
currency_code: string;
|
|
1575
|
+
countries?: Array<{
|
|
1576
|
+
id: string;
|
|
1577
|
+
iso_2: string;
|
|
1578
|
+
name: string;
|
|
1579
|
+
display_name?: string;
|
|
1580
|
+
}>;
|
|
1581
|
+
}>>;
|
|
1582
|
+
/**
|
|
1583
|
+
* Get all orders for a customer (storefront).
|
|
1584
|
+
*
|
|
1585
|
+
* Note: This retrieves orders from the storefront API (store.order.list),
|
|
1586
|
+
* which returns orders only for the authenticated customer in the JWT.
|
|
1587
|
+
*
|
|
1588
|
+
* @param options - Order query options (supports callbacks for custom backends)
|
|
1589
|
+
* @returns Array of orders for the authenticated customer
|
|
1590
|
+
*
|
|
1591
|
+
* @example
|
|
1592
|
+
* ```typescript
|
|
1593
|
+
* const orders = await provider.getOrders();
|
|
1594
|
+
* console.log(`Found ${orders.length} orders`);
|
|
1595
|
+
* ```
|
|
1596
|
+
*/
|
|
1597
|
+
getOrders(options?: GetOrdersOptions): Promise<Order[]>;
|
|
1598
|
+
/**
|
|
1599
|
+
* Get a single order by ID
|
|
1600
|
+
*
|
|
1601
|
+
* @param orderId - Order ID
|
|
1602
|
+
* @returns Order or undefined if not found
|
|
1603
|
+
*
|
|
1604
|
+
* @example
|
|
1605
|
+
* ```typescript
|
|
1606
|
+
* const order = await provider.getOrder('order_123');
|
|
1607
|
+
* if (order) {
|
|
1608
|
+
* console.log(`Order ${order.orderNumber} - ${order.status}`);
|
|
1609
|
+
* }
|
|
1610
|
+
* ```
|
|
1611
|
+
*/
|
|
1612
|
+
getOrder(orderId: string): Promise<Order | undefined>;
|
|
1613
|
+
/**
|
|
1614
|
+
* List customers with optional filtering and pagination.
|
|
1615
|
+
*
|
|
1616
|
+
* Uses the Medusa admin API — requires admin-level JWT.
|
|
1617
|
+
*
|
|
1618
|
+
* @param options - Query options (search, sort, pagination)
|
|
1619
|
+
* @returns Array of customers
|
|
1620
|
+
*
|
|
1621
|
+
* @example
|
|
1622
|
+
* ```typescript
|
|
1623
|
+
* const customers = await provider.getCustomers({ search: 'john', limit: 20, offset: 0 });
|
|
1624
|
+
* ```
|
|
1625
|
+
*/
|
|
1626
|
+
getCustomers(options?: GetCustomersOptions): Promise<Customer[]>;
|
|
1627
|
+
/**
|
|
1628
|
+
* Get a single customer by ID.
|
|
1629
|
+
*
|
|
1630
|
+
* Uses the Medusa admin API.
|
|
1631
|
+
*
|
|
1632
|
+
* @param customerId - Customer ID
|
|
1633
|
+
* @returns Customer or undefined if not found
|
|
1634
|
+
*/
|
|
1635
|
+
getCustomer(customerId: string): Promise<Customer | undefined>;
|
|
1636
|
+
/**
|
|
1637
|
+
* Update customer information.
|
|
1638
|
+
*
|
|
1639
|
+
* Uses the Medusa admin API.
|
|
1640
|
+
*
|
|
1641
|
+
* @param customerId - Customer ID
|
|
1642
|
+
* @param data - Fields to update
|
|
1643
|
+
* @returns Updated customer
|
|
1644
|
+
*/
|
|
1645
|
+
updateCustomer(customerId: string, data: Partial<Omit<Customer, 'id' | 'createdAt'>>): Promise<Customer>;
|
|
1646
|
+
/**
|
|
1647
|
+
* Get orders placed by a specific customer (admin view).
|
|
1648
|
+
*
|
|
1649
|
+
* @param customerId - Customer ID
|
|
1650
|
+
* @param limit - Max number of orders (default: 10)
|
|
1651
|
+
* @returns Array of orders
|
|
1652
|
+
*/
|
|
1653
|
+
getCustomerOrders(customerId: string, limit?: number): Promise<Order[]>;
|
|
1654
|
+
/**
|
|
1655
|
+
* List customers for admin dashboard.
|
|
1656
|
+
*
|
|
1657
|
+
* Uses makeAdminRequest() to ensure proper admin authentication.
|
|
1658
|
+
* Unlike getCustomers() (which currently lacks admin auth), this method
|
|
1659
|
+
* properly awaits admin initialization and authenticates via SDK admin session.
|
|
1660
|
+
*
|
|
1661
|
+
* Gracefully degrades to empty result when adminConfig is not provided.
|
|
1662
|
+
*
|
|
1663
|
+
* @param options - Query options (search, limit, offset, salesChannelId)
|
|
1664
|
+
* @returns Object with customers array and count
|
|
1665
|
+
*/
|
|
1666
|
+
getAdminCustomers(options?: {
|
|
1667
|
+
search?: string;
|
|
1668
|
+
limit?: number;
|
|
1669
|
+
offset?: number;
|
|
1670
|
+
salesChannelId?: string;
|
|
1671
|
+
}): Promise<{
|
|
1672
|
+
customers: Customer[];
|
|
1673
|
+
count: number;
|
|
1674
|
+
}>;
|
|
1675
|
+
/**
|
|
1676
|
+
* Get a single customer by ID for admin dashboard.
|
|
1677
|
+
*
|
|
1678
|
+
* Uses makeAdminRequest() for proper admin authentication.
|
|
1679
|
+
* Returns undefined (not an error) when the customer is not found (404).
|
|
1680
|
+
*
|
|
1681
|
+
* @param customerId - Customer ID
|
|
1682
|
+
* @returns Customer or undefined if not found
|
|
1683
|
+
*/
|
|
1684
|
+
getAdminCustomer(customerId: string): Promise<Customer | undefined>;
|
|
1685
|
+
/**
|
|
1686
|
+
* Get all addresses for a customer (admin operation).
|
|
1687
|
+
* Uses sdk.admin.customer.listAddresses() for proper admin authentication.
|
|
1688
|
+
*
|
|
1689
|
+
* @param customerId - The customer's ID
|
|
1690
|
+
* @returns Array of addresses
|
|
1691
|
+
*/
|
|
1692
|
+
getAdminCustomerAddresses(customerId: string): Promise<Address[]>;
|
|
1693
|
+
/**
|
|
1694
|
+
* Get all orders for admin dashboard listing.
|
|
1695
|
+
*
|
|
1696
|
+
* Unlike getCustomerOrders() (which filters by a specific customerId via
|
|
1697
|
+
* sdk.admin.order.list with storefront JWT), this method:
|
|
1698
|
+
* - Lists ALL orders across the store
|
|
1699
|
+
* - Uses fetchAdminAPI() with proper admin credentials
|
|
1700
|
+
* - Applies multi-tenant channel scoping via filterByChannel()
|
|
1701
|
+
* - Gracefully degrades to empty result when adminConfig is not provided
|
|
1702
|
+
*
|
|
1703
|
+
* IMPORTANT: Do NOT use sdk.admin.order.list() here — it uses storefront
|
|
1704
|
+
* JWT auth which is insufficient for Medusa Admin API.
|
|
1705
|
+
*/
|
|
1706
|
+
getAdminOrders(options?: {
|
|
1707
|
+
search?: string;
|
|
1708
|
+
status?: string | string[];
|
|
1709
|
+
limit?: number;
|
|
1710
|
+
offset?: number;
|
|
1711
|
+
/** Medusa field name for sorting, e.g. 'created_at', 'total' */
|
|
1712
|
+
order?: string;
|
|
1713
|
+
direction?: 'asc' | 'desc';
|
|
1714
|
+
/** Filter by sales channel — uses Medusa native `sales_channel_id` query. */
|
|
1715
|
+
salesChannelId?: string;
|
|
1716
|
+
/**
|
|
1717
|
+
* When true, also fetches draft orders from /admin/draft-orders and merges
|
|
1718
|
+
* them into the result sorted by created_at desc. Draft orders are stored
|
|
1719
|
+
* as a separate entity from regular orders in Medusa v2 and do NOT appear
|
|
1720
|
+
* in GET /admin/orders.
|
|
1721
|
+
*/
|
|
1722
|
+
includeDrafts?: boolean;
|
|
1723
|
+
}): Promise<{
|
|
1724
|
+
orders: Order[];
|
|
1725
|
+
count: number;
|
|
1726
|
+
}>;
|
|
1727
|
+
/**
|
|
1728
|
+
* Cancel an order (admin operation).
|
|
1729
|
+
* Uses sdk.admin.order.cancel() for proper SDK integration.
|
|
1730
|
+
* Throws ProviderAPIError if adminConfig is not provided.
|
|
1731
|
+
*/
|
|
1732
|
+
cancelOrder(orderId: string): Promise<Order>;
|
|
1733
|
+
/**
|
|
1734
|
+
* Create a fulfillment for an order (admin operation).
|
|
1735
|
+
* Uses sdk.admin.order.createFulfillment() for proper SDK integration.
|
|
1736
|
+
* Throws ProviderAPIError if adminConfig is not provided.
|
|
1737
|
+
*
|
|
1738
|
+
* @param items - Optional specific line-items + quantities.
|
|
1739
|
+
* When omitted, Medusa fulfills all unfulfilled items.
|
|
1740
|
+
*/
|
|
1741
|
+
createFulfillment(orderId: string, items?: Array<{
|
|
1742
|
+
id: string;
|
|
1743
|
+
quantity: number;
|
|
1744
|
+
}>): Promise<void>;
|
|
1745
|
+
/**
|
|
1746
|
+
* Create a refund for an order (admin operation).
|
|
1747
|
+
*
|
|
1748
|
+
* Uses fetchAdminAPI() — NOT sdk.admin.refund.create().
|
|
1749
|
+
* Throws ProviderAPIError if adminConfig is not provided.
|
|
1750
|
+
*
|
|
1751
|
+
* @param amount - Amount in cents. Omit to refund the full order total.
|
|
1752
|
+
* @param reason - Reason string (default: 'admin_refund').
|
|
1753
|
+
*/
|
|
1754
|
+
createRefund(orderId: string, amount?: number, reason?: string): Promise<void>;
|
|
1755
|
+
/**
|
|
1756
|
+
* List all regions for admin dashboard (used in Create Order dialog).
|
|
1757
|
+
*
|
|
1758
|
+
* Returns Region[] compatible with CommerceProvider contract.
|
|
1759
|
+
* Maps Medusa's currency_code → currency and provides empty countryCodes array
|
|
1760
|
+
* when country detail is not required for the admin region picker.
|
|
1761
|
+
*/
|
|
1762
|
+
getAdminRegions(): Promise<Region[]>;
|
|
1763
|
+
/**
|
|
1764
|
+
* Get a single order by ID for admin dashboard detail view.
|
|
1765
|
+
*
|
|
1766
|
+
* Uses makeAdminRequest() for proper admin authentication.
|
|
1767
|
+
* Returns full order with items, addresses, customer.
|
|
1768
|
+
*
|
|
1769
|
+
* @returns Order or undefined if not found
|
|
1770
|
+
*/
|
|
1771
|
+
getAdminOrder(orderId: string): Promise<Order | undefined>;
|
|
1772
|
+
/**
|
|
1773
|
+
* Get a single product by ID for admin dashboard detail view.
|
|
1774
|
+
*
|
|
1775
|
+
* Uses makeAdminRequest() for proper admin authentication.
|
|
1776
|
+
* Returns full product with variants and prices.
|
|
1777
|
+
*
|
|
1778
|
+
* @returns AdminProduct or undefined if not found
|
|
1779
|
+
*/
|
|
1780
|
+
getAdminProduct(productId: string): Promise<AdminProduct | undefined>;
|
|
1781
|
+
/**
|
|
1782
|
+
* Create a draft order.
|
|
1783
|
+
*
|
|
1784
|
+
* Uses Medusa v2 `sdk.admin.draftOrder.create()` API.
|
|
1785
|
+
* Draft orders have `is_draft_order = true` and can be converted to regular orders.
|
|
1786
|
+
*
|
|
1787
|
+
* @param params - Draft order parameters
|
|
1788
|
+
* @returns Created draft order as a transformed Order
|
|
1789
|
+
*/
|
|
1790
|
+
createDraftOrder(params: {
|
|
1791
|
+
email: string;
|
|
1792
|
+
regionId: string;
|
|
1793
|
+
salesChannelId?: string;
|
|
1794
|
+
items: Array<{
|
|
1795
|
+
variantId: string;
|
|
1796
|
+
quantity: number;
|
|
1797
|
+
}>;
|
|
1798
|
+
shippingAddress?: {
|
|
1799
|
+
firstName?: string;
|
|
1800
|
+
lastName?: string;
|
|
1801
|
+
address1?: string;
|
|
1802
|
+
city?: string;
|
|
1803
|
+
countryCode?: string;
|
|
1804
|
+
postalCode?: string;
|
|
1805
|
+
};
|
|
1806
|
+
}): Promise<Order>;
|
|
1807
|
+
/**
|
|
1808
|
+
* Convert a draft order into a regular (pending) order.
|
|
1809
|
+
*
|
|
1810
|
+
* Uses `sdk.admin.draftOrder.convertToOrder()` which maps to
|
|
1811
|
+
* `POST /admin/draft-orders/{id}/convert-to-order`.
|
|
1812
|
+
* Returns the newly created order transformed into `@thorprovider/types.Order`.
|
|
1813
|
+
*/
|
|
1814
|
+
undraftOrder(draftOrderId: string): Promise<Order>;
|
|
1815
|
+
/**
|
|
1816
|
+
* Assign a customer to a sales channel via metadata.
|
|
1817
|
+
*
|
|
1818
|
+
* This is the primary mechanism for multi-tenant isolation of entities
|
|
1819
|
+
* that the backend does not natively scope to a sales channel
|
|
1820
|
+
* (e.g. customers in Medusa).
|
|
1821
|
+
*
|
|
1822
|
+
* Writes `sales_channel_id` + audit fields into `customer.metadata`.
|
|
1823
|
+
* After assignment, `getCustomers({ salesChannelId })` will include
|
|
1824
|
+
* this customer in its results.
|
|
1825
|
+
*
|
|
1826
|
+
* @param customerId - Customer to assign
|
|
1827
|
+
* @param channelId - Target sales channel
|
|
1828
|
+
* @param assignedBy - Optional: who triggered the assignment
|
|
1829
|
+
* @returns Updated customer with new metadata
|
|
1830
|
+
*
|
|
1831
|
+
* @example
|
|
1832
|
+
* ```typescript
|
|
1833
|
+
* // Dropshipper creates customer → assign to their channel
|
|
1834
|
+
* const customer = await commerce.assignCustomerToChannel(
|
|
1835
|
+
* 'cus_01HXXX',
|
|
1836
|
+
* process.env.NEXT_PUBLIC_SALES_CHANNEL_ID!,
|
|
1837
|
+
* 'admin@mystore.com',
|
|
1838
|
+
* );
|
|
1839
|
+
* ```
|
|
1840
|
+
*/
|
|
1841
|
+
assignCustomerToChannel(customerId: string, channelId: string, assignedBy?: string): Promise<Customer>;
|
|
1842
|
+
/**
|
|
1843
|
+
* Assign an order to a sales channel via metadata.
|
|
1844
|
+
*
|
|
1845
|
+
* Same pattern as `assignCustomerToChannel` but for orders.
|
|
1846
|
+
* Useful when orders are created through flows that don't automatically
|
|
1847
|
+
* link them to a channel.
|
|
1848
|
+
*
|
|
1849
|
+
* @param orderId - Order to assign
|
|
1850
|
+
* @param channelId - Target sales channel
|
|
1851
|
+
* @param assignedBy - Optional: who triggered the assignment
|
|
1852
|
+
*/
|
|
1853
|
+
assignOrderToChannel(orderId: string, channelId: string, assignedBy?: string): Promise<void>;
|
|
1854
|
+
/**
|
|
1855
|
+
* Get available payment methods
|
|
1856
|
+
*
|
|
1857
|
+
* Queries Medusa for payment providers available in a specific region.
|
|
1858
|
+
* Region is determined either from options.regionId or from the cart.
|
|
1859
|
+
*
|
|
1860
|
+
* @param options - Payment methods query options (regionId or cartId required)
|
|
1861
|
+
* @returns Array of available payment methods
|
|
1862
|
+
*
|
|
1863
|
+
* @example
|
|
1864
|
+
* ```typescript
|
|
1865
|
+
* // Get payment methods for a region
|
|
1866
|
+
* const methods = await provider.getPaymentMethods({
|
|
1867
|
+
* regionId: 'reg_123',
|
|
1868
|
+
* enabledOnly: true
|
|
1869
|
+
* });
|
|
1870
|
+
*
|
|
1871
|
+
* // Get payment methods for a cart
|
|
1872
|
+
* const methods = await provider.getPaymentMethods({
|
|
1873
|
+
* cartId: 'cart_123'
|
|
1874
|
+
* });
|
|
1875
|
+
* ```
|
|
1876
|
+
*/
|
|
1877
|
+
getPaymentMethods(options: PaymentMethodsOptions): Promise<PaymentMethod[]>;
|
|
1878
|
+
/**
|
|
1879
|
+
* Complete checkout and create order from cart
|
|
1880
|
+
*
|
|
1881
|
+
* Finalizes the checkout process and converts the cart into an order.
|
|
1882
|
+
* Cart must have shipping address, shipping method, and payment session.
|
|
1883
|
+
*
|
|
1884
|
+
* @param cartId - Cart ID to checkout
|
|
1885
|
+
* @returns Created order
|
|
1886
|
+
* @throws {ProviderAPIError} If checkout fails
|
|
1887
|
+
*/
|
|
1888
|
+
completeCheckout(cartId: string): Promise<Order>;
|
|
1889
|
+
/**
|
|
1890
|
+
* Get available shipping methods for cart
|
|
1891
|
+
*
|
|
1892
|
+
* Fetches shipping options based on cart region and shipping address.
|
|
1893
|
+
*
|
|
1894
|
+
* @param cartId - Cart ID
|
|
1895
|
+
* @returns List of shipping methods with prices
|
|
1896
|
+
* @throws {ProviderAPIError} If cart not found or region not configured
|
|
1897
|
+
*/
|
|
1898
|
+
getShippingMethods(cartId: string): Promise<_thorprovider_types.ShippingMethod[]>;
|
|
1899
|
+
/**
|
|
1900
|
+
* Check if admin API is configured
|
|
1901
|
+
*/
|
|
1902
|
+
private get isAdminConfigured();
|
|
1903
|
+
/**
|
|
1904
|
+
* Ensure admin is configured.
|
|
1905
|
+
* Synchronous check — API key auth has no async initialization.
|
|
1906
|
+
* @throws ProviderAPIError if admin configuration is missing
|
|
1907
|
+
*/
|
|
1908
|
+
private ensureAdminConfigured;
|
|
1909
|
+
/**
|
|
1910
|
+
* Make an authenticated request to the Medusa Admin API via SDK
|
|
1911
|
+
* SDK automatically includes Bearer token in all admin requests
|
|
1912
|
+
* Awaits auth initialization before executing the operation
|
|
1913
|
+
*/
|
|
1914
|
+
private makeAdminRequest;
|
|
1915
|
+
/**
|
|
1916
|
+
* Fetch stock locations, optionally filtered by sales channel.
|
|
1917
|
+
* Returns empty array when admin config is not provided (graceful degradation).
|
|
1918
|
+
*/
|
|
1919
|
+
getStockLocations(params?: {
|
|
1920
|
+
salesChannelId?: string;
|
|
1921
|
+
}): Promise<StockLocation[]>;
|
|
1922
|
+
/**
|
|
1923
|
+
* Check inventory levels for a variant across locations.
|
|
1924
|
+
* Returns empty array when admin config is not provided (graceful degradation).
|
|
1925
|
+
*/
|
|
1926
|
+
checkInventoryLevels(variantId: string, salesChannelId?: string): Promise<InventoryLevel[]>;
|
|
1927
|
+
/**
|
|
1928
|
+
* Validate cart stock availability across all items.
|
|
1929
|
+
* Returns all-available when admin config is not provided (graceful degradation).
|
|
1930
|
+
*/
|
|
1931
|
+
validateCartStock(cartId: string): Promise<StockValidation>;
|
|
1932
|
+
/**
|
|
1933
|
+
* Get fulfillment options enriched with stock location data.
|
|
1934
|
+
* Not yet implemented — requires fulfillment planning + Admin inventory.
|
|
1935
|
+
*/
|
|
1936
|
+
getFulfillmentOptions(cartId: string, salesChannelId: string): Promise<FulfillmentOption[]>;
|
|
1937
|
+
/**
|
|
1938
|
+
* Get a map of product IDs → admin status ('published' | 'draft' | etc.)
|
|
1939
|
+
* Returns {} when admin config is not provided (graceful degradation).
|
|
1940
|
+
*/
|
|
1941
|
+
getAdminProductStatuses(options?: {
|
|
1942
|
+
limit?: number;
|
|
1943
|
+
}): Promise<Record<string, string>>;
|
|
1944
|
+
/**
|
|
1945
|
+
* Get the distinct product status values available in Medusa.
|
|
1946
|
+
* Derives values from getAdminProductStatuses and caches them for the process lifetime.
|
|
1947
|
+
* Returns [] when admin credentials are not configured.
|
|
1948
|
+
*/
|
|
1949
|
+
getAvailableProductStatuses(): Promise<string[]>;
|
|
1950
|
+
/**
|
|
1951
|
+
* List ALL products from the admin API (including non-published).
|
|
1952
|
+
* Returns real backend status values and variant-level price/inventory data.
|
|
1953
|
+
* Gracefully degrades to empty result when admin credentials are not configured.
|
|
1954
|
+
*/
|
|
1955
|
+
getAdminProducts(options?: {
|
|
1956
|
+
query?: string;
|
|
1957
|
+
limit?: number;
|
|
1958
|
+
offset?: number;
|
|
1959
|
+
}): Promise<{
|
|
1960
|
+
products: AdminProduct[];
|
|
1961
|
+
count: number;
|
|
1962
|
+
}>;
|
|
1963
|
+
/**
|
|
1964
|
+
* Get available countries for a region
|
|
1965
|
+
*
|
|
1966
|
+
* Returns list of countries that can be used for shipping addresses
|
|
1967
|
+
* in the specified region. Results are cached for 5 minutes.
|
|
1968
|
+
*
|
|
1969
|
+
* @param regionId - Region ID
|
|
1970
|
+
* @returns Array of countries with codes and names
|
|
1971
|
+
* @throws {ProviderAPIError} If region not found or API error
|
|
1972
|
+
*
|
|
1973
|
+
* @example
|
|
1974
|
+
* ```typescript
|
|
1975
|
+
* const countries = await medusa.getRegionCountries('reg_01KHCJQ5YXYRWWCKSTYQ4SCM8V');
|
|
1976
|
+
* // [{ code: 'ES', name: 'Spain' }, { code: 'FR', name: 'France' }, ...]
|
|
1977
|
+
* ```
|
|
1978
|
+
*/
|
|
1979
|
+
getRegionCountries(regionId: string): Promise<_thorprovider_types.Country[]>;
|
|
1980
|
+
/**
|
|
1981
|
+
* Add shipping method to cart
|
|
1982
|
+
*
|
|
1983
|
+
* Applies a shipping method to the cart and updates totals.
|
|
1984
|
+
*
|
|
1985
|
+
* @param cartId - Cart ID
|
|
1986
|
+
* @param methodId - Shipping method ID (from getShippingMethods)
|
|
1987
|
+
* @returns Updated cart with shipping
|
|
1988
|
+
* @throws {ProviderAPIError} If method invalid or cart not ready
|
|
1989
|
+
*/
|
|
1990
|
+
addShippingMethod(cartId: string, methodId: string): Promise<Cart>;
|
|
1991
|
+
/**
|
|
1992
|
+
* Initiate payment session with provider
|
|
1993
|
+
*
|
|
1994
|
+
* Creates a payment session for the cart with the specified provider.
|
|
1995
|
+
*
|
|
1996
|
+
* @param cartId - Cart ID
|
|
1997
|
+
* @param providerId - Payment provider ID (from getPaymentMethods)
|
|
1998
|
+
* @throws {ProviderAPIError} If provider invalid or cart not ready
|
|
1999
|
+
*/
|
|
2000
|
+
initiatePaymentSession(cartId: string, providerId: string): Promise<void>;
|
|
2001
|
+
/**
|
|
2002
|
+
* Apply discount code to cart
|
|
2003
|
+
*
|
|
2004
|
+
* Validates and applies a discount/promo code to the cart.
|
|
2005
|
+
*
|
|
2006
|
+
* @param cartId - Cart ID
|
|
2007
|
+
* @param code - Discount code
|
|
2008
|
+
* @returns Updated cart with discount
|
|
2009
|
+
* @throws {ProviderAPIError} If code invalid or expired
|
|
2010
|
+
*/
|
|
2011
|
+
applyDiscountCode(cartId: string, code: string): Promise<Cart>;
|
|
2012
|
+
/**
|
|
2013
|
+
* Remove discount code from cart
|
|
2014
|
+
*
|
|
2015
|
+
* Removes a previously applied discount code.
|
|
2016
|
+
*
|
|
2017
|
+
* @param cartId - Cart ID
|
|
2018
|
+
* @param code - Discount code to remove
|
|
2019
|
+
* @returns Updated cart without discount
|
|
2020
|
+
* @throws {ProviderAPIError} If cart not found
|
|
2021
|
+
*/
|
|
2022
|
+
removeDiscountCode(cartId: string, code: string): Promise<Cart>;
|
|
2023
|
+
/**
|
|
2024
|
+
* Update cart shipping address
|
|
2025
|
+
* @param cartId - Cart ID
|
|
2026
|
+
* @param address - Shipping address details
|
|
2027
|
+
* @returns Updated cart
|
|
2028
|
+
*
|
|
2029
|
+
* **CRITICAL**: Must be called BEFORE initiatePaymentSession
|
|
2030
|
+
* Medusa requires shipping_address on cart before creating payment session
|
|
2031
|
+
*/
|
|
2032
|
+
updateShippingAddress(cartId: string, address: {
|
|
2033
|
+
email: string;
|
|
2034
|
+
firstName: string;
|
|
2035
|
+
lastName: string;
|
|
2036
|
+
address1: string;
|
|
2037
|
+
address2?: string;
|
|
2038
|
+
company?: string;
|
|
2039
|
+
city: string;
|
|
2040
|
+
province: string;
|
|
2041
|
+
postalCode: string;
|
|
2042
|
+
countryCode: string;
|
|
2043
|
+
phone: string;
|
|
2044
|
+
}): Promise<void>;
|
|
2045
|
+
/**
|
|
2046
|
+
* Update cart billing address
|
|
2047
|
+
* @param cartId - Cart ID
|
|
2048
|
+
* @param address - Billing address details
|
|
2049
|
+
* @returns Updated cart
|
|
2050
|
+
*
|
|
2051
|
+
* **Usage**: Call when billing address differs from shipping address
|
|
2052
|
+
* Recommended to call BEFORE initiatePaymentSession
|
|
2053
|
+
*/
|
|
2054
|
+
updateBillingAddress(cartId: string, address: {
|
|
2055
|
+
firstName: string;
|
|
2056
|
+
lastName: string;
|
|
2057
|
+
address1: string;
|
|
2058
|
+
address2?: string;
|
|
2059
|
+
company?: string;
|
|
2060
|
+
city: string;
|
|
2061
|
+
province: string;
|
|
2062
|
+
postalCode: string;
|
|
2063
|
+
countryCode: string;
|
|
2064
|
+
phone?: string;
|
|
2065
|
+
}): Promise<Cart>;
|
|
2066
|
+
/**
|
|
2067
|
+
* Get the current storefront/sales channel context.
|
|
2068
|
+
*
|
|
2069
|
+
* Validates that NEXT_PUBLIC_SALES_CHANNEL_ID is set and that the
|
|
2070
|
+
* corresponding sales channel exists in the Medusa backend.
|
|
2071
|
+
* Results are cached for 60 seconds.
|
|
2072
|
+
*
|
|
2073
|
+
* @returns StorefrontContext for the current storefront
|
|
2074
|
+
* @throws {StorefrontConfigError} if NEXT_PUBLIC_SALES_CHANNEL_ID is missing or invalid
|
|
2075
|
+
* @throws {ProviderAPIError} if the backend request fails
|
|
2076
|
+
*/
|
|
2077
|
+
getStorefrontContext(): Promise<StorefrontContext>;
|
|
2078
|
+
/**
|
|
2079
|
+
* Medusa always requires storefront configuration for multi-tenant support.
|
|
2080
|
+
*/
|
|
2081
|
+
isStorefrontRequired(): boolean;
|
|
2082
|
+
/** In-memory cache for storefront config (60s TTL) */
|
|
2083
|
+
private _storefrontConfigCache;
|
|
2084
|
+
/** In-memory cache for designer config (60s TTL) */
|
|
2085
|
+
private _designerConfigCache;
|
|
2086
|
+
/** Cache TTL for Thor plugin configs (60 seconds) */
|
|
2087
|
+
private readonly THOR_CONFIG_CACHE_TTL;
|
|
2088
|
+
/**
|
|
2089
|
+
* Get per-channel storefront configuration from Thor Commerce plugin.
|
|
2090
|
+
* Calls `GET /store/thor/config`.
|
|
2091
|
+
*
|
|
2092
|
+
* @returns StorefrontConfig or null if plugin is not installed / config not set
|
|
2093
|
+
*/
|
|
2094
|
+
getStorefrontConfig(): Promise<StorefrontConfig | null>;
|
|
2095
|
+
/**
|
|
2096
|
+
* Get active Site Designer configuration from Thor Commerce plugin.
|
|
2097
|
+
* Calls `GET /store/thor/site-config`.
|
|
2098
|
+
*
|
|
2099
|
+
* @returns Versioned DesignerConfig or null if plugin is not installed / config not set
|
|
2100
|
+
*/
|
|
2101
|
+
getDesignerConfig(): Promise<{
|
|
2102
|
+
version: string;
|
|
2103
|
+
config: DesignerConfig;
|
|
2104
|
+
} | null>;
|
|
2105
|
+
/**
|
|
2106
|
+
* Get admin Site Designer config + history for a sales channel.
|
|
2107
|
+
* Calls `GET /admin/thor/site-config/:salesChannelId`.
|
|
2108
|
+
*/
|
|
2109
|
+
getAdminDesignerConfig(salesChannelId: string): Promise<{
|
|
2110
|
+
version: string;
|
|
2111
|
+
config: DesignerConfig;
|
|
2112
|
+
history?: DesignerHistoryEntry[];
|
|
2113
|
+
} | null>;
|
|
2114
|
+
/**
|
|
2115
|
+
* Update the Site Designer config for a sales channel.
|
|
2116
|
+
* Calls `PUT /admin/thor/site-config/:salesChannelId`.
|
|
2117
|
+
*/
|
|
2118
|
+
updateAdminDesignerConfig(salesChannelId: string, config: DesignerConfig): Promise<{
|
|
2119
|
+
version: string;
|
|
2120
|
+
config: DesignerConfig;
|
|
2121
|
+
}>;
|
|
2122
|
+
/**
|
|
2123
|
+
* Restore a previous Site Designer config version.
|
|
2124
|
+
* Calls `POST /admin/thor/site-config/:salesChannelId/restore/:version`.
|
|
2125
|
+
*/
|
|
2126
|
+
restoreAdminDesignerConfig(salesChannelId: string, version: string): Promise<{
|
|
2127
|
+
version: string;
|
|
2128
|
+
config: DesignerConfig;
|
|
2129
|
+
}>;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* Shopify provider configuration
|
|
2134
|
+
*/
|
|
2135
|
+
interface ShopifyProviderConfig extends ProviderConfig {
|
|
2136
|
+
/** Store domain (e.g., 'your-store.myshopify.com') */
|
|
2137
|
+
storeDomain: string;
|
|
2138
|
+
/** Public Storefront API access token */
|
|
2139
|
+
publicAccessToken: string;
|
|
2140
|
+
/** Private Storefront API access token (server-side only) */
|
|
2141
|
+
privateAccessToken?: string;
|
|
2142
|
+
/** API version (default: '2026-04') */
|
|
2143
|
+
apiVersion?: string;
|
|
2144
|
+
}
|
|
2145
|
+
/**
|
|
2146
|
+
* Shopify commerce provider
|
|
2147
|
+
*
|
|
2148
|
+
* Implements CommerceProvider for Shopify Storefront API.
|
|
2149
|
+
* Uses raw fetch + GraphQL queries (no SDK dependency to stay L2-pure).
|
|
2150
|
+
*/
|
|
2151
|
+
declare class ShopifyProvider implements CommerceProvider {
|
|
2152
|
+
readonly name = "shopify";
|
|
2153
|
+
readonly version = "1.0.0";
|
|
2154
|
+
readonly capabilities: BackendCapabilities;
|
|
2155
|
+
private logger;
|
|
2156
|
+
private storeDomain;
|
|
2157
|
+
private apiVersion;
|
|
2158
|
+
private endpoint;
|
|
2159
|
+
private headers;
|
|
2160
|
+
constructor(config: ShopifyProviderConfig);
|
|
2161
|
+
private query;
|
|
2162
|
+
getProduct(handle: string): Promise<Product | undefined>;
|
|
2163
|
+
getProducts(options?: GetProductsOptions): Promise<Product[]>;
|
|
2164
|
+
getProductRecommendations(productId: string): Promise<Product[]>;
|
|
2165
|
+
getCollection(handle: string): Promise<Collection | undefined>;
|
|
2166
|
+
getCollections(options?: GetCollectionsOptions): Promise<Collection[]>;
|
|
2167
|
+
getCollectionProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2168
|
+
getCategory(): Promise<ProductCategory | undefined>;
|
|
2169
|
+
getCategories(): Promise<ProductCategory[]>;
|
|
2170
|
+
getCategoryProducts(): Promise<Product[]>;
|
|
2171
|
+
createCart(): Promise<Cart>;
|
|
2172
|
+
getCart(cartId: string): Promise<Cart | undefined>;
|
|
2173
|
+
addToCart(cartId: string, lines: CartLineInput[]): Promise<Cart>;
|
|
2174
|
+
removeFromCart(cartId: string, lineIds: string[]): Promise<Cart>;
|
|
2175
|
+
updateCart(cartId: string, lines: CartLineUpdate[]): Promise<Cart>;
|
|
2176
|
+
completeCheckout(_cartId: string): Promise<Order>;
|
|
2177
|
+
getShippingMethods(_cartId: string): Promise<ShippingMethod[]>;
|
|
2178
|
+
getRegionCountries(): Promise<_thorprovider_types.Country[]>;
|
|
2179
|
+
addShippingMethod(_cartId: string, _methodId: string): Promise<Cart>;
|
|
2180
|
+
initiatePaymentSession(_cartId: string, _providerId: string): Promise<void>;
|
|
2181
|
+
applyDiscountCode(cartId: string, code: string): Promise<Cart>;
|
|
2182
|
+
removeDiscountCode(cartId: string, _code: string): Promise<Cart>;
|
|
2183
|
+
getOrders(options: GetOrdersOptions): Promise<Order[]>;
|
|
2184
|
+
getPaymentMethods(_options: PaymentMethodsOptions): Promise<PaymentMethod[]>;
|
|
2185
|
+
getStockLocations(): Promise<StockLocation[]>;
|
|
2186
|
+
checkInventoryLevels(): Promise<InventoryLevel[]>;
|
|
2187
|
+
validateCartStock(): Promise<StockValidation>;
|
|
2188
|
+
getFulfillmentOptions(): Promise<FulfillmentOption[]>;
|
|
2189
|
+
cancelOrder(_orderId: string): Promise<Order>;
|
|
2190
|
+
createFulfillment(_orderId: string): Promise<void>;
|
|
2191
|
+
createRefund(_orderId: string): Promise<void>;
|
|
2192
|
+
getAdminOrders(): Promise<{
|
|
2193
|
+
orders: Order[];
|
|
2194
|
+
count: number;
|
|
2195
|
+
}>;
|
|
2196
|
+
getStorefrontContext(): Promise<StorefrontContext>;
|
|
2197
|
+
isStorefrontRequired(): boolean;
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
/**
|
|
2201
|
+
* BigCommerce provider configuration
|
|
2202
|
+
*/
|
|
2203
|
+
interface BigCommerceProviderConfig extends ProviderConfig {
|
|
2204
|
+
/** BigCommerce store hash */
|
|
2205
|
+
storeHash: string;
|
|
2206
|
+
/** Storefront API token (JWT) */
|
|
2207
|
+
storefrontApiToken: string;
|
|
2208
|
+
/** Storefront API URL (usually https://store-{hash}.mybigcommerce.com) */
|
|
2209
|
+
storefrontApiUrl: string;
|
|
2210
|
+
/** Channel ID */
|
|
2211
|
+
channelId: string;
|
|
2212
|
+
/** Default currency code (default: 'USD') */
|
|
2213
|
+
currencyCode?: string;
|
|
2214
|
+
}
|
|
2215
|
+
declare class BigCommerceProvider implements CommerceProvider {
|
|
2216
|
+
readonly name = "bigcommerce";
|
|
2217
|
+
readonly version = "1.0.0";
|
|
2218
|
+
readonly capabilities: BackendCapabilities;
|
|
2219
|
+
private logger;
|
|
2220
|
+
private storefrontApiUrl;
|
|
2221
|
+
private storeHash;
|
|
2222
|
+
private channelId;
|
|
2223
|
+
private currencyCode;
|
|
2224
|
+
private headers;
|
|
2225
|
+
constructor(config: BigCommerceProviderConfig);
|
|
2226
|
+
private fetchApi;
|
|
2227
|
+
getProduct(handle: string): Promise<Product | undefined>;
|
|
2228
|
+
getProducts(options?: GetProductsOptions): Promise<Product[]>;
|
|
2229
|
+
getProductRecommendations(_productId: string): Promise<Product[]>;
|
|
2230
|
+
getCollection(handle: string): Promise<Collection | undefined>;
|
|
2231
|
+
getCollections(options?: GetCollectionsOptions): Promise<Collection[]>;
|
|
2232
|
+
getCollectionProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2233
|
+
getCategory(idOrHandle: string): Promise<ProductCategory | undefined>;
|
|
2234
|
+
getCategories(options?: GetCategoriesOptions): Promise<ProductCategory[]>;
|
|
2235
|
+
getCategoryProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2236
|
+
createCart(): Promise<Cart>;
|
|
2237
|
+
getCart(cartId: string): Promise<Cart | undefined>;
|
|
2238
|
+
addToCart(cartId: string, lines: CartLineInput[]): Promise<Cart>;
|
|
2239
|
+
removeFromCart(cartId: string, lineIds: string[]): Promise<Cart>;
|
|
2240
|
+
updateCart(cartId: string, lines: CartLineUpdate[]): Promise<Cart>;
|
|
2241
|
+
completeCheckout(_cartId: string): Promise<Order>;
|
|
2242
|
+
getShippingMethods(_cartId: string): Promise<ShippingMethod[]>;
|
|
2243
|
+
getRegionCountries(): Promise<_thorprovider_types.Country[]>;
|
|
2244
|
+
addShippingMethod(_cartId: string, _methodId: string): Promise<Cart>;
|
|
2245
|
+
initiatePaymentSession(_cartId: string, _providerId: string): Promise<void>;
|
|
2246
|
+
applyDiscountCode(cartId: string, code: string): Promise<Cart>;
|
|
2247
|
+
removeDiscountCode(cartId: string, code: string): Promise<Cart>;
|
|
2248
|
+
getOrders(_options: GetOrdersOptions): Promise<Order[]>;
|
|
2249
|
+
getPaymentMethods(_options: PaymentMethodsOptions): Promise<PaymentMethod[]>;
|
|
2250
|
+
getStockLocations(): Promise<StockLocation[]>;
|
|
2251
|
+
checkInventoryLevels(): Promise<InventoryLevel[]>;
|
|
2252
|
+
validateCartStock(): Promise<StockValidation>;
|
|
2253
|
+
getFulfillmentOptions(): Promise<FulfillmentOption[]>;
|
|
2254
|
+
cancelOrder(_orderId: string): Promise<Order>;
|
|
2255
|
+
createFulfillment(_orderId: string): Promise<void>;
|
|
2256
|
+
createRefund(_orderId: string): Promise<void>;
|
|
2257
|
+
getAdminOrders(): Promise<{
|
|
2258
|
+
orders: Order[];
|
|
2259
|
+
count: number;
|
|
2260
|
+
}>;
|
|
2261
|
+
getStorefrontContext(): Promise<StorefrontContext>;
|
|
2262
|
+
isStorefrontRequired(): boolean;
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
/**
|
|
2266
|
+
* WooCommerce provider configuration
|
|
2267
|
+
*/
|
|
2268
|
+
interface WooCommerceProviderConfig extends ProviderConfig {
|
|
2269
|
+
/** WordPress site URL (e.g., 'https://mystore.com') */
|
|
2270
|
+
url: string;
|
|
2271
|
+
/** WooCommerce REST API consumer key (for authenticated operations) */
|
|
2272
|
+
consumerKey?: string;
|
|
2273
|
+
/** WooCommerce REST API consumer secret (for authenticated operations) */
|
|
2274
|
+
consumerSecret?: string;
|
|
2275
|
+
/** Default currency code (default: 'USD') */
|
|
2276
|
+
currencyCode?: string;
|
|
2277
|
+
}
|
|
2278
|
+
declare class WooCommerceProvider implements CommerceProvider {
|
|
2279
|
+
readonly name = "woocommerce";
|
|
2280
|
+
readonly version = "1.0.0";
|
|
2281
|
+
readonly capabilities: BackendCapabilities;
|
|
2282
|
+
private logger;
|
|
2283
|
+
private baseUrl;
|
|
2284
|
+
private storeApiBase;
|
|
2285
|
+
private restApiBase;
|
|
2286
|
+
private currencyCode;
|
|
2287
|
+
private authHeader?;
|
|
2288
|
+
constructor(config: WooCommerceProviderConfig);
|
|
2289
|
+
private storeApiFetch;
|
|
2290
|
+
private restApiFetch;
|
|
2291
|
+
getProduct(handle: string): Promise<Product | undefined>;
|
|
2292
|
+
getProducts(options?: GetProductsOptions): Promise<Product[]>;
|
|
2293
|
+
getProductRecommendations(_productId: string): Promise<Product[]>;
|
|
2294
|
+
getCollection(handle: string): Promise<Collection | undefined>;
|
|
2295
|
+
getCollections(options?: GetCollectionsOptions): Promise<Collection[]>;
|
|
2296
|
+
getCollectionProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2297
|
+
getCategory(idOrHandle: string): Promise<ProductCategory | undefined>;
|
|
2298
|
+
getCategories(options?: GetCategoriesOptions): Promise<ProductCategory[]>;
|
|
2299
|
+
getCategoryProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2300
|
+
createCart(): Promise<Cart>;
|
|
2301
|
+
getCart(_cartId: string): Promise<Cart | undefined>;
|
|
2302
|
+
addToCart(_cartId: string, lines: CartLineInput[]): Promise<Cart>;
|
|
2303
|
+
removeFromCart(_cartId: string, lineIds: string[]): Promise<Cart>;
|
|
2304
|
+
updateCart(_cartId: string, lines: CartLineUpdate[]): Promise<Cart>;
|
|
2305
|
+
completeCheckout(_cartId: string): Promise<Order>;
|
|
2306
|
+
getShippingMethods(_cartId: string): Promise<ShippingMethod[]>;
|
|
2307
|
+
getRegionCountries(): Promise<_thorprovider_types.Country[]>;
|
|
2308
|
+
addShippingMethod(_cartId: string, methodId: string): Promise<Cart>;
|
|
2309
|
+
initiatePaymentSession(_cartId: string, _providerId: string): Promise<void>;
|
|
2310
|
+
applyDiscountCode(_cartId: string, code: string): Promise<Cart>;
|
|
2311
|
+
removeDiscountCode(_cartId: string, code: string): Promise<Cart>;
|
|
2312
|
+
getOrders(_options: GetOrdersOptions): Promise<Order[]>;
|
|
2313
|
+
getPaymentMethods(_options: PaymentMethodsOptions): Promise<PaymentMethod[]>;
|
|
2314
|
+
getStockLocations(): Promise<StockLocation[]>;
|
|
2315
|
+
checkInventoryLevels(): Promise<InventoryLevel[]>;
|
|
2316
|
+
validateCartStock(): Promise<StockValidation>;
|
|
2317
|
+
getFulfillmentOptions(): Promise<FulfillmentOption[]>;
|
|
2318
|
+
cancelOrder(_orderId: string): Promise<Order>;
|
|
2319
|
+
createFulfillment(_orderId: string): Promise<void>;
|
|
2320
|
+
createRefund(_orderId: string): Promise<void>;
|
|
2321
|
+
getAdminOrders(): Promise<{
|
|
2322
|
+
orders: Order[];
|
|
2323
|
+
count: number;
|
|
2324
|
+
}>;
|
|
2325
|
+
getStorefrontContext(): Promise<StorefrontContext>;
|
|
2326
|
+
isStorefrontRequired(): boolean;
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2329
|
+
/**
|
|
2330
|
+
* Spree provider configuration
|
|
2331
|
+
*/
|
|
2332
|
+
interface SpreeProviderConfig extends ProviderConfig {
|
|
2333
|
+
/** Spree store base URL (e.g., 'https://myspreestore.com') */
|
|
2334
|
+
baseUrl: string;
|
|
2335
|
+
/** Bearer token for authenticated operations (customer or OAuth) */
|
|
2336
|
+
bearerToken?: string;
|
|
2337
|
+
/** Default currency code (default: 'USD') */
|
|
2338
|
+
currencyCode?: string;
|
|
2339
|
+
}
|
|
2340
|
+
declare class SpreeProvider implements CommerceProvider {
|
|
2341
|
+
readonly name = "spree";
|
|
2342
|
+
readonly version = "1.0.0";
|
|
2343
|
+
readonly capabilities: BackendCapabilities;
|
|
2344
|
+
private logger;
|
|
2345
|
+
private baseUrl;
|
|
2346
|
+
private apiBase;
|
|
2347
|
+
private currencyCode;
|
|
2348
|
+
private bearerToken?;
|
|
2349
|
+
private orderToken?;
|
|
2350
|
+
constructor(config: SpreeProviderConfig);
|
|
2351
|
+
private apiFetch;
|
|
2352
|
+
getProduct(handle: string): Promise<Product | undefined>;
|
|
2353
|
+
getProducts(options?: GetProductsOptions): Promise<Product[]>;
|
|
2354
|
+
getProductRecommendations(_productId: string): Promise<Product[]>;
|
|
2355
|
+
getCollection(handle: string): Promise<Collection | undefined>;
|
|
2356
|
+
getCollections(options?: GetCollectionsOptions): Promise<Collection[]>;
|
|
2357
|
+
getCollectionProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2358
|
+
getCategory(handle: string): Promise<ProductCategory | undefined>;
|
|
2359
|
+
getCategories(options?: GetCategoriesOptions): Promise<ProductCategory[]>;
|
|
2360
|
+
getCategoryProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2361
|
+
createCart(): Promise<Cart>;
|
|
2362
|
+
getCart(_cartId: string): Promise<Cart | undefined>;
|
|
2363
|
+
addToCart(_cartId: string, lines: CartLineInput[]): Promise<Cart>;
|
|
2364
|
+
removeFromCart(_cartId: string, lineIds: string[]): Promise<Cart>;
|
|
2365
|
+
updateCart(_cartId: string, lines: CartLineUpdate[]): Promise<Cart>;
|
|
2366
|
+
completeCheckout(_cartId: string): Promise<Order>;
|
|
2367
|
+
getShippingMethods(_cartId: string): Promise<ShippingMethod[]>;
|
|
2368
|
+
getRegionCountries(): Promise<_thorprovider_types.Country[]>;
|
|
2369
|
+
addShippingMethod(_cartId: string, methodId: string): Promise<Cart>;
|
|
2370
|
+
initiatePaymentSession(_cartId: string, _providerId: string): Promise<void>;
|
|
2371
|
+
applyDiscountCode(_cartId: string, code: string): Promise<Cart>;
|
|
2372
|
+
removeDiscountCode(_cartId: string, code: string): Promise<Cart>;
|
|
2373
|
+
getOrders(_options: GetOrdersOptions): Promise<Order[]>;
|
|
2374
|
+
getPaymentMethods(_options: PaymentMethodsOptions): Promise<PaymentMethod[]>;
|
|
2375
|
+
getStockLocations(): Promise<StockLocation[]>;
|
|
2376
|
+
checkInventoryLevels(): Promise<InventoryLevel[]>;
|
|
2377
|
+
validateCartStock(): Promise<StockValidation>;
|
|
2378
|
+
getFulfillmentOptions(): Promise<FulfillmentOption[]>;
|
|
2379
|
+
cancelOrder(_orderId: string): Promise<Order>;
|
|
2380
|
+
createFulfillment(_orderId: string): Promise<void>;
|
|
2381
|
+
createRefund(_orderId: string): Promise<void>;
|
|
2382
|
+
getAdminOrders(): Promise<{
|
|
2383
|
+
orders: Order[];
|
|
2384
|
+
count: number;
|
|
2385
|
+
}>;
|
|
2386
|
+
getStorefrontContext(): Promise<StorefrontContext>;
|
|
2387
|
+
isStorefrontRequired(): boolean;
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
/**
|
|
2391
|
+
* Magento provider configuration
|
|
2392
|
+
*/
|
|
2393
|
+
interface MagentoProviderConfig extends ProviderConfig {
|
|
2394
|
+
/** Magento base URL (e.g., 'https://mymagento.com') */
|
|
2395
|
+
baseUrl: string;
|
|
2396
|
+
/** Store code for multi-tenant (default: 'default') */
|
|
2397
|
+
storeCode?: string;
|
|
2398
|
+
/** Customer bearer token (for authenticated operations) */
|
|
2399
|
+
customerToken?: string;
|
|
2400
|
+
/** Integration access token (for admin-level operations) */
|
|
2401
|
+
accessToken?: string;
|
|
2402
|
+
/** Default currency code (default: 'USD') */
|
|
2403
|
+
currencyCode?: string;
|
|
2404
|
+
}
|
|
2405
|
+
declare class MagentoProvider implements CommerceProvider {
|
|
2406
|
+
readonly name = "magento";
|
|
2407
|
+
readonly version = "1.0.0";
|
|
2408
|
+
readonly capabilities: BackendCapabilities;
|
|
2409
|
+
private logger;
|
|
2410
|
+
private baseUrl;
|
|
2411
|
+
private storeCode;
|
|
2412
|
+
private currencyCode;
|
|
2413
|
+
private graphqlEndpoint;
|
|
2414
|
+
private customerToken?;
|
|
2415
|
+
private accessToken?;
|
|
2416
|
+
constructor(config: MagentoProviderConfig);
|
|
2417
|
+
private graphql;
|
|
2418
|
+
getProduct(handle: string): Promise<Product | undefined>;
|
|
2419
|
+
getProducts(options?: GetProductsOptions): Promise<Product[]>;
|
|
2420
|
+
getProductRecommendations(_productId: string): Promise<Product[]>;
|
|
2421
|
+
getCollection(handle: string): Promise<Collection | undefined>;
|
|
2422
|
+
getCollections(options?: GetCollectionsOptions): Promise<Collection[]>;
|
|
2423
|
+
getCollectionProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2424
|
+
getCategory(handle: string): Promise<ProductCategory | undefined>;
|
|
2425
|
+
getCategories(options?: GetCategoriesOptions): Promise<ProductCategory[]>;
|
|
2426
|
+
getCategoryProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]>;
|
|
2427
|
+
createCart(): Promise<Cart>;
|
|
2428
|
+
getCart(cartId: string): Promise<Cart | undefined>;
|
|
2429
|
+
addToCart(cartId: string, lines: CartLineInput[]): Promise<Cart>;
|
|
2430
|
+
removeFromCart(cartId: string, lineIds: string[]): Promise<Cart>;
|
|
2431
|
+
updateCart(cartId: string, lines: CartLineUpdate[]): Promise<Cart>;
|
|
2432
|
+
completeCheckout(_cartId: string): Promise<Order>;
|
|
2433
|
+
getShippingMethods(_cartId: string): Promise<ShippingMethod[]>;
|
|
2434
|
+
getRegionCountries(): Promise<_thorprovider_types.Country[]>;
|
|
2435
|
+
addShippingMethod(_cartId: string, _methodId: string): Promise<Cart>;
|
|
2436
|
+
initiatePaymentSession(_cartId: string, _providerId: string): Promise<void>;
|
|
2437
|
+
applyDiscountCode(cartId: string, code: string): Promise<Cart>;
|
|
2438
|
+
removeDiscountCode(cartId: string, _code: string): Promise<Cart>;
|
|
2439
|
+
getOrders(_options: GetOrdersOptions): Promise<Order[]>;
|
|
2440
|
+
getPaymentMethods(_options: PaymentMethodsOptions): Promise<PaymentMethod[]>;
|
|
2441
|
+
getStockLocations(): Promise<StockLocation[]>;
|
|
2442
|
+
checkInventoryLevels(): Promise<InventoryLevel[]>;
|
|
2443
|
+
validateCartStock(): Promise<StockValidation>;
|
|
2444
|
+
getFulfillmentOptions(): Promise<FulfillmentOption[]>;
|
|
2445
|
+
cancelOrder(_orderId: string): Promise<Order>;
|
|
2446
|
+
createFulfillment(_orderId: string): Promise<void>;
|
|
2447
|
+
createRefund(_orderId: string): Promise<void>;
|
|
2448
|
+
getAdminOrders(): Promise<{
|
|
2449
|
+
orders: Order[];
|
|
2450
|
+
count: number;
|
|
2451
|
+
}>;
|
|
2452
|
+
getStorefrontContext(): Promise<StorefrontContext>;
|
|
2453
|
+
isStorefrontRequired(): boolean;
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
/**
|
|
2457
|
+
* @thorprovider/adapters v2.0
|
|
2458
|
+
* Provider Factory - Create commerce providers dynamically
|
|
2459
|
+
*
|
|
2460
|
+
* This factory is bound to SupportedProviderType from @thorprovider/types (L1).
|
|
2461
|
+
* When adding a new provider:
|
|
2462
|
+
* 1. Update SupportedProviderType enum in packages/types/src/provider.ts
|
|
2463
|
+
* 2. Add new discriminated union case here
|
|
2464
|
+
* 3. Create packages/adapters/src/providers/[platform]/
|
|
2465
|
+
* 4. Implement CommerceProvider interface
|
|
2466
|
+
*/
|
|
2467
|
+
|
|
2468
|
+
/**
|
|
2469
|
+
* Supported provider types (imported from @thorprovider/types L1)
|
|
2470
|
+
* Kept for backward compatibility; prefer ProviderTypeString from @thorprovider/types
|
|
2471
|
+
*/
|
|
2472
|
+
type ProviderType = ProviderTypeString;
|
|
2473
|
+
/**
|
|
2474
|
+
* Provider configuration discriminated union
|
|
2475
|
+
*/
|
|
2476
|
+
type ProviderFactoryConfig = {
|
|
2477
|
+
provider: 'medusa';
|
|
2478
|
+
config: MedusaProviderConfig;
|
|
2479
|
+
} | {
|
|
2480
|
+
provider: 'shopify';
|
|
2481
|
+
config: ShopifyProviderConfig;
|
|
2482
|
+
} | {
|
|
2483
|
+
provider: 'bigcommerce';
|
|
2484
|
+
config: BigCommerceProviderConfig;
|
|
2485
|
+
} | {
|
|
2486
|
+
provider: 'woocommerce';
|
|
2487
|
+
config: WooCommerceProviderConfig;
|
|
2488
|
+
} | {
|
|
2489
|
+
provider: 'spree';
|
|
2490
|
+
config: SpreeProviderConfig;
|
|
2491
|
+
} | {
|
|
2492
|
+
provider: 'magento';
|
|
2493
|
+
config: MagentoProviderConfig;
|
|
2494
|
+
};
|
|
2495
|
+
/**
|
|
2496
|
+
* Runtime provider configuration (accepts any ProviderTypeString from env vars)
|
|
2497
|
+
*/
|
|
2498
|
+
type RuntimeProviderConfig = {
|
|
2499
|
+
provider: ProviderTypeString;
|
|
2500
|
+
config: Record<string, unknown>;
|
|
2501
|
+
};
|
|
2502
|
+
/**
|
|
2503
|
+
* Create a commerce provider instance
|
|
2504
|
+
*
|
|
2505
|
+
* @example
|
|
2506
|
+
* ```ts
|
|
2507
|
+
* const commerce = createProvider({
|
|
2508
|
+
* provider: 'medusa',
|
|
2509
|
+
* config: {
|
|
2510
|
+
* baseUrl: process.env.MEDUSA_BACKEND_URL,
|
|
2511
|
+
* publishableKey: process.env.MEDUSA_PUBLISHABLE_KEY,
|
|
2512
|
+
* }
|
|
2513
|
+
* });
|
|
2514
|
+
*
|
|
2515
|
+
* const products = await commerce.getProducts();
|
|
2516
|
+
* ```
|
|
2517
|
+
*/
|
|
2518
|
+
declare function createProvider(options: ProviderFactoryConfig | RuntimeProviderConfig): CommerceProvider;
|
|
2519
|
+
/**
|
|
2520
|
+
* Type guard to check if a provider is of a specific type
|
|
2521
|
+
*/
|
|
2522
|
+
declare function isProviderType<T extends ProviderType>(provider: CommerceProvider, type: T): boolean;
|
|
2523
|
+
|
|
2524
|
+
export { AdminAuthService, type AdminSession, AdminSessionService, BIGCOMMERCE_CAPABILITIES, type BackendMapping, type BackendMetadataAdapter, type BackendMetadataAdapterConfig, BigCommerceProvider, type BigCommerceProviderConfig, CHANNEL_ASSIGNED_AT_KEY, CHANNEL_ASSIGNED_BY_KEY, CHANNEL_SCOPE_KEY, type ChannelScopeMetadata, ChannelScopeValidationError, type ChannelScopeable, CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, type CircuitBreakerStats, type CircuitState, CommerceError, ConfigurationError, type Coordinates, type FulfillmentGroup, type FulfillmentPlan, type LogLevel, type Logger, MAGENTO_CAPABILITIES, MEDUSA_CAPABILITIES, MagentoProvider, type MagentoProviderConfig, MedusaMetadataAdapter, MedusaProvider, type MedusaProviderConfig, type MetricsOrderInput, type MetricsProductInput, MetricsService, type PlanFulfillmentShippingAddress, ProviderAPIError, type ProviderFactoryConfig, ProviderNotFoundError, type ProviderType, ResourceNotFoundError, SHOPIFY_CAPABILITIES, SPREE_CAPABILITIES, ShopifyProvider, type ShopifyProviderConfig, SpreeProvider, type SpreeProviderConfig, type UICartItem, type UICartTotals, type UIDiscountCode, type UIPaymentMethod, type UIShippingMethod, WOOCOMMERCE_CAPABILITIES, WooCommerceProvider, type WooCommerceProviderConfig, assertEntityBelongsToChannel, backendCircuitBreaker, buildChannelScopeMetadata, calculateDistance, createBackendMetadataAdapter, createLogger, createProvider, filterByChannel, filterGlobalOnly, geocodeAddress, getBackendProviderId, getCapabilityDescription, getChannelScope, isBackendCapabilities, isGlobalEntity, isProviderType, isScopedToChannel, moneyToNumber, moneyToNumberSafe, numberToMoney, partitionByChannel, planFulfillment, transformFulfillmentOption, transformInventoryLevel, transformStockLocation, transformStorefrontConfig, validateAssignedBy, validateChannelId, validateChannelScopeAssignment, validateEntityId, validatePaymentId };
|