@thorprovider/adapters 5.0.10 → 5.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/AGENTS.md +1 -1
  2. package/dist/index.d.mts +376 -16
  3. package/dist/index.d.ts +376 -16
  4. package/dist/index.js +1687 -528
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +1680 -530
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +3 -2
  9. package/src/core/errors.ts +31 -0
  10. package/src/factory/index.ts +16 -6
  11. package/src/factory/provider-types.test.ts +32 -0
  12. package/src/factory/provider-types.ts +176 -0
  13. package/src/index.ts +6 -4
  14. package/src/providers/index.ts +1 -1
  15. package/src/providers/medusa/auth.test.ts +148 -25
  16. package/src/providers/medusa/auth.ts +129 -16
  17. package/src/providers/medusa/available-filters.test.ts +280 -0
  18. package/src/providers/medusa/catalog-facet-support.test.ts +715 -0
  19. package/src/providers/medusa/catalog-query.test.ts +422 -0
  20. package/src/providers/medusa/catalog-sort.test.ts +175 -0
  21. package/src/providers/medusa/customer-orders.test.ts +142 -0
  22. package/src/providers/medusa/index.test.ts +480 -0
  23. package/src/providers/medusa/index.ts +1592 -538
  24. package/src/providers/medusa/live-smoke.test.ts +68 -0
  25. package/src/providers/medusa/transforms.test.ts +222 -0
  26. package/src/providers/medusa/transforms.ts +152 -66
  27. package/src/providers/mock/catalog-query.test.ts +491 -0
  28. package/src/providers/mock/index.test.ts +66 -0
  29. package/src/providers/mock/index.ts +43 -1
  30. package/src/providers/mock/mock.ts +513 -3
  31. package/src/types/completion.ts +57 -0
  32. package/src/types/index.ts +7 -0
  33. package/.turbo/turbo-build.log +0 -18
  34. package/.turbo/turbo-test.log +0 -372
  35. package/.turbo/turbo-type-check.log +0 -0
  36. package/dist/.tsbuildinfo +0 -1
  37. package/publish.log +0 -93
package/AGENTS.md CHANGED
@@ -1 +1 @@
1
- <!-- ADAPTERS-AGENTS-MD-START -->[@thorprovider/adapters Docs]|root: ./adapters|CRITICAL: Framework-agnostic business logic only. Never import Next.js or React. Check README.md and docs/getting-started.md before making changes.|To regenerate: yarn workspace @thorprovider/adapters generate:agent-index|.:{PROVIDER_IMPLEMENTATION_ANALYSIS.md,README.md,quick-reference.md}|docs:{RETRY_SOLUTION_SUMMARY.md,authentication.md,capabilities-system.md,category-customization.md,fetch-reliability-solution.md,getting-started.md,multi-tenant-channel-scoping.md,profile-management.md,providers-overview.md,services-overview.md,update-documentation.md}|src/resilience:{README.md}<!-- ADAPTERS-AGENTS-MD-END -->
1
+ <!-- ADAPTERS-AGENTS-MD-START -->[@thorprovider/adapters Docs]|root: ./adapters|CRITICAL: Framework-agnostic business logic only. Never import Next.js or React. Check README.md and docs/getting-started.md before making changes. Electrostore MVP: see director roadmap.|To regenerate: yarn workspace @thorprovider/adapters generate:agent-index|.:{PROVIDER_IMPLEMENTATION_ANALYSIS.md,README.md,quick-reference.md}|docs:{RETRY_SOLUTION_SUMMARY.md,authentication.md,capabilities-system.md,category-customization.md,fetch-reliability-solution.md,getting-started.md,multi-tenant-channel-scoping.md,profile-management.md,providers-overview.md,services-overview.md,update-documentation.md}|src/resilience:{README.md}<!-- ADAPTERS-AGENTS-MD-END -->
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _thorprovider_types from '@thorprovider/types';
2
- import { BackendCapabilities, Money, PaymentMethod, FulfillmentOption, CartItem, StockLocation, InventoryLevel, StorefrontConfig, DashboardMetrics, ProviderTypeString, CommerceProvider, AuthProvider, ProviderConfig, AuthConfig, Product, GetProductsOptions, AdvancedSearchProductsOptions, SearchResultMeta, FilterConfig, Collection, GetCollectionsOptions, CollectionProductsOptions, ProductCategory, GetCategoriesOptions, Cart, CartLineInput, CartLineUpdate, GetOrdersOptions, Order, GetCustomersOptions, Customer, Address, Region, AdminProduct, PaymentMethodsOptions, StockValidation, StorefrontContext, DesignerConfig, DesignerHistoryEntry, ShippingMethod, Country } from '@thorprovider/types';
2
+ import { Order, Cart, BackendCapabilities, Money, PaymentMethod, FulfillmentOption, CartItem, StockLocation, InventoryLevel, StorefrontConfig, DashboardMetrics, ProviderTypeString, CommerceProvider, AuthProvider, ProviderConfig, AuthConfig, Product, GetProductsOptions, CatalogQuery, CatalogQueryOutcome, FacetSupport, AdvancedSearchProductsOptions, SearchResultMeta, FilterConfig, Collection, GetCollectionsOptions, CollectionProductsOptions, ProductCategory, GetCategoriesOptions, CartLineInput, CartLineUpdate, GetOrdersOptions, GetCustomerOrdersPageOptions, CustomerOrdersPage, GetCustomersOptions, Customer, Address, Region, AdminProduct, PaymentMethodsOptions, StockValidation, StorefrontContext, DesignerConfig, DesignerHistoryEntry, ShippingMethod, Country } from '@thorprovider/types';
3
3
  export * from '@thorprovider/types';
4
- export { BackendCapabilities, CommerceProvider, DesignerConfig, DesignerHistoryEntry, DesignerNavItem, DesignerThemeConfig, DesignerThemePreset, ProviderConfig, StorefrontConfig, StorefrontConfigError, StorefrontContext, StorefrontPlatformType, StorefrontSeoDefaults } from '@thorprovider/types';
4
+ export { BackendCapabilities, CommerceProvider, DesignerConfig, DesignerHistoryEntry, DesignerNavItem, DesignerThemeConfig, DesignerThemePreset, ProviderConfig, StorefrontConfig, StorefrontContext, StorefrontPlatformType, StorefrontSeoDefaults } from '@thorprovider/types';
5
5
  import Medusa from '@medusajs/js-sdk';
6
6
 
7
7
  /**
@@ -211,6 +211,64 @@ interface UIPaymentMethod {
211
211
  description?: string;
212
212
  }
213
213
 
214
+ /**
215
+ * @thorprovider/adapters — Cart completion contract
216
+ *
217
+ * Completion of a backend cart is discriminated (change B, decision 11): a
218
+ * native complete may return an order, a cart carrying a structured error, or
219
+ * an ambiguous/unresolved result whose outcome must be reconciled before any
220
+ * retry. This type is provider-agnostic and lives in adapters (not
221
+ * `@thorprovider/types`, which stays type-only and frozen).
222
+ */
223
+
224
+ /**
225
+ * Structured completion error. `raw` carries the backend's own error object
226
+ * when one was supplied so the discriminator and details are preserved.
227
+ */
228
+ interface CartCompletionError {
229
+ /** Human-readable message. */
230
+ message: string;
231
+ /** Stable error code when the backend or transport supplies one. */
232
+ code?: string;
233
+ /** HTTP/transport status when one is known. */
234
+ status?: number;
235
+ /** Backend error details, carried through unchanged. */
236
+ raw?: unknown;
237
+ }
238
+ /**
239
+ * The discriminated result of completing a cart.
240
+ *
241
+ * - `order` — the cart was completed and an order was placed.
242
+ * - `cart` — the backend returned a cart with a structured error (the native
243
+ * HTTP 200 `type: "cart"` discriminator is preserved).
244
+ * - `unresolved` — the mutation's outcome is unknown (timeout/transport/5xx).
245
+ * Never blindly retry: reconcile the committed cart before another attempt.
246
+ */
247
+ type CartCompletionResult = {
248
+ type: 'order';
249
+ order: Order;
250
+ } | {
251
+ type: 'cart';
252
+ cart: Cart;
253
+ error: CartCompletionError;
254
+ } | {
255
+ type: 'unresolved';
256
+ error: CartCompletionError;
257
+ };
258
+ /**
259
+ * Optional capability a provider may implement to expose the discriminated
260
+ * completion and reconciliation protocol. Providers that do not implement it
261
+ * still satisfy `CommerceProvider`; the runtime falls back to
262
+ * `completeCheckout` for them.
263
+ */
264
+ interface CartCompletionCapable {
265
+ /**
266
+ * Complete the cart once, preserving the native discriminator. Must not
267
+ * retry an ambiguous mutation.
268
+ */
269
+ completeCart?(cartId: string): Promise<CartCompletionResult>;
270
+ }
271
+
214
272
  /**
215
273
  * @thorprovider/adapters v2.0
216
274
  * Backend Capabilities System
@@ -309,6 +367,26 @@ declare class ProviderNotFoundError extends CommerceError {
309
367
  declare class ConfigurationError extends CommerceError {
310
368
  constructor(message: string);
311
369
  }
370
+ /**
371
+ * Storefront validation error.
372
+ * Thrown when storefront configuration is invalid or missing.
373
+ *
374
+ * Moved here from `@thorprovider/types` so that package stays type-only.
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * throw new StorefrontConfigError(
379
+ * 'Medusa requires NEXT_PUBLIC_SALES_CHANNEL_ID',
380
+ * 'medusa',
381
+ * 'NEXT_PUBLIC_SALES_CHANNEL_ID',
382
+ * );
383
+ * ```
384
+ */
385
+ declare class StorefrontConfigError extends Error {
386
+ readonly platformType: string;
387
+ readonly requiredEnvVar?: string;
388
+ constructor(message: string, platformType: string, requiredEnvVar?: string);
389
+ }
312
390
  /**
313
391
  * Resource not found error
314
392
  */
@@ -1442,6 +1520,12 @@ interface MedusaProviderConfig extends ProviderConfig {
1442
1520
  * Region ID (optional, will use default region if not provided)
1443
1521
  */
1444
1522
  regionId?: string;
1523
+ /**
1524
+ * Per-request catalog listing bound. Listing is paginated with this bound
1525
+ * instead of an unbounded scan; it is a configured safety bound, not a
1526
+ * backend maximum. Defaults to `MEDUSA_CATALOG_PAGE_SIZE` or 50.
1527
+ */
1528
+ catalogPageSize?: number;
1445
1529
  /**
1446
1530
  * Authentication configuration (optional)
1447
1531
  * If not provided, auth methods will not be available
@@ -1480,9 +1564,21 @@ interface MedusaProviderConfig extends ProviderConfig {
1480
1564
  *
1481
1565
  * Implements CommerceProvider interface for Medusa.js v2
1482
1566
  */
1483
- declare class MedusaProvider implements CommerceProvider {
1567
+ declare class MedusaProvider implements CommerceProvider, CartCompletionCapable {
1484
1568
  readonly name = "medusa";
1485
1569
  readonly version = "2.0.0";
1570
+ /**
1571
+ * Canonical catalog sort keys this provider applies at the query level.
1572
+ *
1573
+ * Advertises only the backend-verified orderings (E2 Decision 6). `price-asc`,
1574
+ * `price-desc`, and `rating` are intentionally absent: they are not applied at
1575
+ * the query level, so the listing never offers them as global sorts.
1576
+ *
1577
+ * The literal tuple is assignable to `CommerceProvider['supportedCatalogSortKeys']`
1578
+ * (`readonly CatalogSortKey[]`); it is written structurally here so the adapter
1579
+ * compiles against the published `@thorprovider/types` declaration.
1580
+ */
1581
+ readonly supportedCatalogSortKeys: readonly ["featured", "name", "newest"];
1486
1582
  /**
1487
1583
  * Medusa backend capabilities.
1488
1584
  * Starts with static defaults, replaced by dynamic values from
@@ -1502,6 +1598,14 @@ declare class MedusaProvider implements CommerceProvider {
1502
1598
  private baseUrl;
1503
1599
  private publishableKey;
1504
1600
  private regionId?;
1601
+ /** Configured per-request catalog listing bound (never an unbounded scan). */
1602
+ private catalogPageSize;
1603
+ /**
1604
+ * Per-scope cache of the truthful facet-support descriptor. The optional
1605
+ * advanced endpoint is probed once per demonstrated scope/query rather than on
1606
+ * every listing request (E2 task 2.4).
1607
+ */
1608
+ private facetSupportCache;
1505
1609
  /** Secret API key for admin operations (if configured). */
1506
1610
  private adminApiKey?;
1507
1611
  /**
@@ -1547,12 +1651,120 @@ declare class MedusaProvider implements CommerceProvider {
1547
1651
  * Handles network failures and temporary backend issues
1548
1652
  */
1549
1653
  private withRetry;
1654
+ /** Fields needed to price a product variant for the current region. */
1655
+ private buildProductFields;
1656
+ /** Scope a store query to the configured storefront sales channel, if any. */
1657
+ private applySalesChannelScope;
1658
+ /**
1659
+ * Directed single-product lookup by a supported native filter (`handle` or
1660
+ * `id`). This is independent of catalog listing pagination, so a known
1661
+ * product beyond the first listing page still resolves without scanning.
1662
+ *
1663
+ * Medusa's store API supports `handle` and `id` on `/store/products`; it
1664
+ * does not expose a variant filter there, so a variant is resolved from the
1665
+ * product once the product is known (see `getProductDetailByHandle` in the
1666
+ * runtime). No `limit` beyond 1 is issued.
1667
+ */
1668
+ private fetchSingleProduct;
1550
1669
  getProduct(handle: string, options?: {
1551
1670
  regionId?: string;
1552
1671
  }): Promise<Product | undefined>;
1672
+ /**
1673
+ * Directed product lookup by backend product ID. Independent of the first
1674
+ * listing page, mirroring `getProduct` for handle-based resolution.
1675
+ */
1676
+ getProductById(id: string, options?: {
1677
+ regionId?: string;
1678
+ }): Promise<Product | undefined>;
1553
1679
  getProducts(options?: GetProductsOptions & {
1554
1680
  regionId?: string;
1555
1681
  }): Promise<Product[]>;
1682
+ /**
1683
+ * Canonical catalog query path (E2 task 2.2).
1684
+ *
1685
+ * Accepts a validated `CatalogQuery`, translates it into Medusa Store
1686
+ * `/store/products` parameters, and returns a truthful `CatalogQueryOutcome`.
1687
+ * The route category scope is always retained and intersected with the
1688
+ * `categories` filter; `categories`/`collections` handles are resolved to
1689
+ * backend IDs through the existing directed lookups (`getCategory`/
1690
+ * `getCollection`). Any requested filter this provider cannot apply
1691
+ * (price/`inStock`/attributes) is rejected as a typed `unsupported-query`
1692
+ * outcome naming the fields — never a partial success and never a silent
1693
+ * drop. Pagination is `offset = (page - 1) * pageSize`, defaulting to the
1694
+ * canonical page size.
1695
+ *
1696
+ * Legacy `getProducts`/`getCategoryProducts` are unchanged; this additive
1697
+ * method is the typed seam the runtime query bridge (E2 task 3.1) consumes.
1698
+ */
1699
+ getCatalogProducts(query: CatalogQuery): Promise<CatalogQueryOutcome>;
1700
+ /**
1701
+ * Execute a basic-only canonical query against the equivalent basic endpoint
1702
+ * `/store/products`, reporting the filters it actually applied.
1703
+ */
1704
+ private queryBasicCatalog;
1705
+ /**
1706
+ * Execute an advanced canonical query against the real optional endpoint
1707
+ * `/store/search`, then re-validate that the response applied every requested
1708
+ * filter. A response that does not confirm a requested field, or an endpoint
1709
+ * failure, yields a typed `unsupported-query` error — never a partial result
1710
+ * labelled success and never a silent fallback to the basic endpoint.
1711
+ */
1712
+ private queryAdvancedCatalog;
1713
+ /** Resolve category handles to Medusa category IDs via directed lookups. */
1714
+ private resolveCategoryIds;
1715
+ /** Resolve collection handles to Medusa collection IDs via directed lookups. */
1716
+ private resolveCollectionIds;
1717
+ /**
1718
+ * Truthful facet-support descriptor for a scope (E2 task 2.4).
1719
+ *
1720
+ * Basic facets (`categories`, `collections`) are always offered: they are
1721
+ * applied by the canonical basic endpoint `/store/products`, and the
1722
+ * descriptor records that endpoint with the applied query and scope as their
1723
+ * demonstration source.
1724
+ *
1725
+ * Optional advanced facets (`price`, `inStock`, and advertised `attr.<name>`)
1726
+ * are offered only when the real optional `/store/search` endpoint has been
1727
+ * demonstrated with the applied query for the current scope AND the response
1728
+ * echoes the filter as applied. Otherwise they are held with the real probe
1729
+ * status/reason — a capability boolean or returned facet metadata is never
1730
+ * accepted as proof (E2 Decisions 4–5; spec "Backend support is proven against
1731
+ * the real endpoint, not assumed").
1732
+ *
1733
+ * The descriptor carries no counts or ranges and no invented timestamp; every
1734
+ * offered facet has an actual `{ endpoint, appliedQuery, scope }` source.
1735
+ */
1736
+ getCatalogFacetSupport(options?: {
1737
+ query?: CatalogQuery;
1738
+ categoryIds?: string[];
1739
+ collectionIds?: string[];
1740
+ scope?: string;
1741
+ }): Promise<FacetSupport>;
1742
+ private resolveCatalogFacetSupport;
1743
+ /**
1744
+ * Demonstrate the optional advanced endpoint with the applied query for the
1745
+ * current scope. A non-2xx response (including the HTTP 404/500 an absent
1746
+ * plugin returns), an unparseable body, or a response that does not echo the
1747
+ * applied filters all mean the facet is not demonstrated — never a silent
1748
+ * assumption of support. Uses a single SDK request (no retry): a support probe
1749
+ * must not amplify a broken optional endpoint into repeated requests.
1750
+ */
1751
+ private probeAdvancedSearchSupport;
1752
+ /**
1753
+ * Build the advanced-endpoint query parameters from the canonical query. The
1754
+ * SDK serializes the plain object, so no manual stringification is needed.
1755
+ */
1756
+ private buildAdvancedSearchQuery;
1757
+ /** Resolve the effective category scope of a query to backend IDs. */
1758
+ private resolveScopeCategoryIds;
1759
+ /**
1760
+ * Advertised filterable attribute handles for the scope. The custom-attributes
1761
+ * endpoint is facet *metadata* (which attributes exist), not proof that a
1762
+ * filter can be applied; these handles are candidates only, and each still
1763
+ * requires the advanced endpoint to echo it as applied before it is offered.
1764
+ */
1765
+ private resolveFilterableAttributeHandles;
1766
+ /** Build a typed `unsupported-query` outcome naming the offending fields. */
1767
+ private unsupportedCatalogOutcome;
1556
1768
  getProductRecommendations(productId: string): Promise<Product[]>;
1557
1769
  /**
1558
1770
  * Advanced product search using /store/search endpoint
@@ -1568,6 +1780,14 @@ declare class MedusaProvider implements CommerceProvider {
1568
1780
  products: Product[];
1569
1781
  meta?: SearchResultMeta;
1570
1782
  }>;
1783
+ /**
1784
+ * Faithful fallback for `searchProductsAdvanced`. A basic-only request is
1785
+ * served by `getProducts`; a request that depends on the optional advanced
1786
+ * endpoint is rejected as a typed `ProviderAPIError` naming the unappliable
1787
+ * fields, so a failed advanced search never returns an unfiltered result
1788
+ * labelled success (E2 task 2.4).
1789
+ */
1790
+ private fallbackAdvancedSearch;
1571
1791
  /**
1572
1792
  * Get available filter options for product filtering
1573
1793
  *
@@ -1685,13 +1905,17 @@ declare class MedusaProvider implements CommerceProvider {
1685
1905
  }>;
1686
1906
  }>>;
1687
1907
  /**
1688
- * Get all orders for a customer (storefront).
1908
+ * Get all orders for a customer (storefront) as an array (legacy surface).
1689
1909
  *
1690
- * Note: This retrieves orders from the storefront API (store.order.list),
1691
- * which returns orders only for the authenticated customer in the JWT.
1910
+ * Delegates to the channel-scoped paginated contract
1911
+ * ({@link customerOrdersPage}) and returns that window's orders. The backend
1912
+ * (`GET /store/thor/orders`) scopes by BOTH the authenticated customer and
1913
+ * the sales channel resolved from the publishable key, so cross-channel
1914
+ * orders are excluded by the backend before pagination and **no client-side
1915
+ * channel filter runs**.
1692
1916
  *
1693
- * @param options - Order query options (supports callbacks for custom backends)
1694
- * @returns Array of orders for the authenticated customer
1917
+ * @param options - Order query options (supports a custom fetcher)
1918
+ * @returns Array of orders for the authenticated customer on the store channel
1695
1919
  *
1696
1920
  * @example
1697
1921
  * ```typescript
@@ -1700,6 +1924,25 @@ declare class MedusaProvider implements CommerceProvider {
1700
1924
  * ```
1701
1925
  */
1702
1926
  getOrders(options?: GetOrdersOptions): Promise<Order[]>;
1927
+ /**
1928
+ * Channel-scoped, paginated order history for the authenticated customer.
1929
+ *
1930
+ * Calls the backend route `GET /store/thor/orders`, which requires the
1931
+ * customer session and scopes `order` by `customer_id` **and** the
1932
+ * `sales_channel_id` resolved from the publishable key, returning
1933
+ * `{ orders, count, limit, offset }` with the backend's real total computed
1934
+ * before pagination.
1935
+ *
1936
+ * The `salesChannelId` option is the store's explicitly configured channel.
1937
+ * When supplied, every returned order is asserted to belong to it; a
1938
+ * foreign-channel order (for example from a multi-channel publishable key that
1939
+ * silently resolved an arbitrary first id) fails closed with a typed error
1940
+ * rather than being presented as the customer's history.
1941
+ *
1942
+ * @param options - Bounded pagination window and the store's sales channel
1943
+ * @returns The backend's `{ orders, count, limit, offset }`
1944
+ */
1945
+ customerOrdersPage(options?: GetCustomerOrdersPageOptions): Promise<CustomerOrdersPage>;
1703
1946
  /**
1704
1947
  * Get a single order by ID
1705
1948
  *
@@ -1991,6 +2234,20 @@ declare class MedusaProvider implements CommerceProvider {
1991
2234
  * @throws {ProviderAPIError} If checkout fails
1992
2235
  */
1993
2236
  completeCheckout(cartId: string): Promise<Order>;
2237
+ /**
2238
+ * Complete a cart exactly once and preserve the native discriminator
2239
+ * (change B, decision 11).
2240
+ *
2241
+ * Medusa's `POST /store/carts/:id/complete` returns HTTP 200 whose body is
2242
+ * either `{ type: 'order', order }` or `{ type: 'cart', cart, error }`. This
2243
+ * method never retries: a thrown transport/timeout/5xx failure becomes an
2244
+ * `unresolved` result so the caller reconciles the committed cart before any
2245
+ * further attempt. The Medusa JS SDK performs no implicit retry of its own,
2246
+ * so there is no blind retry beneath this call either.
2247
+ */
2248
+ completeCart(cartId: string): Promise<CartCompletionResult>;
2249
+ /** Normalize any thrown/returned completion failure into a structured error. */
2250
+ private toCompletionError;
1994
2251
  /**
1995
2252
  * Get available shipping methods for cart
1996
2253
  *
@@ -2636,15 +2893,24 @@ declare class StelOrderProvider implements CommerceProvider {
2636
2893
  private wrapError;
2637
2894
  }
2638
2895
 
2896
+ /**
2897
+ * Stable sales channel the fixture cart is scoped to. Exported so a host can
2898
+ * build a matching `StoreContext` for the mock data source; the runtime
2899
+ * context check compares against it like a real backend channel.
2900
+ */
2901
+ declare const MOCK_SALES_CHANNEL_ID = "mock-sales-channel";
2902
+
2639
2903
  interface MockProviderConfig extends ProviderConfig {
2640
2904
  currencyCode?: string;
2641
2905
  siteUrl?: string;
2642
2906
  }
2643
- declare class MockProvider implements CommerceProvider {
2907
+
2908
+ declare class MockProvider implements CommerceProvider, CartCompletionCapable {
2644
2909
  readonly name = "mock";
2645
2910
  readonly version = "1.0.0";
2646
2911
  readonly capabilities: Readonly<_thorprovider_types.BackendCapabilities>;
2647
2912
  readonly isMock = true;
2913
+ readonly supportedCatalogSortKeys: readonly _thorprovider_types.CatalogSortKey[];
2648
2914
  private readonly currencyCode;
2649
2915
  private readonly siteUrl;
2650
2916
  constructor(config?: MockProviderConfig);
@@ -2653,6 +2919,16 @@ declare class MockProvider implements CommerceProvider {
2653
2919
  regionId?: string;
2654
2920
  }): Promise<Product | undefined>;
2655
2921
  getProducts(options?: GetProductsOptions): Promise<Product[]>;
2922
+ /**
2923
+ * Canonical catalog query path (E2 task 2.5).
2924
+ *
2925
+ * Delegates to the fixture-backed canonical implementation so mock mode is a
2926
+ * faithful stand-in for the same contract the Medusa adapter honors: scope ∩
2927
+ * categories, collection resolution, global ordering before pagination, the
2928
+ * real full match count, and a typed `unsupported-query` for advanced filters
2929
+ * the mock does not implement.
2930
+ */
2931
+ getCatalogProducts(query: CatalogQuery): Promise<CatalogQueryOutcome>;
2656
2932
  getProductRecommendations(productId: string): Promise<Product[]>;
2657
2933
  getCollection(handle: string): Promise<Collection | undefined>;
2658
2934
  getCollections(options?: GetCollectionsOptions): Promise<Collection[]>;
@@ -2679,6 +2955,15 @@ declare class MockProvider implements CommerceProvider {
2679
2955
  }>;
2680
2956
  }>>;
2681
2957
  completeCheckout(cartId: string): Promise<Order>;
2958
+ /**
2959
+ * Discriminated completion for the fixture provider.
2960
+ *
2961
+ * Completion is idempotent by construction (the fixture order id derives from
2962
+ * the cart id), so completing an already-completed cart returns the same
2963
+ * persisted order — mirroring the native reconcile path without a second
2964
+ * order.
2965
+ */
2966
+ completeCart(cartId: string): Promise<CartCompletionResult>;
2682
2967
  getShippingMethods(cartId: string): Promise<ShippingMethod[]>;
2683
2968
  getRegionCountries(regionId: string): Promise<_thorprovider_types.Country[]>;
2684
2969
  addShippingMethod(cartId: string, methodId: string): Promise<Cart>;
@@ -2706,20 +2991,95 @@ declare class MockProvider implements CommerceProvider {
2706
2991
  isStorefrontRequired(): boolean;
2707
2992
  }
2708
2993
 
2994
+ /**
2995
+ * @thorprovider/adapters — Provider registry (runtime)
2996
+ *
2997
+ * Runtime owner of the provider registry: the `SupportedProviderType` enum,
2998
+ * its metadata, and the guards. The provider-type union contract
2999
+ * (`ProviderTypeString`) stays type-only in `@thorprovider/types`.
3000
+ *
3001
+ * When adding a new provider:
3002
+ * 1. Add the string to `ProviderTypeString` in packages/types/src/provider.ts.
3003
+ * 2. Add the enum member + metadata entry here.
3004
+ * 3. Create packages/adapters/src/providers/[platform]/.
3005
+ */
3006
+
3007
+ /**
3008
+ * All supported commerce platform providers.
3009
+ * `mock` is the backend-optional runtime provider used for layout/design mode.
3010
+ * `medusa` is fully implemented for real backend usage; others are placeholders for future expansion.
3011
+ *
3012
+ * @remarks Implementation status:
3013
+ * - ✅ mock: Fixture-backed provider for backend-optional storefronts
3014
+ * - ✅ medusa: Fully implemented
3015
+ * - 🟡 stelorder: In progress (ERP adapter v1)
3016
+ * - 🟡 shopify: Planned (Phase 2)
3017
+ * - 🟡 bigcommerce: Planned (Phase 2)
3018
+ * - 🟡 woocommerce: Planned (Phase 3)
3019
+ * - 🟡 spree: Planned (Phase 3)
3020
+ * - 🟡 magento: Planned (Phase 3)
3021
+ */
3022
+ declare enum SupportedProviderType {
3023
+ Mock = "mock",
3024
+ Medusa = "medusa",
3025
+ StelOrder = "stelorder",
3026
+ Shopify = "shopify",
3027
+ BigCommerce = "bigcommerce",
3028
+ WooCommerce = "woocommerce",
3029
+ Spree = "spree",
3030
+ Magento = "magento"
3031
+ }
3032
+ /**
3033
+ * Metadata about each provider.
3034
+ * Useful for UI, error messages, validation, and documentation.
3035
+ */
3036
+ declare const PROVIDER_METADATA: Record<ProviderTypeString, {
3037
+ name: string;
3038
+ description: string;
3039
+ requiresStorefront: boolean;
3040
+ requiredEnvVars: string[];
3041
+ maxRetries: number;
3042
+ }>;
3043
+ /**
3044
+ * Check if a string is a valid provider type.
3045
+ *
3046
+ * @example
3047
+ * ```typescript
3048
+ * if (isSupportedProviderType(process.env.COMMERCE_PROVIDER)) {
3049
+ * // type is narrowed to ProviderTypeString
3050
+ * }
3051
+ * ```
3052
+ */
3053
+ declare function isSupportedProviderType(value: unknown): value is ProviderTypeString;
3054
+ /**
3055
+ * Get metadata for a provider type.
3056
+ * Useful for validation, error messages, and logging.
3057
+ *
3058
+ * @example
3059
+ * ```typescript
3060
+ * const meta = getProviderMetadata('medusa');
3061
+ * console.log(`Using ${meta.name} with max ${meta.maxRetries} retries`);
3062
+ * ```
3063
+ */
3064
+ declare function getProviderMetadata(type: ProviderTypeString): (typeof PROVIDER_METADATA)[ProviderTypeString];
3065
+
2709
3066
  /**
2710
3067
  * @thorprovider/adapters v2.0
2711
3068
  * Provider Factory - Create commerce providers dynamically
2712
3069
  *
2713
- * This factory is bound to SupportedProviderType from @thorprovider/types (L1).
3070
+ * This factory owns the runtime provider registry (SupportedProviderType +
3071
+ * metadata + guards) and is bound to the type-only ProviderTypeString union
3072
+ * from @thorprovider/types (L1).
2714
3073
  * When adding a new provider:
2715
- * 1. Update SupportedProviderType enum in packages/types/src/provider.ts
2716
- * 2. Add new discriminated union case here
2717
- * 3. Create packages/adapters/src/providers/[platform]/
2718
- * 4. Implement CommerceProvider interface
3074
+ * 1. Update ProviderTypeString in packages/types/src/provider.ts
3075
+ * 2. Add the enum member + metadata in ./provider-types.ts
3076
+ * 3. Add new discriminated union case here
3077
+ * 4. Create packages/adapters/src/providers/[platform]/
3078
+ * 5. Implement CommerceProvider interface
2719
3079
  */
2720
3080
 
2721
3081
  /**
2722
- * Supported provider types (imported from @thorprovider/types L1)
3082
+ * Supported provider types (type-only union owned by @thorprovider/types L1)
2723
3083
  * Kept for backward compatibility; prefer ProviderTypeString from @thorprovider/types
2724
3084
  */
2725
3085
  type ProviderType = ProviderTypeString;
@@ -2780,4 +3140,4 @@ declare function createProvider(options: ProviderFactoryConfig | RuntimeProvider
2780
3140
  */
2781
3141
  declare function isProviderType<T extends ProviderType>(provider: CommerceProvider, type: T): boolean;
2782
3142
 
2783
- export { AdminAuthService, type AdminSession, AdminSessionService, BIGCOMMERCE_CAPABILITIES, type BackendMapping, type BackendMetadataAdapter, type BackendMetadataAdapterConfig, BigCommerceProvider, type BigCommerceProviderConfig, CHANNEL_ASSIGNED_AT_KEY, CHANNEL_ASSIGNED_BY_KEY, CHANNEL_SCOPE_KEY, type ChannelScopeMetadata, ChannelScopeValidationError, type ChannelScopeable, CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, type CircuitBreakerStats, type CircuitState, CommerceError, ConfigurationError, type Coordinates, type FulfillmentGroup, type FulfillmentPlan, type LogLevel, type Logger, MAGENTO_CAPABILITIES, MEDUSA_CAPABILITIES, MOCK_CAPABILITIES, MagentoProvider, type MagentoProviderConfig, MedusaMetadataAdapter, MedusaProvider, type MedusaProviderConfig, type MetricsOrderInput, type MetricsProductInput, MetricsService, MockProvider, type MockProviderConfig, type PlanFulfillmentShippingAddress, ProviderAPIError, type ProviderFactoryConfig, ProviderNotFoundError, type ProviderType, ResourceNotFoundError, type RetryConfig, SHOPIFY_CAPABILITIES, SPREE_CAPABILITIES, STELORDER_CAPABILITIES, ShopifyProvider, type ShopifyProviderConfig, SpreeProvider, type SpreeProviderConfig, StelOrderProvider, type StelOrderProviderConfig, type UICartItem, type UICartTotals, type UIDiscountCode, type UIPaymentMethod, type UIShippingMethod, WOOCOMMERCE_CAPABILITIES, WooCommerceProvider, type WooCommerceProviderConfig, assertEntityBelongsToChannel, backendCircuitBreaker, buildChannelScopeMetadata, calculateDistance, createBackendMetadataAdapter, createFetchWithRetry, createLogger, createProvider, extractErrorMessage, fetchWithRetry, filterByChannel, filterGlobalOnly, geocodeAddress, getBackendProviderId, getCapabilityDescription, getChannelScope, isBackendCapabilities, isGlobalEntity, isProviderType, isScopedToChannel, moneyToNumber, moneyToNumberSafe, numberToMoney, partitionByChannel, planFulfillment, transformFulfillmentOption, transformInventoryLevel, transformStockLocation, transformStorefrontConfig, validateAssignedBy, validateChannelId, validateChannelScopeAssignment, validateEntityId, validatePaymentId };
3143
+ export { AdminAuthService, type AdminSession, AdminSessionService, BIGCOMMERCE_CAPABILITIES, type BackendMapping, type BackendMetadataAdapter, type BackendMetadataAdapterConfig, BigCommerceProvider, type BigCommerceProviderConfig, CHANNEL_ASSIGNED_AT_KEY, CHANNEL_ASSIGNED_BY_KEY, CHANNEL_SCOPE_KEY, type CartCompletionCapable, type CartCompletionError, type CartCompletionResult, type ChannelScopeMetadata, ChannelScopeValidationError, type ChannelScopeable, CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, type CircuitBreakerStats, type CircuitState, CommerceError, ConfigurationError, type Coordinates, type FulfillmentGroup, type FulfillmentPlan, type LogLevel, type Logger, MAGENTO_CAPABILITIES, MEDUSA_CAPABILITIES, MOCK_CAPABILITIES, MOCK_SALES_CHANNEL_ID, MagentoProvider, type MagentoProviderConfig, MedusaMetadataAdapter, MedusaProvider, type MedusaProviderConfig, type MetricsOrderInput, type MetricsProductInput, MetricsService, MockProvider, type MockProviderConfig, PROVIDER_METADATA, type PlanFulfillmentShippingAddress, ProviderAPIError, type ProviderFactoryConfig, ProviderNotFoundError, type ProviderType, ResourceNotFoundError, type RetryConfig, SHOPIFY_CAPABILITIES, SPREE_CAPABILITIES, STELORDER_CAPABILITIES, ShopifyProvider, type ShopifyProviderConfig, SpreeProvider, type SpreeProviderConfig, StelOrderProvider, type StelOrderProviderConfig, StorefrontConfigError, SupportedProviderType, type UICartItem, type UICartTotals, type UIDiscountCode, type UIPaymentMethod, type UIShippingMethod, WOOCOMMERCE_CAPABILITIES, WooCommerceProvider, type WooCommerceProviderConfig, assertEntityBelongsToChannel, backendCircuitBreaker, buildChannelScopeMetadata, calculateDistance, createBackendMetadataAdapter, createFetchWithRetry, createLogger, createProvider, extractErrorMessage, fetchWithRetry, filterByChannel, filterGlobalOnly, geocodeAddress, getBackendProviderId, getCapabilityDescription, getChannelScope, getProviderMetadata, isBackendCapabilities, isGlobalEntity, isProviderType, isScopedToChannel, isSupportedProviderType, moneyToNumber, moneyToNumberSafe, numberToMoney, partitionByChannel, planFulfillment, transformFulfillmentOption, transformInventoryLevel, transformStockLocation, transformStorefrontConfig, validateAssignedBy, validateChannelId, validateChannelScopeAssignment, validateEntityId, validatePaymentId };