@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
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @thorprovider/adapters v2.0
|
|
3
|
+
* Backend Capabilities System
|
|
4
|
+
*
|
|
5
|
+
* Defines what operations each backend platform supports.
|
|
6
|
+
* This is a compile-time capability detection system, NOT runtime feature flags.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: BackendCapabilities interface is defined in @thorprovider/types (L1: Foundation).
|
|
9
|
+
* This file re-exports it and provides platform-specific implementations.
|
|
10
|
+
*
|
|
11
|
+
* @see packages/core/docs/BACKEND_CAPABILITIES_ANALYSIS.md
|
|
12
|
+
* @see packages/core/docs/COMMERCE_PROVIDER_ARCHITECTURE.md
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { BackendCapabilities } from '@thorprovider/types';
|
|
16
|
+
|
|
17
|
+
export type { BackendCapabilities };
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Medusa backend capabilities
|
|
21
|
+
*
|
|
22
|
+
* @see https://docs.medusajs.com/api/store
|
|
23
|
+
*/
|
|
24
|
+
export const MEDUSA_CAPABILITIES: Readonly<BackendCapabilities> = {
|
|
25
|
+
// Profile Management
|
|
26
|
+
updateProfile: true,
|
|
27
|
+
updateEmail: false, // Security restriction
|
|
28
|
+
changePasswordDirect: false, // Email flow only
|
|
29
|
+
changePasswordViaEmail: true,
|
|
30
|
+
deleteAccount: true, // Implemented via ThorMedusaClient
|
|
31
|
+
|
|
32
|
+
// Avatar
|
|
33
|
+
uploadAvatar: false,
|
|
34
|
+
avatarViaMetadata: true,
|
|
35
|
+
|
|
36
|
+
// Custom Attributes
|
|
37
|
+
customAttributes: true,
|
|
38
|
+
|
|
39
|
+
// Orders
|
|
40
|
+
fetchOrders: true,
|
|
41
|
+
cancelOrder: true,
|
|
42
|
+
|
|
43
|
+
// Addresses
|
|
44
|
+
manageAddresses: true,
|
|
45
|
+
defaultAddress: true,
|
|
46
|
+
|
|
47
|
+
// Cart/Checkout
|
|
48
|
+
applyDiscounts: true,
|
|
49
|
+
shippingCalculation: true,
|
|
50
|
+
guestCheckout: true,
|
|
51
|
+
savedPaymentMethods: false, // Depends on payment provider
|
|
52
|
+
listPaymentProviders: true,
|
|
53
|
+
regionSpecificPayments: true,
|
|
54
|
+
|
|
55
|
+
// Wishlist
|
|
56
|
+
wishlist: false, // Requires custom implementation
|
|
57
|
+
|
|
58
|
+
// Search
|
|
59
|
+
advancedSearch: true,
|
|
60
|
+
facetedFilters: true,
|
|
61
|
+
|
|
62
|
+
// Reviews
|
|
63
|
+
productReviews: false, // Requires custom implementation
|
|
64
|
+
|
|
65
|
+
// Loyalty
|
|
66
|
+
loyaltyProgram: false, // Requires custom implementation
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Shopify backend capabilities
|
|
71
|
+
*
|
|
72
|
+
* @see https://shopify.dev/docs/api/storefront
|
|
73
|
+
*/
|
|
74
|
+
export const SHOPIFY_CAPABILITIES: Readonly<BackendCapabilities> = {
|
|
75
|
+
// Profile Management
|
|
76
|
+
updateProfile: true,
|
|
77
|
+
updateEmail: true,
|
|
78
|
+
changePasswordDirect: true,
|
|
79
|
+
changePasswordViaEmail: true,
|
|
80
|
+
deleteAccount: false, // Requires admin API
|
|
81
|
+
|
|
82
|
+
// Avatar
|
|
83
|
+
uploadAvatar: false,
|
|
84
|
+
avatarViaMetadata: true,
|
|
85
|
+
|
|
86
|
+
// Custom Attributes
|
|
87
|
+
customAttributes: true,
|
|
88
|
+
|
|
89
|
+
// Orders
|
|
90
|
+
fetchOrders: true,
|
|
91
|
+
cancelOrder: true,
|
|
92
|
+
|
|
93
|
+
// Addresses
|
|
94
|
+
manageAddresses: true,
|
|
95
|
+
defaultAddress: true,
|
|
96
|
+
|
|
97
|
+
// Cart/Checkout
|
|
98
|
+
applyDiscounts: true,
|
|
99
|
+
shippingCalculation: true,
|
|
100
|
+
guestCheckout: true,
|
|
101
|
+
savedPaymentMethods: true,
|
|
102
|
+
listPaymentProviders: true,
|
|
103
|
+
regionSpecificPayments: false, // Global payment methods
|
|
104
|
+
|
|
105
|
+
// Wishlist
|
|
106
|
+
wishlist: false, // Requires app
|
|
107
|
+
|
|
108
|
+
// Search
|
|
109
|
+
advancedSearch: true,
|
|
110
|
+
facetedFilters: true,
|
|
111
|
+
|
|
112
|
+
// Reviews
|
|
113
|
+
productReviews: false, // Requires app
|
|
114
|
+
|
|
115
|
+
// Loyalty
|
|
116
|
+
loyaltyProgram: false, // Requires app
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* BigCommerce backend capabilities
|
|
121
|
+
*
|
|
122
|
+
* @see https://developer.bigcommerce.com/docs/rest-storefront
|
|
123
|
+
*/
|
|
124
|
+
export const BIGCOMMERCE_CAPABILITIES: Readonly<BackendCapabilities> = {
|
|
125
|
+
// Profile Management
|
|
126
|
+
updateProfile: true,
|
|
127
|
+
updateEmail: true,
|
|
128
|
+
changePasswordDirect: true,
|
|
129
|
+
changePasswordViaEmail: true,
|
|
130
|
+
deleteAccount: false,
|
|
131
|
+
|
|
132
|
+
// Avatar
|
|
133
|
+
uploadAvatar: false,
|
|
134
|
+
avatarViaMetadata: false,
|
|
135
|
+
|
|
136
|
+
// Custom Attributes
|
|
137
|
+
customAttributes: true,
|
|
138
|
+
|
|
139
|
+
// Orders
|
|
140
|
+
fetchOrders: true,
|
|
141
|
+
cancelOrder: false, // Admin API only
|
|
142
|
+
|
|
143
|
+
// Addresses
|
|
144
|
+
manageAddresses: true,
|
|
145
|
+
defaultAddress: false,
|
|
146
|
+
|
|
147
|
+
// Cart/Checkout
|
|
148
|
+
applyDiscounts: true,
|
|
149
|
+
shippingCalculation: true,
|
|
150
|
+
guestCheckout: true,
|
|
151
|
+
savedPaymentMethods: true,
|
|
152
|
+
listPaymentProviders: true,
|
|
153
|
+
regionSpecificPayments: false,
|
|
154
|
+
|
|
155
|
+
// Wishlist
|
|
156
|
+
wishlist: true, // Native support
|
|
157
|
+
|
|
158
|
+
// Search
|
|
159
|
+
advancedSearch: true,
|
|
160
|
+
facetedFilters: true,
|
|
161
|
+
|
|
162
|
+
// Reviews
|
|
163
|
+
productReviews: true, // Native support
|
|
164
|
+
|
|
165
|
+
// Loyalty
|
|
166
|
+
loyaltyProgram: false,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* WooCommerce backend capabilities
|
|
171
|
+
*
|
|
172
|
+
* @see https://developer.woocommerce.com/docs/apis/store-api
|
|
173
|
+
*/
|
|
174
|
+
export const WOOCOMMERCE_CAPABILITIES: Readonly<BackendCapabilities> = {
|
|
175
|
+
// Profile Management
|
|
176
|
+
updateProfile: true,
|
|
177
|
+
updateEmail: true,
|
|
178
|
+
changePasswordDirect: false, // WordPress handles auth
|
|
179
|
+
changePasswordViaEmail: true,
|
|
180
|
+
deleteAccount: false,
|
|
181
|
+
|
|
182
|
+
// Avatar
|
|
183
|
+
uploadAvatar: false,
|
|
184
|
+
avatarViaMetadata: false, // Gravatar-based
|
|
185
|
+
|
|
186
|
+
// Custom Attributes
|
|
187
|
+
customAttributes: true, // Via meta_data
|
|
188
|
+
|
|
189
|
+
// Orders
|
|
190
|
+
fetchOrders: true,
|
|
191
|
+
cancelOrder: true,
|
|
192
|
+
|
|
193
|
+
// Addresses
|
|
194
|
+
manageAddresses: true,
|
|
195
|
+
defaultAddress: false, // Billing/shipping only
|
|
196
|
+
|
|
197
|
+
// Cart/Checkout
|
|
198
|
+
applyDiscounts: true, // Coupon codes
|
|
199
|
+
shippingCalculation: true,
|
|
200
|
+
guestCheckout: true,
|
|
201
|
+
savedPaymentMethods: false,
|
|
202
|
+
listPaymentProviders: true,
|
|
203
|
+
regionSpecificPayments: false,
|
|
204
|
+
|
|
205
|
+
// Wishlist
|
|
206
|
+
wishlist: false, // Requires plugin
|
|
207
|
+
|
|
208
|
+
// Search
|
|
209
|
+
advancedSearch: false, // Basic WP search
|
|
210
|
+
facetedFilters: false, // Requires plugin
|
|
211
|
+
|
|
212
|
+
// Reviews
|
|
213
|
+
productReviews: true, // Native WP reviews
|
|
214
|
+
|
|
215
|
+
// Loyalty
|
|
216
|
+
loyaltyProgram: false,
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Spree Commerce backend capabilities
|
|
221
|
+
*
|
|
222
|
+
* @see https://docs.spreecommerce.org/api-reference
|
|
223
|
+
*/
|
|
224
|
+
export const SPREE_CAPABILITIES: Readonly<BackendCapabilities> = {
|
|
225
|
+
// Profile Management
|
|
226
|
+
updateProfile: true,
|
|
227
|
+
updateEmail: true,
|
|
228
|
+
changePasswordDirect: true,
|
|
229
|
+
changePasswordViaEmail: true,
|
|
230
|
+
deleteAccount: false,
|
|
231
|
+
|
|
232
|
+
// Avatar
|
|
233
|
+
uploadAvatar: false,
|
|
234
|
+
avatarViaMetadata: false,
|
|
235
|
+
|
|
236
|
+
// Custom Attributes
|
|
237
|
+
customAttributes: false,
|
|
238
|
+
|
|
239
|
+
// Orders
|
|
240
|
+
fetchOrders: true,
|
|
241
|
+
cancelOrder: true,
|
|
242
|
+
|
|
243
|
+
// Addresses
|
|
244
|
+
manageAddresses: true,
|
|
245
|
+
defaultAddress: true,
|
|
246
|
+
|
|
247
|
+
// Cart/Checkout
|
|
248
|
+
applyDiscounts: true,
|
|
249
|
+
shippingCalculation: true,
|
|
250
|
+
guestCheckout: true,
|
|
251
|
+
savedPaymentMethods: false,
|
|
252
|
+
listPaymentProviders: true,
|
|
253
|
+
regionSpecificPayments: false,
|
|
254
|
+
|
|
255
|
+
// Wishlist
|
|
256
|
+
wishlist: true, // Native support
|
|
257
|
+
|
|
258
|
+
// Search
|
|
259
|
+
advancedSearch: false,
|
|
260
|
+
facetedFilters: true, // Taxon-based filtering
|
|
261
|
+
|
|
262
|
+
// Reviews
|
|
263
|
+
productReviews: false, // Requires extension
|
|
264
|
+
|
|
265
|
+
// Loyalty
|
|
266
|
+
loyaltyProgram: false,
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Adobe Commerce / Magento backend capabilities
|
|
271
|
+
*
|
|
272
|
+
* @see https://developer.adobe.com/commerce/webapi/graphql/
|
|
273
|
+
*/
|
|
274
|
+
export const MAGENTO_CAPABILITIES: Readonly<BackendCapabilities> = {
|
|
275
|
+
// Profile Management
|
|
276
|
+
updateProfile: true,
|
|
277
|
+
updateEmail: true,
|
|
278
|
+
changePasswordDirect: true,
|
|
279
|
+
changePasswordViaEmail: true,
|
|
280
|
+
deleteAccount: false, // Admin only
|
|
281
|
+
|
|
282
|
+
// Avatar
|
|
283
|
+
uploadAvatar: false,
|
|
284
|
+
avatarViaMetadata: false,
|
|
285
|
+
|
|
286
|
+
// Custom Attributes
|
|
287
|
+
customAttributes: true, // EAV model
|
|
288
|
+
|
|
289
|
+
// Orders
|
|
290
|
+
fetchOrders: true,
|
|
291
|
+
cancelOrder: true,
|
|
292
|
+
|
|
293
|
+
// Addresses
|
|
294
|
+
manageAddresses: true,
|
|
295
|
+
defaultAddress: true,
|
|
296
|
+
|
|
297
|
+
// Cart/Checkout
|
|
298
|
+
applyDiscounts: true,
|
|
299
|
+
shippingCalculation: true,
|
|
300
|
+
guestCheckout: true,
|
|
301
|
+
savedPaymentMethods: true,
|
|
302
|
+
listPaymentProviders: true,
|
|
303
|
+
regionSpecificPayments: true, // Store-view scoped
|
|
304
|
+
|
|
305
|
+
// Wishlist
|
|
306
|
+
wishlist: true, // Native support
|
|
307
|
+
|
|
308
|
+
// Search
|
|
309
|
+
advancedSearch: true, // Elasticsearch/OpenSearch
|
|
310
|
+
facetedFilters: true, // Layered navigation
|
|
311
|
+
|
|
312
|
+
// Reviews
|
|
313
|
+
productReviews: true, // Native support
|
|
314
|
+
|
|
315
|
+
// Loyalty
|
|
316
|
+
loyaltyProgram: false, // Requires extension
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Type guard to check if an object is a valid BackendCapabilities
|
|
321
|
+
*/
|
|
322
|
+
export function isBackendCapabilities(obj: unknown): obj is BackendCapabilities {
|
|
323
|
+
if (typeof obj !== 'object' || obj === null) return false;
|
|
324
|
+
|
|
325
|
+
const capabilities = obj as Partial<BackendCapabilities>;
|
|
326
|
+
|
|
327
|
+
// Check required profile management capabilities
|
|
328
|
+
return (
|
|
329
|
+
typeof capabilities.updateProfile === 'boolean' &&
|
|
330
|
+
typeof capabilities.updateEmail === 'boolean' &&
|
|
331
|
+
typeof capabilities.changePasswordDirect === 'boolean'
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Get capability description for UI display
|
|
337
|
+
*/
|
|
338
|
+
export function getCapabilityDescription(capability: keyof BackendCapabilities): string {
|
|
339
|
+
const descriptions: Record<keyof BackendCapabilities, string> = {
|
|
340
|
+
updateProfile: 'Update profile information (name, phone)',
|
|
341
|
+
updateEmail: 'Change email address',
|
|
342
|
+
changePasswordDirect: 'Change password directly',
|
|
343
|
+
changePasswordViaEmail: 'Request password reset via email',
|
|
344
|
+
deleteAccount: 'Delete account (self-service)',
|
|
345
|
+
uploadAvatar: 'Upload profile picture',
|
|
346
|
+
avatarViaMetadata: 'Store avatar URL in metadata',
|
|
347
|
+
customAttributes: 'Custom customer attributes',
|
|
348
|
+
fetchOrders: 'View order history',
|
|
349
|
+
cancelOrder: 'Cancel orders',
|
|
350
|
+
manageAddresses: 'Add/update/delete addresses',
|
|
351
|
+
defaultAddress: 'Set default address',
|
|
352
|
+
applyDiscounts: 'Apply discount codes',
|
|
353
|
+
shippingCalculation: 'Calculate shipping rates',
|
|
354
|
+
guestCheckout: 'Checkout without account',
|
|
355
|
+
savedPaymentMethods: 'Save payment methods',
|
|
356
|
+
listPaymentProviders: 'List available payment providers',
|
|
357
|
+
regionSpecificPayments: 'Region-specific payment methods',
|
|
358
|
+
wishlist: 'Wishlist/favorites',
|
|
359
|
+
advancedSearch: 'Advanced product search',
|
|
360
|
+
facetedFilters: 'Filter by product attributes',
|
|
361
|
+
productReviews: 'Product reviews and ratings',
|
|
362
|
+
loyaltyProgram: 'Loyalty/rewards program',
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
return descriptions[capability] || capability;
|
|
366
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @thorprovider/adapters v2.0
|
|
3
|
+
* Type exports - unified commerce types
|
|
4
|
+
*
|
|
5
|
+
* Re-exports from @thorprovider/types package
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Re-export all shared types from @thorprovider/types
|
|
9
|
+
export type * from '@thorprovider/types';
|
|
10
|
+
|
|
11
|
+
// Provider-specific types (remain in adapters)
|
|
12
|
+
export type {
|
|
13
|
+
CommerceProvider,
|
|
14
|
+
ProviderConfig,
|
|
15
|
+
} from './provider';
|
|
16
|
+
|
|
17
|
+
// UI-ready response types (transformed for direct UI consumption)
|
|
18
|
+
export type {
|
|
19
|
+
UICartItem,
|
|
20
|
+
UICartTotals,
|
|
21
|
+
UIShippingMethod,
|
|
22
|
+
UIDiscountCode,
|
|
23
|
+
UIPaymentMethod,
|
|
24
|
+
} from './ui-responses';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @thorprovider/adapters v2.0
|
|
4
|
+
* Provider interface - unified commerce operations across all platforms
|
|
5
|
+
*
|
|
6
|
+
* NOTE: This file re-exports CommerceProvider from @thorprovider/types for backward compatibility.
|
|
7
|
+
* The actual interface definition lives in @thorprovider/types (L1: Foundation).
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @thorprovider/adapters v2.0
|
|
3
|
+
* Provider interface - unified commerce operations across all platforms
|
|
4
|
+
*
|
|
5
|
+
* NOTE: This file re-exports CommerceProvider from @thorprovider/types for backward compatibility.
|
|
6
|
+
* The actual interface definition lives in @thorprovider/types (L1: Foundation).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type { CommerceProvider, BackendCapabilities, ProviderConfig } from '@thorprovider/types';
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @thorprovider/adapters
|
|
3
|
+
* UI-ready response types
|
|
4
|
+
*
|
|
5
|
+
* These types extend domain types from @thorprovider/types (L1) but with transformations
|
|
6
|
+
* applied for direct UI consumption. This is where Money→number conversions happen.
|
|
7
|
+
*
|
|
8
|
+
* L3 (@thorprovider/components) should import these types, not the raw domain types.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
CartItem as DomainCartItem,
|
|
13
|
+
ShippingMethod as DomainShippingMethod,
|
|
14
|
+
Address,
|
|
15
|
+
Customer,
|
|
16
|
+
DiscountCode,
|
|
17
|
+
Money,
|
|
18
|
+
} from '@thorprovider/types';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* UI-ready cart item with prices as numbers
|
|
22
|
+
*
|
|
23
|
+
* Simplified cart item for UI consumption with prices in major currency units (e.g., dollars, euros).
|
|
24
|
+
* Transformed from domain CartItem by adapter services.
|
|
25
|
+
* Values come from Money.amount (decimal string in major units) parsed to number.
|
|
26
|
+
*
|
|
27
|
+
* This is a flattened structure optimized for UI display, unlike the nested
|
|
28
|
+
* domain CartItem which follows the Shopify/Medusa structure.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const uiItem: UICartItem = {
|
|
33
|
+
* id: 'item_123',
|
|
34
|
+
* productId: 'prod_abc',
|
|
35
|
+
* variantId: 'var_xyz',
|
|
36
|
+
* name: 'T-Shirt',
|
|
37
|
+
* variant: 'Red / Large',
|
|
38
|
+
* image: 'https://...',
|
|
39
|
+
* price: 19.99, // $19.99 in major units
|
|
40
|
+
* quantity: 2,
|
|
41
|
+
* total: 39.98, // $39.98 in major units
|
|
42
|
+
* isAvailable: true
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export interface UICartItem {
|
|
47
|
+
/** Unique item identifier */
|
|
48
|
+
id: string;
|
|
49
|
+
|
|
50
|
+
/** Product ID */
|
|
51
|
+
productId: string;
|
|
52
|
+
|
|
53
|
+
/** Variant ID */
|
|
54
|
+
variantId: string;
|
|
55
|
+
|
|
56
|
+
/** Product name */
|
|
57
|
+
name: string;
|
|
58
|
+
|
|
59
|
+
/** Product description (optional) */
|
|
60
|
+
description?: string;
|
|
61
|
+
|
|
62
|
+
/** Variant description (e.g., 'Red / Large') */
|
|
63
|
+
variant: string;
|
|
64
|
+
|
|
65
|
+
/** Product image URL */
|
|
66
|
+
image: string;
|
|
67
|
+
|
|
68
|
+
/** Unit price in major currency units (e.g., dollars, euros) */
|
|
69
|
+
price: number;
|
|
70
|
+
|
|
71
|
+
/** Quantity in cart */
|
|
72
|
+
quantity: number;
|
|
73
|
+
|
|
74
|
+
/** Total price (price × quantity) in major currency units */
|
|
75
|
+
total: number;
|
|
76
|
+
|
|
77
|
+
/** Whether item is available for purchase */
|
|
78
|
+
isAvailable?: boolean;
|
|
79
|
+
|
|
80
|
+
/** Maximum quantity available in stock */
|
|
81
|
+
maxQuantity?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* UI-ready cart totals with amounts as numbers
|
|
86
|
+
*
|
|
87
|
+
* All monetary values are in major currency units (e.g., dollars, euros).
|
|
88
|
+
* Values come from Money.amount (decimal string in major units) parsed to number.
|
|
89
|
+
* Transformed from domain CartCost by adapter services.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const totals: UICartTotals = {
|
|
94
|
+
* subtotal: 59.97, // $59.97
|
|
95
|
+
* discount: 10.00, // $10.00
|
|
96
|
+
* shipping: 5.00, // $5.00
|
|
97
|
+
* tax: 5.39, // $5.39
|
|
98
|
+
* total: 60.36, // $60.36
|
|
99
|
+
* currency: 'USD',
|
|
100
|
+
* itemCount: 3
|
|
101
|
+
* }
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export interface UICartTotals {
|
|
105
|
+
/** Subtotal before discounts/shipping/tax (in major currency units) */
|
|
106
|
+
subtotal: number;
|
|
107
|
+
|
|
108
|
+
/** Discount amount if any (in major currency units) */
|
|
109
|
+
discount?: number;
|
|
110
|
+
|
|
111
|
+
/** Discount code applied */
|
|
112
|
+
discountCode?: string;
|
|
113
|
+
|
|
114
|
+
/** Shipping cost (in major currency units) */
|
|
115
|
+
shipping?: number;
|
|
116
|
+
|
|
117
|
+
/** Tax amount (in major currency units) */
|
|
118
|
+
tax?: number;
|
|
119
|
+
|
|
120
|
+
/** Final total amount (in major currency units) */
|
|
121
|
+
total: number;
|
|
122
|
+
|
|
123
|
+
/** Currency code (ISO 4217, e.g., 'USD', 'EUR') */
|
|
124
|
+
currency: string;
|
|
125
|
+
|
|
126
|
+
/** Total number of items in cart */
|
|
127
|
+
itemCount: number;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* UI-ready shipping method with price as number
|
|
132
|
+
*
|
|
133
|
+
* Price is in the currency's smallest unit.
|
|
134
|
+
* Transformed from domain ShippingMethod by adapter services.
|
|
135
|
+
*
|
|
136
|
+
* Includes alias fields for compatibility with existing checkout components.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* const method: UIShippingMethod = {
|
|
141
|
+
* id: 'ship_standard',
|
|
142
|
+
* methodId: 'ship_standard', // alias for id
|
|
143
|
+
* name: 'Standard Shipping',
|
|
144
|
+
* price: 500, // $5.00 as 500 cents
|
|
145
|
+
* amount: 500, // alias for price
|
|
146
|
+
* estimatedDays: '3-5 business days'
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export interface UIShippingMethod {
|
|
151
|
+
/** Unique identifier */
|
|
152
|
+
id: string;
|
|
153
|
+
|
|
154
|
+
/** Alias for id (for compatibility with checkout components) */
|
|
155
|
+
methodId: string;
|
|
156
|
+
|
|
157
|
+
/** Display name */
|
|
158
|
+
name: string;
|
|
159
|
+
|
|
160
|
+
/** Shipping price in smallest currency unit */
|
|
161
|
+
price: number;
|
|
162
|
+
|
|
163
|
+
/** Alias for price (for compatibility with checkout components) */
|
|
164
|
+
amount: number;
|
|
165
|
+
|
|
166
|
+
/** Optional description */
|
|
167
|
+
description?: string;
|
|
168
|
+
|
|
169
|
+
/** Estimated delivery time (human-readable string) */
|
|
170
|
+
estimatedDays?: string;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* UI-ready discount code with value as number
|
|
175
|
+
*
|
|
176
|
+
* Transformed from domain DiscountCode by adapter services.
|
|
177
|
+
* Value is in the currency's smallest unit for fixed discounts,
|
|
178
|
+
* or a percentage (0-100) for percentage discounts.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* // Fixed discount
|
|
183
|
+
* const fixedDiscount: UIDiscountCode = {
|
|
184
|
+
* code: 'SAVE10',
|
|
185
|
+
* value: 1000, // $10.00 as 1000 cents
|
|
186
|
+
* isPercentage: false,
|
|
187
|
+
* description: 'Save $10 on your order'
|
|
188
|
+
* }
|
|
189
|
+
*
|
|
190
|
+
* // Percentage discount
|
|
191
|
+
* const percentDiscount: UIDiscountCode = {
|
|
192
|
+
* code: 'SAVE20',
|
|
193
|
+
* value: 20, // 20%
|
|
194
|
+
* isPercentage: true,
|
|
195
|
+
* description: 'Save 20% on your order'
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export interface UIDiscountCode {
|
|
200
|
+
/** Discount code */
|
|
201
|
+
code: string;
|
|
202
|
+
|
|
203
|
+
/** Discount value - either amount in smallest currency unit or percentage (0-100) */
|
|
204
|
+
value: number;
|
|
205
|
+
|
|
206
|
+
/** Whether value is a percentage (true) or fixed amount (false) */
|
|
207
|
+
isPercentage: boolean;
|
|
208
|
+
|
|
209
|
+
/** Human-readable description of the discount */
|
|
210
|
+
description?: string;
|
|
211
|
+
|
|
212
|
+
/** Minimum purchase amount required (in smallest currency unit) */
|
|
213
|
+
minimumAmount?: number;
|
|
214
|
+
|
|
215
|
+
/** Expiration date */
|
|
216
|
+
expiresAt?: Date;
|
|
217
|
+
|
|
218
|
+
/** Maximum number of uses allowed */
|
|
219
|
+
maxUses?: number;
|
|
220
|
+
|
|
221
|
+
/** Current usage count */
|
|
222
|
+
usageCount?: number;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* UI-ready payment method for checkout selection
|
|
227
|
+
*
|
|
228
|
+
* Simplified version of domain PaymentMethod with additional
|
|
229
|
+
* providerId field for backend-specific provider identification.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* const payment: UIPaymentMethod = {
|
|
234
|
+
* id: 'pp_stripe_stripe',
|
|
235
|
+
* providerId: 'stripe',
|
|
236
|
+
* name: 'Credit Card',
|
|
237
|
+
* description: 'Visa, Mastercard, American Express'
|
|
238
|
+
* }
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
export interface UIPaymentMethod {
|
|
242
|
+
/** Unique identifier */
|
|
243
|
+
id: string;
|
|
244
|
+
|
|
245
|
+
/** Provider identifier (e.g., 'stripe', 'paypal', 'manual') */
|
|
246
|
+
providerId: string;
|
|
247
|
+
|
|
248
|
+
/** Display name for UI */
|
|
249
|
+
name: string;
|
|
250
|
+
|
|
251
|
+
/** Optional description */
|
|
252
|
+
description?: string;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Re-export domain types that don't need transformation
|
|
257
|
+
*
|
|
258
|
+
* These types are used as-is from L1 without modification.
|
|
259
|
+
* L3 can import them from here for convenience.
|
|
260
|
+
*/
|
|
261
|
+
export type { Address, Customer, DiscountCode };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* City coordinates lookup table
|
|
3
|
+
*
|
|
4
|
+
* Lightweight approximation for geocoding without external APIs.
|
|
5
|
+
* Keep this small and extend as needed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface CityCoordinates {
|
|
9
|
+
lat: number;
|
|
10
|
+
lng: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const CITY_COORDINATES: Record<string, Record<string, CityCoordinates>> = {
|
|
14
|
+
US: {
|
|
15
|
+
'New York': { lat: 40.7128, lng: -74.0060 },
|
|
16
|
+
'Los Angeles': { lat: 34.0522, lng: -118.2437 },
|
|
17
|
+
Chicago: { lat: 41.8781, lng: -87.6298 },
|
|
18
|
+
Miami: { lat: 25.7617, lng: -80.1918 },
|
|
19
|
+
},
|
|
20
|
+
GB: {
|
|
21
|
+
London: { lat: 51.5074, lng: -0.1278 },
|
|
22
|
+
Manchester: { lat: 53.4808, lng: -2.2426 },
|
|
23
|
+
},
|
|
24
|
+
DE: {
|
|
25
|
+
Berlin: { lat: 52.52, lng: 13.405 },
|
|
26
|
+
Hamburg: { lat: 53.5511, lng: 9.9937 },
|
|
27
|
+
},
|
|
28
|
+
ES: {
|
|
29
|
+
Madrid: { lat: 40.4168, lng: -3.7038 },
|
|
30
|
+
Barcelona: { lat: 41.3851, lng: 2.1734 },
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function getCityCoordinates(city: string, countryCode: string): CityCoordinates | null {
|
|
35
|
+
const country = CITY_COORDINATES[countryCode.toUpperCase()];
|
|
36
|
+
if (!country) return null;
|
|
37
|
+
|
|
38
|
+
const cityKey = Object.keys(country).find((key) => key.toLowerCase() === city.toLowerCase());
|
|
39
|
+
return cityKey ? country[cityKey] : null;
|
|
40
|
+
}
|