@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,145 @@
1
+ /**
2
+ * Metrics Calculation Service
3
+ *
4
+ * Framework-agnostic business logic for calculating dashboard metrics
5
+ * from raw order and product data.
6
+ *
7
+ * @remarks
8
+ * - L2: Pure business logic, no framework dependencies
9
+ * - Works with @thorprovider/types Order and Product interfaces
10
+ * - Stateless static methods for easy testing
11
+ *
12
+ * @module admin/MetricsService
13
+ */
14
+
15
+ import type { DashboardMetrics, ChartDataPoint } from '@thorprovider/types';
16
+
17
+ /**
18
+ * Raw order data for metrics calculation
19
+ *
20
+ * @remarks
21
+ * Minimal interface to avoid coupling to specific Order type fields.
22
+ * Accepts the common fields available across all commerce providers.
23
+ */
24
+ export interface MetricsOrderInput {
25
+ total?: number;
26
+ status?: string;
27
+ created_at?: string;
28
+ createdAt?: string;
29
+ }
30
+
31
+ /**
32
+ * Raw product data for metrics calculation
33
+ */
34
+ export interface MetricsProductInput {
35
+ id: string;
36
+ variants?: Array<{
37
+ quantityAvailable?: number;
38
+ }>;
39
+ }
40
+
41
+ /**
42
+ * Metrics Service
43
+ *
44
+ * Calculates dashboard analytics from raw commerce data.
45
+ * All methods are static and pure (no side effects).
46
+ */
47
+ export class MetricsService {
48
+ /** Threshold for low stock alerts */
49
+ static readonly LOW_STOCK_THRESHOLD = 10;
50
+
51
+ /**
52
+ * Calculate complete dashboard metrics from orders and products
53
+ *
54
+ * @param orders - Array of order data
55
+ * @param products - Array of product data
56
+ * @returns Calculated DashboardMetrics
57
+ */
58
+ static calculate(
59
+ orders: MetricsOrderInput[],
60
+ products: MetricsProductInput[],
61
+ ): DashboardMetrics {
62
+ const now = new Date();
63
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
64
+ const weekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
65
+ const monthAgo = new Date(today.getTime() - 30 * 24 * 60 * 60 * 1000);
66
+
67
+ // Calculate sales
68
+ const totalSales = orders.reduce((sum, o) => sum + (o.total || 0), 0);
69
+ const todaySales = orders
70
+ .filter((o) => new Date(o.created_at || o.createdAt || '') >= today)
71
+ .reduce((sum, o) => sum + (o.total || 0), 0);
72
+ const weekSales = orders
73
+ .filter((o) => new Date(o.created_at || o.createdAt || '') >= weekAgo)
74
+ .reduce((sum, o) => sum + (o.total || 0), 0);
75
+ const monthSales = orders
76
+ .filter((o) => new Date(o.created_at || o.createdAt || '') >= monthAgo)
77
+ .reduce((sum, o) => sum + (o.total || 0), 0);
78
+
79
+ // Calculate orders by status
80
+ const ordersByStatus = {
81
+ total: orders.length,
82
+ pending: orders.filter((o) => o.status === 'pending').length,
83
+ processing: orders.filter((o) => o.status === 'processing').length,
84
+ completed: orders.filter((o) => o.status === 'completed').length,
85
+ };
86
+
87
+ // Calculate products
88
+ const lowStockCount = products.filter((p) => {
89
+ const totalQty = (p.variants || []).reduce(
90
+ (sum, v) => sum + (v.quantityAvailable || 0),
91
+ 0,
92
+ );
93
+ return totalQty < MetricsService.LOW_STOCK_THRESHOLD;
94
+ }).length;
95
+
96
+ const productsMetrics = {
97
+ total: products.length,
98
+ lowStock: lowStockCount,
99
+ };
100
+
101
+ // Generate chart data (last 7 days)
102
+ const chartData = MetricsService.generateChartData(orders, today);
103
+
104
+ return {
105
+ sales: {
106
+ total: totalSales,
107
+ today: todaySales,
108
+ week: weekSales,
109
+ month: monthSales,
110
+ },
111
+ orders: ordersByStatus,
112
+ products: productsMetrics,
113
+ chartData,
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Generate chart data for the last 7 days
119
+ */
120
+ private static generateChartData(
121
+ orders: MetricsOrderInput[],
122
+ today: Date,
123
+ ): ChartDataPoint[] {
124
+ const chartData: ChartDataPoint[] = [];
125
+
126
+ for (let i = 6; i >= 0; i--) {
127
+ const date = new Date(today.getTime() - i * 24 * 60 * 60 * 1000);
128
+ const nextDate = new Date(date.getTime() + 24 * 60 * 60 * 1000);
129
+
130
+ const daySales = orders
131
+ .filter((o) => {
132
+ const orderDate = new Date(o.created_at || o.createdAt || '');
133
+ return orderDate >= date && orderDate < nextDate;
134
+ })
135
+ .reduce((sum, o) => sum + (o.total || 0), 0);
136
+
137
+ chartData.push({
138
+ date: date.toISOString().split('T')[0],
139
+ sales: daySales,
140
+ });
141
+ }
142
+
143
+ return chartData;
144
+ }
145
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Admin Services
3
+ *
4
+ * Central export point for all admin-related services.
5
+ *
6
+ * @module admin
7
+ */
8
+
9
+ export { AdminAuthService } from './AdminAuthService';
10
+ export { AdminSessionService } from './AdminSessionService';
11
+ export type { AdminSession } from './AdminSessionService';
12
+ export { MetricsService } from './MetricsService';
13
+ export type { MetricsOrderInput, MetricsProductInput } from './MetricsService';
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Backend Metadata Adapter Interface
3
+ *
4
+ * Framework-agnostic interface for storing configuration in backend metadata fields.
5
+ * This replaces the need for a separate database (SQLite/Supabase).
6
+ *
7
+ * Each backend (Medusa, Shopify, WordPress) implements this interface
8
+ * using their native metadata/metafields/postmeta capabilities.
9
+ *
10
+ * @module backend/BackendMetadataAdapter
11
+ */
12
+
13
+ /**
14
+ * Backend Metadata Adapter
15
+ *
16
+ * @remarks
17
+ * Supported resource types by backend:
18
+ * - Medusa: `'sales_channel'`, `'customer'`, `'order'` (via admin API)
19
+ * - Shopify: Uses metafields API (TBD)
20
+ * - WordPress: Uses post_meta or user_meta (TBD)
21
+ *
22
+ * Multi-tenant channel scoping:
23
+ * Use with `'customer'` / `'order'` resource types and the well-known key
24
+ * `'sales_channel_id'` to tag entities to a specific sales channel.
25
+ * See `@thorprovider/adapters/metadata/channel-scope` for helper utilities.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Store site configuration in Medusa sales channel metadata
30
+ * await adapter.setMetadata(
31
+ * 'sales_channel',
32
+ * 'sc_01HXXX',
33
+ * 'site_config',
34
+ * { version: '2026-03-25', config: {...} }
35
+ * );
36
+ *
37
+ * // Tag a customer to a sales channel (multi-tenant)
38
+ * await adapter.setMetadata(
39
+ * 'customer',
40
+ * 'cus_01HXXX',
41
+ * 'sales_channel_id',
42
+ * 'sc_01HXXX'
43
+ * );
44
+ * ```
45
+ */
46
+ export interface BackendMetadataAdapter {
47
+ /**
48
+ * Get metadata value from backend resource
49
+ *
50
+ * @param resourceType - Type of resource (`'sales_channel'` | `'customer'` | `'order'` | `'store'`)
51
+ * @param resourceId - ID of the resource
52
+ * @param key - Metadata key (e.g., `'site_config'`, `'sales_channel_id'`)
53
+ * @returns Metadata value or null if not found
54
+ */
55
+ getMetadata(
56
+ resourceType: string,
57
+ resourceId: string,
58
+ key: string
59
+ ): Promise<any | null>;
60
+
61
+ /**
62
+ * Set metadata value on backend resource
63
+ *
64
+ * @param resourceType - Type of resource
65
+ * @param resourceId - ID of the resource
66
+ * @param key - Metadata key
67
+ * @param value - Metadata value (will be JSON serialized)
68
+ */
69
+ setMetadata(
70
+ resourceType: string,
71
+ resourceId: string,
72
+ key: string,
73
+ value: any
74
+ ): Promise<void>;
75
+
76
+ /**
77
+ * Delete metadata key from backend resource
78
+ *
79
+ * @param resourceType - Type of resource
80
+ * @param resourceId - ID of the resource
81
+ * @param key - Metadata key
82
+ */
83
+ deleteMetadata(
84
+ resourceType: string,
85
+ resourceId: string,
86
+ key: string
87
+ ): Promise<void>;
88
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Backend Metadata Adapter Factory
3
+ *
4
+ * Framework-agnostic factory to create backend metadata adapters for admin/dashboard.
5
+ * Keeps vendor-specific code in L2, prevents lock-in in L5.
6
+ *
7
+ * @remarks
8
+ * This factory is distinct from the main provider factory (createProvider).
9
+ * It's used for admin operations that require metadata/catalog access.
10
+ * Provider types are imported from @thorprovider/types (L1) to maintain sync.
11
+ *
12
+ * @module backend/factory
13
+ */
14
+
15
+ import Medusa from '@medusajs/js-sdk';
16
+ import { MedusaMetadataAdapter } from './medusa/MedusaMetadataAdapter';
17
+ import type { BackendMetadataAdapter } from './BackendMetadataAdapter';
18
+ import type { ProviderTypeString } from '@thorprovider/types';
19
+
20
+ /**
21
+ * Configuration for creating a backend metadata adapter
22
+ *
23
+ * @remarks
24
+ * Currently only 'medusa' is implemented. When adding Shopify/WooCommerce metadata adapters:
25
+ * 1. Uncomment the provider type in packages/types/src/provider.ts
26
+ * 2. Update this interface to accept the new provider type
27
+ * 3. Implement ShopifyMetadataAdapter, WooCommerceMetadataAdapter
28
+ * 4. Add cases to createBackendMetadataAdapter() switch
29
+ */
30
+ export interface BackendMetadataAdapterConfig {
31
+ /** Backend provider type (from @thorprovider/types L1) */
32
+ provider: ProviderTypeString;
33
+
34
+ /** Backend base URL */
35
+ baseUrl: string;
36
+
37
+ /** Publishable API key (for storefront access) */
38
+ publishableKey?: string;
39
+
40
+ /** Enable debug logging */
41
+ debug?: boolean;
42
+
43
+ /**
44
+ * Secret admin API key (from COMMERCE_ADMIN_API_KEY).
45
+ * When provided, the metadata adapter SDK instance will send
46
+ * `x-medusa-access-token` header on all admin requests.
47
+ * Required for getMetadata/setMetadata to work after removing email/password auth.
48
+ */
49
+ adminApiKey?: string;
50
+ }
51
+
52
+ /**
53
+ * Create a backend metadata adapter (Factory Pattern)
54
+ *
55
+ * Keeps vendor-specific code in L2, prevents lock-in in L5.
56
+ * L5 only provides configuration from env vars.
57
+ *
58
+ * @param config - Adapter configuration
59
+ * @returns BackendMetadataAdapter instance
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * // In L5 (starters)
64
+ * import { createBackendMetadataAdapter } from '@thorprovider/adapters';
65
+ *
66
+ * export const metadataAdapter = createBackendMetadataAdapter({
67
+ * provider: process.env.NEXT_PUBLIC_COMMERCE_PROVIDER as any,
68
+ * baseUrl: process.env.NEXT_PUBLIC_COMMERCE_API_URL!,
69
+ * publishableKey: process.env.NEXT_PUBLIC_COMMERCE_API_KEY!,
70
+ * });
71
+ * ```
72
+ *
73
+ * @throws {Error} If provider is not supported
74
+ */
75
+ export function createBackendMetadataAdapter(
76
+ config: BackendMetadataAdapterConfig
77
+ ): BackendMetadataAdapter {
78
+ const { provider, baseUrl, publishableKey, debug } = config;
79
+
80
+ if (provider === 'medusa') {
81
+ const { adminApiKey } = config;
82
+
83
+ // Create Medusa SDK client instance
84
+ const medusa = new Medusa({
85
+ baseUrl,
86
+ publishableKey,
87
+ debug: debug ?? false,
88
+ // When adminApiKey is provided: sends x-medusa-access-token on all requests.
89
+ // When not provided: requests are unauthenticated — admin routes will 401.
90
+ ...(adminApiKey && { apiKey: adminApiKey }),
91
+ });
92
+
93
+ return new MedusaMetadataAdapter(medusa);
94
+ }
95
+
96
+ if (provider === 'shopify') {
97
+ // TODO: Implement Shopify metadata adapter
98
+ throw new Error('Shopify metadata adapter not yet implemented');
99
+ }
100
+
101
+ if (provider === 'woocommerce') {
102
+ // TODO: Implement WooCommerce metadata adapter
103
+ throw new Error('WooCommerce metadata adapter not yet implemented');
104
+ }
105
+
106
+ throw new Error(`Unsupported provider: ${provider}`);
107
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Backend Metadata Adapters
3
+ *
4
+ * Central export point for all backend metadata adapters.
5
+ * Framework-agnostic factory pattern to prevent vendor lock-in in L5.
6
+ *
7
+ * @module backend
8
+ */
9
+
10
+ export * from './BackendMetadataAdapter';
11
+ export * from './factory';
12
+ export * from './medusa/MedusaMetadataAdapter';
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Medusa Metadata Adapter
3
+ *
4
+ * Implementation of BackendMetadataAdapter for Medusa.js v2.
5
+ * Uses Medusa's native metadata fields on sales_channel, customer, and order resources.
6
+ *
7
+ * Supported resource types:
8
+ * - `'sales_channel'` — site config, channel-level settings
9
+ * - `'customer'` — multi-tenant scoping (`sales_channel_id` key)
10
+ * - `'order'` — multi-tenant scoping (`sales_channel_id` key)
11
+ *
12
+ * All operations require admin-level JWT authentication.
13
+ *
14
+ * @module backend/medusa/MedusaMetadataAdapter
15
+ */
16
+
17
+ import type Medusa from '@medusajs/js-sdk';
18
+ import type { BackendMetadataAdapter } from '../BackendMetadataAdapter';
19
+
20
+ /**
21
+ * Medusa Metadata Adapter
22
+ *
23
+ * @remarks
24
+ * - Supports 'sales_channel' and 'store' resource types
25
+ * - Uses Medusa admin API (requires admin token)
26
+ * - Metadata is stored as JSON in the metadata field
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const adapter = new MedusaMetadataAdapter(medusaClient);
31
+ *
32
+ * // Store site configuration
33
+ * await adapter.setMetadata(
34
+ * 'sales_channel',
35
+ * 'sc_01HXXX',
36
+ * 'site_config',
37
+ * { version: '2026-03-25', config: {...} }
38
+ * );
39
+ * ```
40
+ */
41
+ export class MedusaMetadataAdapter implements BackendMetadataAdapter {
42
+ constructor(private sdk: Medusa) {}
43
+
44
+ /**
45
+ * Get metadata value from Medusa resource
46
+ */
47
+ async getMetadata(
48
+ resourceType: string,
49
+ resourceId: string,
50
+ key: string
51
+ ): Promise<any | null> {
52
+ try {
53
+ if (resourceType === 'sales_channel') {
54
+ const { sales_channel } = await this.sdk.admin.salesChannel.retrieve(
55
+ resourceId
56
+ );
57
+ return sales_channel.metadata?.[key] ?? null;
58
+ }
59
+
60
+ if (resourceType === 'customer') {
61
+ const result = await (this.sdk as any).admin.customer.retrieve(resourceId);
62
+ return result?.customer?.metadata?.[key] ?? null;
63
+ }
64
+
65
+ if (resourceType === 'order') {
66
+ const result = await (this.sdk as any).admin.order.retrieve(resourceId);
67
+ return result?.order?.metadata?.[key] ?? null;
68
+ }
69
+
70
+ // Note: Store API in Medusa v2 requires store ID
71
+ // Store support can be added when we have a reliable way to get the store ID
72
+
73
+ throw new Error(
74
+ `Unsupported resource type: ${resourceType}. ` +
75
+ `Supported: 'sales_channel', 'customer', 'order'.`
76
+ );
77
+ } catch (error: any) {
78
+ // If resource not found or metadata key doesn't exist, return null
79
+ if (error.response?.status === 404 || error.status === 404) {
80
+ return null;
81
+ }
82
+ throw error;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Set metadata value on Medusa resource
88
+ */
89
+ async setMetadata(
90
+ resourceType: string,
91
+ resourceId: string,
92
+ key: string,
93
+ value: any
94
+ ): Promise<void> {
95
+ if (resourceType === 'sales_channel') {
96
+ await this.sdk.admin.salesChannel.update(resourceId, {
97
+ metadata: { [key]: value },
98
+ });
99
+ return;
100
+ }
101
+
102
+ if (resourceType === 'customer') {
103
+ await (this.sdk as any).admin.customer.update(resourceId, {
104
+ metadata: { [key]: value },
105
+ });
106
+ return;
107
+ }
108
+
109
+ if (resourceType === 'order') {
110
+ await (this.sdk as any).admin.order.update(resourceId, {
111
+ metadata: { [key]: value },
112
+ });
113
+ return;
114
+ }
115
+
116
+ // Note: Store API in Medusa v2 requires store ID
117
+ // Store support can be added when we have a reliable way to get the store ID
118
+
119
+ throw new Error(
120
+ `Unsupported resource type: ${resourceType}. ` +
121
+ `Supported: 'sales_channel', 'customer', 'order'.`
122
+ );
123
+ }
124
+
125
+ /**
126
+ * Delete metadata key from Medusa resource
127
+ *
128
+ * @remarks
129
+ * Medusa deletes metadata keys by setting them to undefined or null
130
+ */
131
+ async deleteMetadata(
132
+ resourceType: string,
133
+ resourceId: string,
134
+ key: string
135
+ ): Promise<void> {
136
+ // Set to null to delete the key
137
+ await this.setMetadata(resourceType, resourceId, key, null);
138
+ }
139
+ }
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ /**
3
+ * @thorprovider/adapters v2.0
4
+ * Core errors
5
+ */
6
+ var __extends = (this && this.__extends) || (function () {
7
+ var extendStatics = function (d, b) {
8
+ extendStatics = Object.setPrototypeOf ||
9
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
10
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
11
+ return extendStatics(d, b);
12
+ };
13
+ return function (d, b) {
14
+ if (typeof b !== "function" && b !== null)
15
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
16
+ extendStatics(d, b);
17
+ function __() { this.constructor = d; }
18
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
19
+ };
20
+ })();
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.ProviderAPIError = exports.ResourceNotFoundError = exports.ConfigurationError = exports.ProviderNotFoundError = exports.CommerceError = void 0;
23
+ exports.extractErrorMessage = extractErrorMessage;
24
+ /**
25
+ * Base error class for commerce providers
26
+ */
27
+ var CommerceError = /** @class */ (function (_super) {
28
+ __extends(CommerceError, _super);
29
+ function CommerceError(message, code, status) {
30
+ var _this = _super.call(this, message) || this;
31
+ _this.code = code;
32
+ _this.status = status;
33
+ _this.name = 'CommerceError';
34
+ return _this;
35
+ }
36
+ return CommerceError;
37
+ }(Error));
38
+ exports.CommerceError = CommerceError;
39
+ /**
40
+ * Provider not found error
41
+ */
42
+ var ProviderNotFoundError = /** @class */ (function (_super) {
43
+ __extends(ProviderNotFoundError, _super);
44
+ function ProviderNotFoundError(providerName) {
45
+ var _this = _super.call(this, "Provider not found: ".concat(providerName), 'PROVIDER_NOT_FOUND') || this;
46
+ _this.name = 'ProviderNotFoundError';
47
+ return _this;
48
+ }
49
+ return ProviderNotFoundError;
50
+ }(CommerceError));
51
+ exports.ProviderNotFoundError = ProviderNotFoundError;
52
+ /**
53
+ * Configuration error
54
+ */
55
+ var ConfigurationError = /** @class */ (function (_super) {
56
+ __extends(ConfigurationError, _super);
57
+ function ConfigurationError(message) {
58
+ var _this = _super.call(this, message, 'CONFIGURATION_ERROR') || this;
59
+ _this.name = 'ConfigurationError';
60
+ return _this;
61
+ }
62
+ return ConfigurationError;
63
+ }(CommerceError));
64
+ exports.ConfigurationError = ConfigurationError;
65
+ /**
66
+ * Resource not found error
67
+ */
68
+ var ResourceNotFoundError = /** @class */ (function (_super) {
69
+ __extends(ResourceNotFoundError, _super);
70
+ function ResourceNotFoundError(resource, identifier) {
71
+ var _this = _super.call(this, "".concat(resource, " not found: ").concat(identifier), 'RESOURCE_NOT_FOUND', 404) || this;
72
+ _this.name = 'ResourceNotFoundError';
73
+ return _this;
74
+ }
75
+ return ResourceNotFoundError;
76
+ }(CommerceError));
77
+ exports.ResourceNotFoundError = ResourceNotFoundError;
78
+ /**
79
+ * API error from provider
80
+ */
81
+ var ProviderAPIError = /** @class */ (function (_super) {
82
+ __extends(ProviderAPIError, _super);
83
+ function ProviderAPIError(message, provider, status) {
84
+ var _this = _super.call(this, message, 'PROVIDER_API_ERROR', status) || this;
85
+ _this.provider = provider;
86
+ _this.name = 'ProviderAPIError';
87
+ return _this;
88
+ }
89
+ return ProviderAPIError;
90
+ }(CommerceError));
91
+ exports.ProviderAPIError = ProviderAPIError;
92
+ /**
93
+ * Extract error message from various error types
94
+ * Handles standard Error objects, API responses, and unknown error types
95
+ */
96
+ function extractErrorMessage(error) {
97
+ var _a, _b, _c, _d, _e, _f;
98
+ // Standard Error object
99
+ if (error instanceof Error && error.message) {
100
+ // Don't return generic messages if there's more data
101
+ if (error.message !== 'An unknown error occurred.') {
102
+ return error.message;
103
+ }
104
+ }
105
+ // Object with message property
106
+ if (typeof error === 'object' && error !== null) {
107
+ var err = error;
108
+ // Check for response body (common in fetch errors)
109
+ if (err.body) {
110
+ if (typeof err.body === 'string')
111
+ return err.body;
112
+ if (err.body.message)
113
+ return String(err.body.message);
114
+ if ((_a = err.body.error) === null || _a === void 0 ? void 0 : _a.message)
115
+ return String(err.body.error.message);
116
+ }
117
+ // Check for response object
118
+ if (err.response) {
119
+ if ((_b = err.response.data) === null || _b === void 0 ? void 0 : _b.message)
120
+ return String(err.response.data.message);
121
+ if ((_c = err.response.data) === null || _c === void 0 ? void 0 : _c.error)
122
+ return String(err.response.data.error);
123
+ if (err.response.statusText)
124
+ return "".concat(err.response.status || '', " ").concat(err.response.statusText).trim();
125
+ }
126
+ // Check for data property
127
+ if ((_d = err.data) === null || _d === void 0 ? void 0 : _d.message)
128
+ return String(err.data.message);
129
+ if ((_e = err.data) === null || _e === void 0 ? void 0 : _e.error)
130
+ return String(err.data.error);
131
+ // Check for error property
132
+ if ((_f = err.error) === null || _f === void 0 ? void 0 : _f.message)
133
+ return String(err.error.message);
134
+ // Check for statusText with status code
135
+ if (err.status && err.statusText) {
136
+ return "HTTP ".concat(err.status, ": ").concat(err.statusText);
137
+ }
138
+ if (err.status && !err.statusText) {
139
+ return "HTTP ".concat(err.status, " Error");
140
+ }
141
+ // Check for message property (not generic)
142
+ if (err.message && err.message !== 'An unknown error occurred.') {
143
+ return String(err.message);
144
+ }
145
+ // Try to stringify the error object
146
+ try {
147
+ var stringified = JSON.stringify(error);
148
+ if (stringified !== '{}')
149
+ return stringified;
150
+ }
151
+ catch (_g) {
152
+ // Ignore JSON.stringify errors
153
+ }
154
+ }
155
+ // String error
156
+ if (typeof error === 'string') {
157
+ return error;
158
+ }
159
+ // Fallback
160
+ return 'An unknown error occurred';
161
+ }