@thorprovider/medusa-extended 1.13.2 → 1.13.4
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/dist/index.d.mts +11 -18
- package/dist/index.d.ts +11 -18
- package/dist/index.js +18 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/dropshipper.test.ts +14 -0
- package/src/recovery.ts +30 -45
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/admin.ts","../src/request-resilience.ts","../src/dropshipper.ts","../src/recovery.ts"],"sourcesContent":["/**\n * @thorprovider/medusa-extended\n * Thor Commerce multi-tenant admin extensions for Medusa\n */\n\nexport { MedusaAdminClient } from './admin';\nexport type { MedusaAdminClientConfig } from './admin';\n\nexport { DropshipperClient } from './dropshipper';\nexport type { DropshipperClientConfig, ChatStreamEvent } from './dropshipper';\n\nexport { RecoveryClient } from './recovery';\nexport type { RecoveryClientConfig } from './recovery';\n\n","/**\n * @fileoverview Medusa Multi-Tenant Admin Client\n * @module @thorprovider/adapters/providers/medusa/admin\n *\n * Wrapper methods for all `/admin/thor/` endpoints defined in the Thor Commerce\n * multi-tenant API contract. Requires an admin API key (`adminConfig.apiKey`)\n * to be provided when creating the Medusa provider.\n *\n * Every method performs a raw `fetch` against the Medusa backend using the\n * admin API key (`x-medusa-access-token`) — the Medusa JS-SDK's admin client\n * does not expose these custom Thor plugin routes, so we use direct HTTP calls.\n *\n * Endpoint reference: `multitenant-api-contract.md`\n */\n\nimport type {\n GetChannelCustomersOptions,\n GetChannelCustomersResponse,\n GetChannelApiKeysResponse,\n GetChannelCategoriesOptions,\n GetChannelCategoriesResponse,\n GetCategorySalesChannelsResponse,\n AssignCategoriesToChannelsBody,\n AssignCategoriesToChannelsResponse,\n UnassignCategoriesFromChannelsBody,\n UnassignCategoriesFromChannelsResponse,\n GetCollectionSalesChannelsResponse,\n AssignCollectionsToChannelsBody,\n AssignCollectionsToChannelsResponse,\n UnassignCollectionsFromChannelsBody,\n UnassignCollectionsFromChannelsResponse,\n GetAdminStorefrontConfigResponse,\n UpdateStorefrontConfigBody,\n UpdateStorefrontConfigResponse,\n GetAdminSiteConfigResponse,\n UpdateSiteConfigBody,\n UpdateSiteConfigResponse,\n GetAdminSiteConfigHistoryOptions,\n GetAdminSiteConfigHistoryResponse,\n RestoreSiteConfigResponse,\n} from '@thorprovider/types';\nimport { createLogger, ProviderAPIError } from '@thorprovider/adapters';\nimport { fetchBackendWithResilience } from './request-resilience';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ntype FetchMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\n/**\n * Configuration required to instantiate the admin client.\n */\nexport interface MedusaAdminClientConfig {\n /** Medusa backend base URL */\n baseUrl: string;\n /** Secret admin API key (x-medusa-access-token) */\n apiKey: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// MedusaAdminClient\n// ---------------------------------------------------------------------------\n\n/**\n * HTTP client for Thor Commerce multi-tenant admin endpoints (`/admin/thor/`).\n *\n * All methods throw `ProviderAPIError` on non-2xx responses.\n *\n * @example\n * ```typescript\n * const admin = new MedusaAdminClient({\n * baseUrl: process.env.MEDUSA_BACKEND_URL!,\n * apiKey: process.env.MEDUSA_ADMIN_API_KEY!,\n * });\n *\n * const { customers } = await admin.getChannelCustomers('sc_01JXXXXX');\n * ```\n */\nexport class MedusaAdminClient {\n private baseUrl: string;\n private apiKey: string;\n private logger: ReturnType<typeof createLogger>;\n\n constructor(config: MedusaAdminClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.logger = createLogger('MedusaAdminClient', config.debug);\n }\n\n // -----------------------------------------------------------------------\n // Private — HTTP helper\n // -----------------------------------------------------------------------\n\n private async request<T>(\n method: FetchMethod,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n this.logger.debug(`[admin] ${method} ${path}`);\n\n const headers: Record<string, string> = {\n 'x-medusa-access-token': this.apiKey,\n 'Content-Type': 'application/json',\n };\n\n const init: RequestInit = {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n };\n\n let response: Response;\n try {\n response = await fetchBackendWithResilience(url, init);\n } catch (networkError: any) {\n throw new ProviderAPIError(\n `[admin] Network error on ${method} ${path}: ${networkError.message}`,\n 'NETWORK_ERROR',\n networkError,\n );\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n try {\n const json = await response.json();\n message = json?.message ?? message;\n } catch {\n // ignore parse errors\n }\n throw new ProviderAPIError(\n `[admin] ${method} ${path} failed: ${message}`,\n `ADMIN_API_${response.status}`,\n response.status,\n );\n }\n\n return response.json() as Promise<T>;\n }\n\n // -----------------------------------------------------------------------\n // 3.1 — Sales Channel: Customers\n // -----------------------------------------------------------------------\n\n /**\n * Paginated list of customers linked to a sales channel.\n *\n * `GET /admin/thor/sales-channels/:id/customers`\n */\n async getChannelCustomers(\n salesChannelId: string,\n options: GetChannelCustomersOptions = {},\n ): Promise<GetChannelCustomersResponse> {\n const { limit = 20, offset = 0 } = options;\n return this.request<GetChannelCustomersResponse>(\n 'GET',\n `/admin/thor/sales-channels/${salesChannelId}/customers?limit=${limit}&offset=${offset}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.2 — Sales Channel: API Keys\n // -----------------------------------------------------------------------\n\n /**\n * Publishable API keys associated with a sales channel.\n *\n * `GET /admin/thor/sales-channels/:id/api-keys`\n */\n async getChannelApiKeys(salesChannelId: string): Promise<GetChannelApiKeysResponse> {\n return this.request<GetChannelApiKeysResponse>(\n 'GET',\n `/admin/thor/sales-channels/${salesChannelId}/api-keys`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.3 — Sales Channel: Categories\n // -----------------------------------------------------------------------\n\n /**\n * Product categories assigned to a sales channel.\n *\n * `GET /admin/thor/sales-channels/:id/categories`\n */\n async getChannelCategories(\n salesChannelId: string,\n options: GetChannelCategoriesOptions = {},\n ): Promise<GetChannelCategoriesResponse> {\n const { limit = 20, offset = 0, include_descendants = false } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n include_descendants: String(include_descendants),\n });\n return this.request<GetChannelCategoriesResponse>(\n 'GET',\n `/admin/thor/sales-channels/${salesChannelId}/categories?${qs}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.4 — Category: Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Sales channels to which a category is assigned.\n *\n * `GET /admin/thor/categories/:id/sales-channels`\n */\n async getCategorySalesChannels(\n categoryId: string,\n ): Promise<GetCategorySalesChannelsResponse> {\n return this.request<GetCategorySalesChannelsResponse>(\n 'GET',\n `/admin/thor/categories/${categoryId}/sales-channels`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.5 — Category: Assign to Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Assign a category to one or more sales channels (idempotent).\n *\n * `POST /admin/thor/categories/:id/sales-channels`\n */\n async assignCategoryToChannels(\n categoryId: string,\n body: AssignCategoriesToChannelsBody,\n ): Promise<AssignCategoriesToChannelsResponse> {\n return this.request<AssignCategoriesToChannelsResponse>(\n 'POST',\n `/admin/thor/categories/${categoryId}/sales-channels`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.6 — Category: Unassign from Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Remove category assignment from one or more sales channels (idempotent).\n *\n * `DELETE /admin/thor/categories/:id/sales-channels`\n */\n async unassignCategoryFromChannels(\n categoryId: string,\n body: UnassignCategoriesFromChannelsBody,\n ): Promise<UnassignCategoriesFromChannelsResponse> {\n return this.request<UnassignCategoriesFromChannelsResponse>(\n 'DELETE',\n `/admin/thor/categories/${categoryId}/sales-channels`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.7 — Collection: Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Sales channels to which a collection is assigned.\n *\n * `GET /admin/thor/collections/:id/sales-channels`\n */\n async getCollectionSalesChannels(\n collectionId: string,\n ): Promise<GetCollectionSalesChannelsResponse> {\n return this.request<GetCollectionSalesChannelsResponse>(\n 'GET',\n `/admin/thor/collections/${collectionId}/sales-channels`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.8 — Collection: Assign to Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Assign a collection to one or more sales channels (idempotent).\n *\n * `POST /admin/thor/collections/:id/sales-channels`\n */\n async assignCollectionToChannels(\n collectionId: string,\n body: AssignCollectionsToChannelsBody,\n ): Promise<AssignCollectionsToChannelsResponse> {\n return this.request<AssignCollectionsToChannelsResponse>(\n 'POST',\n `/admin/thor/collections/${collectionId}/sales-channels`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.9 — Collection: Unassign from Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Remove collection assignment from one or more sales channels (idempotent).\n *\n * `DELETE /admin/thor/collections/:id/sales-channels`\n */\n async unassignCollectionFromChannels(\n collectionId: string,\n body: UnassignCollectionsFromChannelsBody,\n ): Promise<UnassignCollectionsFromChannelsResponse> {\n return this.request<UnassignCollectionsFromChannelsResponse>(\n 'DELETE',\n `/admin/thor/collections/${collectionId}/sales-channels`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.10 — Storefront Config: Read\n // -----------------------------------------------------------------------\n\n /**\n * Read the visual storefront configuration for a channel.\n * `:id` is the `sales_channel_id`.\n *\n * `GET /admin/thor/storefront-config/:id`\n */\n async getStorefrontConfig(\n salesChannelId: string,\n ): Promise<GetAdminStorefrontConfigResponse> {\n return this.request<GetAdminStorefrontConfigResponse>(\n 'GET',\n `/admin/thor/storefront-config/${salesChannelId}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.11 — Storefront Config: Update\n // -----------------------------------------------------------------------\n\n /**\n * Update the visual storefront configuration for a channel.\n * Triggers the `storefront_config.updated` event → ISR webhook.\n *\n * `PUT /admin/thor/storefront-config/:id`\n */\n async updateStorefrontConfig(\n salesChannelId: string,\n body: UpdateStorefrontConfigBody,\n ): Promise<UpdateStorefrontConfigResponse> {\n return this.request<UpdateStorefrontConfigResponse>(\n 'PUT',\n `/admin/thor/storefront-config/${salesChannelId}`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.12 — Site Designer Config: Read\n // -----------------------------------------------------------------------\n\n /**\n * Read the active Site Designer configuration for a channel, including the\n * last 10 history entries.\n *\n * `GET /admin/thor/site-config/:sales_channel_id`\n */\n async getSiteConfig(salesChannelId: string): Promise<GetAdminSiteConfigResponse> {\n return this.request<GetAdminSiteConfigResponse>(\n 'GET',\n `/admin/thor/site-config/${salesChannelId}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.13 — Site Designer Config: Update\n // -----------------------------------------------------------------------\n\n /**\n * Update the Site Designer configuration for a channel.\n * Creates a new history entry on every PUT.\n *\n * `PUT /admin/thor/site-config/:sales_channel_id`\n */\n async updateSiteConfig(\n salesChannelId: string,\n body: UpdateSiteConfigBody,\n ): Promise<UpdateSiteConfigResponse> {\n return this.request<UpdateSiteConfigResponse>(\n 'PUT',\n `/admin/thor/site-config/${salesChannelId}`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.14 — Site Designer Config: History\n // -----------------------------------------------------------------------\n\n /**\n * Full paginated history of Site Designer versions for a channel.\n * Entries are immutable — they are never deleted.\n *\n * `GET /admin/thor/site-config/:sales_channel_id/history`\n */\n async getSiteConfigHistory(\n salesChannelId: string,\n options: GetAdminSiteConfigHistoryOptions = {},\n ): Promise<GetAdminSiteConfigHistoryResponse> {\n const { limit = 20, offset = 0 } = options;\n return this.request<GetAdminSiteConfigHistoryResponse>(\n 'GET',\n `/admin/thor/site-config/${salesChannelId}/history?limit=${limit}&offset=${offset}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.15 — Site Designer Config: Restore\n // -----------------------------------------------------------------------\n\n /**\n * Restore a previous Site Designer version.\n * Internally runs the update workflow with the stored config of the target\n * version — this creates a **new** history entry and does NOT mutate past\n * entries.\n *\n * `POST /admin/thor/site-config/:sales_channel_id/restore/:version`\n */\n async restoreSiteConfig(\n salesChannelId: string,\n version: string,\n ): Promise<RestoreSiteConfigResponse> {\n return this.request<RestoreSiteConfigResponse>(\n 'POST',\n `/admin/thor/site-config/${salesChannelId}/restore/${encodeURIComponent(version)}`,\n );\n }\n}\n","import { ProviderAPIError, backendCircuitBreaker } from '@thorprovider/adapters'\n\nexport type RetryConfig = {\n maxRetries?: number\n initialDelayMs?: number\n backoffMultiplier?: number\n maxDelayMs?: number\n timeoutMs?: number\n retryableStatusCodes?: number[]\n}\n\nconst DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n initialDelayMs: 300,\n backoffMultiplier: 2,\n maxDelayMs: 5000,\n timeoutMs: 10000,\n retryableStatusCodes: [408, 429, 500, 502, 503, 504],\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction calculateDelay(attempt: number, config: Required<RetryConfig>): number {\n const delay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt)\n return Math.min(delay, config.maxDelayMs)\n}\n\nfunction isRetryableError(error: unknown, config: Required<RetryConfig>): boolean {\n const err = error as { name?: string; message?: string; status?: number }\n\n if (err.name === 'TypeError' || err.message?.includes('fetch failed')) return true\n if (err.name === 'AbortError' || err.message?.includes('timeout')) return true\n if (typeof err.status === 'number' && config.retryableStatusCodes.includes(err.status)) return true\n return false\n}\n\nasync function fetchWithRetry(url: string, init: RequestInit, retryConfig?: RetryConfig): Promise<Response> {\n const config = { ...DEFAULT_RETRY_CONFIG, ...retryConfig }\n const method = (init.method || 'GET').toUpperCase()\n const isMutation = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)\n let lastError: unknown\n\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), config.timeoutMs)\n\n const response = await fetch(url, { ...init, signal: controller.signal })\n clearTimeout(timeoutId)\n\n if (!response.ok && config.retryableStatusCodes.includes(response.status)) {\n const error = new Error(`HTTP ${response.status}: ${response.statusText}`) as Error & { status?: number }\n error.status = response.status\n throw error\n }\n\n return response\n } catch (error) {\n lastError = error\n\n // Never retry mutations (POST/PUT/PATCH/DELETE) on timeout/network error.\n // The first request may have succeeded on the backend, and retrying would\n // create duplicate resources (customers, orders, etc.).\n const isTimeoutOrNetwork = error instanceof Error &&\n (error.name === 'AbortError' || error.message?.includes('timeout') || error.message?.includes('fetch failed'))\n if (isMutation && isTimeoutOrNetwork) {\n break\n }\n\n const shouldRetry = attempt < config.maxRetries && isRetryableError(error, config)\n\n if (shouldRetry) {\n await sleep(calculateDelay(attempt, config))\n continue\n }\n\n break\n }\n }\n\n throw lastError instanceof Error ? lastError : new Error('Backend request failed')\n}\n\nexport async function fetchBackendWithResilience(url: string, init: RequestInit, retryConfig?: RetryConfig): Promise<Response> {\n try {\n return await backendCircuitBreaker.execute(() => fetchWithRetry(url, init, retryConfig))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new ProviderAPIError(`Backend request failed: ${message}`, 'backend', 503)\n }\n}\n","/**\n * @fileoverview Dropshipper Client — Thor Commerce Extended\n * @module @thorprovider/medusa-extended/dropshipper\n *\n * HTTP client for all `/admin/thor/dropshipper/` endpoints.\n *\n * Used by both:\n * - X (ThorProvider admin) — authenticated via admin JWT, role \"Admin\"\n * - Y (Dropshipper panel) — authenticated via dropshipper JWT, role \"Dropshipper\"\n *\n * Access control is enforced server-side via `withDropshipperScope` middleware.\n * This client always sends `Authorization: Bearer <token>`.\n *\n * Endpoint reference: `dropshipping-api-contract.md`\n */\n\nimport type {\n // Onboarding\n OnboardDropshipperBody,\n OnboardDropshipperResponse,\n // Products & Prices\n DropshipperCostTier,\n DropshipperSaleTier,\n GetDropshipperProductsOptions,\n GetDropshipperProductsResponse,\n ValidateCheckoutItemsRequest,\n ValidateCheckoutItemsResponse,\n CostPriceChangesCheckResponse,\n CostPriceChangesResponse,\n AcknowledgeCostPriceChangesResponse,\n UpdateDropshipperProductStatusBody,\n UpdateDropshipperProductStatusResponse,\n UpdateDropshipperPricesBody,\n UpdateDropshipperPricesResponse,\n GetDropshipperAttributesResponse,\n // Orders\n GetDropshipperOrdersOptions,\n GetDropshipperOrdersResponse,\n GetDropshipperShippingOptionsBody,\n GetDropshipperShippingOptionsResponse,\n GetDropshipperOrderDetailResponse,\n ExtendedCreateDropshipperOrderBody,\n ExtendedCreateDropshipperOrderResponse,\n SetPaymentCollectorBody,\n SetPaymentCollectorResponse,\n // Order Cancel & Edits\n CancelDropshipperOrderResponse,\n CreateOrderEditBody,\n CreateOrderEditResponse,\n AddOrderEditItemBody,\n AddOrderEditItemResponse,\n ConfirmOrderEditResponse,\n // Order Notes\n OrderNote,\n CreateOrderNoteBody,\n GetOrderNotesResponse,\n CreateOrderNoteResponse,\n DeleteOrderNoteResponse,\n // Draft Orders\n GetDropshipperDraftOrdersOptions,\n GetDropshipperDraftOrdersResponse,\n GetDropshipperDraftOrderDetailResponse,\n CreateDropshipperDraftOrderBody,\n CreateDropshipperDraftOrderResponse,\n UpdateDropshipperDraftOrderBody,\n UpdateDropshipperDraftOrderResponse,\n ConvertDropshipperDraftOrderBody,\n ConvertDropshipperDraftOrderResponse,\n DeleteDropshipperDraftOrderResponse,\n // Dropshipper Addresses\n DropshipperAddressBody,\n DropshipperAddressResponse,\n GetDropshipperAddressesResponse,\n // Categories\n GetDropshipperCategoriesOptions,\n GetDropshipperCategoriesResponse,\n CreateDropshipperCategoryBody,\n UpdateDropshipperCategoryBody,\n DeleteDropshipperCategoryResponse,\n GetProviderCategoriesResponse,\n GetCategoryMappingsOptions,\n GetCategoryMappingsResponse,\n CreateCategoryMappingBody,\n CreateCategoryMappingResponse,\n DeleteCategoryMappingResponse,\n // Customers\n GetDropshipperCustomersOptions,\n GetDropshipperCustomersResponse,\n GetDropshipperCustomerDetailResponse,\n CreateDropshipperCustomerBody,\n CreateDropshipperCustomerResponse,\n UpdateDropshipperCustomerBody,\n UpdateDropshipperCustomerResponse,\n // Account & Settlements (Y)\n GetDropshipperAccountResponse,\n GetDropshipperPayableResponse,\n GetDropshipperReceivableResponse,\n GetSettlementsOptions,\n GetSettlementsResponse,\n GetSettlementDetailResponse,\n // Admin Settlements (X)\n CreateSettlementBody,\n CreateSettlementResponse,\n ConfirmSettlementBody,\n CancelSettlementBody,\n UpdateSettlementStatusResponse,\n // Admin Account Management (X)\n GetAdminDropshipperAccountsResponse,\n GetAdminAccountBalanceResponse,\n GetAdminPriceListsResponse,\n GetUserChannelResponse,\n // Promotions\n GetDropshipperPromotionsOptions,\n GetDropshipperPromotionsResponse,\n CreateDropshipperPromotionBody,\n UpdateDropshipperPromotionBody,\n DeleteDropshipperPromotionResponse,\n // Dashboard\n GetDashboardStatsOptions,\n GetDashboardStatsResponse,\n // Storefront (V)\n GetStorefrontDropshipperCategoriesResponse,\n // Financial Endpoints — Group A\n GetDropshipperAccountBalanceResponse,\n GetDropshipperAccountOrdersOptions,\n GetDropshipperAccountOrdersResponse,\n GetAdminDropshipperAccountOrdersResponse,\n GetAdminDropshipperAccountSettlementsOptions,\n GetAdminDropshipperAccountSettlementsResponse,\n ResolveGuaranteeBody,\n ResolveGuaranteeResponse,\n CreateCompensacionBody,\n CreateCompensacionResponse,\n CreateAjusteBody,\n CreateAjusteResponse,\n // Financial Endpoints — Group B\n CreateCobroBody,\n CreateCobroResponse,\n CreatePagoBody,\n CreatePagoResponse,\n CreateReversoBody,\n CreateReversoResponse,\n ConfirmMovementBody,\n ConfirmMovementResponse,\n CancelMovementBody,\n CancelMovementResponse,\n GetFinancialAnalysisResponse,\n RegisterPaymentBody,\n RegisterPaymentResponse,\n SetPaymentMethodBody,\n SetPaymentMethodResponse,\n // Geo-reference\n GetGeoCountriesResponse,\n GetGeoProvincesResponse,\n GetGeoCitiesResponse,\n // Dashboard Capabilities\n DropshipperDashboardCapabilities,\n // AI Assistant Chat\n ChatRequest,\n ChatResponse,\n ChatIntent,\n ChatSource,\n ChatAssistantHealthResponse,\n // Profile\n GetMyProfileResponse,\n // Notifications\n GetNotificationsOptions,\n GetNotificationsResponse,\n // Notification preferences\n DropshipperNotificationEventType,\n DropshipperNotificationPreference,\n UpdateNotificationPreferencesBody,\n GetNotificationPreferencesResponse,\n // Dropshipper business policy\n GetBusinessPolicyResponse,\n UpdateBusinessPolicyBody,\n UpdateBusinessPolicyResponse,\n // Inline return types\n DropshipperCategory,\n DropshipperPromotion,\n // Product Attributes\n GetProductAttributesResponse,\n // Unified Query\n QueryEntitiesInput,\n QueryResponse,\n} from '@thorprovider/types';\nimport { createLogger, ProviderAPIError } from '@thorprovider/adapters';\nimport { fetchBackendWithResilience } from './request-resilience';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype FetchMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\n// ---------------------------------------------------------------------------\n// AI Assistant — streaming chat events\n// ---------------------------------------------------------------------------\n\n/**\n * One event from the streamed AI assistant chat (`chatAssistantStream`).\n *\n * The backend returns a UI-message stream (SSE over `text/event-stream`) for\n * catalog searches, and a plain JSON `ChatResponse` for `default` intents.\n * `chatAssistantStream` normalizes both into this single event type so\n * consumers can render incremental text and update the \"thinking\" label as the\n * model progresses without knowing the transport details.\n */\nexport type ChatStreamEvent =\n | {\n type: 'start';\n /** Semantic intent as soon as the backend resolves it. */\n intent?: ChatIntent;\n }\n | {\n type: 'text-delta';\n /** A chunk of the assistant's answer, appended to the bubble. */\n delta: string;\n }\n | {\n type: 'finish';\n intent: ChatIntent;\n /** Products referenced by the answer (empty for `default` intents). */\n sources: ChatSource[];\n }\n | {\n type: 'error';\n errorText: string;\n };\n\n/**\n * Configuration required to instantiate the dropshipper client.\n */\nexport interface DropshipperClientConfig {\n /** Medusa backend base URL */\n baseUrl: string;\n /**\n * JWT token obtained from `POST /auth/user/emailpass`.\n * Used as `Authorization: Bearer <token>`.\n */\n token: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// DropshipperClient\n// ---------------------------------------------------------------------------\n\n/**\n * HTTP client for Thor Commerce dropshipping endpoints (`/admin/thor/dropshipper/`).\n *\n * All methods throw `ProviderAPIError` on non-2xx responses.\n *\n * @example\n * ```typescript\n * const client = new DropshipperClient({\n * baseUrl: process.env.MEDUSA_BACKEND_URL!,\n * token: jwtFromLogin,\n * });\n *\n * // Y: list own products\n * const { products } = await client.getProducts();\n *\n * // X: onboard a new dropshipper\n * const { dropshipper } = await client.onboardDropshipper({ ... });\n * ```\n */\nexport class DropshipperClient {\n private baseUrl: string;\n private token: string;\n private logger: ReturnType<typeof createLogger>;\n\n constructor(config: DropshipperClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.token = config.token;\n this.logger = createLogger('DropshipperClient', config.debug);\n }\n\n // -------------------------------------------------------------------------\n // Private — HTTP helper\n // -------------------------------------------------------------------------\n\n private async request<T>(\n method: FetchMethod,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n this.logger.debug(`[dropshipper] ${method} ${path}`);\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n };\n\n const init: RequestInit = {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n };\n\n let response: Response;\n try {\n response = await fetchBackendWithResilience(url, init);\n } catch (networkError: any) {\n throw new ProviderAPIError(\n `[dropshipper] Network error on ${method} ${path}: ${networkError.message}`,\n 'NETWORK_ERROR',\n networkError,\n );\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n try {\n const json = await response.json();\n message = json?.message ?? message;\n } catch {\n // ignore parse errors\n }\n throw new ProviderAPIError(\n `[dropshipper] ${method} ${path} failed: ${message}`,\n `DROPSHIPPER_API_${response.status}`,\n response.status,\n );\n }\n\n return response.json() as Promise<T>;\n }\n\n // -------------------------------------------------------------------------\n // Unified Query\n // -------------------------------------------------------------------------\n\n /**\n * Resolve multiple entities in a single request.\n *\n * `POST /admin/thor/dropshipper/query`\n *\n * Entities are resolved in parallel (per layer) and errors are isolated per\n * entity: `response.errors[key]` holds the per-entity error while the rest\n * of `data` still resolves. `data[key]` is an array (list entities) or a\n * single object (singular entities such as account, balance, me).\n *\n * @example\n * ```typescript\n * const { data } = await client.query({\n * entities: [\n * { entity: 'capabilities' },\n * { entity: 'me' },\n * { entity: 'account' },\n * ],\n * });\n * ```\n */\n async query(input: QueryEntitiesInput): Promise<QueryResponse> {\n return this.request<QueryResponse>(\n 'POST',\n '/admin/thor/dropshipper/query',\n input,\n );\n }\n\n // -------------------------------------------------------------------------\n // Capabilities\n // -------------------------------------------------------------------------\n\n /**\n * Fetch dashboard capabilities from the backend.\n *\n * `GET /admin/thor/dropshipper/capabilities`\n */\n async getCapabilities(): Promise<DropshipperDashboardCapabilities> {\n return this.request<DropshipperDashboardCapabilities>(\n 'GET',\n '/admin/thor/dropshipper/capabilities',\n );\n }\n\n /**\n * Fetch the authenticated dropshipper's personal profile including\n * first_name, last_name, email, avatar_url, and linked sales channel.\n *\n * `GET /admin/thor/dropshipper/me`\n */\n async getMyProfile(): Promise<GetMyProfileResponse> {\n return this.request<GetMyProfileResponse>(\n 'GET',\n '/admin/thor/dropshipper/me',\n );\n }\n\n /**\n * Send a chat message to the AI assistant (catalog intelligence).\n * The conversation is stateless — the client sends the full message\n * history on every request.\n *\n * `POST /admin/thor/dropshipper/ai/chat`\n *\n * @example\n * ```typescript\n * const { answer, sources } = await client.chatAssistant({\n * messages: [{ role: 'user', content: 'productos con mejor margen' }],\n * });\n * ```\n */\n async chatAssistant(body: ChatRequest): Promise<ChatResponse> {\n return this.request<ChatResponse>(\n 'POST',\n '/admin/thor/dropshipper/ai/chat',\n body,\n );\n }\n\n /**\n * Stream the AI assistant's reply.\n *\n * Unlike `chatAssistant`, this surfaces the model's progress: the backend\n * resolves the intent first and then streams the answer token by token\n * (catalog searches) or returns the full answer in one shot (`default`).\n * The response is normalized into a single `ReadableStream<ChatStreamEvent>`\n * so callers can show a live \"thinking\" label and render text incrementally.\n *\n * `POST /admin/thor/dropshipper/ai/chat`\n */\n async chatAssistantStream(body: ChatRequest): Promise<ReadableStream<ChatStreamEvent>> {\n const url = `${this.baseUrl}/admin/thor/dropshipper/ai/chat`;\n this.logger.debug('[dropshipper] POST /admin/thor/dropshipper/ai/chat (stream)');\n\n const init: RequestInit = {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n },\n body: JSON.stringify(body),\n };\n\n let response: Response;\n try {\n // This endpoint performs two LLM round-trips plus channel-scoped retrieval\n // BEFORE it starts streaming (headers only flush when Stage 3 begins), so\n // the default 10s timeout aborts legitimate catalog searches. Use a larger\n // per-attempt timeout; once headers arrive the timer is cleared and the\n // streamed body is unaffected. POST is a mutation, so on timeout/network it\n // won't be retried — maxRetries:1 only guards against redundant 5xx/red work.\n response = await fetchBackendWithResilience(url, init, {\n timeoutMs: 60_000,\n maxRetries: 1,\n });\n } catch (networkError: any) {\n throw new ProviderAPIError(\n `[dropshipper] Network error on POST /admin/thor/dropshipper/ai/chat: ${networkError.message}`,\n 'NETWORK_ERROR',\n networkError,\n );\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n let errorCode: string | undefined;\n let requestId: string | undefined;\n let details: string | undefined;\n try {\n const json: any = await response.json();\n message = json?.message ?? message;\n errorCode = json?.error_code ?? json?.type;\n requestId = json?.request_id;\n details = json?.details;\n } catch {\n // ignore parse errors\n }\n this.logger.error(\n `[dropshipper] POST /admin/thor/dropshipper/ai/chat failed status=${response.status} message=${message}` +\n (errorCode ? ` error_code=${errorCode}` : '') +\n (requestId ? ` request_id=${requestId}` : '') +\n (details ? ` details=${details}` : '')\n );\n throw new ProviderAPIError(\n `[dropshipper] POST /admin/thor/dropshipper/ai/chat failed: ${message}`,\n `DROPSHIPPER_API_${response.status}`,\n response.status,\n {\n message,\n status: response.status,\n errorCode,\n requestId,\n details,\n },\n );\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n if (contentType.includes('text/event-stream') && response.body) {\n return mapUiMessageStreamToEvents(response.body, this.logger);\n }\n\n // Non-streamed reply (`default`): synthesize a one-shot event stream.\n const data: ChatResponse = await response.json();\n return new ReadableStream<ChatStreamEvent>({\n start(controller) {\n controller.enqueue({ type: 'start', intent: data.intent });\n controller.enqueue({ type: 'text-delta', delta: data.answer });\n controller.enqueue({\n type: 'finish',\n intent: data.intent,\n sources: data.sources ?? [],\n });\n controller.close();\n },\n });\n }\n\n /**\n * Cheap liveness probe for the AI assistant.\n *\n * The backend performs no LLM or retrieval work, so this is safe to poll\n * (e.g. from a dashboard availability indicator). Returns 200 with\n * `available: true` when the assistant is configured; the backend answers\n * HTTP 503 with `available: false` when `AI_GATEWAY_API_KEY` is missing.\n *\n * Deliberately does NOT go through `fetchBackendWithResilience`: that layer\n * funnels every call through the SHARED `backendCircuitBreaker`, and the\n * definitive 503 \"not configured\" answer would count as failures and could\n * open the circuit, taking down all dropshipper API traffic. A health probe\n * must stay isolated, with no retries and a short timeout.\n *\n * `GET /admin/thor/dropshipper/ai/health`\n */\n async chatAssistantHealth(): Promise<ChatAssistantHealthResponse> {\n const url = `${this.baseUrl}/admin/thor/dropshipper/ai/health`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 5000);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'GET',\n headers: { Authorization: `Bearer ${this.token}` },\n signal: controller.signal,\n cache: 'no-store',\n });\n } catch (error: any) {\n clearTimeout(timeoutId);\n throw new ProviderAPIError(\n `[dropshipper] Network error on GET /admin/thor/dropshipper/ai/health: ${error.message}`,\n 'NETWORK_ERROR',\n 0,\n );\n }\n clearTimeout(timeoutId);\n\n // 503 is the backend's definitive \"not configured\" answer, not a transient\n // failure: parse it as a valid (unavailable) health response.\n if (response.status === 503) {\n try {\n const body = await response.json();\n if (body && typeof body.available === 'boolean') {\n return body as ChatAssistantHealthResponse;\n }\n } catch {\n // fall through to the generic failure below\n }\n }\n\n if (!response.ok) {\n throw new ProviderAPIError(\n `[dropshipper] GET /admin/thor/dropshipper/ai/health failed: HTTP ${response.status}`,\n `DROPSHIPPER_API_${response.status}`,\n response.status,\n );\n }\n\n return response.json() as Promise<ChatAssistantHealthResponse>;\n }\n\n // -------------------------------------------------------------------------\n // Notifications\n // -------------------------------------------------------------------------\n\n /**\n * List feed notifications for the authenticated dropshipper.\n *\n * `GET /admin/thor/dropshipper/notifications`\n */\n async getNotifications(\n options: GetNotificationsOptions = {},\n ): Promise<GetNotificationsResponse> {\n const { limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n });\n return this.request<GetNotificationsResponse>(\n 'GET',\n `/admin/thor/dropshipper/notifications?${qs}`,\n );\n }\n\n /**\n * Get the authenticated dropshipper's notification preferences.\n *\n * `GET /admin/thor/dropshipper/notifications/preferences`\n */\n async getNotificationPreferences(): Promise<GetNotificationPreferencesResponse> {\n return this.request<GetNotificationPreferencesResponse>(\n 'GET',\n '/admin/thor/dropshipper/notifications/preferences',\n );\n }\n\n /**\n * Update the authenticated dropshipper's notification preferences.\n *\n * `PATCH /admin/thor/dropshipper/notifications/preferences`\n */\n async updateNotificationPreferences(\n body: UpdateNotificationPreferencesBody,\n ): Promise<GetNotificationPreferencesResponse> {\n return this.request<GetNotificationPreferencesResponse>(\n 'PATCH',\n '/admin/thor/dropshipper/notifications/preferences',\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Onboarding (Solo X)\n // -------------------------------------------------------------------------\n\n /**\n * Create a new dropshipper account (sales channel + user + price list).\n *\n * `POST /admin/thor/dropshipper/onboard`\n */\n async onboardDropshipper(\n body: OnboardDropshipperBody,\n ): Promise<OnboardDropshipperResponse> {\n return this.request<OnboardDropshipperResponse>(\n 'POST',\n '/admin/thor/dropshipper/onboard',\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Products (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * List products available in Y's channel with cost/margin data.\n *\n * `GET /admin/thor/dropshipper/products`\n */\n async getProducts(\n options: GetDropshipperProductsOptions = {},\n ): Promise<GetDropshipperProductsResponse> {\n const { q, category_id, collection_id, status, in_stock, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(q ? { q } : {}),\n ...(category_id ? { category_id } : {}),\n ...(collection_id ? { collection_id } : {}),\n ...(status ? { status } : {}),\n ...(in_stock !== undefined ? { in_stock: String(in_stock) } : {}),\n });\n return this.request<GetDropshipperProductsResponse>(\n 'GET',\n `/admin/thor/dropshipper/products?${qs}`,\n );\n }\n\n /**\n * Validate cart items for checkout — returns current availableQuantity, sale_price,\n * and cost_price for each variant so the client can detect stale prices or\n * insufficient stock before creating an order or converting a draft.\n *\n * `POST /admin/thor/dropshipper/checkout/validate`\n */\n async validateCheckoutItems(\n body: ValidateCheckoutItemsRequest,\n ): Promise<ValidateCheckoutItemsResponse> {\n return this.request<ValidateCheckoutItemsResponse>(\n 'POST',\n '/admin/thor/dropshipper/checkout/validate',\n body,\n );\n }\n\n /**\n * Check whether cost prices have changed since the last acknowledgment.\n * Compares a hash of all base cost prices from the channel's price list\n * against a stored snapshot on the dropshipper account.\n *\n * `GET /admin/thor/dropshipper/cost-prices/has-changes`\n */\n async checkCostPriceChanges(): Promise<CostPriceChangesCheckResponse> {\n return this.request<CostPriceChangesCheckResponse>(\n 'GET',\n '/admin/thor/dropshipper/cost-prices/has-changes',\n );\n }\n\n /**\n * Get the full diff of cost price changes since the last acknowledgment.\n * Returns product/variant info with old and new cost prices.\n *\n * `GET /admin/thor/dropshipper/cost-prices/changes`\n */\n async getCostPriceChanges(): Promise<CostPriceChangesResponse> {\n return this.request<CostPriceChangesResponse>(\n 'GET',\n '/admin/thor/dropshipper/cost-prices/changes',\n );\n }\n\n /**\n * Acknowledge current cost prices as reviewed. Stores the current hash\n * and snapshot so subsequent checks will not report these prices as changed.\n *\n * `POST /admin/thor/dropshipper/cost-prices/acknowledge`\n */\n async acknowledgeCostPriceChanges(): Promise<AcknowledgeCostPriceChangesResponse> {\n return this.request<AcknowledgeCostPriceChangesResponse>(\n 'POST',\n '/admin/thor/dropshipper/cost-prices/acknowledge',\n );\n }\n\n /**\n * Toggle whether a product is visible in the public store for the current sales channel.\n * This does not mutate the shared global Medusa product status.\n *\n * `POST /admin/thor/dropshipper/products/:id/status`\n */\n async updateProductStatus(\n productId: string,\n body: UpdateDropshipperProductStatusBody,\n ): Promise<UpdateDropshipperProductStatusResponse> {\n return this.request<UpdateDropshipperProductStatusResponse>(\n 'POST',\n `/admin/thor/dropshipper/products/${productId}/status`,\n body,\n );\n }\n\n /**\n * Fetch custom attribute values assigned to a product, grouped by attribute.\n *\n * `GET /admin/thor/dropshipper/products/:id/attributes`\n */\n async getProductAttributes(\n productId: string,\n ): Promise<GetProductAttributesResponse> {\n return this.request<GetProductAttributesResponse>(\n 'GET',\n `/admin/thor/dropshipper/products/${productId}/attributes`,\n );\n }\n\n /**\n * List attribute definitions (with their possible values) scoped to the\n * dropshipper's channel. Only attributes linked to at least one channel\n * product are returned.\n *\n * `GET /admin/thor/dropshipper/attributes`\n */\n async getAttributes(): Promise<GetDropshipperAttributesResponse> {\n return this.request<GetDropshipperAttributesResponse>(\n 'GET',\n '/admin/thor/dropshipper/attributes',\n );\n }\n\n // -------------------------------------------------------------------------\n // Prices (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * Bulk-update product and variant margins on Y's channel price list.\n *\n * `PUT /admin/thor/dropshipper/prices`\n */\n async updatePrices(\n body: UpdateDropshipperPricesBody,\n ): Promise<UpdateDropshipperPricesResponse> {\n return this.request<UpdateDropshipperPricesResponse>(\n 'PUT',\n '/admin/thor/dropshipper/prices',\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Orders (Y + X for set-payment-collector)\n // -------------------------------------------------------------------------\n\n /**\n * Paginated list of orders in Y's channel.\n *\n * `GET /admin/thor/dropshipper/orders`\n */\n async getOrders(\n options: GetDropshipperOrdersOptions = {},\n ): Promise<GetDropshipperOrdersResponse> {\n const { status, payment_collector, settlement_status, from, to, q, customer_id, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(status ? { status } : {}),\n ...(payment_collector ? { payment_collector } : {}),\n ...(settlement_status ? { settlement_status } : {}),\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n ...(q ? { q } : {}),\n ...(customer_id ? { customer_id } : {}),\n });\n return this.request<GetDropshipperOrdersResponse>(\n 'GET',\n `/admin/thor/dropshipper/orders?${qs}`,\n );\n }\n\n /**\n * Full detail for a single order with profit breakdown.\n *\n * `GET /admin/thor/dropshipper/orders/:id`\n */\n async getOrder(orderId: string): Promise<GetDropshipperOrderDetailResponse> {\n return this.request<GetDropshipperOrderDetailResponse>(\n 'GET',\n `/admin/thor/dropshipper/orders/${orderId}`,\n );\n }\n\n /**\n * List shipping groups and their valid options for a manual dropshipper order.\n *\n * `POST /admin/thor/dropshipper/orders/shipping-options`\n */\n async getOrderShippingOptions(\n body: GetDropshipperShippingOptionsBody,\n ): Promise<GetDropshipperShippingOptionsResponse> {\n return this.request<GetDropshipperShippingOptionsResponse>(\n 'POST',\n '/admin/thor/dropshipper/orders/shipping-options',\n {\n ...body,\n currency_code: body.currency_code.toLowerCase(),\n },\n );\n }\n\n /**\n * Manually create an order on behalf of a customer.\n *\n * `POST /admin/thor/dropshipper/orders`\n */\n async createOrder(\n body: ExtendedCreateDropshipperOrderBody,\n ): Promise<ExtendedCreateDropshipperOrderResponse> {\n return this.request<ExtendedCreateDropshipperOrderResponse>(\n 'POST',\n '/admin/thor/dropshipper/orders',\n body,\n );\n }\n\n /**\n * Set who collects payment for an order (Solo X).\n *\n * `POST /admin/thor/dropshipper/orders/:id/set-payment-collector`\n */\n async setPaymentCollector(\n orderId: string,\n body: SetPaymentCollectorBody,\n ): Promise<SetPaymentCollectorResponse> {\n return this.request<SetPaymentCollectorResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/set-payment-collector`,\n body,\n );\n }\n\n /**\n * Change the payment method of a confirmed order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/set-payment-method`\n */\n async setPaymentMethod(\n orderId: string,\n body: SetPaymentMethodBody,\n ): Promise<SetPaymentMethodResponse> {\n return this.request<SetPaymentMethodResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/set-payment-method`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Order Cancel & Edits (Solo Y) — B-04\n // -------------------------------------------------------------------------\n\n /**\n * Cancel a dropshipper order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/cancel`\n */\n async cancelOrder(orderId: string): Promise<CancelDropshipperOrderResponse> {\n return this.request<CancelDropshipperOrderResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/cancel`,\n );\n }\n\n /**\n * Create an order edit for a dropshipper order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/edit`\n */\n async createOrderEdit(\n orderId: string,\n body: CreateOrderEditBody = {},\n ): Promise<CreateOrderEditResponse> {\n return this.request<CreateOrderEditResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/edit`,\n body,\n );\n }\n\n /**\n * Add an item to the active order edit.\n *\n * `POST /admin/thor/dropshipper/orders/:id/edit/items`\n */\n async addOrderEditItem(\n orderId: string,\n body: AddOrderEditItemBody,\n ): Promise<AddOrderEditItemResponse> {\n return this.request<AddOrderEditItemResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/edit/items`,\n body,\n );\n }\n\n /**\n * Confirm the active order edit, applying changes to the order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/edit/confirm`\n */\n async confirmOrderEdit(\n orderId: string,\n ): Promise<ConfirmOrderEditResponse> {\n return this.request<ConfirmOrderEditResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/edit/confirm`,\n );\n }\n\n /**\n * Get all notes for an order.\n *\n * `GET /admin/thor/dropshipper/orders/:id/notes`\n */\n async getOrderNotes(orderId: string): Promise<GetOrderNotesResponse> {\n return this.request<GetOrderNotesResponse>(\n 'GET',\n `/admin/thor/dropshipper/orders/${orderId}/notes`,\n );\n }\n\n /**\n * Create a new note for an order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/notes`\n */\n async createOrderNote(\n orderId: string,\n body: CreateOrderNoteBody,\n ): Promise<CreateOrderNoteResponse> {\n return this.request<CreateOrderNoteResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/notes`,\n body,\n );\n }\n\n /**\n * Delete a note from an order.\n *\n * `DELETE /admin/thor/dropshipper/orders/:id/notes/:noteId`\n */\n async deleteOrderNote(\n orderId: string,\n noteId: string,\n ): Promise<DeleteOrderNoteResponse> {\n return this.request<DeleteOrderNoteResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/orders/${orderId}/notes/${noteId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Custom Categories (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * List Medusa provider categories linked to Y's channel (read-only).\n *\n * `GET /admin/thor/dropshipper/categories/provider`\n */\n async getProviderCategories(): Promise<GetProviderCategoriesResponse> {\n return this.request<GetProviderCategoriesResponse>(\n 'GET',\n '/admin/thor/dropshipper/categories/provider',\n );\n }\n\n /**\n * List Y's custom product categories.\n *\n * `GET /admin/thor/dropshipper/categories`\n */\n async getCategories(\n options: GetDropshipperCategoriesOptions = {},\n ): Promise<GetDropshipperCategoriesResponse> {\n const { parent_id, include_children } = options;\n const qs = new URLSearchParams({\n ...(parent_id ? { parent_id } : {}),\n ...(include_children !== undefined ? { include_children: String(include_children) } : {}),\n });\n const query = qs.toString() ? `?${qs}` : '';\n return this.request<GetDropshipperCategoriesResponse>(\n 'GET',\n `/admin/thor/dropshipper/categories${query}`,\n );\n }\n\n /**\n * Create a custom category in Y's channel.\n *\n * `POST /admin/thor/dropshipper/categories`\n */\n async createCategory(\n body: CreateDropshipperCategoryBody,\n ): Promise<DropshipperCategory> {\n return this.request<DropshipperCategory>(\n 'POST',\n '/admin/thor/dropshipper/categories',\n body,\n );\n }\n\n /**\n * Update a custom category.\n *\n * `PUT /admin/thor/dropshipper/categories/:id`\n */\n async updateCategory(\n categoryId: string,\n body: UpdateDropshipperCategoryBody,\n ): Promise<DropshipperCategory> {\n return this.request<DropshipperCategory>(\n 'PUT',\n `/admin/thor/dropshipper/categories/${categoryId}`,\n body,\n );\n }\n\n /**\n * Delete a custom category.\n *\n * `DELETE /admin/thor/dropshipper/categories/:id`\n */\n async deleteCategory(\n categoryId: string,\n options: { force?: boolean } = {},\n ): Promise<DeleteDropshipperCategoryResponse> {\n const qs = options.force ? '?force=true' : '';\n return this.request<DeleteDropshipperCategoryResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/categories/${categoryId}${qs}`,\n );\n }\n\n /**\n * List product-to-category mappings, optionally filtered by product.\n *\n * `GET /admin/thor/dropshipper/category-mappings`\n */\n async getCategoryMappings(\n options: GetCategoryMappingsOptions = {},\n ): Promise<GetCategoryMappingsResponse> {\n const qs = options.product_id ? `?product_id=${options.product_id}` : '';\n return this.request<GetCategoryMappingsResponse>(\n 'GET',\n `/admin/thor/dropshipper/category-mappings${qs}`,\n );\n }\n\n /**\n * Map a product to a custom category.\n *\n * `POST /admin/thor/dropshipper/category-mappings`\n */\n async createCategoryMapping(\n body: CreateCategoryMappingBody,\n ): Promise<CreateCategoryMappingResponse> {\n return this.request<CreateCategoryMappingResponse>(\n 'POST',\n `/admin/thor/dropshipper/category-mappings`,\n body,\n );\n }\n\n /**\n * Remove a product-to-category mapping.\n *\n * `DELETE /admin/thor/dropshipper/category-mappings/:id`\n */\n async deleteCategoryMapping(\n mappingId: string,\n ): Promise<DeleteCategoryMappingResponse> {\n return this.request<DeleteCategoryMappingResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/category-mappings/${mappingId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Customers (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * Paginated list of customers in Y's channel.\n *\n * `GET /admin/thor/dropshipper/customers`\n */\n async getCustomers(\n options: GetDropshipperCustomersOptions = {},\n ): Promise<GetDropshipperCustomersResponse> {\n const { q, has_orders, from, limit = 20, offset = 0, order } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(q ? { q } : {}),\n ...(has_orders !== undefined ? { has_orders: String(has_orders) } : {}),\n ...(from ? { from } : {}),\n ...(order ? { order } : {}),\n });\n return this.request<GetDropshipperCustomersResponse>(\n 'GET',\n `/admin/thor/dropshipper/customers?${qs}`,\n );\n }\n\n /**\n * Backwards-compatible alias used by the dashboard checkout flow.\n */\n async getChannelCustomers(\n _channelId: string,\n options: GetDropshipperCustomersOptions = {},\n ): Promise<GetDropshipperCustomersResponse> {\n return this.getCustomers(options);\n }\n\n /**\n * Full detail for a single customer.\n *\n * `GET /admin/thor/dropshipper/customers/:id`\n */\n async getCustomer(\n customerId: string,\n ): Promise<GetDropshipperCustomerDetailResponse> {\n return this.request<GetDropshipperCustomerDetailResponse>(\n 'GET',\n `/admin/thor/dropshipper/customers/${customerId}`,\n );\n }\n\n /**\n * Create a customer scoped to Y's channel.\n *\n * `POST /admin/thor/dropshipper/customers`\n */\n async createCustomer(\n body: CreateDropshipperCustomerBody,\n ): Promise<CreateDropshipperCustomerResponse> {\n return this.request<CreateDropshipperCustomerResponse>(\n 'POST',\n '/admin/thor/dropshipper/customers',\n body,\n );\n }\n\n /**\n * Update a customer scoped to Y's channel.\n *\n * `POST /admin/thor/dropshipper/customers/:id`\n */\n async updateCustomer(\n customerId: string,\n body: UpdateDropshipperCustomerBody,\n ): Promise<UpdateDropshipperCustomerResponse> {\n return this.request<UpdateDropshipperCustomerResponse>(\n 'POST',\n `/admin/thor/dropshipper/customers/${customerId}`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Customer Addresses (Solo Y) — B-06\n // -------------------------------------------------------------------------\n\n /**\n * Transform a raw snake_case address from the API into a camelCase Address.\n */\n private transformAddress(raw: any): import('@thorprovider/types').Address {\n return {\n id: raw.id ?? undefined,\n firstName: raw.first_name ?? '',\n lastName: raw.last_name ?? '',\n company: raw.company ?? undefined,\n address1: raw.address_1 ?? '',\n address2: raw.address_2 ?? undefined,\n city: raw.city ?? '',\n province: raw.province ?? '',\n postalCode: raw.postal_code ?? '',\n countryCode: raw.country_code ?? '',\n phone: raw.phone ?? undefined,\n isDefault: raw.is_default ?? undefined,\n isDefaultBilling: raw.is_default_billing ?? undefined,\n isDefaultShipping: raw.is_default_shipping ?? undefined,\n metadata: raw.address_name\n ? { ...(raw.metadata ?? {}), label: raw.address_name }\n : (raw.metadata ?? undefined),\n };\n }\n\n /**\n * List addresses for a customer in Y's channel.\n *\n * `GET /admin/thor/dropshipper/customers/:id/addresses`\n */\n async getCustomerAddresses(\n customerId: string,\n ): Promise<GetDropshipperAddressesResponse> {\n const raw = await this.request<{\n addresses: any[];\n count: number;\n }>('GET', `/admin/thor/dropshipper/customers/${customerId}/addresses`);\n\n return {\n addresses: raw.addresses.map((a) => this.transformAddress(a)),\n count: raw.count,\n };\n }\n\n /**\n * Create a new address for a customer.\n *\n * `POST /admin/thor/dropshipper/customers/:id/addresses`\n */\n async createCustomerAddress(\n customerId: string,\n body: DropshipperAddressBody,\n ): Promise<DropshipperAddressResponse> {\n const raw = await this.request<{ address: any }>(\n 'POST',\n `/admin/thor/dropshipper/customers/${customerId}/addresses`,\n body,\n );\n\n return { address: this.transformAddress(raw.address) };\n }\n\n /**\n * Update an existing customer address.\n *\n * `POST /admin/thor/dropshipper/customers/:id/addresses/:addressId`\n */\n async updateCustomerAddress(\n customerId: string,\n addressId: string,\n body: Partial<DropshipperAddressBody>,\n ): Promise<DropshipperAddressResponse> {\n const raw = await this.request<{ address: any }>(\n 'POST',\n `/admin/thor/dropshipper/customers/${customerId}/addresses/${addressId}`,\n body,\n );\n\n return { address: this.transformAddress(raw.address) };\n }\n\n /**\n * Delete a customer address.\n *\n * `DELETE /admin/thor/dropshipper/customers/:id/addresses/:addressId`\n */\n async deleteCustomerAddress(\n customerId: string,\n addressId: string,\n ): Promise<{ deleted: true; id: string }> {\n return this.request<{ deleted: true; id: string }>(\n 'DELETE',\n `/admin/thor/dropshipper/customers/${customerId}/addresses/${addressId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Account & Settlements (Y read-only)\n // -------------------------------------------------------------------------\n\n /**\n * Y's account info with current balance.\n *\n * `GET /admin/thor/dropshipper/account`\n */\n async getAccount(): Promise<GetDropshipperAccountResponse> {\n return this.request<GetDropshipperAccountResponse>(\n 'GET',\n '/admin/thor/dropshipper/account',\n );\n }\n\n /**\n * Get the authenticated dropshipper's business policy text.\n * Returns an empty string when no policy is set.\n *\n * `GET /admin/thor/dropshipper/account/policies`\n */\n async getBusinessPolicy(): Promise<GetBusinessPolicyResponse> {\n return this.request<GetBusinessPolicyResponse>(\n 'GET',\n '/admin/thor/dropshipper/account/policies',\n );\n }\n\n /**\n * Update the authenticated dropshipper's business policy text.\n * The value is trimmed server-side before being persisted.\n *\n * `PATCH /admin/thor/dropshipper/account/policies`\n */\n async updateBusinessPolicy(\n body: UpdateBusinessPolicyBody,\n ): Promise<UpdateBusinessPolicyResponse> {\n return this.request<UpdateBusinessPolicyResponse>(\n 'PATCH',\n '/admin/thor/dropshipper/account/policies',\n body,\n );\n }\n\n /**\n * Orders where Y owes money to X (Y collected payment, needs to pay costs).\n *\n * `GET /admin/thor/dropshipper/account/payable`\n */\n async getPayable(): Promise<GetDropshipperPayableResponse> {\n return this.request<GetDropshipperPayableResponse>(\n 'GET',\n '/admin/thor/dropshipper/account/payable',\n );\n }\n\n /**\n * Orders where X owes money to Y (X collected COD, needs to transfer profit).\n *\n * `GET /admin/thor/dropshipper/account/receivable`\n */\n async getReceivable(): Promise<GetDropshipperReceivableResponse> {\n return this.request<GetDropshipperReceivableResponse>(\n 'GET',\n '/admin/thor/dropshipper/account/receivable',\n );\n }\n\n /**\n * List settlements (Y sees own; X can filter by account_id).\n *\n * `GET /admin/thor/dropshipper/settlements`\n */\n async getSettlements(\n options: GetSettlementsOptions = {},\n ): Promise<GetSettlementsResponse> {\n const { status, type, account_id, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(status ? { status } : {}),\n ...(type ? { type } : {}),\n ...(account_id ? { account_id } : {}),\n });\n return this.request<GetSettlementsResponse>(\n 'GET',\n `/admin/thor/dropshipper/settlements?${qs}`,\n );\n }\n\n /**\n * Full detail for a single settlement record.\n *\n * `GET /admin/thor/dropshipper/settlements/:id`\n */\n async getSettlement(\n settlementId: string,\n ): Promise<GetSettlementDetailResponse> {\n return this.request<GetSettlementDetailResponse>(\n 'GET',\n `/admin/thor/dropshipper/settlements/${settlementId}`,\n\n );\n }\n\n /**\n * Consolidated financial balance for the authenticated dropshipper.\n *\n * `GET /admin/thor/dropshipper/account/balance`\n */\n async getAccountBalance(): Promise<GetDropshipperAccountBalanceResponse> {\n return this.request<GetDropshipperAccountBalanceResponse>(\n 'GET',\n '/admin/thor/dropshipper/account/balance',\n );\n }\n\n /**\n * Unified financial order list for the authenticated dropshipper.\n *\n * `GET /admin/thor/dropshipper/account/orders`\n */\n async getAccountOrders(\n options: GetDropshipperAccountOrdersOptions = {},\n ): Promise<GetDropshipperAccountOrdersResponse> {\n const { tab, status, limit = 20, offset = 0, q } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(tab ? { tab } : {}),\n ...(status ? { status } : {}),\n ...(q ? { q } : {}),\n });\n return this.request<GetDropshipperAccountOrdersResponse>(\n 'GET',\n `/admin/thor/dropshipper/account/orders?${qs}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Admin Settlements (Solo X)\n // -------------------------------------------------------------------------\n\n /**\n * Create a settlement record for a dropshipper account.\n *\n * `POST /admin/thor/dropshipper/admin/settlements`\n */\n async createSettlement(\n body: CreateSettlementBody,\n ): Promise<CreateSettlementResponse> {\n return this.request<CreateSettlementResponse>(\n 'POST',\n '/admin/thor/dropshipper/admin/settlements',\n body,\n );\n }\n\n /**\n * Confirm a pending settlement (marks it as paid/received).\n *\n * `POST /admin/thor/dropshipper/admin/settlements/:id/confirm`\n */\n async confirmSettlement(\n settlementId: string,\n body: ConfirmSettlementBody = {},\n ): Promise<UpdateSettlementStatusResponse> {\n return this.request<UpdateSettlementStatusResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/settlements/${settlementId}/confirm`,\n body,\n );\n }\n\n /**\n * Cancel a pending settlement.\n *\n * `POST /admin/thor/dropshipper/admin/settlements/:id/cancel`\n */\n async cancelSettlement(\n settlementId: string,\n body: CancelSettlementBody = {},\n ): Promise<UpdateSettlementStatusResponse> {\n return this.request<UpdateSettlementStatusResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/settlements/${settlementId}/cancel`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Admin Settlements — list (Solo X)\n // -------------------------------------------------------------------------\n\n /**\n * X views all settlement records across all dropshipper accounts.\n *\n * `GET /admin/thor/dropshipper/admin/settlements`\n */\n async getAdminSettlements(\n options: GetSettlementsOptions = {},\n ): Promise<GetSettlementsResponse> {\n const { status, type, account_id, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(status ? { status } : {}),\n ...(type ? { type } : {}),\n ...(account_id ? { account_id } : {}),\n });\n return this.request<GetSettlementsResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/settlements?${qs}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Admin Account Management (Solo X)\n // -------------------------------------------------------------------------\n\n /**\n * List all dropshipper accounts.\n *\n * `GET /admin/thor/dropshipper/admin/accounts`\n */\n async getAdminAccounts(): Promise<GetAdminDropshipperAccountsResponse> {\n return this.request<GetAdminDropshipperAccountsResponse>(\n 'GET',\n '/admin/thor/dropshipper/admin/accounts',\n );\n }\n\n /**\n * Full balance detail for a specific dropshipper account.\n *\n * `GET /admin/thor/dropshipper/admin/accounts/:id/balance`\n */\n async getAdminAccountBalance(\n accountId: string,\n ): Promise<GetAdminAccountBalanceResponse> {\n return this.request<GetAdminAccountBalanceResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/balance`,\n );\n }\n\n /**\n * List all dropshipper price lists.\n *\n * `GET /admin/thor/dropshipper/admin/price-lists`\n */\n async getAdminPriceLists(): Promise<GetAdminPriceListsResponse> {\n return this.request<GetAdminPriceListsResponse>(\n 'GET',\n '/admin/thor/dropshipper/admin/price-lists',\n );\n }\n\n /**\n * Utility: look up which sales channel a user belongs to.\n *\n * `GET /admin/thor/dropshipper/admin/user-channel`\n */\n async getUserChannel(): Promise<GetUserChannelResponse> {\n return this.request<GetUserChannelResponse>(\n 'GET',\n '/admin/thor/dropshipper/admin/user-channel',\n );\n }\n\n // -------------------------------------------------------------------------\n // Financial Endpoints — Group A (Admin X)\n // -------------------------------------------------------------------------\n\n /**\n * List orders with financial detail for a dropshipper account (Admin only).\n *\n * `GET /admin/thor/dropshipper/admin/accounts/:id/orders`\n */\n async getAdminAccountOrders(\n accountId: string,\n options: GetDropshipperAccountOrdersOptions = {},\n ): Promise<GetAdminDropshipperAccountOrdersResponse> {\n const { tab, status, limit = 20, offset = 0, q } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(tab ? { tab } : {}),\n ...(status ? { status } : {}),\n ...(q ? { q } : {}),\n });\n return this.request<GetAdminDropshipperAccountOrdersResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/orders?${qs}`,\n );\n }\n\n /**\n * List financial movements for a dropshipper account (Admin only).\n *\n * `GET /admin/thor/dropshipper/admin/accounts/:id/settlements`\n */\n async getAdminAccountSettlements(\n accountId: string,\n options: GetAdminDropshipperAccountSettlementsOptions = {},\n ): Promise<GetAdminDropshipperAccountSettlementsResponse> {\n const { type, status, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(type ? { type } : {}),\n ...(status ? { status } : {}),\n });\n return this.request<GetAdminDropshipperAccountSettlementsResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements?${qs}`,\n );\n }\n\n /**\n * Manually resolve a guarantee on an order (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/guarantee/:order_id`\n */\n async resolveGuarantee(\n accountId: string,\n orderId: string,\n body: ResolveGuaranteeBody,\n ): Promise<ResolveGuaranteeResponse> {\n return this.request<ResolveGuaranteeResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/guarantee/${orderId}`,\n body,\n );\n }\n\n /**\n * Create an internal compensation (netting) between DS and Thor debts (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/compensacion`\n */\n async createCompensacion(\n accountId: string,\n body: CreateCompensacionBody,\n ): Promise<CreateCompensacionResponse> {\n return this.request<CreateCompensacionResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/compensacion`,\n body,\n );\n }\n\n /**\n * Create a financial adjustment (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/ajuste`\n */\n async createAjuste(\n accountId: string,\n body: CreateAjusteBody,\n ): Promise<CreateAjusteResponse> {\n return this.request<CreateAjusteResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/ajuste`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Financial Endpoints — Group B (Admin X)\n // -------------------------------------------------------------------------\n\n /**\n * Register a cobro — DS pays Thor the product cost (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/cobro`\n */\n async createCobro(\n accountId: string,\n body: CreateCobroBody,\n ): Promise<CreateCobroResponse> {\n return this.request<CreateCobroResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/cobro`,\n body,\n );\n }\n\n /**\n * Register a pago — Thor pays the dropshipper their commission (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/pago`\n */\n async createPago(\n accountId: string,\n body: CreatePagoBody,\n ): Promise<CreatePagoResponse> {\n return this.request<CreatePagoResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/pago`,\n body,\n );\n }\n\n /**\n * Reverse a confirmed financial movement (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/:mov_id/reverso`\n */\n async reverseSettlement(\n accountId: string,\n movementId: string,\n body: CreateReversoBody,\n ): Promise<CreateReversoResponse> {\n return this.request<CreateReversoResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/${movementId}/reverso`,\n body,\n );\n }\n\n /**\n * Confirm a pending financial movement (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/:mov_id/confirm`\n */\n async confirmSettlementMovement(\n accountId: string,\n movementId: string,\n body: ConfirmMovementBody = {},\n ): Promise<ConfirmMovementResponse> {\n return this.request<ConfirmMovementResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/${movementId}/confirm`,\n body,\n );\n }\n\n /**\n * Cancel a pending financial movement draft (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/:mov_id/cancel`\n */\n async cancelSettlementMovement(\n accountId: string,\n movementId: string,\n body: CancelMovementBody,\n ): Promise<CancelMovementResponse> {\n return this.request<CancelMovementResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/${movementId}/cancel`,\n body,\n );\n }\n\n /**\n * Get financial analysis for a dropshipper order (Admin only).\n *\n * `GET /admin/thor/dropshipper/admin/orders/:id/financial-analysis`\n */\n async getOrderFinancialAnalysis(\n orderId: string,\n ): Promise<GetFinancialAnalysisResponse> {\n return this.request<GetFinancialAnalysisResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/orders/${orderId}/financial-analysis`,\n );\n }\n\n /**\n * Register a partial or full payment for an order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/payment`\n */\n async registerOrderPayment(\n orderId: string,\n body: RegisterPaymentBody,\n ): Promise<RegisterPaymentResponse> {\n return this.request<RegisterPaymentResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/payment`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Promotions (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * List Y's promotions (discount codes).\n *\n * `GET /admin/thor/dropshipper/promotions`\n */\n async getPromotions(\n options: GetDropshipperPromotionsOptions = {},\n ): Promise<GetDropshipperPromotionsResponse> {\n const { type, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(type ? { type } : {}),\n });\n return this.request<GetDropshipperPromotionsResponse>(\n 'GET',\n `/admin/thor/dropshipper/promotions?${qs}`,\n );\n }\n\n /**\n * Create a promotion for Y's channel.\n *\n * `POST /admin/thor/dropshipper/promotions`\n */\n async createPromotion(\n body: CreateDropshipperPromotionBody,\n ): Promise<DropshipperPromotion> {\n return this.request<DropshipperPromotion>(\n 'POST',\n '/admin/thor/dropshipper/promotions',\n body,\n );\n }\n\n /**\n * Get a single promotion by ID.\n *\n * `GET /admin/thor/dropshipper/promotions/:id`\n */\n async getPromotion(promotionId: string): Promise<DropshipperPromotion> {\n return this.request<DropshipperPromotion>(\n 'GET',\n `/admin/thor/dropshipper/promotions/${promotionId}`,\n );\n }\n\n /**\n * Update an existing promotion.\n *\n * `PUT /admin/thor/dropshipper/promotions/:id`\n */\n async updatePromotion(\n promotionId: string,\n body: UpdateDropshipperPromotionBody,\n ): Promise<DropshipperPromotion> {\n return this.request<DropshipperPromotion>(\n 'PUT',\n `/admin/thor/dropshipper/promotions/${promotionId}`,\n body,\n );\n }\n\n /**\n * Delete a promotion.\n *\n * `DELETE /admin/thor/dropshipper/promotions/:id`\n */\n async deletePromotion(\n promotionId: string,\n ): Promise<DeleteDropshipperPromotionResponse> {\n return this.request<DeleteDropshipperPromotionResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/promotions/${promotionId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Dashboard (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * Aggregate stats for Y's dashboard (revenue, profit, top products).\n *\n * `GET /admin/thor/dropshipper/dashboard/stats`\n */\n async getDashboardStats(\n options: GetDashboardStatsOptions = {},\n ): Promise<GetDashboardStatsResponse> {\n const { period, from, to, currency_code } = options;\n const qs = new URLSearchParams({\n ...(period ? { period } : {}),\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n ...(currency_code ? { currency_code } : {}),\n });\n const query = qs.toString() ? `?${qs}` : '';\n return this.request<GetDashboardStatsResponse>(\n 'GET',\n `/admin/thor/dropshipper/dashboard/stats${query}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Storefront (V — end customer, uses publishable API key)\n // -------------------------------------------------------------------------\n\n /**\n * Public endpoint: dropshipper-scoped categories for the storefront.\n * Typically called with a publishable API key rather than a JWT.\n *\n * `GET /store/thor/dropshipper-categories`\n */\n async getStorefrontCategories(): Promise<GetStorefrontDropshipperCategoriesResponse> {\n return this.request<GetStorefrontDropshipperCategoriesResponse>(\n 'GET',\n '/store/thor/dropshipper-categories',\n );\n }\n\n // -------------------------------------------------------------------------\n // Draft Orders\n // -------------------------------------------------------------------------\n\n /**\n * List all draft orders in the dropshipper's channel.\n *\n * `GET /admin/thor/dropshipper/draft-orders`\n */\n async getDraftOrders(\n options: GetDropshipperDraftOrdersOptions = {},\n ): Promise<GetDropshipperDraftOrdersResponse> {\n const { customer_id, from, to, q, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(customer_id ? { customer_id } : {}),\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n ...(q ? { q } : {}),\n });\n return this.request<GetDropshipperDraftOrdersResponse>(\n 'GET',\n `/admin/thor/dropshipper/draft-orders?${qs}`,\n );\n }\n\n /**\n * Get a specific draft order by ID.\n *\n * `GET /admin/thor/dropshipper/draft-orders/:id`\n */\n async getDraftOrder(\n draftOrderId: string,\n ): Promise<GetDropshipperDraftOrderDetailResponse> {\n return this.request<GetDropshipperDraftOrderDetailResponse>(\n 'GET',\n `/admin/thor/dropshipper/draft-orders/${draftOrderId}`,\n );\n }\n\n /**\n * Create a new draft order.\n *\n * `POST /admin/thor/dropshipper/draft-orders`\n */\n async createDraftOrder(\n body: CreateDropshipperDraftOrderBody,\n ): Promise<CreateDropshipperDraftOrderResponse> {\n return this.request<CreateDropshipperDraftOrderResponse>(\n 'POST',\n '/admin/thor/dropshipper/draft-orders',\n body,\n );\n }\n\n /**\n * Update a draft order.\n *\n * `POST /admin/thor/dropshipper/draft-orders/:id`\n */\n async updateDraftOrder(\n draftOrderId: string,\n body: UpdateDropshipperDraftOrderBody,\n ): Promise<UpdateDropshipperDraftOrderResponse> {\n return this.request<UpdateDropshipperDraftOrderResponse>(\n 'POST',\n `/admin/thor/dropshipper/draft-orders/${draftOrderId}`,\n body,\n );\n }\n\n /**\n * Convert a draft order to a real order.\n *\n * `POST /admin/thor/dropshipper/draft-orders/:id/convert`\n */\n async convertDraftOrder(\n draftOrderId: string,\n body: ConvertDropshipperDraftOrderBody,\n ): Promise<ConvertDropshipperDraftOrderResponse> {\n return this.request<ConvertDropshipperDraftOrderResponse>(\n 'POST',\n `/admin/thor/dropshipper/draft-orders/${draftOrderId}/convert`,\n body,\n );\n }\n\n /**\n * Delete a draft order.\n *\n * `DELETE /admin/thor/dropshipper/draft-orders/:id`\n */\n async deleteDraftOrder(\n draftOrderId: string,\n ): Promise<DeleteDropshipperDraftOrderResponse> {\n return this.request<DeleteDropshipperDraftOrderResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/draft-orders/${draftOrderId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Geo-reference\n // -------------------------------------------------------------------------\n\n /**\n * List all geo-reference countries.\n *\n * `GET /admin/geo-reference`\n */\n async getGeoCountries(): Promise<GetGeoCountriesResponse> {\n return this.request<GetGeoCountriesResponse>('GET', '/admin/geo-reference');\n }\n\n /**\n * List provinces/states for a country.\n *\n * `GET /admin/geo-reference/countries/:iso_2/provinces`\n */\n async getGeoProvinces(iso2: string): Promise<GetGeoProvincesResponse> {\n return this.request<GetGeoProvincesResponse>(\n 'GET',\n `/admin/geo-reference/countries/${iso2}/provinces`,\n );\n }\n\n /**\n * List cities for a province/state.\n *\n * `GET /admin/geo-reference/provinces/:code/cities`\n */\n async getGeoCities(code: string): Promise<GetGeoCitiesResponse> {\n return this.request<GetGeoCitiesResponse>(\n 'GET',\n `/admin/geo-reference/provinces/${code}/cities`,\n );\n }\n}\n\n// Re-export types used by callers so they don't need to import from @thorprovider/types directly.\nexport type { DropshipperCategory, DropshipperPromotion, NotificationData, PriceUpdatedNotificationData, ProductAssignedNotificationData, StockChangeNotificationData, ManualAdminNotificationData, RawNotification, GetNotificationsOptions, GetNotificationsResponse, DropshipperNotificationEventType, DropshipperNotificationPreference, UpdateNotificationPreferencesBody, GetNotificationPreferencesResponse, GetBusinessPolicyResponse, UpdateBusinessPolicyBody, UpdateBusinessPolicyResponse, ChatRequest, ChatResponse, ChatMessage, ChatIntent, ChatSource, ChatSourceVariant } from '@thorprovider/types';\n\n// ---------------------------------------------------------------------------\n// AI Assistant — streaming helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Yields one parsed JSON object per `data:` line of a Server-Sent Events body.\n */\nasync function* parseSse(\n stream: ReadableStream<Uint8Array>,\n logger?: ReturnType<typeof createLogger>,\n): AsyncGenerator<unknown> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let frameIndex = 0;\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith('data:')) continue;\n const payload = trimmed.slice(5).trim();\n if (!payload || payload === '[DONE]') continue;\n frameIndex += 1;\n try {\n yield JSON.parse(payload);\n } catch (err: any) {\n logger?.warn(\n `[dropshipper] sse-malformed-frame frame=${frameIndex} payload=${payload.slice(0, 200)}`\n );\n }\n }\n }\n const tail = buffer.trim();\n if (tail.startsWith('data:')) {\n const payload = tail.slice(5).trim();\n if (payload && payload !== '[DONE]') {\n frameIndex += 1;\n try {\n yield JSON.parse(payload);\n } catch (err: any) {\n logger?.warn(\n `[dropshipper] sse-malformed-frame frame=${frameIndex} payload=${payload.slice(0, 200)}`\n );\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Normalize the backend's UI-message stream (SSE of `UIMessageChunk` frames)\n * into the consumer-friendly `ChatStreamEvent` type.\n */\nfunction mapUiMessageStreamToEvents(\n stream: ReadableStream<Uint8Array>,\n logger?: ReturnType<typeof createLogger>,\n): ReadableStream<ChatStreamEvent> {\n return new ReadableStream<ChatStreamEvent>({\n async start(controller) {\n let eventCount = 0;\n for await (const raw of parseSse(stream, logger)) {\n const chunk = raw as {\n type?: string;\n messageId?: string;\n delta?: string;\n errorText?: string;\n messageMetadata?: { intent?: ChatIntent; sources?: ChatSource[] };\n };\n switch (chunk.type) {\n case 'start':\n controller.enqueue({\n type: 'start',\n intent: chunk.messageMetadata?.intent,\n });\n eventCount += 1;\n break;\n case 'text-delta':\n if (chunk.delta !== undefined) {\n controller.enqueue({ type: 'text-delta', delta: chunk.delta });\n eventCount += 1;\n }\n break;\n case 'finish':\n controller.enqueue({\n type: 'finish',\n intent: chunk.messageMetadata?.intent ?? 'default',\n sources: chunk.messageMetadata?.sources ?? [],\n });\n eventCount += 1;\n break;\n case 'error':\n logger?.warn(\n `[dropshipper] chat-stream-error errorText=${chunk.errorText}`\n );\n controller.enqueue({\n type: 'error',\n errorText: chunk.errorText ?? 'Error inesperado del asistente.',\n });\n eventCount += 1;\n break;\n default:\n logger?.debug(\n `[dropshipper] chat-stream-unknown-frame type=${chunk.type}`\n );\n }\n }\n logger?.debug(`[dropshipper] chat-stream-completed events=${eventCount}`);\n controller.close();\n },\n cancel() {\n stream.cancel?.();\n },\n });\n}\n","/**\n * @fileoverview Recovery Client — Thor Commerce Extended\n * @module @thorprovider/medusa-extended/recovery\n *\n * Public HTTP client for account-recovery flows (password reset + activation).\n *\n * Unlike `DropshipperClient`, this client does NOT require a JWT: it talks to\n * public storefront endpoints so a user can recover access without being\n * logged in. Backend URLs are owned here; the dashboard never builds them.\n *\n * Endpoints:\n * - `POST /auth/user/emailpass/reset-password` (request reset, Medusa native)\n * - `GET /store/dropshipper/auth/reset-password/verify` (verify reset token, no consume)\n * - `POST /auth/user/emailpass/update` (confirm reset, consumes token)\n * - `GET /store/dropshipper/applications/activate/verify`(verify activation token, no consume)\n * - `POST /store/dropshipper/applications/activate` (confirm activation, consumes token)\n * - `POST /public/dropshipper/applications` (submit application, no auth)\n *\n * Confirm methods follow the two-phase contract: verify (no consume) first,\n * then confirm (atomic consume). A re-verify after a failed confirm maps the\n * TOCTOU state (used/expired/revoked) into `RecoveryConfirmResult.status`.\n *\n * `submitApplication` returns a discriminated `SubmitApplicationResult` instead\n * of throwing on 400/409/429 so the caller can surface the backend's structured\n * payload (existing application on 409, retry window on 429). Network/5xx\n * errors are re-thrown as `ProviderAPIError`.\n */\n\nimport type {\n SubmitApplicationBody,\n SubmitApplicationConflictApplication,\n SubmitApplicationResponse,\n SubmitApplicationResult,\n TokenVerifyResult,\n RecoveryConfirmResult,\n} from '@thorprovider/types';\nimport { createLogger, ProviderAPIError } from '@thorprovider/adapters';\nimport { fetchBackendWithResilience, type RetryConfig } from './request-resilience';\n\ntype FetchMethod = 'GET' | 'POST';\n\n/**\n * Configuration required to instantiate the recovery client.\n */\nexport interface RecoveryClientConfig {\n /** Medusa backend base URL */\n baseUrl: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * HTTP client for account-recovery endpoints (public, no auth required).\n *\n * All methods throw `ProviderAPIError` on non-2xx responses except the\n * confirm methods, which normalize failures into `RecoveryConfirmResult`.\n *\n * @example\n * ```typescript\n * const client = new RecoveryClient({\n * baseUrl: process.env.MEDUSA_BACKEND_URL!,\n * });\n *\n * await client.requestUserPasswordReset('juan@ejemplo.com');\n * const result = await client.verifyUserPasswordResetToken(token);\n * const confirm = await client.confirmUserPasswordReset(token, 'NuevaClave1');\n * ```\n */\nexport class RecoveryClient {\n private baseUrl: string;\n private logger: ReturnType<typeof createLogger>;\n\n constructor(config: RecoveryClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.logger = createLogger('RecoveryClient', config.debug);\n }\n\n // -------------------------------------------------------------------------\n // Private — HTTP helper\n // -------------------------------------------------------------------------\n\n private async request<T>(\n method: FetchMethod,\n path: string,\n body?: unknown,\n retryConfig?: RetryConfig,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n this.logger.debug(`[recovery] ${method} ${path}`);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n const init: RequestInit = {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n };\n\n let response: Response;\n try {\n response = await fetchBackendWithResilience(url, init, retryConfig);\n } catch (networkError: any) {\n throw new ProviderAPIError(\n `[recovery] Network error on ${method} ${path}: ${networkError.message}`,\n 'NETWORK_ERROR',\n networkError,\n );\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n let details: Record<string, unknown> | undefined;\n try {\n const json = await response.json();\n message = json?.message ?? message;\n details = json && typeof json === 'object' ? (json as Record<string, unknown>) : undefined;\n } catch {\n // ignore parse errors\n }\n throw new ProviderAPIError(\n `[recovery] ${method} ${path} failed: ${message}`,\n `RECOVERY_API_${response.status}`,\n response.status,\n details,\n );\n }\n\n return response.json() as Promise<T>;\n }\n\n // -------------------------------------------------------------------------\n // Private — reset token helpers\n // -------------------------------------------------------------------------\n\n /**\n * Decodes the `entity_id` (email) claim from a Medusa reset-password JWT.\n *\n * The JWT is unsigned-trust for this claim: the email is later sent to\n * `POST /auth/user/emailpass/update`, where Medusa itself re-validates the\n * token signature and payload before applying the change.\n */\n private decodeResetTokenEmail(token: string): string | null {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n try {\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf8'));\n return typeof payload.entity_id === 'string' && payload.entity_id.length > 0\n ? payload.entity_id\n : null;\n } catch {\n return null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Password reset\n // -------------------------------------------------------------------------\n\n /**\n * Solicita un email de reset de contraseña para el actor `user`\n * (dropshippers). El backend responde de forma uniforme exista o no la\n * cuenta (anti enumeración).\n *\n * `POST /auth/user/emailpass/reset-password`\n */\n async requestUserPasswordReset(email: string): Promise<void> {\n await this.request('POST', '/auth/user/emailpass/reset-password', {\n identifier: email,\n });\n }\n\n /**\n * Verifica un token de reset de contraseña sin consumirlo. Devuelve el\n * email enmascarado (p. ej. `j***@ejemplo.com`) solo cuando `status === 'valid'`.\n *\n * `GET /store/dropshipper/auth/reset-password/verify`\n */\n async verifyUserPasswordResetToken(token: string): Promise<TokenVerifyResult> {\n return this.request('GET', `/store/dropshipper/auth/reset-password/verify?token=${encodeURIComponent(token)}`);\n }\n\n /**\n * Confirma el reset: re-verifica el token (sin consumir), luego consume el\n * token vía `POST /auth/user/emailpass/update`. El email se deriva del\n * propio JWT. Nunca devuelve auto-login: al éxito, la UI redirige a /login.\n */\n async confirmUserPasswordReset(token: string, password: string): Promise<RecoveryConfirmResult> {\n const verify = await this.verifyUserPasswordResetToken(token);\n if (verify.status !== 'valid') {\n return { ok: false, status: verify.status };\n }\n\n const email = this.decodeResetTokenEmail(token);\n if (!email) {\n return { ok: false, status: 'invalid' };\n }\n\n try {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n };\n const response = await fetchBackendWithResilience(`${this.baseUrl}/auth/user/emailpass/update`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ email, password }),\n });\n if (!response.ok) {\n throw new ProviderAPIError(\n `[recovery] POST /auth/user/emailpass/update failed: HTTP ${response.status}`,\n 'RECOVERY_API_' + response.status,\n response.status,\n );\n }\n return { ok: true };\n } catch (error) {\n // TOCTOU: el token pudo consumirse/expirar entre verify y update.\n this.logger.warn('[recovery] confirmUserPasswordReset failed, re-verifying', error);\n try {\n const recheck = await this.verifyUserPasswordResetToken(token);\n return { ok: false, status: recheck.status };\n } catch {\n return { ok: false, status: 'invalid' };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Account activation\n // -------------------------------------------------------------------------\n\n /**\n * Verifica un token de activación de cuenta dropshipper sin consumirlo.\n *\n * `GET /store/dropshipper/applications/activate/verify`\n */\n async verifyActivationToken(token: string): Promise<TokenVerifyResult> {\n return this.request('GET', `/store/dropshipper/applications/activate/verify?token=${encodeURIComponent(token)}`);\n }\n\n /**\n * Activa la cuenta: re-verifica el token (sin consumir), luego consume el\n * token vía `POST /store/dropshipper/applications/activate` y establece la\n * contraseña inicial. Al éxito, la UI redirige a /login sin auto-login.\n */\n async activateAccount(token: string, password: string): Promise<RecoveryConfirmResult> {\n const verify = await this.verifyActivationToken(token);\n if (verify.status !== 'valid') {\n return { ok: false, status: verify.status };\n }\n\n try {\n await this.request('POST', '/store/dropshipper/applications/activate', { token, password });\n return { ok: true };\n } catch (error) {\n // TOCTOU: re-verificar para distinguir used/expired/revoked.\n this.logger.warn('[recovery] activateAccount failed, re-verifying', error);\n try {\n const recheck = await this.verifyActivationToken(token);\n return { ok: false, status: recheck.status };\n } catch {\n return { ok: false, status: 'invalid' };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Dropshipper application submission\n // -------------------------------------------------------------------------\n\n /**\n * Envía una solicitud de acceso dropshipper al endpoint público.\n *\n * `POST /public/dropshipper/applications`\n *\n * No requiere autenticación. Devuelve un resultado discriminado:\n * - `{ ok: true }` → 201, solicitud creada (`application.number`).\n * - `{ ok: false, reason: 'conflict' }` → 409, email ya registrado; la\n * solicitud existente incluye `status_label`/`reason` para la UI.\n * - `{ ok: false, reason: 'rate_limited' }` → 429, se respetó el límite del\n * backend; `retryAfterSeconds` indica cuándo reintentar.\n * - `{ ok: false, reason: 'invalid_data' }` → 400, validación del backend.\n *\n * Los errores de red/5xx se re-lanzan como `ProviderAPIError` para que el\n * llamador los categorice (p. ej. con `parseError`). El 429 no se reintenta\n * (`retryableStatusCodes` sin 429) para que el caller reciba de inmediato el\n * `retry_after_seconds` del backend y pueda bloquear el envío.\n */\n async submitApplication(body: SubmitApplicationBody): Promise<SubmitApplicationResult> {\n try {\n const response = await this.request<SubmitApplicationResponse>(\n 'POST',\n '/public/dropshipper/applications',\n body,\n { retryableStatusCodes: [408, 500, 502, 503, 504] },\n );\n return { ok: true, application: response.application };\n } catch (error) {\n if (error instanceof ProviderAPIError) {\n const details = error.details ?? {};\n if (error.status === 409 && details.application) {\n return {\n ok: false,\n reason: 'conflict',\n application: details.application as SubmitApplicationConflictApplication,\n };\n }\n if (error.status === 429 && typeof details.retry_after_seconds === 'number') {\n return {\n ok: false,\n reason: 'rate_limited',\n retryAfterSeconds: details.retry_after_seconds,\n };\n }\n if (error.status === 400 && details?.type === 'challenge_failed') {\n return {\n ok: false,\n reason: 'challenge_failed',\n ...(typeof details.message === 'string' ? { message: details.message } : {}),\n };\n }\n if (error.status === 400) {\n return {\n ok: false,\n reason: 'invalid_data',\n fields: details.fields as Record<string, string[]> | undefined,\n };\n }\n }\n throw error;\n }\n }\n}"],"mappings":"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","names":["import_adapters","import_adapters","import_adapters"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/admin.ts","../src/request-resilience.ts","../src/dropshipper.ts","../src/recovery.ts"],"sourcesContent":["/**\n * @thorprovider/medusa-extended\n * Thor Commerce multi-tenant admin extensions for Medusa\n */\n\nexport { MedusaAdminClient } from './admin';\nexport type { MedusaAdminClientConfig } from './admin';\n\nexport { DropshipperClient } from './dropshipper';\nexport type { DropshipperClientConfig, ChatStreamEvent } from './dropshipper';\n\nexport { RecoveryClient } from './recovery';\nexport type { RecoveryClientConfig } from './recovery';\n\n","/**\n * @fileoverview Medusa Multi-Tenant Admin Client\n * @module @thorprovider/adapters/providers/medusa/admin\n *\n * Wrapper methods for all `/admin/thor/` endpoints defined in the Thor Commerce\n * multi-tenant API contract. Requires an admin API key (`adminConfig.apiKey`)\n * to be provided when creating the Medusa provider.\n *\n * Every method performs a raw `fetch` against the Medusa backend using the\n * admin API key (`x-medusa-access-token`) — the Medusa JS-SDK's admin client\n * does not expose these custom Thor plugin routes, so we use direct HTTP calls.\n *\n * Endpoint reference: `multitenant-api-contract.md`\n */\n\nimport type {\n GetChannelCustomersOptions,\n GetChannelCustomersResponse,\n GetChannelApiKeysResponse,\n GetChannelCategoriesOptions,\n GetChannelCategoriesResponse,\n GetCategorySalesChannelsResponse,\n AssignCategoriesToChannelsBody,\n AssignCategoriesToChannelsResponse,\n UnassignCategoriesFromChannelsBody,\n UnassignCategoriesFromChannelsResponse,\n GetCollectionSalesChannelsResponse,\n AssignCollectionsToChannelsBody,\n AssignCollectionsToChannelsResponse,\n UnassignCollectionsFromChannelsBody,\n UnassignCollectionsFromChannelsResponse,\n GetAdminStorefrontConfigResponse,\n UpdateStorefrontConfigBody,\n UpdateStorefrontConfigResponse,\n GetAdminSiteConfigResponse,\n UpdateSiteConfigBody,\n UpdateSiteConfigResponse,\n GetAdminSiteConfigHistoryOptions,\n GetAdminSiteConfigHistoryResponse,\n RestoreSiteConfigResponse,\n} from '@thorprovider/types';\nimport { createLogger, ProviderAPIError } from '@thorprovider/adapters';\nimport { fetchBackendWithResilience } from './request-resilience';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ntype FetchMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\n/**\n * Configuration required to instantiate the admin client.\n */\nexport interface MedusaAdminClientConfig {\n /** Medusa backend base URL */\n baseUrl: string;\n /** Secret admin API key (x-medusa-access-token) */\n apiKey: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// MedusaAdminClient\n// ---------------------------------------------------------------------------\n\n/**\n * HTTP client for Thor Commerce multi-tenant admin endpoints (`/admin/thor/`).\n *\n * All methods throw `ProviderAPIError` on non-2xx responses.\n *\n * @example\n * ```typescript\n * const admin = new MedusaAdminClient({\n * baseUrl: process.env.MEDUSA_BACKEND_URL!,\n * apiKey: process.env.MEDUSA_ADMIN_API_KEY!,\n * });\n *\n * const { customers } = await admin.getChannelCustomers('sc_01JXXXXX');\n * ```\n */\nexport class MedusaAdminClient {\n private baseUrl: string;\n private apiKey: string;\n private logger: ReturnType<typeof createLogger>;\n\n constructor(config: MedusaAdminClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.logger = createLogger('MedusaAdminClient', config.debug);\n }\n\n // -----------------------------------------------------------------------\n // Private — HTTP helper\n // -----------------------------------------------------------------------\n\n private async request<T>(\n method: FetchMethod,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n this.logger.debug(`[admin] ${method} ${path}`);\n\n const headers: Record<string, string> = {\n 'x-medusa-access-token': this.apiKey,\n 'Content-Type': 'application/json',\n };\n\n const init: RequestInit = {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n };\n\n let response: Response;\n try {\n response = await fetchBackendWithResilience(url, init);\n } catch (networkError: any) {\n throw new ProviderAPIError(\n `[admin] Network error on ${method} ${path}: ${networkError.message}`,\n 'NETWORK_ERROR',\n networkError,\n );\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n try {\n const json = await response.json();\n message = json?.message ?? message;\n } catch {\n // ignore parse errors\n }\n throw new ProviderAPIError(\n `[admin] ${method} ${path} failed: ${message}`,\n `ADMIN_API_${response.status}`,\n response.status,\n );\n }\n\n return response.json() as Promise<T>;\n }\n\n // -----------------------------------------------------------------------\n // 3.1 — Sales Channel: Customers\n // -----------------------------------------------------------------------\n\n /**\n * Paginated list of customers linked to a sales channel.\n *\n * `GET /admin/thor/sales-channels/:id/customers`\n */\n async getChannelCustomers(\n salesChannelId: string,\n options: GetChannelCustomersOptions = {},\n ): Promise<GetChannelCustomersResponse> {\n const { limit = 20, offset = 0 } = options;\n return this.request<GetChannelCustomersResponse>(\n 'GET',\n `/admin/thor/sales-channels/${salesChannelId}/customers?limit=${limit}&offset=${offset}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.2 — Sales Channel: API Keys\n // -----------------------------------------------------------------------\n\n /**\n * Publishable API keys associated with a sales channel.\n *\n * `GET /admin/thor/sales-channels/:id/api-keys`\n */\n async getChannelApiKeys(salesChannelId: string): Promise<GetChannelApiKeysResponse> {\n return this.request<GetChannelApiKeysResponse>(\n 'GET',\n `/admin/thor/sales-channels/${salesChannelId}/api-keys`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.3 — Sales Channel: Categories\n // -----------------------------------------------------------------------\n\n /**\n * Product categories assigned to a sales channel.\n *\n * `GET /admin/thor/sales-channels/:id/categories`\n */\n async getChannelCategories(\n salesChannelId: string,\n options: GetChannelCategoriesOptions = {},\n ): Promise<GetChannelCategoriesResponse> {\n const { limit = 20, offset = 0, include_descendants = false } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n include_descendants: String(include_descendants),\n });\n return this.request<GetChannelCategoriesResponse>(\n 'GET',\n `/admin/thor/sales-channels/${salesChannelId}/categories?${qs}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.4 — Category: Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Sales channels to which a category is assigned.\n *\n * `GET /admin/thor/categories/:id/sales-channels`\n */\n async getCategorySalesChannels(\n categoryId: string,\n ): Promise<GetCategorySalesChannelsResponse> {\n return this.request<GetCategorySalesChannelsResponse>(\n 'GET',\n `/admin/thor/categories/${categoryId}/sales-channels`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.5 — Category: Assign to Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Assign a category to one or more sales channels (idempotent).\n *\n * `POST /admin/thor/categories/:id/sales-channels`\n */\n async assignCategoryToChannels(\n categoryId: string,\n body: AssignCategoriesToChannelsBody,\n ): Promise<AssignCategoriesToChannelsResponse> {\n return this.request<AssignCategoriesToChannelsResponse>(\n 'POST',\n `/admin/thor/categories/${categoryId}/sales-channels`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.6 — Category: Unassign from Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Remove category assignment from one or more sales channels (idempotent).\n *\n * `DELETE /admin/thor/categories/:id/sales-channels`\n */\n async unassignCategoryFromChannels(\n categoryId: string,\n body: UnassignCategoriesFromChannelsBody,\n ): Promise<UnassignCategoriesFromChannelsResponse> {\n return this.request<UnassignCategoriesFromChannelsResponse>(\n 'DELETE',\n `/admin/thor/categories/${categoryId}/sales-channels`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.7 — Collection: Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Sales channels to which a collection is assigned.\n *\n * `GET /admin/thor/collections/:id/sales-channels`\n */\n async getCollectionSalesChannels(\n collectionId: string,\n ): Promise<GetCollectionSalesChannelsResponse> {\n return this.request<GetCollectionSalesChannelsResponse>(\n 'GET',\n `/admin/thor/collections/${collectionId}/sales-channels`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.8 — Collection: Assign to Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Assign a collection to one or more sales channels (idempotent).\n *\n * `POST /admin/thor/collections/:id/sales-channels`\n */\n async assignCollectionToChannels(\n collectionId: string,\n body: AssignCollectionsToChannelsBody,\n ): Promise<AssignCollectionsToChannelsResponse> {\n return this.request<AssignCollectionsToChannelsResponse>(\n 'POST',\n `/admin/thor/collections/${collectionId}/sales-channels`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.9 — Collection: Unassign from Sales Channels\n // -----------------------------------------------------------------------\n\n /**\n * Remove collection assignment from one or more sales channels (idempotent).\n *\n * `DELETE /admin/thor/collections/:id/sales-channels`\n */\n async unassignCollectionFromChannels(\n collectionId: string,\n body: UnassignCollectionsFromChannelsBody,\n ): Promise<UnassignCollectionsFromChannelsResponse> {\n return this.request<UnassignCollectionsFromChannelsResponse>(\n 'DELETE',\n `/admin/thor/collections/${collectionId}/sales-channels`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.10 — Storefront Config: Read\n // -----------------------------------------------------------------------\n\n /**\n * Read the visual storefront configuration for a channel.\n * `:id` is the `sales_channel_id`.\n *\n * `GET /admin/thor/storefront-config/:id`\n */\n async getStorefrontConfig(\n salesChannelId: string,\n ): Promise<GetAdminStorefrontConfigResponse> {\n return this.request<GetAdminStorefrontConfigResponse>(\n 'GET',\n `/admin/thor/storefront-config/${salesChannelId}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.11 — Storefront Config: Update\n // -----------------------------------------------------------------------\n\n /**\n * Update the visual storefront configuration for a channel.\n * Triggers the `storefront_config.updated` event → ISR webhook.\n *\n * `PUT /admin/thor/storefront-config/:id`\n */\n async updateStorefrontConfig(\n salesChannelId: string,\n body: UpdateStorefrontConfigBody,\n ): Promise<UpdateStorefrontConfigResponse> {\n return this.request<UpdateStorefrontConfigResponse>(\n 'PUT',\n `/admin/thor/storefront-config/${salesChannelId}`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.12 — Site Designer Config: Read\n // -----------------------------------------------------------------------\n\n /**\n * Read the active Site Designer configuration for a channel, including the\n * last 10 history entries.\n *\n * `GET /admin/thor/site-config/:sales_channel_id`\n */\n async getSiteConfig(salesChannelId: string): Promise<GetAdminSiteConfigResponse> {\n return this.request<GetAdminSiteConfigResponse>(\n 'GET',\n `/admin/thor/site-config/${salesChannelId}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.13 — Site Designer Config: Update\n // -----------------------------------------------------------------------\n\n /**\n * Update the Site Designer configuration for a channel.\n * Creates a new history entry on every PUT.\n *\n * `PUT /admin/thor/site-config/:sales_channel_id`\n */\n async updateSiteConfig(\n salesChannelId: string,\n body: UpdateSiteConfigBody,\n ): Promise<UpdateSiteConfigResponse> {\n return this.request<UpdateSiteConfigResponse>(\n 'PUT',\n `/admin/thor/site-config/${salesChannelId}`,\n body,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.14 — Site Designer Config: History\n // -----------------------------------------------------------------------\n\n /**\n * Full paginated history of Site Designer versions for a channel.\n * Entries are immutable — they are never deleted.\n *\n * `GET /admin/thor/site-config/:sales_channel_id/history`\n */\n async getSiteConfigHistory(\n salesChannelId: string,\n options: GetAdminSiteConfigHistoryOptions = {},\n ): Promise<GetAdminSiteConfigHistoryResponse> {\n const { limit = 20, offset = 0 } = options;\n return this.request<GetAdminSiteConfigHistoryResponse>(\n 'GET',\n `/admin/thor/site-config/${salesChannelId}/history?limit=${limit}&offset=${offset}`,\n );\n }\n\n // -----------------------------------------------------------------------\n // 3.15 — Site Designer Config: Restore\n // -----------------------------------------------------------------------\n\n /**\n * Restore a previous Site Designer version.\n * Internally runs the update workflow with the stored config of the target\n * version — this creates a **new** history entry and does NOT mutate past\n * entries.\n *\n * `POST /admin/thor/site-config/:sales_channel_id/restore/:version`\n */\n async restoreSiteConfig(\n salesChannelId: string,\n version: string,\n ): Promise<RestoreSiteConfigResponse> {\n return this.request<RestoreSiteConfigResponse>(\n 'POST',\n `/admin/thor/site-config/${salesChannelId}/restore/${encodeURIComponent(version)}`,\n );\n }\n}\n","import { ProviderAPIError, backendCircuitBreaker } from '@thorprovider/adapters'\n\nexport type RetryConfig = {\n maxRetries?: number\n initialDelayMs?: number\n backoffMultiplier?: number\n maxDelayMs?: number\n timeoutMs?: number\n retryableStatusCodes?: number[]\n}\n\nconst DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n initialDelayMs: 300,\n backoffMultiplier: 2,\n maxDelayMs: 5000,\n timeoutMs: 10000,\n retryableStatusCodes: [408, 429, 500, 502, 503, 504],\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction calculateDelay(attempt: number, config: Required<RetryConfig>): number {\n const delay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt)\n return Math.min(delay, config.maxDelayMs)\n}\n\nfunction isRetryableError(error: unknown, config: Required<RetryConfig>): boolean {\n const err = error as { name?: string; message?: string; status?: number }\n\n if (err.name === 'TypeError' || err.message?.includes('fetch failed')) return true\n if (err.name === 'AbortError' || err.message?.includes('timeout')) return true\n if (typeof err.status === 'number' && config.retryableStatusCodes.includes(err.status)) return true\n return false\n}\n\nasync function fetchWithRetry(url: string, init: RequestInit, retryConfig?: RetryConfig): Promise<Response> {\n const config = { ...DEFAULT_RETRY_CONFIG, ...retryConfig }\n const method = (init.method || 'GET').toUpperCase()\n const isMutation = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)\n let lastError: unknown\n\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), config.timeoutMs)\n\n const response = await fetch(url, { ...init, signal: controller.signal })\n clearTimeout(timeoutId)\n\n if (!response.ok && config.retryableStatusCodes.includes(response.status)) {\n const error = new Error(`HTTP ${response.status}: ${response.statusText}`) as Error & { status?: number }\n error.status = response.status\n throw error\n }\n\n return response\n } catch (error) {\n lastError = error\n\n // Never retry mutations (POST/PUT/PATCH/DELETE) on timeout/network error.\n // The first request may have succeeded on the backend, and retrying would\n // create duplicate resources (customers, orders, etc.).\n const isTimeoutOrNetwork = error instanceof Error &&\n (error.name === 'AbortError' || error.message?.includes('timeout') || error.message?.includes('fetch failed'))\n if (isMutation && isTimeoutOrNetwork) {\n break\n }\n\n const shouldRetry = attempt < config.maxRetries && isRetryableError(error, config)\n\n if (shouldRetry) {\n await sleep(calculateDelay(attempt, config))\n continue\n }\n\n break\n }\n }\n\n throw lastError instanceof Error ? lastError : new Error('Backend request failed')\n}\n\nexport async function fetchBackendWithResilience(url: string, init: RequestInit, retryConfig?: RetryConfig): Promise<Response> {\n try {\n return await backendCircuitBreaker.execute(() => fetchWithRetry(url, init, retryConfig))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new ProviderAPIError(`Backend request failed: ${message}`, 'backend', 503)\n }\n}\n","/**\n * @fileoverview Dropshipper Client — Thor Commerce Extended\n * @module @thorprovider/medusa-extended/dropshipper\n *\n * HTTP client for all `/admin/thor/dropshipper/` endpoints.\n *\n * Used by both:\n * - X (ThorProvider admin) — authenticated via admin JWT, role \"Admin\"\n * - Y (Dropshipper panel) — authenticated via dropshipper JWT, role \"Dropshipper\"\n *\n * Access control is enforced server-side via `withDropshipperScope` middleware.\n * This client always sends `Authorization: Bearer <token>`.\n *\n * Endpoint reference: `dropshipping-api-contract.md`\n */\n\nimport type {\n // Onboarding\n OnboardDropshipperBody,\n OnboardDropshipperResponse,\n // Products & Prices\n DropshipperCostTier,\n DropshipperSaleTier,\n GetDropshipperProductsOptions,\n GetDropshipperProductsResponse,\n ValidateCheckoutItemsRequest,\n ValidateCheckoutItemsResponse,\n CostPriceChangesCheckResponse,\n CostPriceChangesResponse,\n AcknowledgeCostPriceChangesResponse,\n UpdateDropshipperProductStatusBody,\n UpdateDropshipperProductStatusResponse,\n UpdateDropshipperPricesBody,\n UpdateDropshipperPricesResponse,\n GetDropshipperAttributesResponse,\n // Orders\n GetDropshipperOrdersOptions,\n GetDropshipperOrdersResponse,\n GetDropshipperShippingOptionsBody,\n GetDropshipperShippingOptionsResponse,\n GetDropshipperOrderDetailResponse,\n ExtendedCreateDropshipperOrderBody,\n ExtendedCreateDropshipperOrderResponse,\n SetPaymentCollectorBody,\n SetPaymentCollectorResponse,\n // Order Cancel & Edits\n CancelDropshipperOrderResponse,\n CreateOrderEditBody,\n CreateOrderEditResponse,\n AddOrderEditItemBody,\n AddOrderEditItemResponse,\n ConfirmOrderEditResponse,\n // Order Notes\n OrderNote,\n CreateOrderNoteBody,\n GetOrderNotesResponse,\n CreateOrderNoteResponse,\n DeleteOrderNoteResponse,\n // Draft Orders\n GetDropshipperDraftOrdersOptions,\n GetDropshipperDraftOrdersResponse,\n GetDropshipperDraftOrderDetailResponse,\n CreateDropshipperDraftOrderBody,\n CreateDropshipperDraftOrderResponse,\n UpdateDropshipperDraftOrderBody,\n UpdateDropshipperDraftOrderResponse,\n ConvertDropshipperDraftOrderBody,\n ConvertDropshipperDraftOrderResponse,\n DeleteDropshipperDraftOrderResponse,\n // Dropshipper Addresses\n DropshipperAddressBody,\n DropshipperAddressResponse,\n GetDropshipperAddressesResponse,\n // Categories\n GetDropshipperCategoriesOptions,\n GetDropshipperCategoriesResponse,\n CreateDropshipperCategoryBody,\n UpdateDropshipperCategoryBody,\n DeleteDropshipperCategoryResponse,\n GetProviderCategoriesResponse,\n GetCategoryMappingsOptions,\n GetCategoryMappingsResponse,\n CreateCategoryMappingBody,\n CreateCategoryMappingResponse,\n DeleteCategoryMappingResponse,\n // Customers\n GetDropshipperCustomersOptions,\n GetDropshipperCustomersResponse,\n GetDropshipperCustomerDetailResponse,\n CreateDropshipperCustomerBody,\n CreateDropshipperCustomerResponse,\n UpdateDropshipperCustomerBody,\n UpdateDropshipperCustomerResponse,\n // Account & Settlements (Y)\n GetDropshipperAccountResponse,\n GetDropshipperPayableResponse,\n GetDropshipperReceivableResponse,\n GetSettlementsOptions,\n GetSettlementsResponse,\n GetSettlementDetailResponse,\n // Admin Settlements (X)\n CreateSettlementBody,\n CreateSettlementResponse,\n ConfirmSettlementBody,\n CancelSettlementBody,\n UpdateSettlementStatusResponse,\n // Admin Account Management (X)\n GetAdminDropshipperAccountsResponse,\n GetAdminAccountBalanceResponse,\n GetAdminPriceListsResponse,\n GetUserChannelResponse,\n // Promotions\n GetDropshipperPromotionsOptions,\n GetDropshipperPromotionsResponse,\n CreateDropshipperPromotionBody,\n UpdateDropshipperPromotionBody,\n DeleteDropshipperPromotionResponse,\n // Dashboard\n GetDashboardStatsOptions,\n GetDashboardStatsResponse,\n // Storefront (V)\n GetStorefrontDropshipperCategoriesResponse,\n // Financial Endpoints — Group A\n GetDropshipperAccountBalanceResponse,\n GetDropshipperAccountOrdersOptions,\n GetDropshipperAccountOrdersResponse,\n GetAdminDropshipperAccountOrdersResponse,\n GetAdminDropshipperAccountSettlementsOptions,\n GetAdminDropshipperAccountSettlementsResponse,\n ResolveGuaranteeBody,\n ResolveGuaranteeResponse,\n CreateCompensacionBody,\n CreateCompensacionResponse,\n CreateAjusteBody,\n CreateAjusteResponse,\n // Financial Endpoints — Group B\n CreateCobroBody,\n CreateCobroResponse,\n CreatePagoBody,\n CreatePagoResponse,\n CreateReversoBody,\n CreateReversoResponse,\n ConfirmMovementBody,\n ConfirmMovementResponse,\n CancelMovementBody,\n CancelMovementResponse,\n GetFinancialAnalysisResponse,\n RegisterPaymentBody,\n RegisterPaymentResponse,\n SetPaymentMethodBody,\n SetPaymentMethodResponse,\n // Geo-reference\n GetGeoCountriesResponse,\n GetGeoProvincesResponse,\n GetGeoCitiesResponse,\n // Dashboard Capabilities\n DropshipperDashboardCapabilities,\n // AI Assistant Chat\n ChatRequest,\n ChatResponse,\n ChatIntent,\n ChatSource,\n ChatAssistantHealthResponse,\n // Profile\n GetMyProfileResponse,\n // Notifications\n GetNotificationsOptions,\n GetNotificationsResponse,\n // Notification preferences\n DropshipperNotificationEventType,\n DropshipperNotificationPreference,\n UpdateNotificationPreferencesBody,\n GetNotificationPreferencesResponse,\n // Dropshipper business policy\n GetBusinessPolicyResponse,\n UpdateBusinessPolicyBody,\n UpdateBusinessPolicyResponse,\n // Inline return types\n DropshipperCategory,\n DropshipperPromotion,\n // Product Attributes\n GetProductAttributesResponse,\n // Unified Query\n QueryEntitiesInput,\n QueryResponse,\n} from '@thorprovider/types';\nimport { createLogger, ProviderAPIError } from '@thorprovider/adapters';\nimport { fetchBackendWithResilience } from './request-resilience';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype FetchMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\n// ---------------------------------------------------------------------------\n// AI Assistant — streaming chat events\n// ---------------------------------------------------------------------------\n\n/**\n * One event from the streamed AI assistant chat (`chatAssistantStream`).\n *\n * The backend returns a UI-message stream (SSE over `text/event-stream`) for\n * catalog searches, and a plain JSON `ChatResponse` for `default` intents.\n * `chatAssistantStream` normalizes both into this single event type so\n * consumers can render incremental text and update the \"thinking\" label as the\n * model progresses without knowing the transport details.\n */\nexport type ChatStreamEvent =\n | {\n type: 'start';\n /** Semantic intent as soon as the backend resolves it. */\n intent?: ChatIntent;\n }\n | {\n type: 'text-delta';\n /** A chunk of the assistant's answer, appended to the bubble. */\n delta: string;\n }\n | {\n type: 'finish';\n intent: ChatIntent;\n /** Products referenced by the answer (empty for `default` intents). */\n sources: ChatSource[];\n }\n | {\n type: 'error';\n errorText: string;\n };\n\n/**\n * Configuration required to instantiate the dropshipper client.\n */\nexport interface DropshipperClientConfig {\n /** Medusa backend base URL */\n baseUrl: string;\n /**\n * JWT token obtained from `POST /auth/user/emailpass`.\n * Used as `Authorization: Bearer <token>`.\n */\n token: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// DropshipperClient\n// ---------------------------------------------------------------------------\n\n/**\n * HTTP client for Thor Commerce dropshipping endpoints (`/admin/thor/dropshipper/`).\n *\n * All methods throw `ProviderAPIError` on non-2xx responses.\n *\n * @example\n * ```typescript\n * const client = new DropshipperClient({\n * baseUrl: process.env.MEDUSA_BACKEND_URL!,\n * token: jwtFromLogin,\n * });\n *\n * // Y: list own products\n * const { products } = await client.getProducts();\n *\n * // X: onboard a new dropshipper\n * const { dropshipper } = await client.onboardDropshipper({ ... });\n * ```\n */\nexport class DropshipperClient {\n private baseUrl: string;\n private token: string;\n private logger: ReturnType<typeof createLogger>;\n\n constructor(config: DropshipperClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.token = config.token;\n this.logger = createLogger('DropshipperClient', config.debug);\n }\n\n // -------------------------------------------------------------------------\n // Private — HTTP helper\n // -------------------------------------------------------------------------\n\n private async request<T>(\n method: FetchMethod,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n this.logger.debug(`[dropshipper] ${method} ${path}`);\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n };\n\n const init: RequestInit = {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n };\n\n let response: Response;\n try {\n response = await fetchBackendWithResilience(url, init);\n } catch (networkError: any) {\n throw new ProviderAPIError(\n `[dropshipper] Network error on ${method} ${path}: ${networkError.message}`,\n 'NETWORK_ERROR',\n networkError,\n );\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n try {\n const json = await response.json();\n message = json?.message ?? message;\n } catch {\n // ignore parse errors\n }\n throw new ProviderAPIError(\n `[dropshipper] ${method} ${path} failed: ${message}`,\n `DROPSHIPPER_API_${response.status}`,\n response.status,\n );\n }\n\n return response.json() as Promise<T>;\n }\n\n // -------------------------------------------------------------------------\n // Unified Query\n // -------------------------------------------------------------------------\n\n /**\n * Resolve multiple entities in a single request.\n *\n * `POST /admin/thor/dropshipper/query`\n *\n * Entities are resolved in parallel (per layer) and errors are isolated per\n * entity: `response.errors[key]` holds the per-entity error while the rest\n * of `data` still resolves. `data[key]` is an array (list entities) or a\n * single object (singular entities such as account, balance, me).\n *\n * @example\n * ```typescript\n * const { data } = await client.query({\n * entities: [\n * { entity: 'capabilities' },\n * { entity: 'me' },\n * { entity: 'account' },\n * ],\n * });\n * ```\n */\n async query(input: QueryEntitiesInput): Promise<QueryResponse> {\n return this.request<QueryResponse>(\n 'POST',\n '/admin/thor/dropshipper/query',\n input,\n );\n }\n\n // -------------------------------------------------------------------------\n // Capabilities\n // -------------------------------------------------------------------------\n\n /**\n * Fetch dashboard capabilities from the backend.\n *\n * `GET /admin/thor/dropshipper/capabilities`\n */\n async getCapabilities(): Promise<DropshipperDashboardCapabilities> {\n return this.request<DropshipperDashboardCapabilities>(\n 'GET',\n '/admin/thor/dropshipper/capabilities',\n );\n }\n\n /**\n * Fetch the authenticated dropshipper's personal profile including\n * first_name, last_name, email, avatar_url, and linked sales channel.\n *\n * `GET /admin/thor/dropshipper/me`\n */\n async getMyProfile(): Promise<GetMyProfileResponse> {\n return this.request<GetMyProfileResponse>(\n 'GET',\n '/admin/thor/dropshipper/me',\n );\n }\n\n /**\n * Send a chat message to the AI assistant (catalog intelligence).\n * The conversation is stateless — the client sends the full message\n * history on every request.\n *\n * `POST /admin/thor/dropshipper/ai/chat`\n *\n * @example\n * ```typescript\n * const { answer, sources } = await client.chatAssistant({\n * messages: [{ role: 'user', content: 'productos con mejor margen' }],\n * });\n * ```\n */\n async chatAssistant(body: ChatRequest): Promise<ChatResponse> {\n return this.request<ChatResponse>(\n 'POST',\n '/admin/thor/dropshipper/ai/chat',\n body,\n );\n }\n\n /**\n * Stream the AI assistant's reply.\n *\n * Unlike `chatAssistant`, this surfaces the model's progress: the backend\n * resolves the intent first and then streams the answer token by token\n * (catalog searches) or returns the full answer in one shot (`default`).\n * The response is normalized into a single `ReadableStream<ChatStreamEvent>`\n * so callers can show a live \"thinking\" label and render text incrementally.\n *\n * `POST /admin/thor/dropshipper/ai/chat`\n */\n async chatAssistantStream(body: ChatRequest): Promise<ReadableStream<ChatStreamEvent>> {\n const url = `${this.baseUrl}/admin/thor/dropshipper/ai/chat`;\n this.logger.debug('[dropshipper] POST /admin/thor/dropshipper/ai/chat (stream)');\n\n const init: RequestInit = {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n },\n body: JSON.stringify(body),\n };\n\n let response: Response;\n try {\n // This endpoint performs two LLM round-trips plus channel-scoped retrieval\n // BEFORE it starts streaming (headers only flush when Stage 3 begins), so\n // the default 10s timeout aborts legitimate catalog searches. Use a larger\n // per-attempt timeout; once headers arrive the timer is cleared and the\n // streamed body is unaffected. POST is a mutation, so on timeout/network it\n // won't be retried — maxRetries:1 only guards against redundant 5xx/red work.\n response = await fetchBackendWithResilience(url, init, {\n timeoutMs: 60_000,\n maxRetries: 1,\n });\n } catch (networkError: any) {\n throw new ProviderAPIError(\n `[dropshipper] Network error on POST /admin/thor/dropshipper/ai/chat: ${networkError.message}`,\n 'NETWORK_ERROR',\n networkError,\n );\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n let errorCode: string | undefined;\n let requestId: string | undefined;\n let details: string | undefined;\n try {\n const json: any = await response.json();\n message = json?.message ?? message;\n errorCode = json?.error_code ?? json?.type;\n requestId = json?.request_id;\n details = json?.details;\n } catch {\n // ignore parse errors\n }\n this.logger.error(\n `[dropshipper] POST /admin/thor/dropshipper/ai/chat failed status=${response.status} message=${message}` +\n (errorCode ? ` error_code=${errorCode}` : '') +\n (requestId ? ` request_id=${requestId}` : '') +\n (details ? ` details=${details}` : '')\n );\n throw new ProviderAPIError(\n `[dropshipper] POST /admin/thor/dropshipper/ai/chat failed: ${message}`,\n `DROPSHIPPER_API_${response.status}`,\n response.status,\n {\n message,\n status: response.status,\n errorCode,\n requestId,\n details,\n },\n );\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n if (contentType.includes('text/event-stream') && response.body) {\n return mapUiMessageStreamToEvents(response.body, this.logger);\n }\n\n // Non-streamed reply (`default`): synthesize a one-shot event stream.\n const data: ChatResponse = await response.json();\n return new ReadableStream<ChatStreamEvent>({\n start(controller) {\n controller.enqueue({ type: 'start', intent: data.intent });\n controller.enqueue({ type: 'text-delta', delta: data.answer });\n controller.enqueue({\n type: 'finish',\n intent: data.intent,\n sources: data.sources ?? [],\n });\n controller.close();\n },\n });\n }\n\n /**\n * Cheap liveness probe for the AI assistant.\n *\n * The backend performs no LLM or retrieval work, so this is safe to poll\n * (e.g. from a dashboard availability indicator). Returns 200 with\n * `available: true` when the assistant is configured; the backend answers\n * HTTP 503 with `available: false` when `AI_GATEWAY_API_KEY` is missing.\n *\n * Deliberately does NOT go through `fetchBackendWithResilience`: that layer\n * funnels every call through the SHARED `backendCircuitBreaker`, and the\n * definitive 503 \"not configured\" answer would count as failures and could\n * open the circuit, taking down all dropshipper API traffic. A health probe\n * must stay isolated, with no retries and a short timeout.\n *\n * `GET /admin/thor/dropshipper/ai/health`\n */\n async chatAssistantHealth(): Promise<ChatAssistantHealthResponse> {\n const url = `${this.baseUrl}/admin/thor/dropshipper/ai/health`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 5000);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'GET',\n headers: { Authorization: `Bearer ${this.token}` },\n signal: controller.signal,\n cache: 'no-store',\n });\n } catch (error: any) {\n clearTimeout(timeoutId);\n throw new ProviderAPIError(\n `[dropshipper] Network error on GET /admin/thor/dropshipper/ai/health: ${error.message}`,\n 'NETWORK_ERROR',\n 0,\n );\n }\n clearTimeout(timeoutId);\n\n // 503 is the backend's definitive \"not configured\" answer, not a transient\n // failure: parse it as a valid (unavailable) health response.\n if (response.status === 503) {\n try {\n const body = await response.json();\n if (body && typeof body.available === 'boolean') {\n return body as ChatAssistantHealthResponse;\n }\n } catch {\n // fall through to the generic failure below\n }\n }\n\n if (!response.ok) {\n throw new ProviderAPIError(\n `[dropshipper] GET /admin/thor/dropshipper/ai/health failed: HTTP ${response.status}`,\n `DROPSHIPPER_API_${response.status}`,\n response.status,\n );\n }\n\n return response.json() as Promise<ChatAssistantHealthResponse>;\n }\n\n // -------------------------------------------------------------------------\n // Notifications\n // -------------------------------------------------------------------------\n\n /**\n * List feed notifications for the authenticated dropshipper.\n *\n * `GET /admin/thor/dropshipper/notifications`\n */\n async getNotifications(\n options: GetNotificationsOptions = {},\n ): Promise<GetNotificationsResponse> {\n const { limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n });\n return this.request<GetNotificationsResponse>(\n 'GET',\n `/admin/thor/dropshipper/notifications?${qs}`,\n );\n }\n\n /**\n * Get the authenticated dropshipper's notification preferences.\n *\n * `GET /admin/thor/dropshipper/notifications/preferences`\n */\n async getNotificationPreferences(): Promise<GetNotificationPreferencesResponse> {\n return this.request<GetNotificationPreferencesResponse>(\n 'GET',\n '/admin/thor/dropshipper/notifications/preferences',\n );\n }\n\n /**\n * Update the authenticated dropshipper's notification preferences.\n *\n * `PATCH /admin/thor/dropshipper/notifications/preferences`\n */\n async updateNotificationPreferences(\n body: UpdateNotificationPreferencesBody,\n ): Promise<GetNotificationPreferencesResponse> {\n return this.request<GetNotificationPreferencesResponse>(\n 'PATCH',\n '/admin/thor/dropshipper/notifications/preferences',\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Onboarding (Solo X)\n // -------------------------------------------------------------------------\n\n /**\n * Create a new dropshipper account (sales channel + user + price list).\n *\n * `POST /admin/thor/dropshipper/onboard`\n */\n async onboardDropshipper(\n body: OnboardDropshipperBody,\n ): Promise<OnboardDropshipperResponse> {\n return this.request<OnboardDropshipperResponse>(\n 'POST',\n '/admin/thor/dropshipper/onboard',\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Products (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * List products available in Y's channel with cost/margin data.\n *\n * `GET /admin/thor/dropshipper/products`\n */\n async getProducts(\n options: GetDropshipperProductsOptions = {},\n ): Promise<GetDropshipperProductsResponse> {\n const { q, category_id, collection_id, status, in_stock, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(q ? { q } : {}),\n ...(category_id ? { category_id } : {}),\n ...(collection_id ? { collection_id } : {}),\n ...(status ? { status } : {}),\n ...(in_stock !== undefined ? { in_stock: String(in_stock) } : {}),\n });\n return this.request<GetDropshipperProductsResponse>(\n 'GET',\n `/admin/thor/dropshipper/products?${qs}`,\n );\n }\n\n /**\n * Validate cart items for checkout — returns current availableQuantity, sale_price,\n * and cost_price for each variant so the client can detect stale prices or\n * insufficient stock before creating an order or converting a draft.\n *\n * `POST /admin/thor/dropshipper/checkout/validate`\n */\n async validateCheckoutItems(\n body: ValidateCheckoutItemsRequest,\n ): Promise<ValidateCheckoutItemsResponse> {\n return this.request<ValidateCheckoutItemsResponse>(\n 'POST',\n '/admin/thor/dropshipper/checkout/validate',\n body,\n );\n }\n\n /**\n * Check whether cost prices have changed since the last acknowledgment.\n * Compares a hash of all base cost prices from the channel's price list\n * against a stored snapshot on the dropshipper account.\n *\n * `GET /admin/thor/dropshipper/cost-prices/has-changes`\n */\n async checkCostPriceChanges(): Promise<CostPriceChangesCheckResponse> {\n return this.request<CostPriceChangesCheckResponse>(\n 'GET',\n '/admin/thor/dropshipper/cost-prices/has-changes',\n );\n }\n\n /**\n * Get the full diff of cost price changes since the last acknowledgment.\n * Returns product/variant info with old and new cost prices.\n *\n * `GET /admin/thor/dropshipper/cost-prices/changes`\n */\n async getCostPriceChanges(): Promise<CostPriceChangesResponse> {\n return this.request<CostPriceChangesResponse>(\n 'GET',\n '/admin/thor/dropshipper/cost-prices/changes',\n );\n }\n\n /**\n * Acknowledge current cost prices as reviewed. Stores the current hash\n * and snapshot so subsequent checks will not report these prices as changed.\n *\n * `POST /admin/thor/dropshipper/cost-prices/acknowledge`\n */\n async acknowledgeCostPriceChanges(): Promise<AcknowledgeCostPriceChangesResponse> {\n return this.request<AcknowledgeCostPriceChangesResponse>(\n 'POST',\n '/admin/thor/dropshipper/cost-prices/acknowledge',\n );\n }\n\n /**\n * Toggle whether a product is visible in the public store for the current sales channel.\n * This does not mutate the shared global Medusa product status.\n *\n * `POST /admin/thor/dropshipper/products/:id/status`\n */\n async updateProductStatus(\n productId: string,\n body: UpdateDropshipperProductStatusBody,\n ): Promise<UpdateDropshipperProductStatusResponse> {\n return this.request<UpdateDropshipperProductStatusResponse>(\n 'POST',\n `/admin/thor/dropshipper/products/${productId}/status`,\n body,\n );\n }\n\n /**\n * Fetch custom attribute values assigned to a product, grouped by attribute.\n *\n * `GET /admin/thor/dropshipper/products/:id/attributes`\n */\n async getProductAttributes(\n productId: string,\n ): Promise<GetProductAttributesResponse> {\n return this.request<GetProductAttributesResponse>(\n 'GET',\n `/admin/thor/dropshipper/products/${productId}/attributes`,\n );\n }\n\n /**\n * List attribute definitions (with their possible values) scoped to the\n * dropshipper's channel. Only attributes linked to at least one channel\n * product are returned.\n *\n * `GET /admin/thor/dropshipper/attributes`\n */\n async getAttributes(): Promise<GetDropshipperAttributesResponse> {\n return this.request<GetDropshipperAttributesResponse>(\n 'GET',\n '/admin/thor/dropshipper/attributes',\n );\n }\n\n // -------------------------------------------------------------------------\n // Prices (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * Bulk-update product and variant margins on Y's channel price list.\n *\n * `PUT /admin/thor/dropshipper/prices`\n */\n async updatePrices(\n body: UpdateDropshipperPricesBody,\n ): Promise<UpdateDropshipperPricesResponse> {\n return this.request<UpdateDropshipperPricesResponse>(\n 'PUT',\n '/admin/thor/dropshipper/prices',\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Orders (Y + X for set-payment-collector)\n // -------------------------------------------------------------------------\n\n /**\n * Paginated list of orders in Y's channel.\n *\n * `GET /admin/thor/dropshipper/orders`\n */\n async getOrders(\n options: GetDropshipperOrdersOptions = {},\n ): Promise<GetDropshipperOrdersResponse> {\n const { status, payment_collector, settlement_status, from, to, q, customer_id, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(status ? { status } : {}),\n ...(payment_collector ? { payment_collector } : {}),\n ...(settlement_status ? { settlement_status } : {}),\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n ...(q ? { q } : {}),\n ...(customer_id ? { customer_id } : {}),\n });\n return this.request<GetDropshipperOrdersResponse>(\n 'GET',\n `/admin/thor/dropshipper/orders?${qs}`,\n );\n }\n\n /**\n * Full detail for a single order with profit breakdown.\n *\n * `GET /admin/thor/dropshipper/orders/:id`\n */\n async getOrder(orderId: string): Promise<GetDropshipperOrderDetailResponse> {\n return this.request<GetDropshipperOrderDetailResponse>(\n 'GET',\n `/admin/thor/dropshipper/orders/${orderId}`,\n );\n }\n\n /**\n * List shipping groups and their valid options for a manual dropshipper order.\n *\n * `POST /admin/thor/dropshipper/orders/shipping-options`\n */\n async getOrderShippingOptions(\n body: GetDropshipperShippingOptionsBody,\n ): Promise<GetDropshipperShippingOptionsResponse> {\n return this.request<GetDropshipperShippingOptionsResponse>(\n 'POST',\n '/admin/thor/dropshipper/orders/shipping-options',\n {\n ...body,\n currency_code: body.currency_code.toLowerCase(),\n },\n );\n }\n\n /**\n * Manually create an order on behalf of a customer.\n *\n * `POST /admin/thor/dropshipper/orders`\n */\n async createOrder(\n body: ExtendedCreateDropshipperOrderBody,\n ): Promise<ExtendedCreateDropshipperOrderResponse> {\n return this.request<ExtendedCreateDropshipperOrderResponse>(\n 'POST',\n '/admin/thor/dropshipper/orders',\n body,\n );\n }\n\n /**\n * Set who collects payment for an order (Solo X).\n *\n * `POST /admin/thor/dropshipper/orders/:id/set-payment-collector`\n */\n async setPaymentCollector(\n orderId: string,\n body: SetPaymentCollectorBody,\n ): Promise<SetPaymentCollectorResponse> {\n return this.request<SetPaymentCollectorResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/set-payment-collector`,\n body,\n );\n }\n\n /**\n * Change the payment method of a confirmed order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/set-payment-method`\n */\n async setPaymentMethod(\n orderId: string,\n body: SetPaymentMethodBody,\n ): Promise<SetPaymentMethodResponse> {\n return this.request<SetPaymentMethodResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/set-payment-method`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Order Cancel & Edits (Solo Y) — B-04\n // -------------------------------------------------------------------------\n\n /**\n * Cancel a dropshipper order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/cancel`\n */\n async cancelOrder(orderId: string): Promise<CancelDropshipperOrderResponse> {\n return this.request<CancelDropshipperOrderResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/cancel`,\n );\n }\n\n /**\n * Create an order edit for a dropshipper order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/edit`\n */\n async createOrderEdit(\n orderId: string,\n body: CreateOrderEditBody = {},\n ): Promise<CreateOrderEditResponse> {\n return this.request<CreateOrderEditResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/edit`,\n body,\n );\n }\n\n /**\n * Add an item to the active order edit.\n *\n * `POST /admin/thor/dropshipper/orders/:id/edit/items`\n */\n async addOrderEditItem(\n orderId: string,\n body: AddOrderEditItemBody,\n ): Promise<AddOrderEditItemResponse> {\n return this.request<AddOrderEditItemResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/edit/items`,\n body,\n );\n }\n\n /**\n * Confirm the active order edit, applying changes to the order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/edit/confirm`\n */\n async confirmOrderEdit(\n orderId: string,\n ): Promise<ConfirmOrderEditResponse> {\n return this.request<ConfirmOrderEditResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/edit/confirm`,\n );\n }\n\n /**\n * Get all notes for an order.\n *\n * `GET /admin/thor/dropshipper/orders/:id/notes`\n */\n async getOrderNotes(orderId: string): Promise<GetOrderNotesResponse> {\n return this.request<GetOrderNotesResponse>(\n 'GET',\n `/admin/thor/dropshipper/orders/${orderId}/notes`,\n );\n }\n\n /**\n * Create a new note for an order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/notes`\n */\n async createOrderNote(\n orderId: string,\n body: CreateOrderNoteBody,\n ): Promise<CreateOrderNoteResponse> {\n return this.request<CreateOrderNoteResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/notes`,\n body,\n );\n }\n\n /**\n * Delete a note from an order.\n *\n * `DELETE /admin/thor/dropshipper/orders/:id/notes/:noteId`\n */\n async deleteOrderNote(\n orderId: string,\n noteId: string,\n ): Promise<DeleteOrderNoteResponse> {\n return this.request<DeleteOrderNoteResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/orders/${orderId}/notes/${noteId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Custom Categories (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * List Medusa provider categories linked to Y's channel (read-only).\n *\n * `GET /admin/thor/dropshipper/categories/provider`\n */\n async getProviderCategories(): Promise<GetProviderCategoriesResponse> {\n return this.request<GetProviderCategoriesResponse>(\n 'GET',\n '/admin/thor/dropshipper/categories/provider',\n );\n }\n\n /**\n * List Y's custom product categories.\n *\n * `GET /admin/thor/dropshipper/categories`\n */\n async getCategories(\n options: GetDropshipperCategoriesOptions = {},\n ): Promise<GetDropshipperCategoriesResponse> {\n const { parent_id, include_children } = options;\n const qs = new URLSearchParams({\n ...(parent_id ? { parent_id } : {}),\n ...(include_children !== undefined ? { include_children: String(include_children) } : {}),\n });\n const query = qs.toString() ? `?${qs}` : '';\n return this.request<GetDropshipperCategoriesResponse>(\n 'GET',\n `/admin/thor/dropshipper/categories${query}`,\n );\n }\n\n /**\n * Create a custom category in Y's channel.\n *\n * `POST /admin/thor/dropshipper/categories`\n */\n async createCategory(\n body: CreateDropshipperCategoryBody,\n ): Promise<DropshipperCategory> {\n return this.request<DropshipperCategory>(\n 'POST',\n '/admin/thor/dropshipper/categories',\n body,\n );\n }\n\n /**\n * Update a custom category.\n *\n * `PUT /admin/thor/dropshipper/categories/:id`\n */\n async updateCategory(\n categoryId: string,\n body: UpdateDropshipperCategoryBody,\n ): Promise<DropshipperCategory> {\n return this.request<DropshipperCategory>(\n 'PUT',\n `/admin/thor/dropshipper/categories/${categoryId}`,\n body,\n );\n }\n\n /**\n * Delete a custom category.\n *\n * `DELETE /admin/thor/dropshipper/categories/:id`\n */\n async deleteCategory(\n categoryId: string,\n options: { force?: boolean } = {},\n ): Promise<DeleteDropshipperCategoryResponse> {\n const qs = options.force ? '?force=true' : '';\n return this.request<DeleteDropshipperCategoryResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/categories/${categoryId}${qs}`,\n );\n }\n\n /**\n * List product-to-category mappings, optionally filtered by product.\n *\n * `GET /admin/thor/dropshipper/category-mappings`\n */\n async getCategoryMappings(\n options: GetCategoryMappingsOptions = {},\n ): Promise<GetCategoryMappingsResponse> {\n const qs = options.product_id ? `?product_id=${options.product_id}` : '';\n return this.request<GetCategoryMappingsResponse>(\n 'GET',\n `/admin/thor/dropshipper/category-mappings${qs}`,\n );\n }\n\n /**\n * Map a product to a custom category.\n *\n * `POST /admin/thor/dropshipper/category-mappings`\n */\n async createCategoryMapping(\n body: CreateCategoryMappingBody,\n ): Promise<CreateCategoryMappingResponse> {\n return this.request<CreateCategoryMappingResponse>(\n 'POST',\n `/admin/thor/dropshipper/category-mappings`,\n body,\n );\n }\n\n /**\n * Remove a product-to-category mapping.\n *\n * `DELETE /admin/thor/dropshipper/category-mappings/:id`\n */\n async deleteCategoryMapping(\n mappingId: string,\n ): Promise<DeleteCategoryMappingResponse> {\n return this.request<DeleteCategoryMappingResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/category-mappings/${mappingId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Customers (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * Paginated list of customers in Y's channel.\n *\n * `GET /admin/thor/dropshipper/customers`\n */\n async getCustomers(\n options: GetDropshipperCustomersOptions = {},\n ): Promise<GetDropshipperCustomersResponse> {\n const { q, has_orders, from, limit = 20, offset = 0, order } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(q ? { q } : {}),\n ...(has_orders !== undefined ? { has_orders: String(has_orders) } : {}),\n ...(from ? { from } : {}),\n ...(order ? { order } : {}),\n });\n return this.request<GetDropshipperCustomersResponse>(\n 'GET',\n `/admin/thor/dropshipper/customers?${qs}`,\n );\n }\n\n /**\n * Backwards-compatible alias used by the dashboard checkout flow.\n */\n async getChannelCustomers(\n _channelId: string,\n options: GetDropshipperCustomersOptions = {},\n ): Promise<GetDropshipperCustomersResponse> {\n return this.getCustomers(options);\n }\n\n /**\n * Full detail for a single customer.\n *\n * `GET /admin/thor/dropshipper/customers/:id`\n */\n async getCustomer(\n customerId: string,\n ): Promise<GetDropshipperCustomerDetailResponse> {\n return this.request<GetDropshipperCustomerDetailResponse>(\n 'GET',\n `/admin/thor/dropshipper/customers/${customerId}`,\n );\n }\n\n /**\n * Create a customer scoped to Y's channel.\n *\n * `POST /admin/thor/dropshipper/customers`\n */\n async createCustomer(\n body: CreateDropshipperCustomerBody,\n ): Promise<CreateDropshipperCustomerResponse> {\n return this.request<CreateDropshipperCustomerResponse>(\n 'POST',\n '/admin/thor/dropshipper/customers',\n body,\n );\n }\n\n /**\n * Update a customer scoped to Y's channel.\n *\n * `POST /admin/thor/dropshipper/customers/:id`\n */\n async updateCustomer(\n customerId: string,\n body: UpdateDropshipperCustomerBody,\n ): Promise<UpdateDropshipperCustomerResponse> {\n return this.request<UpdateDropshipperCustomerResponse>(\n 'POST',\n `/admin/thor/dropshipper/customers/${customerId}`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Customer Addresses (Solo Y) — B-06\n // -------------------------------------------------------------------------\n\n /**\n * Transform a raw snake_case address from the API into a camelCase Address.\n */\n private transformAddress(raw: any): import('@thorprovider/types').Address {\n return {\n id: raw.id ?? undefined,\n firstName: raw.first_name ?? '',\n lastName: raw.last_name ?? '',\n company: raw.company ?? undefined,\n address1: raw.address_1 ?? '',\n address2: raw.address_2 ?? undefined,\n city: raw.city ?? '',\n province: raw.province ?? '',\n postalCode: raw.postal_code ?? '',\n countryCode: raw.country_code ?? '',\n phone: raw.phone ?? undefined,\n isDefault: raw.is_default ?? undefined,\n isDefaultBilling: raw.is_default_billing ?? undefined,\n isDefaultShipping: raw.is_default_shipping ?? undefined,\n metadata: raw.address_name\n ? { ...(raw.metadata ?? {}), label: raw.address_name }\n : (raw.metadata ?? undefined),\n };\n }\n\n /**\n * List addresses for a customer in Y's channel.\n *\n * `GET /admin/thor/dropshipper/customers/:id/addresses`\n */\n async getCustomerAddresses(\n customerId: string,\n ): Promise<GetDropshipperAddressesResponse> {\n const raw = await this.request<{\n addresses: any[];\n count: number;\n }>('GET', `/admin/thor/dropshipper/customers/${customerId}/addresses`);\n\n return {\n addresses: raw.addresses.map((a) => this.transformAddress(a)),\n count: raw.count,\n };\n }\n\n /**\n * Create a new address for a customer.\n *\n * `POST /admin/thor/dropshipper/customers/:id/addresses`\n */\n async createCustomerAddress(\n customerId: string,\n body: DropshipperAddressBody,\n ): Promise<DropshipperAddressResponse> {\n const raw = await this.request<{ address: any }>(\n 'POST',\n `/admin/thor/dropshipper/customers/${customerId}/addresses`,\n body,\n );\n\n return { address: this.transformAddress(raw.address) };\n }\n\n /**\n * Update an existing customer address.\n *\n * `POST /admin/thor/dropshipper/customers/:id/addresses/:addressId`\n */\n async updateCustomerAddress(\n customerId: string,\n addressId: string,\n body: Partial<DropshipperAddressBody>,\n ): Promise<DropshipperAddressResponse> {\n const raw = await this.request<{ address: any }>(\n 'POST',\n `/admin/thor/dropshipper/customers/${customerId}/addresses/${addressId}`,\n body,\n );\n\n return { address: this.transformAddress(raw.address) };\n }\n\n /**\n * Delete a customer address.\n *\n * `DELETE /admin/thor/dropshipper/customers/:id/addresses/:addressId`\n */\n async deleteCustomerAddress(\n customerId: string,\n addressId: string,\n ): Promise<{ deleted: true; id: string }> {\n return this.request<{ deleted: true; id: string }>(\n 'DELETE',\n `/admin/thor/dropshipper/customers/${customerId}/addresses/${addressId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Account & Settlements (Y read-only)\n // -------------------------------------------------------------------------\n\n /**\n * Y's account info with current balance.\n *\n * `GET /admin/thor/dropshipper/account`\n */\n async getAccount(): Promise<GetDropshipperAccountResponse> {\n return this.request<GetDropshipperAccountResponse>(\n 'GET',\n '/admin/thor/dropshipper/account',\n );\n }\n\n /**\n * Get the authenticated dropshipper's business policy text.\n * Returns an empty string when no policy is set.\n *\n * `GET /admin/thor/dropshipper/account/policies`\n */\n async getBusinessPolicy(): Promise<GetBusinessPolicyResponse> {\n return this.request<GetBusinessPolicyResponse>(\n 'GET',\n '/admin/thor/dropshipper/account/policies',\n );\n }\n\n /**\n * Update the authenticated dropshipper's business policy text.\n * The value is trimmed server-side before being persisted.\n *\n * `PATCH /admin/thor/dropshipper/account/policies`\n */\n async updateBusinessPolicy(\n body: UpdateBusinessPolicyBody,\n ): Promise<UpdateBusinessPolicyResponse> {\n return this.request<UpdateBusinessPolicyResponse>(\n 'PATCH',\n '/admin/thor/dropshipper/account/policies',\n body,\n );\n }\n\n /**\n * Orders where Y owes money to X (Y collected payment, needs to pay costs).\n *\n * `GET /admin/thor/dropshipper/account/payable`\n */\n async getPayable(): Promise<GetDropshipperPayableResponse> {\n return this.request<GetDropshipperPayableResponse>(\n 'GET',\n '/admin/thor/dropshipper/account/payable',\n );\n }\n\n /**\n * Orders where X owes money to Y (X collected COD, needs to transfer profit).\n *\n * `GET /admin/thor/dropshipper/account/receivable`\n */\n async getReceivable(): Promise<GetDropshipperReceivableResponse> {\n return this.request<GetDropshipperReceivableResponse>(\n 'GET',\n '/admin/thor/dropshipper/account/receivable',\n );\n }\n\n /**\n * List settlements (Y sees own; X can filter by account_id).\n *\n * `GET /admin/thor/dropshipper/settlements`\n */\n async getSettlements(\n options: GetSettlementsOptions = {},\n ): Promise<GetSettlementsResponse> {\n const { status, type, account_id, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(status ? { status } : {}),\n ...(type ? { type } : {}),\n ...(account_id ? { account_id } : {}),\n });\n return this.request<GetSettlementsResponse>(\n 'GET',\n `/admin/thor/dropshipper/settlements?${qs}`,\n );\n }\n\n /**\n * Full detail for a single settlement record.\n *\n * `GET /admin/thor/dropshipper/settlements/:id`\n */\n async getSettlement(\n settlementId: string,\n ): Promise<GetSettlementDetailResponse> {\n return this.request<GetSettlementDetailResponse>(\n 'GET',\n `/admin/thor/dropshipper/settlements/${settlementId}`,\n\n );\n }\n\n /**\n * Consolidated financial balance for the authenticated dropshipper.\n *\n * `GET /admin/thor/dropshipper/account/balance`\n */\n async getAccountBalance(): Promise<GetDropshipperAccountBalanceResponse> {\n return this.request<GetDropshipperAccountBalanceResponse>(\n 'GET',\n '/admin/thor/dropshipper/account/balance',\n );\n }\n\n /**\n * Unified financial order list for the authenticated dropshipper.\n *\n * `GET /admin/thor/dropshipper/account/orders`\n */\n async getAccountOrders(\n options: GetDropshipperAccountOrdersOptions = {},\n ): Promise<GetDropshipperAccountOrdersResponse> {\n const { tab, status, limit = 20, offset = 0, q } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(tab ? { tab } : {}),\n ...(status ? { status } : {}),\n ...(q ? { q } : {}),\n });\n return this.request<GetDropshipperAccountOrdersResponse>(\n 'GET',\n `/admin/thor/dropshipper/account/orders?${qs}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Admin Settlements (Solo X)\n // -------------------------------------------------------------------------\n\n /**\n * Create a settlement record for a dropshipper account.\n *\n * `POST /admin/thor/dropshipper/admin/settlements`\n */\n async createSettlement(\n body: CreateSettlementBody,\n ): Promise<CreateSettlementResponse> {\n return this.request<CreateSettlementResponse>(\n 'POST',\n '/admin/thor/dropshipper/admin/settlements',\n body,\n );\n }\n\n /**\n * Confirm a pending settlement (marks it as paid/received).\n *\n * `POST /admin/thor/dropshipper/admin/settlements/:id/confirm`\n */\n async confirmSettlement(\n settlementId: string,\n body: ConfirmSettlementBody = {},\n ): Promise<UpdateSettlementStatusResponse> {\n return this.request<UpdateSettlementStatusResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/settlements/${settlementId}/confirm`,\n body,\n );\n }\n\n /**\n * Cancel a pending settlement.\n *\n * `POST /admin/thor/dropshipper/admin/settlements/:id/cancel`\n */\n async cancelSettlement(\n settlementId: string,\n body: CancelSettlementBody = {},\n ): Promise<UpdateSettlementStatusResponse> {\n return this.request<UpdateSettlementStatusResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/settlements/${settlementId}/cancel`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Admin Settlements — list (Solo X)\n // -------------------------------------------------------------------------\n\n /**\n * X views all settlement records across all dropshipper accounts.\n *\n * `GET /admin/thor/dropshipper/admin/settlements`\n */\n async getAdminSettlements(\n options: GetSettlementsOptions = {},\n ): Promise<GetSettlementsResponse> {\n const { status, type, account_id, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(status ? { status } : {}),\n ...(type ? { type } : {}),\n ...(account_id ? { account_id } : {}),\n });\n return this.request<GetSettlementsResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/settlements?${qs}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Admin Account Management (Solo X)\n // -------------------------------------------------------------------------\n\n /**\n * List all dropshipper accounts.\n *\n * `GET /admin/thor/dropshipper/admin/accounts`\n */\n async getAdminAccounts(): Promise<GetAdminDropshipperAccountsResponse> {\n return this.request<GetAdminDropshipperAccountsResponse>(\n 'GET',\n '/admin/thor/dropshipper/admin/accounts',\n );\n }\n\n /**\n * Full balance detail for a specific dropshipper account.\n *\n * `GET /admin/thor/dropshipper/admin/accounts/:id/balance`\n */\n async getAdminAccountBalance(\n accountId: string,\n ): Promise<GetAdminAccountBalanceResponse> {\n return this.request<GetAdminAccountBalanceResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/balance`,\n );\n }\n\n /**\n * List all dropshipper price lists.\n *\n * `GET /admin/thor/dropshipper/admin/price-lists`\n */\n async getAdminPriceLists(): Promise<GetAdminPriceListsResponse> {\n return this.request<GetAdminPriceListsResponse>(\n 'GET',\n '/admin/thor/dropshipper/admin/price-lists',\n );\n }\n\n /**\n * Utility: look up which sales channel a user belongs to.\n *\n * `GET /admin/thor/dropshipper/admin/user-channel`\n */\n async getUserChannel(): Promise<GetUserChannelResponse> {\n return this.request<GetUserChannelResponse>(\n 'GET',\n '/admin/thor/dropshipper/admin/user-channel',\n );\n }\n\n // -------------------------------------------------------------------------\n // Financial Endpoints — Group A (Admin X)\n // -------------------------------------------------------------------------\n\n /**\n * List orders with financial detail for a dropshipper account (Admin only).\n *\n * `GET /admin/thor/dropshipper/admin/accounts/:id/orders`\n */\n async getAdminAccountOrders(\n accountId: string,\n options: GetDropshipperAccountOrdersOptions = {},\n ): Promise<GetAdminDropshipperAccountOrdersResponse> {\n const { tab, status, limit = 20, offset = 0, q } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(tab ? { tab } : {}),\n ...(status ? { status } : {}),\n ...(q ? { q } : {}),\n });\n return this.request<GetAdminDropshipperAccountOrdersResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/orders?${qs}`,\n );\n }\n\n /**\n * List financial movements for a dropshipper account (Admin only).\n *\n * `GET /admin/thor/dropshipper/admin/accounts/:id/settlements`\n */\n async getAdminAccountSettlements(\n accountId: string,\n options: GetAdminDropshipperAccountSettlementsOptions = {},\n ): Promise<GetAdminDropshipperAccountSettlementsResponse> {\n const { type, status, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(type ? { type } : {}),\n ...(status ? { status } : {}),\n });\n return this.request<GetAdminDropshipperAccountSettlementsResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements?${qs}`,\n );\n }\n\n /**\n * Manually resolve a guarantee on an order (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/guarantee/:order_id`\n */\n async resolveGuarantee(\n accountId: string,\n orderId: string,\n body: ResolveGuaranteeBody,\n ): Promise<ResolveGuaranteeResponse> {\n return this.request<ResolveGuaranteeResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/guarantee/${orderId}`,\n body,\n );\n }\n\n /**\n * Create an internal compensation (netting) between DS and Thor debts (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/compensacion`\n */\n async createCompensacion(\n accountId: string,\n body: CreateCompensacionBody,\n ): Promise<CreateCompensacionResponse> {\n return this.request<CreateCompensacionResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/compensacion`,\n body,\n );\n }\n\n /**\n * Create a financial adjustment (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/ajuste`\n */\n async createAjuste(\n accountId: string,\n body: CreateAjusteBody,\n ): Promise<CreateAjusteResponse> {\n return this.request<CreateAjusteResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/ajuste`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Financial Endpoints — Group B (Admin X)\n // -------------------------------------------------------------------------\n\n /**\n * Register a cobro — DS pays Thor the product cost (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/cobro`\n */\n async createCobro(\n accountId: string,\n body: CreateCobroBody,\n ): Promise<CreateCobroResponse> {\n return this.request<CreateCobroResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/cobro`,\n body,\n );\n }\n\n /**\n * Register a pago — Thor pays the dropshipper their commission (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/pago`\n */\n async createPago(\n accountId: string,\n body: CreatePagoBody,\n ): Promise<CreatePagoResponse> {\n return this.request<CreatePagoResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/pago`,\n body,\n );\n }\n\n /**\n * Reverse a confirmed financial movement (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/:mov_id/reverso`\n */\n async reverseSettlement(\n accountId: string,\n movementId: string,\n body: CreateReversoBody,\n ): Promise<CreateReversoResponse> {\n return this.request<CreateReversoResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/${movementId}/reverso`,\n body,\n );\n }\n\n /**\n * Confirm a pending financial movement (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/:mov_id/confirm`\n */\n async confirmSettlementMovement(\n accountId: string,\n movementId: string,\n body: ConfirmMovementBody = {},\n ): Promise<ConfirmMovementResponse> {\n return this.request<ConfirmMovementResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/${movementId}/confirm`,\n body,\n );\n }\n\n /**\n * Cancel a pending financial movement draft (Admin only).\n *\n * `POST /admin/thor/dropshipper/admin/accounts/:id/settlements/:mov_id/cancel`\n */\n async cancelSettlementMovement(\n accountId: string,\n movementId: string,\n body: CancelMovementBody,\n ): Promise<CancelMovementResponse> {\n return this.request<CancelMovementResponse>(\n 'POST',\n `/admin/thor/dropshipper/admin/accounts/${accountId}/settlements/${movementId}/cancel`,\n body,\n );\n }\n\n /**\n * Get financial analysis for a dropshipper order (Admin only).\n *\n * `GET /admin/thor/dropshipper/admin/orders/:id/financial-analysis`\n */\n async getOrderFinancialAnalysis(\n orderId: string,\n ): Promise<GetFinancialAnalysisResponse> {\n return this.request<GetFinancialAnalysisResponse>(\n 'GET',\n `/admin/thor/dropshipper/admin/orders/${orderId}/financial-analysis`,\n );\n }\n\n /**\n * Register a partial or full payment for an order.\n *\n * `POST /admin/thor/dropshipper/orders/:id/payment`\n */\n async registerOrderPayment(\n orderId: string,\n body: RegisterPaymentBody,\n ): Promise<RegisterPaymentResponse> {\n return this.request<RegisterPaymentResponse>(\n 'POST',\n `/admin/thor/dropshipper/orders/${orderId}/payment`,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Promotions (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * List Y's promotions (discount codes).\n *\n * `GET /admin/thor/dropshipper/promotions`\n */\n async getPromotions(\n options: GetDropshipperPromotionsOptions = {},\n ): Promise<GetDropshipperPromotionsResponse> {\n const { type, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(type ? { type } : {}),\n });\n return this.request<GetDropshipperPromotionsResponse>(\n 'GET',\n `/admin/thor/dropshipper/promotions?${qs}`,\n );\n }\n\n /**\n * Create a promotion for Y's channel.\n *\n * `POST /admin/thor/dropshipper/promotions`\n */\n async createPromotion(\n body: CreateDropshipperPromotionBody,\n ): Promise<DropshipperPromotion> {\n return this.request<DropshipperPromotion>(\n 'POST',\n '/admin/thor/dropshipper/promotions',\n body,\n );\n }\n\n /**\n * Get a single promotion by ID.\n *\n * `GET /admin/thor/dropshipper/promotions/:id`\n */\n async getPromotion(promotionId: string): Promise<DropshipperPromotion> {\n return this.request<DropshipperPromotion>(\n 'GET',\n `/admin/thor/dropshipper/promotions/${promotionId}`,\n );\n }\n\n /**\n * Update an existing promotion.\n *\n * `PUT /admin/thor/dropshipper/promotions/:id`\n */\n async updatePromotion(\n promotionId: string,\n body: UpdateDropshipperPromotionBody,\n ): Promise<DropshipperPromotion> {\n return this.request<DropshipperPromotion>(\n 'PUT',\n `/admin/thor/dropshipper/promotions/${promotionId}`,\n body,\n );\n }\n\n /**\n * Delete a promotion.\n *\n * `DELETE /admin/thor/dropshipper/promotions/:id`\n */\n async deletePromotion(\n promotionId: string,\n ): Promise<DeleteDropshipperPromotionResponse> {\n return this.request<DeleteDropshipperPromotionResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/promotions/${promotionId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Dashboard (Solo Y)\n // -------------------------------------------------------------------------\n\n /**\n * Aggregate stats for Y's dashboard (revenue, profit, top products).\n *\n * `GET /admin/thor/dropshipper/dashboard/stats`\n */\n async getDashboardStats(\n options: GetDashboardStatsOptions = {},\n ): Promise<GetDashboardStatsResponse> {\n const { period, from, to, currency_code } = options;\n const qs = new URLSearchParams({\n ...(period ? { period } : {}),\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n ...(currency_code ? { currency_code } : {}),\n });\n const query = qs.toString() ? `?${qs}` : '';\n return this.request<GetDashboardStatsResponse>(\n 'GET',\n `/admin/thor/dropshipper/dashboard/stats${query}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Storefront (V — end customer, uses publishable API key)\n // -------------------------------------------------------------------------\n\n /**\n * Public endpoint: dropshipper-scoped categories for the storefront.\n * Typically called with a publishable API key rather than a JWT.\n *\n * `GET /store/thor/dropshipper-categories`\n */\n async getStorefrontCategories(): Promise<GetStorefrontDropshipperCategoriesResponse> {\n return this.request<GetStorefrontDropshipperCategoriesResponse>(\n 'GET',\n '/store/thor/dropshipper-categories',\n );\n }\n\n // -------------------------------------------------------------------------\n // Draft Orders\n // -------------------------------------------------------------------------\n\n /**\n * List all draft orders in the dropshipper's channel.\n *\n * `GET /admin/thor/dropshipper/draft-orders`\n */\n async getDraftOrders(\n options: GetDropshipperDraftOrdersOptions = {},\n ): Promise<GetDropshipperDraftOrdersResponse> {\n const { customer_id, from, to, q, limit = 20, offset = 0 } = options;\n const qs = new URLSearchParams({\n limit: String(limit),\n offset: String(offset),\n ...(customer_id ? { customer_id } : {}),\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n ...(q ? { q } : {}),\n });\n return this.request<GetDropshipperDraftOrdersResponse>(\n 'GET',\n `/admin/thor/dropshipper/draft-orders?${qs}`,\n );\n }\n\n /**\n * Get a specific draft order by ID.\n *\n * `GET /admin/thor/dropshipper/draft-orders/:id`\n */\n async getDraftOrder(\n draftOrderId: string,\n ): Promise<GetDropshipperDraftOrderDetailResponse> {\n return this.request<GetDropshipperDraftOrderDetailResponse>(\n 'GET',\n `/admin/thor/dropshipper/draft-orders/${draftOrderId}`,\n );\n }\n\n /**\n * Create a new draft order.\n *\n * `POST /admin/thor/dropshipper/draft-orders`\n */\n async createDraftOrder(\n body: CreateDropshipperDraftOrderBody,\n ): Promise<CreateDropshipperDraftOrderResponse> {\n return this.request<CreateDropshipperDraftOrderResponse>(\n 'POST',\n '/admin/thor/dropshipper/draft-orders',\n body,\n );\n }\n\n /**\n * Update a draft order.\n *\n * `POST /admin/thor/dropshipper/draft-orders/:id`\n */\n async updateDraftOrder(\n draftOrderId: string,\n body: UpdateDropshipperDraftOrderBody,\n ): Promise<UpdateDropshipperDraftOrderResponse> {\n return this.request<UpdateDropshipperDraftOrderResponse>(\n 'POST',\n `/admin/thor/dropshipper/draft-orders/${draftOrderId}`,\n body,\n );\n }\n\n /**\n * Convert a draft order to a real order.\n *\n * `POST /admin/thor/dropshipper/draft-orders/:id/convert`\n */\n async convertDraftOrder(\n draftOrderId: string,\n body: ConvertDropshipperDraftOrderBody,\n ): Promise<ConvertDropshipperDraftOrderResponse> {\n return this.request<ConvertDropshipperDraftOrderResponse>(\n 'POST',\n `/admin/thor/dropshipper/draft-orders/${draftOrderId}/convert`,\n body,\n );\n }\n\n /**\n * Delete a draft order.\n *\n * `DELETE /admin/thor/dropshipper/draft-orders/:id`\n */\n async deleteDraftOrder(\n draftOrderId: string,\n ): Promise<DeleteDropshipperDraftOrderResponse> {\n return this.request<DeleteDropshipperDraftOrderResponse>(\n 'DELETE',\n `/admin/thor/dropshipper/draft-orders/${draftOrderId}`,\n );\n }\n\n // -------------------------------------------------------------------------\n // Geo-reference\n // -------------------------------------------------------------------------\n\n /**\n * List all geo-reference countries.\n *\n * `GET /admin/geo-reference`\n */\n async getGeoCountries(): Promise<GetGeoCountriesResponse> {\n return this.request<GetGeoCountriesResponse>('GET', '/admin/geo-reference');\n }\n\n /**\n * List provinces/states for a country.\n *\n * `GET /admin/geo-reference/countries/:iso_2/provinces`\n */\n async getGeoProvinces(iso2: string): Promise<GetGeoProvincesResponse> {\n return this.request<GetGeoProvincesResponse>(\n 'GET',\n `/admin/geo-reference/countries/${iso2}/provinces`,\n );\n }\n\n /**\n * List cities for a province/state.\n *\n * `GET /admin/geo-reference/provinces/:code/cities`\n */\n async getGeoCities(code: string): Promise<GetGeoCitiesResponse> {\n return this.request<GetGeoCitiesResponse>(\n 'GET',\n `/admin/geo-reference/provinces/${code}/cities`,\n );\n }\n}\n\n// Re-export types used by callers so they don't need to import from @thorprovider/types directly.\nexport type { DropshipperCategory, DropshipperPromotion, NotificationData, PriceUpdatedNotificationData, ProductAssignedNotificationData, StockChangeNotificationData, ManualAdminNotificationData, RawNotification, GetNotificationsOptions, GetNotificationsResponse, DropshipperNotificationEventType, DropshipperNotificationPreference, UpdateNotificationPreferencesBody, GetNotificationPreferencesResponse, GetBusinessPolicyResponse, UpdateBusinessPolicyBody, UpdateBusinessPolicyResponse, ChatRequest, ChatResponse, ChatMessage, ChatIntent, ChatSource, ChatSourceVariant } from '@thorprovider/types';\n\n// ---------------------------------------------------------------------------\n// AI Assistant — streaming helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Yields one parsed JSON object per `data:` line of a Server-Sent Events body.\n */\nasync function* parseSse(\n stream: ReadableStream<Uint8Array>,\n logger?: ReturnType<typeof createLogger>,\n): AsyncGenerator<unknown> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let frameIndex = 0;\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith('data:')) continue;\n const payload = trimmed.slice(5).trim();\n if (!payload || payload === '[DONE]') continue;\n frameIndex += 1;\n try {\n yield JSON.parse(payload);\n } catch (err: any) {\n logger?.warn(\n `[dropshipper] sse-malformed-frame frame=${frameIndex} payload=${payload.slice(0, 200)}`\n );\n }\n }\n }\n const tail = buffer.trim();\n if (tail.startsWith('data:')) {\n const payload = tail.slice(5).trim();\n if (payload && payload !== '[DONE]') {\n frameIndex += 1;\n try {\n yield JSON.parse(payload);\n } catch (err: any) {\n logger?.warn(\n `[dropshipper] sse-malformed-frame frame=${frameIndex} payload=${payload.slice(0, 200)}`\n );\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Normalize the backend's UI-message stream (SSE of `UIMessageChunk` frames)\n * into the consumer-friendly `ChatStreamEvent` type.\n */\nfunction mapUiMessageStreamToEvents(\n stream: ReadableStream<Uint8Array>,\n logger?: ReturnType<typeof createLogger>,\n): ReadableStream<ChatStreamEvent> {\n return new ReadableStream<ChatStreamEvent>({\n async start(controller) {\n let eventCount = 0;\n for await (const raw of parseSse(stream, logger)) {\n const chunk = raw as {\n type?: string;\n messageId?: string;\n delta?: string;\n errorText?: string;\n messageMetadata?: { intent?: ChatIntent; sources?: ChatSource[] };\n };\n switch (chunk.type) {\n case 'start':\n controller.enqueue({\n type: 'start',\n intent: chunk.messageMetadata?.intent,\n });\n eventCount += 1;\n break;\n case 'text-delta':\n if (chunk.delta !== undefined) {\n controller.enqueue({ type: 'text-delta', delta: chunk.delta });\n eventCount += 1;\n }\n break;\n case 'finish':\n controller.enqueue({\n type: 'finish',\n intent: chunk.messageMetadata?.intent ?? 'default',\n sources: chunk.messageMetadata?.sources ?? [],\n });\n eventCount += 1;\n break;\n case 'error':\n logger?.warn(\n `[dropshipper] chat-stream-error errorText=${chunk.errorText}`\n );\n controller.enqueue({\n type: 'error',\n errorText: chunk.errorText ?? 'Error inesperado del asistente.',\n });\n eventCount += 1;\n break;\n default:\n logger?.debug(\n `[dropshipper] chat-stream-unknown-frame type=${chunk.type}`\n );\n }\n }\n logger?.debug(`[dropshipper] chat-stream-completed events=${eventCount}`);\n controller.close();\n },\n cancel() {\n stream.cancel?.();\n },\n });\n}\n","/**\n * @fileoverview Recovery Client — Thor Commerce Extended\n * @module @thorprovider/medusa-extended/recovery\n *\n * Public HTTP client for account-recovery flows (password reset + activation).\n *\n * Unlike `DropshipperClient`, this client does NOT require a JWT: it talks to\n * public storefront endpoints so a user can recover access without being\n * logged in. Backend URLs are owned here; the dashboard never builds them.\n *\n * Endpoints:\n * - `POST /dropshipper/auth/emailpass/reset-password` (request reset, dropshipper)\n * - `GET /dropshipper/auth/emailpass/reset-password/verify` (verify reset token, no consume)\n * - `POST /dropshipper/auth/emailpass/update` (confirm reset, consumes token)\n * - `GET /store/dropshipper/applications/activate/verify` (verify activation token, no consume)\n * - `POST /store/dropshipper/applications/activate` (confirm activation, consumes token)\n * - `POST /public/dropshipper/applications` (submit application, no auth)\n *\n * Confirm methods follow the two-phase contract: verify (no consume) first,\n * then confirm (atomic consume). A re-verify after a failed confirm maps the\n * TOCTOU state (used/expired/revoked) into `RecoveryConfirmResult.status`.\n *\n * `submitApplication` returns a discriminated `SubmitApplicationResult` instead\n * of throwing on 400/409/429 so the caller can surface the backend's structured\n * payload (existing application on 409, retry window on 429). Network/5xx\n * errors are re-thrown as `ProviderAPIError`.\n */\n\nimport type {\n SubmitApplicationBody,\n SubmitApplicationConflictApplication,\n SubmitApplicationResponse,\n SubmitApplicationResult,\n TokenVerifyResult,\n RecoveryConfirmResult,\n} from '@thorprovider/types';\nimport { createLogger, ProviderAPIError } from '@thorprovider/adapters';\nimport { fetchBackendWithResilience, type RetryConfig } from './request-resilience';\n\ntype FetchMethod = 'GET' | 'POST';\n\n/**\n * Configuration required to instantiate the recovery client.\n */\nexport interface RecoveryClientConfig {\n /** Medusa backend base URL */\n baseUrl: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * HTTP client for account-recovery endpoints (public, no auth required).\n *\n * All methods throw `ProviderAPIError` on non-2xx responses except the\n * confirm methods, which normalize failures into `RecoveryConfirmResult`.\n *\n * @example\n * ```typescript\n * const client = new RecoveryClient({\n * baseUrl: process.env.MEDUSA_BACKEND_URL!,\n * });\n *\n * await client.requestUserPasswordReset('juan@ejemplo.com');\n * const result = await client.verifyUserPasswordResetToken(token);\n * const confirm = await client.confirmUserPasswordReset(token, 'NuevaClave1');\n * ```\n */\nexport class RecoveryClient {\n private baseUrl: string;\n private logger: ReturnType<typeof createLogger>;\n\n constructor(config: RecoveryClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.logger = createLogger('RecoveryClient', config.debug);\n }\n\n // -------------------------------------------------------------------------\n // Private — HTTP helper\n // -------------------------------------------------------------------------\n\n private async request<T>(\n method: FetchMethod,\n path: string,\n body?: unknown,\n retryConfig?: RetryConfig,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n this.logger.debug(`[recovery] ${method} ${path}`);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n const init: RequestInit = {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n };\n\n let response: Response;\n try {\n response = await fetchBackendWithResilience(url, init, retryConfig);\n } catch (networkError: any) {\n throw new ProviderAPIError(\n `[recovery] Network error on ${method} ${path}: ${networkError.message}`,\n 'NETWORK_ERROR',\n networkError,\n );\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n let details: Record<string, unknown> | undefined;\n try {\n const json = await response.json();\n message = json?.message ?? message;\n details = json && typeof json === 'object' ? (json as Record<string, unknown>) : undefined;\n } catch {\n // ignore parse errors\n }\n throw new ProviderAPIError(\n `[recovery] ${method} ${path} failed: ${message}`,\n `RECOVERY_API_${response.status}`,\n response.status,\n details,\n );\n }\n\n // 2xx success with a JSON body: parse and return it.\n if ((response.headers.get('content-type') ?? '').includes('application/json')) {\n try {\n return (await response.json()) as T;\n } catch {\n // A 2xx that claims JSON but fails to parse should not crash the\n // caller as a raw SyntaxError; the stub lets the caller handle it.\n return {} as T;\n }\n }\n\n // 2xx success without a JSON body (204 No Content, or plain-text bodies\n // like `201 Created` from native endpoints). No value to return.\n return {} as T;\n }\n\n // -------------------------------------------------------------------------\n // Password reset\n // -------------------------------------------------------------------------\n\n /**\n * Solicita un email de reset de contraseña para el actor `user`\n * (dropshippers). El backend responde de forma uniforme exista o no la\n * cuenta (anti enumeración).\n *\n * `POST /dropshipper/auth/emailpass/reset-password`\n */\n async requestUserPasswordReset(email: string): Promise<void> {\n await this.request('POST', '/dropshipper/auth/emailpass/reset-password', {\n email,\n });\n }\n\n /**\n * Verifica un token de reset de contraseña sin consumirlo. Devuelve el\n * email enmascarado (p. ej. `j***@ejemplo.com`) solo cuando `status === 'valid'`.\n *\n * `GET /dropshipper/auth/emailpass/reset-password/verify`\n */\n async verifyUserPasswordResetToken(token: string): Promise<TokenVerifyResult> {\n return this.request('GET', `/dropshipper/auth/emailpass/reset-password/verify?token=${encodeURIComponent(token)}`);\n }\n\n /**\n * Confirma el reset: re-verifica el token (sin consumir), luego consume el\n * token vía `POST /dropshipper/auth/emailpass/update`. El email se deriva del\n * propio JWT en el backend; aquí solo se envía la nueva contraseña. Nunca\n * devuelve auto-login: al éxito, la UI redirige a /login.\n */\n async confirmUserPasswordReset(token: string, password: string): Promise<RecoveryConfirmResult> {\n const verify = await this.verifyUserPasswordResetToken(token);\n if (verify.status !== 'valid') {\n return { ok: false, status: verify.status };\n }\n\n try {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n };\n const response = await fetchBackendWithResilience(`${this.baseUrl}/dropshipper/auth/emailpass/update`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ password }),\n });\n if (!response.ok) {\n throw new ProviderAPIError(\n `[recovery] POST /dropshipper/auth/emailpass/update failed: HTTP ${response.status}`,\n 'RECOVERY_API_' + response.status,\n response.status,\n );\n }\n return { ok: true };\n } catch (error) {\n // TOCTOU: el token pudo consumirse/expirar entre verify y update.\n this.logger.warn('[recovery] confirmUserPasswordReset failed, re-verifying', error);\n try {\n const recheck = await this.verifyUserPasswordResetToken(token);\n return { ok: false, status: recheck.status };\n } catch {\n return { ok: false, status: 'invalid' };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Account activation\n // -------------------------------------------------------------------------\n\n /**\n * Verifica un token de activación de cuenta dropshipper sin consumirlo.\n *\n * `GET /store/dropshipper/applications/activate/verify`\n */\n async verifyActivationToken(token: string): Promise<TokenVerifyResult> {\n return this.request('GET', `/store/dropshipper/applications/activate/verify?token=${encodeURIComponent(token)}`);\n }\n\n /**\n * Activa la cuenta: re-verifica el token (sin consumir), luego consume el\n * token vía `POST /store/dropshipper/applications/activate` y establece la\n * contraseña inicial. Al éxito, la UI redirige a /login sin auto-login.\n */\n async activateAccount(token: string, password: string): Promise<RecoveryConfirmResult> {\n const verify = await this.verifyActivationToken(token);\n if (verify.status !== 'valid') {\n return { ok: false, status: verify.status };\n }\n\n try {\n await this.request('POST', '/store/dropshipper/applications/activate', { token, password });\n return { ok: true };\n } catch (error) {\n // TOCTOU: re-verificar para distinguir used/expired/revoked.\n this.logger.warn('[recovery] activateAccount failed, re-verifying', error);\n try {\n const recheck = await this.verifyActivationToken(token);\n return { ok: false, status: recheck.status };\n } catch {\n return { ok: false, status: 'invalid' };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Dropshipper application submission\n // -------------------------------------------------------------------------\n\n /**\n * Envía una solicitud de acceso dropshipper al endpoint público.\n *\n * `POST /public/dropshipper/applications`\n *\n * No requiere autenticación. Devuelve un resultado discriminado:\n * - `{ ok: true }` → 201, solicitud creada (`application.number`).\n * - `{ ok: false, reason: 'conflict' }` → 409, email ya registrado; la\n * solicitud existente incluye `status_label`/`reason` para la UI.\n * - `{ ok: false, reason: 'rate_limited' }` → 429, se respetó el límite del\n * backend; `retryAfterSeconds` indica cuándo reintentar.\n * - `{ ok: false, reason: 'invalid_data' }` → 400, validación del backend.\n *\n * Los errores de red/5xx se re-lanzan como `ProviderAPIError` para que el\n * llamador los categorice (p. ej. con `parseError`). El 429 no se reintenta\n * (`retryableStatusCodes` sin 429) para que el caller reciba de inmediato el\n * `retry_after_seconds` del backend y pueda bloquear el envío.\n */\n async submitApplication(body: SubmitApplicationBody): Promise<SubmitApplicationResult> {\n try {\n const response = await this.request<SubmitApplicationResponse>(\n 'POST',\n '/public/dropshipper/applications',\n body,\n { retryableStatusCodes: [408, 500, 502, 503, 504] },\n );\n return { ok: true, application: response.application };\n } catch (error) {\n if (error instanceof ProviderAPIError) {\n const details = error.details ?? {};\n if (error.status === 409 && details.application) {\n return {\n ok: false,\n reason: 'conflict',\n application: details.application as SubmitApplicationConflictApplication,\n };\n }\n if (error.status === 429 && typeof details.retry_after_seconds === 'number') {\n return {\n ok: false,\n reason: 'rate_limited',\n retryAfterSeconds: details.retry_after_seconds,\n };\n }\n if (error.status === 400 && details?.type === 'challenge_failed') {\n return {\n ok: false,\n reason: 'challenge_failed',\n ...(typeof details.message === 'string' ? { message: details.message } : {}),\n };\n }\n if (error.status === 400) {\n return {\n ok: false,\n reason: 'invalid_data',\n fields: details.fields as Record<string, string[]> | undefined,\n };\n }\n }\n throw error;\n }\n }\n}"],"mappings":"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","names":["import_adapters","import_adapters","import_adapters"]}
|