@thorprovider/adapters 4.0.1 → 4.2.0

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.mjs CHANGED
@@ -4,6 +4,31 @@ import {
4
4
  } from "@thorprovider/types";
5
5
 
6
6
  // src/types/capabilities.types.ts
7
+ var MOCK_CAPABILITIES = {
8
+ updateProfile: false,
9
+ updateEmail: false,
10
+ changePasswordDirect: false,
11
+ changePasswordViaEmail: false,
12
+ deleteAccount: false,
13
+ uploadAvatar: false,
14
+ avatarViaMetadata: false,
15
+ customAttributes: false,
16
+ fetchOrders: true,
17
+ cancelOrder: true,
18
+ manageAddresses: false,
19
+ defaultAddress: false,
20
+ applyDiscounts: true,
21
+ shippingCalculation: true,
22
+ guestCheckout: true,
23
+ savedPaymentMethods: false,
24
+ listPaymentProviders: true,
25
+ regionSpecificPayments: true,
26
+ wishlist: false,
27
+ advancedSearch: false,
28
+ facetedFilters: false,
29
+ productReviews: false,
30
+ loyaltyProgram: false
31
+ };
7
32
  var MEDUSA_CAPABILITIES = {
8
33
  // Profile Management
9
34
  updateProfile: true,
@@ -7952,6 +7977,1011 @@ var MagentoProvider = class {
7952
7977
  }
7953
7978
  };
7954
7979
 
7980
+ // src/providers/mock/mock.ts
7981
+ var FIXTURE_TIMESTAMP = "2026-01-01T00:00:00.000Z";
7982
+ var DEFAULT_SITE_URL = "https://mock.thorcommerce.local";
7983
+ var regionFixtures = [
7984
+ {
7985
+ id: "mock-region-us",
7986
+ name: "United States",
7987
+ currencyCode: "USD",
7988
+ locale: "en-US",
7989
+ taxRate: 0.08,
7990
+ countries: [{ code: "US", name: "United States" }]
7991
+ },
7992
+ {
7993
+ id: "mock-region-eu",
7994
+ name: "Europe",
7995
+ currencyCode: "EUR",
7996
+ locale: "en-ES",
7997
+ taxRate: 0.21,
7998
+ countries: [
7999
+ { code: "ES", name: "Spain" },
8000
+ { code: "FR", name: "France" },
8001
+ { code: "DE", name: "Germany" }
8002
+ ]
8003
+ }
8004
+ ];
8005
+ var collectionFixtures = [
8006
+ {
8007
+ id: "mock-collection-new-arrivals",
8008
+ handle: "new-arrivals",
8009
+ title: "New Arrivals",
8010
+ description: "Fresh mock catalog items for layout and merchandising flows."
8011
+ },
8012
+ {
8013
+ id: "mock-collection-best-sellers",
8014
+ handle: "best-sellers",
8015
+ title: "Best Sellers",
8016
+ description: "High-performing mock products used to design hero grids and featured sections."
8017
+ },
8018
+ {
8019
+ id: "mock-collection-studio-essentials",
8020
+ handle: "studio-essentials",
8021
+ title: "Studio Essentials",
8022
+ description: "A balanced fixture set for mock storefront navigation and detail pages."
8023
+ }
8024
+ ];
8025
+ var categoryFixtures = [
8026
+ {
8027
+ id: "mock-category-jackets",
8028
+ handle: "jackets",
8029
+ name: "Jackets",
8030
+ description: "Outerwear and layering pieces."
8031
+ },
8032
+ {
8033
+ id: "mock-category-dresses",
8034
+ handle: "dresses",
8035
+ name: "Dresses",
8036
+ description: "Editorial silhouettes for seasonal collections."
8037
+ },
8038
+ {
8039
+ id: "mock-category-home",
8040
+ handle: "home",
8041
+ name: "Home",
8042
+ description: "Decor and living objects for lifestyle layouts."
8043
+ },
8044
+ {
8045
+ id: "mock-category-accessories",
8046
+ handle: "accessories",
8047
+ name: "Accessories",
8048
+ description: "Complementary products for cart and bundle flows."
8049
+ }
8050
+ ];
8051
+ var productFixtures = [
8052
+ {
8053
+ id: "mock-product-aurora-jacket",
8054
+ handle: "aurora-jacket",
8055
+ title: "Aurora Quilted Jacket",
8056
+ description: "Lightweight quilted outerwear with tonal hardware and a soft structured collar.",
8057
+ imageLabel: "Aurora Jacket",
8058
+ imageHue: 222,
8059
+ collectionHandles: ["new-arrivals", "best-sellers"],
8060
+ categoryHandle: "jackets",
8061
+ productType: "outerwear",
8062
+ vendor: "Thor Atelier",
8063
+ tags: ["outerwear", "quilted", "winter"],
8064
+ options: [
8065
+ { id: "aurora-size", name: "Size", values: ["S", "M", "L"] },
8066
+ { id: "aurora-color", name: "Color", values: ["Midnight"] }
8067
+ ],
8068
+ variants: [
8069
+ {
8070
+ id: "mock-variant-aurora-s",
8071
+ title: "S / Midnight",
8072
+ price: 129,
8073
+ compareAtPrice: 159,
8074
+ quantityAvailable: 8,
8075
+ selectedOptions: [
8076
+ { name: "Size", value: "S" },
8077
+ { name: "Color", value: "Midnight" }
8078
+ ]
8079
+ },
8080
+ {
8081
+ id: "mock-variant-aurora-m",
8082
+ title: "M / Midnight",
8083
+ price: 129,
8084
+ compareAtPrice: 159,
8085
+ quantityAvailable: 12,
8086
+ selectedOptions: [
8087
+ { name: "Size", value: "M" },
8088
+ { name: "Color", value: "Midnight" }
8089
+ ]
8090
+ }
8091
+ ]
8092
+ },
8093
+ {
8094
+ id: "mock-product-solis-dress",
8095
+ handle: "solis-dress",
8096
+ title: "Solis Pleated Dress",
8097
+ description: "A fluid pleated dress with a clean neckline designed for hero storytelling.",
8098
+ imageLabel: "Solis Dress",
8099
+ imageHue: 18,
8100
+ collectionHandles: ["new-arrivals", "studio-essentials"],
8101
+ categoryHandle: "dresses",
8102
+ productType: "dress",
8103
+ vendor: "Thor Atelier",
8104
+ tags: ["dress", "occasion", "pleated"],
8105
+ options: [
8106
+ { id: "solis-size", name: "Size", values: ["XS", "S", "M"] },
8107
+ { id: "solis-color", name: "Color", values: ["Clay"] }
8108
+ ],
8109
+ variants: [
8110
+ {
8111
+ id: "mock-variant-solis-xs",
8112
+ title: "XS / Clay",
8113
+ price: 164,
8114
+ quantityAvailable: 4,
8115
+ selectedOptions: [
8116
+ { name: "Size", value: "XS" },
8117
+ { name: "Color", value: "Clay" }
8118
+ ]
8119
+ },
8120
+ {
8121
+ id: "mock-variant-solis-s",
8122
+ title: "S / Clay",
8123
+ price: 164,
8124
+ quantityAvailable: 9,
8125
+ selectedOptions: [
8126
+ { name: "Size", value: "S" },
8127
+ { name: "Color", value: "Clay" }
8128
+ ]
8129
+ }
8130
+ ]
8131
+ },
8132
+ {
8133
+ id: "mock-product-helios-lamp",
8134
+ handle: "helios-lamp",
8135
+ title: "Helios Table Lamp",
8136
+ description: "Warm ambient lamp with sculptural proportions for lifestyle and home grids.",
8137
+ imageLabel: "Helios Lamp",
8138
+ imageHue: 45,
8139
+ collectionHandles: ["best-sellers", "studio-essentials"],
8140
+ categoryHandle: "home",
8141
+ productType: "lighting",
8142
+ vendor: "Thor Home",
8143
+ tags: ["home", "lighting", "decor"],
8144
+ options: [{ id: "helios-finish", name: "Finish", values: ["Brass"] }],
8145
+ variants: [
8146
+ {
8147
+ id: "mock-variant-helios-brass",
8148
+ title: "Brass",
8149
+ price: 96,
8150
+ quantityAvailable: 15,
8151
+ selectedOptions: [{ name: "Finish", value: "Brass" }]
8152
+ }
8153
+ ]
8154
+ },
8155
+ {
8156
+ id: "mock-product-luna-bag",
8157
+ handle: "luna-bag",
8158
+ title: "Luna Crossbody Bag",
8159
+ description: "Compact everyday bag for accessory rails, checkout add-ons, and bundle modules.",
8160
+ imageLabel: "Luna Bag",
8161
+ imageHue: 306,
8162
+ collectionHandles: ["studio-essentials"],
8163
+ categoryHandle: "accessories",
8164
+ productType: "bag",
8165
+ vendor: "Thor Atelier",
8166
+ tags: ["bag", "accessory", "everyday"],
8167
+ options: [{ id: "luna-color", name: "Color", values: ["Berry"] }],
8168
+ variants: [
8169
+ {
8170
+ id: "mock-variant-luna-berry",
8171
+ title: "Berry",
8172
+ price: 82,
8173
+ quantityAvailable: 18,
8174
+ selectedOptions: [{ name: "Color", value: "Berry" }]
8175
+ }
8176
+ ]
8177
+ }
8178
+ ];
8179
+ var stockLocationFixture = {
8180
+ id: "mock-stock-primary",
8181
+ name: "Mock Main Warehouse",
8182
+ address: {
8183
+ address1: "100 Mock Avenue",
8184
+ city: "Design City",
8185
+ countryCode: "US",
8186
+ postalCode: "10001",
8187
+ province: "NY"
8188
+ },
8189
+ metadata: {
8190
+ timezone: "America/New_York"
8191
+ }
8192
+ };
8193
+ var cartStore = /* @__PURE__ */ new Map();
8194
+ var orderStore = /* @__PURE__ */ new Map();
8195
+ var sequence = 0;
8196
+ function nextId(prefix) {
8197
+ sequence += 1;
8198
+ return `${prefix}-${sequence}`;
8199
+ }
8200
+ function createMoney(amount, currencyCode) {
8201
+ return {
8202
+ amount: amount.toFixed(2),
8203
+ currencyCode
8204
+ };
8205
+ }
8206
+ function createImage(label, hue) {
8207
+ const svg = `
8208
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200" role="img" aria-label="${label}">
8209
+ <defs>
8210
+ <linearGradient id="g" x1="0" x2="1" y1="0" y2="1">
8211
+ <stop offset="0%" stop-color="hsl(${hue}, 72%, 72%)" />
8212
+ <stop offset="100%" stop-color="hsl(${(hue + 48) % 360}, 62%, 42%)" />
8213
+ </linearGradient>
8214
+ </defs>
8215
+ <rect width="1200" height="1200" fill="url(#g)" rx="48" />
8216
+ <circle cx="910" cy="280" r="180" fill="rgba(255,255,255,0.22)" />
8217
+ <text x="90" y="990" fill="white" font-family="Arial, sans-serif" font-size="96" font-weight="700">${label}</text>
8218
+ </svg>
8219
+ `.trim();
8220
+ return {
8221
+ url: `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(svg)}`,
8222
+ altText: label,
8223
+ width: 1200,
8224
+ height: 1200
8225
+ };
8226
+ }
8227
+ function getRegionFixture(regionId) {
8228
+ if (!regionId) {
8229
+ return regionFixtures[0];
8230
+ }
8231
+ return regionFixtures.find((region) => region.id === regionId) ?? regionFixtures[0];
8232
+ }
8233
+ function createProductImageSet(label, hue) {
8234
+ const featuredImage = createImage(label, hue);
8235
+ return {
8236
+ featuredImage,
8237
+ images: [featuredImage, createImage(`${label} Detail`, (hue + 18) % 360)]
8238
+ };
8239
+ }
8240
+ function buildCollections() {
8241
+ return collectionFixtures.map((collection) => ({
8242
+ id: collection.id,
8243
+ handle: collection.handle,
8244
+ title: collection.title,
8245
+ description: collection.description,
8246
+ path: `/collections/${collection.handle}`,
8247
+ updatedAt: FIXTURE_TIMESTAMP
8248
+ }));
8249
+ }
8250
+ function buildCategories() {
8251
+ return categoryFixtures.map((category) => ({
8252
+ id: category.id,
8253
+ handle: category.handle,
8254
+ name: category.name,
8255
+ description: category.description,
8256
+ parentCategoryId: category.parentCategoryId,
8257
+ productCount: productFixtures.filter((product) => product.categoryHandle === category.handle).length,
8258
+ image: createImage(category.name, 180).url
8259
+ }));
8260
+ }
8261
+ function buildProducts(currencyCode) {
8262
+ const collections = buildCollections();
8263
+ return productFixtures.map((product) => {
8264
+ const { featuredImage, images } = createProductImageSet(product.imageLabel, product.imageHue);
8265
+ const variants = product.variants.map((variant) => ({
8266
+ id: variant.id,
8267
+ title: variant.title,
8268
+ availableForSale: variant.quantityAvailable > 0,
8269
+ selectedOptions: variant.selectedOptions,
8270
+ price: createMoney(variant.price, currencyCode),
8271
+ compareAtPrice: variant.compareAtPrice ? createMoney(variant.compareAtPrice, currencyCode) : void 0,
8272
+ quantityAvailable: variant.quantityAvailable,
8273
+ image: featuredImage
8274
+ }));
8275
+ const prices = product.variants.map((variant) => variant.price);
8276
+ return {
8277
+ id: product.id,
8278
+ handle: product.handle,
8279
+ title: product.title,
8280
+ description: product.description,
8281
+ availableForSale: variants.some((variant) => variant.availableForSale),
8282
+ options: product.options,
8283
+ variants,
8284
+ featuredImage,
8285
+ images,
8286
+ priceRange: {
8287
+ minVariantPrice: createMoney(Math.min(...prices), currencyCode),
8288
+ maxVariantPrice: createMoney(Math.max(...prices), currencyCode)
8289
+ },
8290
+ collections: product.collectionHandles.map((handle) => collections.find((collection) => collection.handle === handle)).filter((collection) => Boolean(collection)).map((collection) => ({
8291
+ id: collection.id,
8292
+ title: collection.title,
8293
+ handle: collection.handle
8294
+ })),
8295
+ productType: product.productType,
8296
+ vendor: product.vendor,
8297
+ tags: product.tags,
8298
+ createdAt: FIXTURE_TIMESTAMP,
8299
+ updatedAt: FIXTURE_TIMESTAMP,
8300
+ metadata: {
8301
+ categoryHandle: product.categoryHandle,
8302
+ collectionHandles: product.collectionHandles
8303
+ }
8304
+ };
8305
+ });
8306
+ }
8307
+ function filterProducts(products, options) {
8308
+ const query = options.query?.trim().toLowerCase();
8309
+ const categoryIds = new Set(options.categoryIds ?? []);
8310
+ const collectionIds = new Set(options.collectionIds ?? []);
8311
+ return products.filter((product) => {
8312
+ if (query) {
8313
+ const matchesQuery = [product.title, product.description, ...product.tags ?? []].join(" ").toLowerCase().includes(query);
8314
+ if (!matchesQuery) {
8315
+ return false;
8316
+ }
8317
+ }
8318
+ if (categoryIds.size > 0) {
8319
+ const categoryHandle = String(product.metadata?.categoryHandle ?? "");
8320
+ const category = categoryFixtures.find((item) => item.handle === categoryHandle);
8321
+ const matchesCategory = category ? categoryIds.has(category.id) || categoryIds.has(category.handle) : false;
8322
+ if (!matchesCategory) {
8323
+ return false;
8324
+ }
8325
+ }
8326
+ if (collectionIds.size > 0) {
8327
+ const productCollections = (product.collections ?? []).map((collection) => collection.handle);
8328
+ const matchesCollection = (product.collections ?? []).some(
8329
+ (collection) => collectionIds.has(collection.id) || collectionIds.has(collection.handle)
8330
+ ) || productCollections.some((handle) => collectionIds.has(handle));
8331
+ if (!matchesCollection) {
8332
+ return false;
8333
+ }
8334
+ }
8335
+ return true;
8336
+ });
8337
+ }
8338
+ function sortProducts(products, sortKey, reverse) {
8339
+ const sorted = [...products];
8340
+ switch (sortKey) {
8341
+ case "price":
8342
+ case "price-asc":
8343
+ case "price-desc":
8344
+ sorted.sort(
8345
+ (left, right) => Number(left.priceRange.minVariantPrice.amount) - Number(right.priceRange.minVariantPrice.amount)
8346
+ );
8347
+ break;
8348
+ case "created_at":
8349
+ case "createdAt":
8350
+ case "newest":
8351
+ sorted.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
8352
+ break;
8353
+ case "title":
8354
+ case "name":
8355
+ default:
8356
+ sorted.sort((left, right) => left.title.localeCompare(right.title));
8357
+ break;
8358
+ }
8359
+ const shouldReverse = reverse || sortKey === "price-desc" || sortKey === "newest";
8360
+ return shouldReverse ? sorted.reverse() : sorted;
8361
+ }
8362
+ function paginateProducts(products, skip, first) {
8363
+ const start = Math.max(0, skip ?? 0);
8364
+ const end = first ? start + first : void 0;
8365
+ return products.slice(start, end);
8366
+ }
8367
+ function resolveVariant(currencyCode, merchandiseId) {
8368
+ const products = buildProducts(currencyCode);
8369
+ for (const product of products) {
8370
+ const variant = product.variants.find((item) => item.id === merchandiseId);
8371
+ if (variant) {
8372
+ return { product, variant };
8373
+ }
8374
+ }
8375
+ return void 0;
8376
+ }
8377
+ function getShippingPrice(methodId) {
8378
+ switch (methodId) {
8379
+ case "mock-shipping-express":
8380
+ return 18;
8381
+ case "mock-shipping-standard":
8382
+ return 8;
8383
+ default:
8384
+ return 0;
8385
+ }
8386
+ }
8387
+ function buildExternalCart(state, currencyCode, siteUrl) {
8388
+ const region = getRegionFixture(state.regionId);
8389
+ const regionCurrency = region.currencyCode || currencyCode;
8390
+ const lines = state.lines.flatMap((line) => {
8391
+ const resolved = resolveVariant(regionCurrency, line.merchandiseId);
8392
+ if (!resolved || !resolved.product.featuredImage) {
8393
+ return [];
8394
+ }
8395
+ const lineTotal = Number(resolved.variant.price.amount) * line.quantity;
8396
+ const stockStatus = resolved.variant.quantityAvailable && resolved.variant.quantityAvailable > 0 ? "in_stock" : "out_of_stock";
8397
+ return [{
8398
+ id: line.id,
8399
+ quantity: line.quantity,
8400
+ stockStatus,
8401
+ cost: {
8402
+ totalAmount: createMoney(lineTotal, regionCurrency)
8403
+ },
8404
+ merchandise: {
8405
+ id: resolved.variant.id,
8406
+ title: resolved.variant.title,
8407
+ selectedOptions: resolved.variant.selectedOptions,
8408
+ product: {
8409
+ id: resolved.product.id,
8410
+ handle: resolved.product.handle,
8411
+ title: resolved.product.title,
8412
+ featuredImage: resolved.product.featuredImage
8413
+ }
8414
+ }
8415
+ }];
8416
+ });
8417
+ const subtotal = lines.reduce(
8418
+ (sum, line) => sum + Number(line.cost.totalAmount.amount),
8419
+ 0
8420
+ );
8421
+ const shipping = getShippingPrice(state.shippingMethodId);
8422
+ const discount = state.discountCode ? subtotal * 0.1 : 0;
8423
+ const taxableBase = Math.max(subtotal + shipping - discount, 0);
8424
+ const totalTax = region.taxRate ? taxableBase * region.taxRate : 0;
8425
+ const total = taxableBase + totalTax;
8426
+ return {
8427
+ id: state.id,
8428
+ checkoutUrl: `${siteUrl}/checkout?cart=${state.id}`,
8429
+ cost: {
8430
+ subtotalAmount: createMoney(subtotal, regionCurrency),
8431
+ totalAmount: createMoney(total, regionCurrency),
8432
+ totalTaxAmount: createMoney(totalTax, regionCurrency)
8433
+ },
8434
+ lines,
8435
+ totalQuantity: lines.reduce((sum, line) => sum + line.quantity, 0),
8436
+ completedAt: state.completedAt
8437
+ };
8438
+ }
8439
+ function buildOrderFromCart(state, currencyCode, siteUrl) {
8440
+ const cart = buildExternalCart(state, currencyCode, siteUrl);
8441
+ return {
8442
+ id: `mock-order-${state.id}`,
8443
+ orderNumber: `${1e3 + sequence}`,
8444
+ email: "mock-customer@thorprovider.dev",
8445
+ status: "completed",
8446
+ paymentStatus: state.paymentProviderId ? "paid" : "pending",
8447
+ fulfillmentStatus: state.shippingMethodId ? "fulfilled" : "unfulfilled",
8448
+ items: cart.lines.map((line) => ({
8449
+ id: line.id ?? nextId("mock-order-line"),
8450
+ title: line.merchandise.product.title,
8451
+ variantTitle: line.merchandise.title,
8452
+ quantity: line.quantity,
8453
+ price: line.merchandise.product.featuredImage ? createMoney(Number(line.cost.totalAmount.amount) / Math.max(line.quantity, 1), cart.cost.totalAmount.currencyCode) : createMoney(0, cart.cost.totalAmount.currencyCode),
8454
+ total: line.cost.totalAmount,
8455
+ productId: line.merchandise.product.id,
8456
+ variantId: line.merchandise.id,
8457
+ image: line.merchandise.product.featuredImage
8458
+ })),
8459
+ subtotal: cart.cost.subtotalAmount,
8460
+ total: cart.cost.totalAmount,
8461
+ tax: cart.cost.totalTaxAmount,
8462
+ shipping: createMoney(getShippingPrice(state.shippingMethodId), cart.cost.totalAmount.currencyCode),
8463
+ discount: createMoney(state.discountCode ? Number(cart.cost.subtotalAmount.amount) * 0.1 : 0, cart.cost.totalAmount.currencyCode),
8464
+ createdAt: FIXTURE_TIMESTAMP,
8465
+ updatedAt: FIXTURE_TIMESTAMP,
8466
+ completedAt: state.completedAt,
8467
+ metadata: {
8468
+ provider: "mock",
8469
+ checkoutUrl: cart.checkoutUrl
8470
+ }
8471
+ };
8472
+ }
8473
+ function getMockCollections() {
8474
+ return buildCollections();
8475
+ }
8476
+ function getMockCategories() {
8477
+ return buildCategories();
8478
+ }
8479
+ function getMockProducts(options) {
8480
+ const region = getRegionFixture(options?.regionId);
8481
+ const currencyCode = options?.currencyCode ?? region.currencyCode;
8482
+ const products = buildProducts(currencyCode);
8483
+ const filtered = filterProducts(products, {
8484
+ query: options?.query,
8485
+ categoryIds: options?.categoryIds,
8486
+ collectionIds: options?.collectionIds
8487
+ });
8488
+ const sorted = sortProducts(filtered, options?.sortKey, options?.reverse);
8489
+ return paginateProducts(sorted, options?.skip, options?.first);
8490
+ }
8491
+ function getMockProduct(handle, regionId) {
8492
+ const region = getRegionFixture(regionId);
8493
+ return buildProducts(region.currencyCode).find(
8494
+ (product) => product.handle === handle || product.id === handle
8495
+ );
8496
+ }
8497
+ function getMockProductRecommendations(productId, regionId) {
8498
+ const product = getMockProduct(productId, regionId) ?? buildProducts(getRegionFixture(regionId).currencyCode).find((item) => item.id === productId);
8499
+ if (!product) {
8500
+ return [];
8501
+ }
8502
+ const collectionHandles = new Set((product.collections ?? []).map((collection) => collection.handle));
8503
+ return buildProducts(getRegionFixture(regionId).currencyCode).filter((candidate) => candidate.id !== product.id).filter(
8504
+ (candidate) => (candidate.collections ?? []).some((collection) => collectionHandles.has(collection.handle))
8505
+ ).slice(0, 4);
8506
+ }
8507
+ function getMockCollection(handle) {
8508
+ return buildCollections().find(
8509
+ (collection) => collection.handle === handle || collection.id === handle
8510
+ );
8511
+ }
8512
+ function getMockCategory(idOrHandle) {
8513
+ return buildCategories().find(
8514
+ (category) => category.handle === idOrHandle || category.id === idOrHandle
8515
+ );
8516
+ }
8517
+ function getMockRegions() {
8518
+ return regionFixtures.map((region) => ({
8519
+ id: region.id,
8520
+ name: region.name,
8521
+ currency_code: region.currencyCode,
8522
+ countries: region.countries.map((country) => ({
8523
+ id: `country-${country.code.toLowerCase()}`,
8524
+ iso_2: country.code.toLowerCase(),
8525
+ name: country.name,
8526
+ display_name: country.name
8527
+ }))
8528
+ }));
8529
+ }
8530
+ function getMockAdminRegions() {
8531
+ return regionFixtures.map((region) => ({
8532
+ id: region.id,
8533
+ name: region.name,
8534
+ countryCodes: region.countries.map((country) => country.code),
8535
+ currency: region.currencyCode,
8536
+ taxRate: region.taxRate,
8537
+ isEnabled: true
8538
+ }));
8539
+ }
8540
+ function getMockRegionCountries(regionId) {
8541
+ const region = regionFixtures.find((item) => item.id === regionId);
8542
+ return region?.countries ?? [];
8543
+ }
8544
+ function createMockCart(regionId) {
8545
+ const cart = {
8546
+ id: nextId("mock-cart"),
8547
+ regionId: regionId ?? regionFixtures[0].id,
8548
+ lines: []
8549
+ };
8550
+ cartStore.set(cart.id, cart);
8551
+ return cart;
8552
+ }
8553
+ function getMockCartState(cartId) {
8554
+ return cartStore.get(cartId);
8555
+ }
8556
+ function saveMockCartState(cart) {
8557
+ cartStore.set(cart.id, cart);
8558
+ return cart;
8559
+ }
8560
+ function buildMockCart(cart, currencyCode, siteUrl) {
8561
+ return buildExternalCart(
8562
+ cart,
8563
+ currencyCode ?? getRegionFixture(cart.regionId).currencyCode,
8564
+ siteUrl ?? DEFAULT_SITE_URL
8565
+ );
8566
+ }
8567
+ function getMockShippingMethods(regionId) {
8568
+ const currencyCode = getRegionFixture(regionId).currencyCode;
8569
+ return [
8570
+ {
8571
+ id: "mock-shipping-standard",
8572
+ name: "Standard Shipping",
8573
+ description: "Fixture shipping option for checkout and cart layouts.",
8574
+ price: createMoney(8, currencyCode),
8575
+ estimatedDays: "3-5 business days"
8576
+ },
8577
+ {
8578
+ id: "mock-shipping-express",
8579
+ name: "Express Shipping",
8580
+ description: "Faster fixture shipping option for premium checkout flows.",
8581
+ price: createMoney(18, currencyCode),
8582
+ estimatedDays: "1-2 business days"
8583
+ }
8584
+ ];
8585
+ }
8586
+ function getMockPaymentMethods(currencyCode) {
8587
+ return [
8588
+ {
8589
+ id: "mock-card",
8590
+ name: "Mock Card",
8591
+ type: "card",
8592
+ isEnabled: true,
8593
+ requiresSetup: true,
8594
+ description: `Fixture card checkout for ${currencyCode}.`
8595
+ },
8596
+ {
8597
+ id: "mock-cash",
8598
+ name: "Cash on Delivery",
8599
+ type: "cash_on_delivery",
8600
+ isEnabled: true,
8601
+ requiresSetup: false,
8602
+ description: "Mock cash payment option for checkout prototypes."
8603
+ }
8604
+ ];
8605
+ }
8606
+ function getMockStockLocations() {
8607
+ return [stockLocationFixture];
8608
+ }
8609
+ function getMockInventoryLevels(variantId) {
8610
+ for (const region of regionFixtures) {
8611
+ const resolved = resolveVariant(region.currencyCode, variantId);
8612
+ if (resolved) {
8613
+ return [{
8614
+ locationId: stockLocationFixture.id,
8615
+ locationName: stockLocationFixture.name,
8616
+ availableQuantity: resolved.variant.quantityAvailable ?? 0,
8617
+ reservedQuantity: 0,
8618
+ stockedQuantity: resolved.variant.quantityAvailable ?? 0
8619
+ }];
8620
+ }
8621
+ }
8622
+ return [];
8623
+ }
8624
+ function validateMockCartStock(cart) {
8625
+ const currencyCode = getRegionFixture(cart.regionId).currencyCode;
8626
+ const unavailableItems = cart.lines.flatMap((line) => {
8627
+ const resolved = resolveVariant(currencyCode, line.merchandiseId);
8628
+ if (!resolved) {
8629
+ return [];
8630
+ }
8631
+ const availableQuantity = resolved.variant.quantityAvailable ?? 0;
8632
+ if (line.quantity <= availableQuantity) {
8633
+ return [];
8634
+ }
8635
+ return [{
8636
+ variantId: resolved.variant.id,
8637
+ productName: resolved.product.title,
8638
+ requestedQuantity: line.quantity,
8639
+ availableQuantity
8640
+ }];
8641
+ });
8642
+ return {
8643
+ allAvailable: unavailableItems.length === 0,
8644
+ unavailableItems
8645
+ };
8646
+ }
8647
+ function getMockFulfillmentOptions(regionId) {
8648
+ return getMockShippingMethods(regionId).map((method) => ({
8649
+ id: method.id,
8650
+ providerId: "mock-fulfillment",
8651
+ name: method.name,
8652
+ description: method.description,
8653
+ price: method.price,
8654
+ estimatedDays: method.estimatedDays,
8655
+ stockLocation: stockLocationFixture
8656
+ }));
8657
+ }
8658
+ function completeMockCheckout(cart, currencyCode, siteUrl) {
8659
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
8660
+ const nextCart = {
8661
+ ...cart,
8662
+ completedAt
8663
+ };
8664
+ cartStore.set(nextCart.id, nextCart);
8665
+ const order = buildOrderFromCart(
8666
+ nextCart,
8667
+ currencyCode ?? getRegionFixture(nextCart.regionId).currencyCode,
8668
+ siteUrl ?? DEFAULT_SITE_URL
8669
+ );
8670
+ orderStore.set(order.id, order);
8671
+ return order;
8672
+ }
8673
+ function getMockAdminOrders() {
8674
+ const orders = Array.from(orderStore.values()).sort(
8675
+ (left, right) => right.createdAt.localeCompare(left.createdAt)
8676
+ );
8677
+ return {
8678
+ orders,
8679
+ count: orders.length
8680
+ };
8681
+ }
8682
+ function getMockOrder(orderId) {
8683
+ return orderStore.get(orderId);
8684
+ }
8685
+ function saveMockOrder(order) {
8686
+ orderStore.set(order.id, order);
8687
+ return order;
8688
+ }
8689
+
8690
+ // src/providers/mock/index.ts
8691
+ var MockProvider = class {
8692
+ name = "mock";
8693
+ version = "1.0.0";
8694
+ capabilities = MOCK_CAPABILITIES;
8695
+ isMock = true;
8696
+ currencyCode;
8697
+ siteUrl;
8698
+ constructor(config = {}) {
8699
+ this.currencyCode = config.currencyCode ?? "USD";
8700
+ this.siteUrl = config.siteUrl ?? "https://mock.thorcommerce.local";
8701
+ }
8702
+ hasVariant(merchandiseId, regionId) {
8703
+ return getMockProducts({
8704
+ currencyCode: this.currencyCode,
8705
+ regionId
8706
+ }).some(
8707
+ (product) => product.variants.some((variant) => variant.id === merchandiseId)
8708
+ );
8709
+ }
8710
+ async getProduct(handle, options) {
8711
+ return getMockProduct(handle, options?.regionId);
8712
+ }
8713
+ async getProducts(options) {
8714
+ return getMockProducts({
8715
+ currencyCode: this.currencyCode,
8716
+ query: options?.query,
8717
+ sortKey: options?.sortKey,
8718
+ reverse: options?.reverse,
8719
+ first: options?.first,
8720
+ skip: options?.skip,
8721
+ categoryIds: options?.categoryIds,
8722
+ collectionIds: options?.collectionIds,
8723
+ regionId: options?.regionId
8724
+ });
8725
+ }
8726
+ async getProductRecommendations(productId) {
8727
+ return getMockProductRecommendations(productId);
8728
+ }
8729
+ async getCollection(handle) {
8730
+ return getMockCollection(handle);
8731
+ }
8732
+ async getCollections(options) {
8733
+ const collections = getMockCollections();
8734
+ const query = options?.query?.trim().toLowerCase();
8735
+ const filtered = query ? collections.filter(
8736
+ (collection) => [collection.title, collection.description, collection.handle].join(" ").toLowerCase().includes(query)
8737
+ ) : collections;
8738
+ return filtered.slice(0, options?.limit ?? filtered.length);
8739
+ }
8740
+ async getCollectionProducts(handle, options) {
8741
+ const collection = getMockCollection(handle);
8742
+ if (!collection) {
8743
+ return [];
8744
+ }
8745
+ return getMockProducts({
8746
+ currencyCode: this.currencyCode,
8747
+ collectionIds: [collection.id],
8748
+ sortKey: options?.sortKey,
8749
+ reverse: options?.reverse,
8750
+ first: options?.first
8751
+ });
8752
+ }
8753
+ async getCategory(idOrHandle) {
8754
+ return getMockCategory(idOrHandle);
8755
+ }
8756
+ async getCategories(options) {
8757
+ const categories = getMockCategories();
8758
+ const query = options?.query?.trim().toLowerCase();
8759
+ let filtered = query ? categories.filter(
8760
+ (category) => [category.name, category.description ?? "", category.handle].join(" ").toLowerCase().includes(query)
8761
+ ) : categories;
8762
+ if (options?.parentCategoryId) {
8763
+ filtered = filtered.filter((category) => category.parentCategoryId === options.parentCategoryId);
8764
+ }
8765
+ return filtered.slice(0, options?.limit ?? filtered.length);
8766
+ }
8767
+ async getCategoryProducts(handle, options) {
8768
+ const category = getMockCategory(handle);
8769
+ if (!category) {
8770
+ return [];
8771
+ }
8772
+ return getMockProducts({
8773
+ currencyCode: this.currencyCode,
8774
+ categoryIds: [category.id],
8775
+ sortKey: options?.sortKey,
8776
+ reverse: options?.reverse,
8777
+ first: options?.first
8778
+ });
8779
+ }
8780
+ async createCart(options) {
8781
+ const cart = createMockCart(options?.regionId);
8782
+ return buildMockCart(cart, this.currencyCode, this.siteUrl);
8783
+ }
8784
+ async getCart(cartId) {
8785
+ const cart = getMockCartState(cartId);
8786
+ return cart ? buildMockCart(cart, this.currencyCode, this.siteUrl) : void 0;
8787
+ }
8788
+ async addToCart(cartId, lines) {
8789
+ const cart = getMockCartState(cartId);
8790
+ if (!cart) {
8791
+ throw new ResourceNotFoundError("cart", cartId);
8792
+ }
8793
+ for (const line of lines) {
8794
+ if (!this.hasVariant(line.merchandiseId, cart.regionId)) {
8795
+ throw new ResourceNotFoundError("variant", line.merchandiseId);
8796
+ }
8797
+ }
8798
+ const nextLines = [...cart.lines];
8799
+ for (const line of lines) {
8800
+ const existing = nextLines.find((item) => item.merchandiseId === line.merchandiseId);
8801
+ if (existing) {
8802
+ existing.quantity += line.quantity;
8803
+ } else {
8804
+ nextLines.push({
8805
+ id: `mock-line-${line.merchandiseId}`,
8806
+ merchandiseId: line.merchandiseId,
8807
+ quantity: line.quantity
8808
+ });
8809
+ }
8810
+ }
8811
+ const saved = saveMockCartState({ ...cart, lines: nextLines });
8812
+ return buildMockCart(saved, this.currencyCode, this.siteUrl);
8813
+ }
8814
+ async removeFromCart(cartId, lineIds) {
8815
+ const cart = getMockCartState(cartId);
8816
+ if (!cart) {
8817
+ throw new ResourceNotFoundError("cart", cartId);
8818
+ }
8819
+ const saved = saveMockCartState({
8820
+ ...cart,
8821
+ lines: cart.lines.filter((line) => !lineIds.includes(line.id))
8822
+ });
8823
+ return buildMockCart(saved, this.currencyCode, this.siteUrl);
8824
+ }
8825
+ async updateCart(cartId, lines) {
8826
+ const cart = getMockCartState(cartId);
8827
+ if (!cart) {
8828
+ throw new ResourceNotFoundError("cart", cartId);
8829
+ }
8830
+ for (const line of lines) {
8831
+ if (!this.hasVariant(line.merchandiseId, cart.regionId)) {
8832
+ throw new ResourceNotFoundError("variant", line.merchandiseId);
8833
+ }
8834
+ }
8835
+ const updates = new Map(lines.map((line) => [line.id, line]));
8836
+ const nextLines = cart.lines.map((line) => {
8837
+ const update = updates.get(line.id);
8838
+ if (!update) {
8839
+ return line;
8840
+ }
8841
+ return {
8842
+ ...line,
8843
+ merchandiseId: update.merchandiseId,
8844
+ quantity: update.quantity
8845
+ };
8846
+ }).filter((line) => line.quantity > 0);
8847
+ const saved = saveMockCartState({ ...cart, lines: nextLines });
8848
+ return buildMockCart(saved, this.currencyCode, this.siteUrl);
8849
+ }
8850
+ async getRegions() {
8851
+ return getMockRegions();
8852
+ }
8853
+ async completeCheckout(cartId) {
8854
+ const cart = getMockCartState(cartId);
8855
+ if (!cart) {
8856
+ throw new ResourceNotFoundError("cart", cartId);
8857
+ }
8858
+ const order = completeMockCheckout(cart, this.currencyCode, this.siteUrl);
8859
+ return order;
8860
+ }
8861
+ async getShippingMethods(cartId) {
8862
+ const cart = getMockCartState(cartId);
8863
+ return getMockShippingMethods(cart?.regionId);
8864
+ }
8865
+ async getRegionCountries(regionId) {
8866
+ return getMockRegionCountries(regionId);
8867
+ }
8868
+ async addShippingMethod(cartId, methodId) {
8869
+ const cart = getMockCartState(cartId);
8870
+ if (!cart) {
8871
+ throw new ResourceNotFoundError("cart", cartId);
8872
+ }
8873
+ const allowed = getMockShippingMethods(cart.regionId).some((method) => method.id === methodId);
8874
+ if (!allowed) {
8875
+ throw new ProviderAPIError(`Unknown mock shipping method: ${methodId}`, "mock", 400);
8876
+ }
8877
+ const saved = saveMockCartState({ ...cart, shippingMethodId: methodId });
8878
+ return buildMockCart(saved, this.currencyCode, this.siteUrl);
8879
+ }
8880
+ async initiatePaymentSession(cartId, providerId) {
8881
+ const cart = getMockCartState(cartId);
8882
+ if (!cart) {
8883
+ throw new ResourceNotFoundError("cart", cartId);
8884
+ }
8885
+ const allowed = getMockPaymentMethods(this.currencyCode).some((method) => method.id === providerId);
8886
+ if (!allowed) {
8887
+ throw new ProviderAPIError(`Unknown mock payment method: ${providerId}`, "mock", 400);
8888
+ }
8889
+ saveMockCartState({ ...cart, paymentProviderId: providerId });
8890
+ }
8891
+ async applyDiscountCode(cartId, code) {
8892
+ const cart = getMockCartState(cartId);
8893
+ if (!cart) {
8894
+ throw new ResourceNotFoundError("cart", cartId);
8895
+ }
8896
+ const normalized = code.trim();
8897
+ if (!normalized) {
8898
+ throw new ProviderAPIError("Discount code is required.", "mock", 400);
8899
+ }
8900
+ const saved = saveMockCartState({ ...cart, discountCode: normalized });
8901
+ return buildMockCart(saved, this.currencyCode, this.siteUrl);
8902
+ }
8903
+ async removeDiscountCode(cartId, _code) {
8904
+ const cart = getMockCartState(cartId);
8905
+ if (!cart) {
8906
+ throw new ResourceNotFoundError("cart", cartId);
8907
+ }
8908
+ const saved = saveMockCartState({ ...cart, discountCode: void 0 });
8909
+ return buildMockCart(saved, this.currencyCode, this.siteUrl);
8910
+ }
8911
+ async getOrders(_options) {
8912
+ return getMockAdminOrders().orders;
8913
+ }
8914
+ async getPaymentMethods(options) {
8915
+ return getMockPaymentMethods(options.currencyCode ?? this.currencyCode);
8916
+ }
8917
+ async getStockLocations() {
8918
+ return getMockStockLocations();
8919
+ }
8920
+ async checkInventoryLevels(variantId) {
8921
+ return getMockInventoryLevels(variantId);
8922
+ }
8923
+ async validateCartStock(cartId) {
8924
+ const cart = getMockCartState(cartId);
8925
+ if (!cart) {
8926
+ throw new ResourceNotFoundError("cart", cartId);
8927
+ }
8928
+ return validateMockCartStock(cart);
8929
+ }
8930
+ async getFulfillmentOptions(cartId, _salesChannelId) {
8931
+ const cart = getMockCartState(cartId);
8932
+ return getMockFulfillmentOptions(cart?.regionId);
8933
+ }
8934
+ async cancelOrder(orderId) {
8935
+ const order = getMockOrder(orderId);
8936
+ if (!order) {
8937
+ throw new ResourceNotFoundError("order", orderId);
8938
+ }
8939
+ return saveMockOrder({
8940
+ ...order,
8941
+ status: "cancelled",
8942
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
8943
+ cancelledAt: (/* @__PURE__ */ new Date()).toISOString()
8944
+ });
8945
+ }
8946
+ async createFulfillment(_orderId, _items) {
8947
+ return;
8948
+ }
8949
+ async createRefund(orderId, _amount, _reason) {
8950
+ const order = getMockOrder(orderId);
8951
+ if (!order) {
8952
+ throw new ResourceNotFoundError("order", orderId);
8953
+ }
8954
+ saveMockOrder({
8955
+ ...order,
8956
+ status: "refunded",
8957
+ paymentStatus: "refunded",
8958
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
8959
+ });
8960
+ }
8961
+ async getAdminOrders() {
8962
+ return getMockAdminOrders();
8963
+ }
8964
+ async getAdminRegions() {
8965
+ return getMockAdminRegions();
8966
+ }
8967
+ async getStorefrontContext() {
8968
+ return {
8969
+ id: "mock-storefront",
8970
+ name: "Mock Storefront",
8971
+ platformType: "mock",
8972
+ requiresProductScoping: false,
8973
+ currencyCode: this.currencyCode,
8974
+ locale: "en-US",
8975
+ metadata: {
8976
+ mode: "design"
8977
+ }
8978
+ };
8979
+ }
8980
+ isStorefrontRequired() {
8981
+ return false;
8982
+ }
8983
+ };
8984
+
7955
8985
  // src/factory/index.ts
7956
8986
  function createProvider(options) {
7957
8987
  if (!options || !options.provider) {
@@ -7962,6 +8992,8 @@ function createProvider(options) {
7962
8992
  }
7963
8993
  const config = options.config;
7964
8994
  switch (options.provider) {
8995
+ case "mock":
8996
+ return new MockProvider(config);
7965
8997
  case "medusa":
7966
8998
  return new MedusaProvider(config);
7967
8999
  case "shopify":
@@ -7996,10 +9028,12 @@ export {
7996
9028
  ConfigurationError,
7997
9029
  MAGENTO_CAPABILITIES,
7998
9030
  MEDUSA_CAPABILITIES,
9031
+ MOCK_CAPABILITIES,
7999
9032
  MagentoProvider,
8000
9033
  MedusaMetadataAdapter,
8001
9034
  MedusaProvider,
8002
9035
  MetricsService,
9036
+ MockProvider,
8003
9037
  ProviderAPIError,
8004
9038
  ProviderNotFoundError,
8005
9039
  ResourceNotFoundError,