@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.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,
|