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