@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.
Files changed (95) hide show
  1. package/.turbo/turbo-build.log +18 -0
  2. package/.turbo/turbo-test.log +1 -0
  3. package/.turbo/turbo-type-check.log +0 -0
  4. package/AGENTS.md +1 -0
  5. package/CHANGELOG.md +271 -0
  6. package/README.md +634 -0
  7. package/dist/.tsbuildinfo +1 -0
  8. package/dist/index.d.mts +2524 -0
  9. package/dist/index.d.ts +2524 -0
  10. package/dist/index.js +8136 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/index.mjs +8045 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/docs/RETRY_SOLUTION_SUMMARY.md +55 -0
  15. package/docs/authentication.md +165 -0
  16. package/docs/capabilities-system.md +143 -0
  17. package/docs/category-customization.md +309 -0
  18. package/docs/fetch-reliability-solution.md +399 -0
  19. package/docs/getting-started.md +154 -0
  20. package/docs/multi-tenant-channel-scoping.md +225 -0
  21. package/docs/profile-management.md +147 -0
  22. package/docs/providers-overview.md +85 -0
  23. package/docs/services-overview.md +135 -0
  24. package/docs/update-documentation.md +113 -0
  25. package/package.json +43 -0
  26. package/publish.log +93 -0
  27. package/quick-reference.md +169 -0
  28. package/src/admin/AdminAuthService.ts +88 -0
  29. package/src/admin/AdminSessionService.ts +91 -0
  30. package/src/admin/MetricsService.ts +145 -0
  31. package/src/admin/index.ts +13 -0
  32. package/src/backend/BackendMetadataAdapter.ts +88 -0
  33. package/src/backend/factory.ts +107 -0
  34. package/src/backend/index.ts +12 -0
  35. package/src/backend/medusa/MedusaMetadataAdapter.ts +139 -0
  36. package/src/core/errors.js +161 -0
  37. package/src/core/errors.ts +132 -0
  38. package/src/core/fetch-utils.js +240 -0
  39. package/src/core/fetch-utils.ts +227 -0
  40. package/src/core/index.ts +8 -0
  41. package/src/core/logger.js +63 -0
  42. package/src/core/logger.ts +37 -0
  43. package/src/factory/index.ts +102 -0
  44. package/src/index.ts +205 -0
  45. package/src/lib/money-transform.ts +80 -0
  46. package/src/metadata/channel-scope-validation.js +136 -0
  47. package/src/metadata/channel-scope-validation.ts +151 -0
  48. package/src/metadata/channel-scope.js +174 -0
  49. package/src/metadata/channel-scope.ts +215 -0
  50. package/src/metadata/index.js +31 -0
  51. package/src/metadata/index.ts +37 -0
  52. package/src/providers/bigcommerce/bigcommerce.ts +6 -0
  53. package/src/providers/bigcommerce/index.ts +315 -0
  54. package/src/providers/bigcommerce/transforms.ts +227 -0
  55. package/src/providers/index.ts +22 -0
  56. package/src/providers/magento/index.ts +387 -0
  57. package/src/providers/magento/magento.ts +5 -0
  58. package/src/providers/magento/queries.ts +267 -0
  59. package/src/providers/magento/transforms.ts +249 -0
  60. package/src/providers/medusa/auth.js +601 -0
  61. package/src/providers/medusa/auth.ts +496 -0
  62. package/src/providers/medusa/fulfillment-planner.ts +225 -0
  63. package/src/providers/medusa/index.js +2485 -0
  64. package/src/providers/medusa/index.ts +4239 -0
  65. package/src/providers/medusa/medusa.ts +8 -0
  66. package/src/providers/medusa/payment.js +265 -0
  67. package/src/providers/medusa/payment.ts +269 -0
  68. package/src/providers/medusa/transforms.js +505 -0
  69. package/src/providers/medusa/transforms.ts +625 -0
  70. package/src/providers/shopify/index.ts +444 -0
  71. package/src/providers/shopify/mutations.ts +102 -0
  72. package/src/providers/shopify/queries.ts +324 -0
  73. package/src/providers/shopify/shopify.ts +7 -0
  74. package/src/providers/shopify/transforms.ts +270 -0
  75. package/src/providers/spree/index.ts +344 -0
  76. package/src/providers/spree/spree.ts +5 -0
  77. package/src/providers/spree/transforms.ts +254 -0
  78. package/src/providers/woocommerce/index.ts +310 -0
  79. package/src/providers/woocommerce/transforms.ts +254 -0
  80. package/src/providers/woocommerce/woocommerce.ts +5 -0
  81. package/src/resilience/README.md +299 -0
  82. package/src/resilience/circuit-breaker.ts +222 -0
  83. package/src/resilience/index.ts +10 -0
  84. package/src/types/capabilities.types.js +141 -0
  85. package/src/types/capabilities.types.ts +366 -0
  86. package/src/types/index.ts +24 -0
  87. package/src/types/provider.js +9 -0
  88. package/src/types/provider.ts +9 -0
  89. package/src/types/ui-responses.ts +261 -0
  90. package/src/utils/city-coordinates.ts +40 -0
  91. package/src/utils/geolocation.ts +52 -0
  92. package/src/utils/payment-utils.js +152 -0
  93. package/src/utils/payment-utils.ts +203 -0
  94. package/tsconfig.json +15 -0
  95. package/tsup.config.ts +14 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Geolocation utilities
3
+ *
4
+ * Framework-agnostic helpers for proximity-based fulfillment.
5
+ */
6
+
7
+ import { getCityCoordinates } from './city-coordinates';
8
+
9
+ export interface Coordinates {
10
+ lat: number;
11
+ lng: number;
12
+ }
13
+
14
+ /**
15
+ * Calculate distance between two coordinates using the Haversine formula.
16
+ * @returns Distance in kilometers
17
+ */
18
+ export function calculateDistance(from: Coordinates, to: Coordinates): number {
19
+ const R = 6371;
20
+ const dLat = toRad(to.lat - from.lat);
21
+ const dLng = toRad(to.lng - from.lng);
22
+
23
+ const a =
24
+ Math.sin(dLat / 2) * Math.sin(dLat / 2) +
25
+ Math.cos(toRad(from.lat)) *
26
+ Math.cos(toRad(to.lat)) *
27
+ Math.sin(dLng / 2) *
28
+ Math.sin(dLng / 2);
29
+
30
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
31
+ return R * c;
32
+ }
33
+
34
+ function toRad(degrees: number): number {
35
+ return degrees * (Math.PI / 180);
36
+ }
37
+
38
+ /**
39
+ * Geocode an address to coordinates.
40
+ *
41
+ * This is intentionally a best-effort approximation (city + country lookup).
42
+ * For production-grade accuracy, integrate a real geocoding provider.
43
+ */
44
+ export async function geocodeAddress(address: {
45
+ city?: string;
46
+ countryCode?: string;
47
+ postalCode?: string;
48
+ }): Promise<Coordinates | null> {
49
+ if (!address.city || !address.countryCode) return null;
50
+
51
+ return getCityCoordinates(address.city, address.countryCode);
52
+ }
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ /**
3
+ * @thorprovider/adapters - Payment Utilities
4
+ *
5
+ * Backend-agnostic utilities for extracting backend provider IDs from
6
+ * normalized PaymentMethod objects using metadata.
7
+ *
8
+ * This solves the problem of losing backend-specific provider IDs during
9
+ * transformation to frontend-friendly formats.
10
+ *
11
+ * @module payment-utils
12
+ * @since 2.0.0
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.getBackendProviderId = getBackendProviderId;
16
+ exports.validatePaymentId = validatePaymentId;
17
+ /**
18
+ * Extract backend provider ID from PaymentMethod
19
+ *
20
+ * Uses the `_backendMapping` metadata to retrieve the original
21
+ * backend-specific provider ID that should be sent to API calls.
22
+ *
23
+ * **Why this exists:**
24
+ * During transformation, we normalize backend IDs to friendly types:
25
+ * - Backend: 'pp_stripe_stripe' → Frontend: type 'card'
26
+ * - Backend: 'pp_system_default' → Frontend: type 'cash_on_delivery'
27
+ *
28
+ * But when making API calls, we need the ORIGINAL backend ID, not the type.
29
+ * This function extracts it from metadata.
30
+ *
31
+ * @param method - PaymentMethod with _backendMapping metadata
32
+ * @returns Backend provider ID (e.g., 'pp_stripe_stripe', 'pp_system_default')
33
+ * @throws {Error} If _backendMapping metadata is missing or invalid
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * // PaymentMethod from backend with metadata
38
+ * const method = {
39
+ * id: 'pp_system_default',
40
+ * type: 'cash_on_delivery',
41
+ * name: 'Cash on Delivery',
42
+ * metadata: {
43
+ * _backendMapping: {
44
+ * backend: 'medusa',
45
+ * originalId: 'pp_system_default',
46
+ * normalizedType: 'cash_on_delivery'
47
+ * }
48
+ * }
49
+ * };
50
+ *
51
+ * const providerId = getBackendProviderId(method);
52
+ * // Returns: 'pp_system_default'
53
+ *
54
+ * // Now safe to use with backend API:
55
+ * await commerce.initiatePaymentSession(cartId, providerId);
56
+ * ```
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * // Handling missing metadata
61
+ * try {
62
+ * const providerId = getBackendProviderId(methodWithoutMetadata);
63
+ * } catch (error) {
64
+ * console.error('Payment method missing backend mapping:', error.message);
65
+ * // Error: PaymentMethod 'stripe' is missing _backendMapping metadata.
66
+ * // This is required to extract the backend provider ID.
67
+ * }
68
+ * ```
69
+ */
70
+ function getBackendProviderId(method) {
71
+ var _a;
72
+ var mapping = (_a = method.metadata) === null || _a === void 0 ? void 0 : _a._backendMapping;
73
+ if (!mapping) {
74
+ throw new Error("PaymentMethod '".concat(method.id, "' is missing _backendMapping metadata. ") +
75
+ "This is required to extract the backend provider ID. " +
76
+ "Ensure the payment method was transformed with metadata preservation. " +
77
+ "Check transformPaymentMethod() implementation in your provider adapter.");
78
+ }
79
+ if (!mapping.originalId) {
80
+ throw new Error("PaymentMethod '".concat(method.id, "' has invalid _backendMapping metadata: ") +
81
+ "'originalId' field is missing or empty. " +
82
+ "Expected structure: { _backendMapping: { backend: 'medusa', originalId: 'pp_...', normalizedType: '...' } }");
83
+ }
84
+ return mapping.originalId;
85
+ }
86
+ /**
87
+ * Validate payment provider ID format
88
+ *
89
+ * Checks if the provider ID is a valid backend-specific identifier,
90
+ * not a normalized type like 'card', 'wallet', etc.
91
+ *
92
+ * **Why this exists:**
93
+ * Common bug: Accidentally sending normalized types to backend APIs:
94
+ * ❌ `initiatePaymentSession(cartId, 'card')` → Backend error
95
+ * ✅ `initiatePaymentSession(cartId, 'pp_stripe_stripe')` → Success
96
+ *
97
+ * This validation catches the bug at runtime with a helpful error message.
98
+ *
99
+ * @param id - Provider ID to validate
100
+ * @throws {Error} If ID appears to be a normalized type instead of backend ID
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * // Valid backend IDs - pass validation:
105
+ * validatePaymentId('pp_stripe_stripe'); // ✅ OK (Medusa)
106
+ * validatePaymentId('pp_system_default'); // ✅ OK (Medusa)
107
+ * validatePaymentId('shopify_payments'); // ✅ OK (Shopify)
108
+ * validatePaymentId('stripe'); // ✅ OK (WooCommerce)
109
+ * validatePaymentId('paypal_express'); // ✅ OK (generic)
110
+ *
111
+ * // Invalid (normalized types) - throw error:
112
+ * validatePaymentId('card'); // ❌ Throws error
113
+ * validatePaymentId('wallet'); // ❌ Throws error
114
+ * validatePaymentId('cash_on_delivery'); // ❌ Throws error
115
+ * ```
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * // Use before API calls:
120
+ * async function initiatePayment(cartId: string, providerId: string) {
121
+ * // Validate before sending to backend
122
+ * validatePaymentId(providerId);
123
+ *
124
+ * return await sdk.payment.initiatePaymentSession(cart, {
125
+ * provider_id: providerId
126
+ * });
127
+ * }
128
+ *
129
+ * // Catches bugs early:
130
+ * await initiatePayment(cartId, 'card');
131
+ * // ❌ Error: Invalid payment provider ID: 'card'.
132
+ * // This appears to be a normalized payment type, not a backend provider ID.
133
+ * // Use getBackendProviderId() to extract the correct backend ID from PaymentMethod.
134
+ * ```
135
+ */
136
+ function validatePaymentId(id) {
137
+ var normalizedTypes = [
138
+ 'card',
139
+ 'wallet',
140
+ 'bank_transfer',
141
+ 'buy_now_pay_later',
142
+ 'cash_on_delivery',
143
+ 'crypto',
144
+ 'other'
145
+ ];
146
+ if (normalizedTypes.includes(id)) {
147
+ throw new Error("Invalid payment provider ID: '".concat(id, "'. ") +
148
+ "This appears to be a normalized payment type, not a backend provider ID. " +
149
+ "Use getBackendProviderId() to extract the correct backend ID from PaymentMethod. " +
150
+ "Expected format examples: 'pp_stripe_stripe', 'pp_system_default', 'shopify_payments', 'stripe'");
151
+ }
152
+ }
@@ -0,0 +1,203 @@
1
+ /**
2
+ * @thorprovider/adapters - Payment Utilities
3
+ *
4
+ * Backend-agnostic utilities for extracting backend provider IDs from
5
+ * normalized PaymentMethod objects using metadata.
6
+ *
7
+ * This solves the problem of losing backend-specific provider IDs during
8
+ * transformation to frontend-friendly formats.
9
+ *
10
+ * @module payment-utils
11
+ * @since 2.0.0
12
+ */
13
+
14
+ import type { PaymentMethod } from '@thorprovider/types';
15
+
16
+ /**
17
+ * Backend mapping metadata stored in PaymentMethod.metadata
18
+ *
19
+ * This metadata is added during payment method transformation
20
+ * to preserve the original backend-specific identifier.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const metadata = {
25
+ * _backendMapping: {
26
+ * backend: 'medusa',
27
+ * originalId: 'pp_stripe_stripe',
28
+ * normalizedType: 'card'
29
+ * }
30
+ * };
31
+ * ```
32
+ */
33
+ export interface BackendMapping {
34
+ /**
35
+ * Backend type (e.g., 'medusa', 'shopify', 'woocommerce')
36
+ */
37
+ backend: string;
38
+
39
+ /**
40
+ * Original backend-specific provider ID
41
+ *
42
+ * Examples:
43
+ * - Medusa: 'pp_stripe_stripe', 'pp_paypal_paypal', 'pp_system_default'
44
+ * - Shopify: 'shopify_payments', 'paypal_express'
45
+ * - WooCommerce: 'stripe', 'paypal', 'cod'
46
+ */
47
+ originalId: string;
48
+
49
+ /**
50
+ * Normalized payment method type
51
+ *
52
+ * The frontend-friendly type we inferred from the backend ID
53
+ * (e.g., 'card', 'wallet', 'bank_transfer', 'cash_on_delivery')
54
+ */
55
+ normalizedType: string;
56
+ }
57
+
58
+ /**
59
+ * Extract backend provider ID from PaymentMethod
60
+ *
61
+ * Uses the `_backendMapping` metadata to retrieve the original
62
+ * backend-specific provider ID that should be sent to API calls.
63
+ *
64
+ * **Why this exists:**
65
+ * During transformation, we normalize backend IDs to friendly types:
66
+ * - Backend: 'pp_stripe_stripe' → Frontend: type 'card'
67
+ * - Backend: 'pp_system_default' → Frontend: type 'cash_on_delivery'
68
+ *
69
+ * But when making API calls, we need the ORIGINAL backend ID, not the type.
70
+ * This function extracts it from metadata.
71
+ *
72
+ * @param method - PaymentMethod with _backendMapping metadata
73
+ * @returns Backend provider ID (e.g., 'pp_stripe_stripe', 'pp_system_default')
74
+ * @throws {Error} If _backendMapping metadata is missing or invalid
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * // PaymentMethod from backend with metadata
79
+ * const method = {
80
+ * id: 'pp_system_default',
81
+ * type: 'cash_on_delivery',
82
+ * name: 'Cash on Delivery',
83
+ * metadata: {
84
+ * _backendMapping: {
85
+ * backend: 'medusa',
86
+ * originalId: 'pp_system_default',
87
+ * normalizedType: 'cash_on_delivery'
88
+ * }
89
+ * }
90
+ * };
91
+ *
92
+ * const providerId = getBackendProviderId(method);
93
+ * // Returns: 'pp_system_default'
94
+ *
95
+ * // Now safe to use with backend API:
96
+ * await commerce.initiatePaymentSession(cartId, providerId);
97
+ * ```
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * // Handling missing metadata
102
+ * try {
103
+ * const providerId = getBackendProviderId(methodWithoutMetadata);
104
+ * } catch (error) {
105
+ * console.error('Payment method missing backend mapping:', error.message);
106
+ * // Error: PaymentMethod 'stripe' is missing _backendMapping metadata.
107
+ * // This is required to extract the backend provider ID.
108
+ * }
109
+ * ```
110
+ */
111
+ export function getBackendProviderId(method: PaymentMethod): string {
112
+ const mapping = method.metadata?._backendMapping as BackendMapping | undefined;
113
+
114
+ if (!mapping) {
115
+ throw new Error(
116
+ `PaymentMethod '${method.id}' is missing _backendMapping metadata. ` +
117
+ `This is required to extract the backend provider ID. ` +
118
+ `Ensure the payment method was transformed with metadata preservation. ` +
119
+ `Check transformPaymentMethod() implementation in your provider adapter.`
120
+ );
121
+ }
122
+
123
+ if (!mapping.originalId) {
124
+ throw new Error(
125
+ `PaymentMethod '${method.id}' has invalid _backendMapping metadata: ` +
126
+ `'originalId' field is missing or empty. ` +
127
+ `Expected structure: { _backendMapping: { backend: 'medusa', originalId: 'pp_...', normalizedType: '...' } }`
128
+ );
129
+ }
130
+
131
+ return mapping.originalId;
132
+ }
133
+
134
+ /**
135
+ * Validate payment provider ID format
136
+ *
137
+ * Checks if the provider ID is a valid backend-specific identifier,
138
+ * not a normalized type like 'card', 'wallet', etc.
139
+ *
140
+ * **Why this exists:**
141
+ * Common bug: Accidentally sending normalized types to backend APIs:
142
+ * ❌ `initiatePaymentSession(cartId, 'card')` → Backend error
143
+ * ✅ `initiatePaymentSession(cartId, 'pp_stripe_stripe')` → Success
144
+ *
145
+ * This validation catches the bug at runtime with a helpful error message.
146
+ *
147
+ * @param id - Provider ID to validate
148
+ * @throws {Error} If ID appears to be a normalized type instead of backend ID
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * // Valid backend IDs - pass validation:
153
+ * validatePaymentId('pp_stripe_stripe'); // ✅ OK (Medusa)
154
+ * validatePaymentId('pp_system_default'); // ✅ OK (Medusa)
155
+ * validatePaymentId('shopify_payments'); // ✅ OK (Shopify)
156
+ * validatePaymentId('stripe'); // ✅ OK (WooCommerce)
157
+ * validatePaymentId('paypal_express'); // ✅ OK (generic)
158
+ *
159
+ * // Invalid (normalized types) - throw error:
160
+ * validatePaymentId('card'); // ❌ Throws error
161
+ * validatePaymentId('wallet'); // ❌ Throws error
162
+ * validatePaymentId('cash_on_delivery'); // ❌ Throws error
163
+ * ```
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * // Use before API calls:
168
+ * async function initiatePayment(cartId: string, providerId: string) {
169
+ * // Validate before sending to backend
170
+ * validatePaymentId(providerId);
171
+ *
172
+ * return await sdk.payment.initiatePaymentSession(cart, {
173
+ * provider_id: providerId
174
+ * });
175
+ * }
176
+ *
177
+ * // Catches bugs early:
178
+ * await initiatePayment(cartId, 'card');
179
+ * // ❌ Error: Invalid payment provider ID: 'card'.
180
+ * // This appears to be a normalized payment type, not a backend provider ID.
181
+ * // Use getBackendProviderId() to extract the correct backend ID from PaymentMethod.
182
+ * ```
183
+ */
184
+ export function validatePaymentId(id: string): void {
185
+ const normalizedTypes = [
186
+ 'card',
187
+ 'wallet',
188
+ 'bank_transfer',
189
+ 'buy_now_pay_later',
190
+ 'cash_on_delivery',
191
+ 'crypto',
192
+ 'other'
193
+ ];
194
+
195
+ if (normalizedTypes.includes(id)) {
196
+ throw new Error(
197
+ `Invalid payment provider ID: '${id}'. ` +
198
+ `This appears to be a normalized payment type, not a backend provider ID. ` +
199
+ `Use getBackendProviderId() to extract the correct backend ID from PaymentMethod. ` +
200
+ `Expected format examples: 'pp_stripe_stripe', 'pp_system_default', 'shopify_payments', 'stripe'`
201
+ );
202
+ }
203
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "outDir": "dist",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "incremental": true,
9
+ "tsBuildInfoFile": "./dist/.tsbuildinfo",
10
+ "moduleResolution": "bundler",
11
+ "baseUrl": "."
12
+ },
13
+ "include": ["src/**/*"],
14
+ "exclude": ["node_modules", "dist"]
15
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: {
5
+ 'index': 'src/index.ts'
6
+ },
7
+ format: ['cjs', 'esm'],
8
+ dts: true,
9
+ splitting: false,
10
+ sourcemap: true,
11
+ clean: true,
12
+ external: ['react', '@medusajs/types', '@tanstack/react-query'],
13
+ onSuccess: process.env.SKIP_TYPE_CHECK === 'true' ? undefined : 'tsc --noEmit --skipLibCheck'
14
+ })