@faststore/api 1.9.6 → 1.9.7
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/CHANGELOG.md +11 -0
- package/dist/api.cjs.development.js +113 -34
- package/dist/api.cjs.development.js.map +1 -1
- package/dist/api.cjs.production.min.js +1 -1
- package/dist/api.cjs.production.min.js.map +1 -1
- package/dist/api.esm.js +113 -34
- package/dist/api.esm.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/platforms/vtex/clients/commerce/types/Portal.d.ts +1 -1
- package/dist/platforms/vtex/index.d.ts +5 -4
- package/dist/platforms/vtex/loaders/index.d.ts +1 -1
- package/dist/platforms/vtex/loaders/sku.d.ts +1 -2
- package/dist/platforms/vtex/resolvers/mutation.d.ts +3 -3
- package/dist/platforms/vtex/resolvers/offer.d.ts +1 -1
- package/dist/platforms/vtex/resolvers/seo.d.ts +1 -0
- package/dist/platforms/vtex/resolvers/validateCart.d.ts +3 -3
- package/dist/platforms/vtex/utils/canonical.d.ts +2 -0
- package/dist/platforms/vtex/utils/facets.d.ts +2 -0
- package/dist/platforms/vtex/utils/orderStatistics.d.ts +4 -0
- package/dist/platforms/vtex/utils/sku.d.ts +8 -0
- package/package.json +2 -2
- package/src/platforms/vtex/clients/commerce/index.ts +1 -1
- package/src/platforms/vtex/clients/commerce/types/Portal.ts +1 -1
- package/src/platforms/vtex/loaders/sku.ts +3 -16
- package/src/platforms/vtex/resolvers/offer.ts +6 -3
- package/src/platforms/vtex/resolvers/product.ts +6 -4
- package/src/platforms/vtex/resolvers/query.ts +44 -1
- package/src/platforms/vtex/resolvers/seo.ts +2 -2
- package/src/platforms/vtex/resolvers/validateCart.ts +3 -3
- package/src/platforms/vtex/utils/canonical.ts +3 -0
- package/src/platforms/vtex/utils/facets.ts +6 -0
- package/src/platforms/vtex/utils/orderStatistics.ts +16 -0
- package/src/platforms/vtex/utils/sku.ts +26 -0
package/dist/api.esm.js
CHANGED
|
@@ -386,18 +386,7 @@ const isBadRequestError = error => {
|
|
|
386
386
|
};
|
|
387
387
|
|
|
388
388
|
const getSkuLoader = (_, clients) => {
|
|
389
|
-
const loader = async
|
|
390
|
-
const skuIds = facetsList.map(facets => {
|
|
391
|
-
const maybeFacet = facets.find(({
|
|
392
|
-
key
|
|
393
|
-
}) => key === 'id');
|
|
394
|
-
|
|
395
|
-
if (!maybeFacet) {
|
|
396
|
-
throw new BadRequestError('Error while loading SKU. Needs to pass an id to selected facets');
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return maybeFacet.value;
|
|
400
|
-
});
|
|
389
|
+
const loader = async skuIds => {
|
|
401
390
|
const {
|
|
402
391
|
products
|
|
403
392
|
} = await clients.search.products({
|
|
@@ -740,15 +729,12 @@ const equals = (storeOrder, orderForm) => {
|
|
|
740
729
|
return isSameOrder && orderItemsAreSync;
|
|
741
730
|
};
|
|
742
731
|
|
|
743
|
-
const orderFormToCart = (form, skuLoader) => {
|
|
732
|
+
const orderFormToCart = async (form, skuLoader) => {
|
|
744
733
|
return {
|
|
745
734
|
order: {
|
|
746
735
|
orderNumber: form.orderFormId,
|
|
747
|
-
acceptedOffer: form.items.map(item => ({ ...item,
|
|
748
|
-
product: skuLoader.load(
|
|
749
|
-
key: 'id',
|
|
750
|
-
value: item.id
|
|
751
|
-
}])
|
|
736
|
+
acceptedOffer: form.items.map(async item => ({ ...item,
|
|
737
|
+
product: await skuLoader.load(item.id)
|
|
752
738
|
}))
|
|
753
739
|
},
|
|
754
740
|
messages: form.messages.map(({
|
|
@@ -1056,13 +1042,13 @@ const StoreOffer = {
|
|
|
1056
1042
|
|
|
1057
1043
|
return null;
|
|
1058
1044
|
},
|
|
1059
|
-
itemOffered:
|
|
1045
|
+
itemOffered: root => {
|
|
1060
1046
|
if (isSearchItem(root)) {
|
|
1061
1047
|
return root.product;
|
|
1062
1048
|
}
|
|
1063
1049
|
|
|
1064
1050
|
if (isOrderFormItem(root)) {
|
|
1065
|
-
return { ...
|
|
1051
|
+
return { ...root.product,
|
|
1066
1052
|
attachmentsValues: root.attachments
|
|
1067
1053
|
};
|
|
1068
1054
|
}
|
|
@@ -1084,6 +1070,10 @@ const StoreOffer = {
|
|
|
1084
1070
|
}
|
|
1085
1071
|
};
|
|
1086
1072
|
|
|
1073
|
+
const canonicalFromProduct = ({
|
|
1074
|
+
linkText
|
|
1075
|
+
}) => `/${linkText}/p`;
|
|
1076
|
+
|
|
1087
1077
|
const enhanceCommercialOffer = ({
|
|
1088
1078
|
offer,
|
|
1089
1079
|
seller,
|
|
@@ -1124,13 +1114,11 @@ const StoreProduct = {
|
|
|
1124
1114
|
}
|
|
1125
1115
|
}) => description,
|
|
1126
1116
|
seo: ({
|
|
1127
|
-
isVariantOf
|
|
1128
|
-
description,
|
|
1129
|
-
productName
|
|
1130
|
-
}
|
|
1117
|
+
isVariantOf
|
|
1131
1118
|
}) => ({
|
|
1132
|
-
title: productName,
|
|
1133
|
-
description
|
|
1119
|
+
title: isVariantOf.productName,
|
|
1120
|
+
description: isVariantOf.description,
|
|
1121
|
+
canonical: canonicalFromProduct(isVariantOf)
|
|
1134
1122
|
}),
|
|
1135
1123
|
brand: ({
|
|
1136
1124
|
isVariantOf: {
|
|
@@ -1190,7 +1178,7 @@ const StoreProduct = {
|
|
|
1190
1178
|
},
|
|
1191
1179
|
review: () => [],
|
|
1192
1180
|
aggregateRating: () => ({}),
|
|
1193
|
-
offers: root => root.sellers.
|
|
1181
|
+
offers: root => root.sellers.map(seller => enhanceCommercialOffer({
|
|
1194
1182
|
offer: seller.commertialOffer,
|
|
1195
1183
|
seller,
|
|
1196
1184
|
product: root
|
|
@@ -1288,15 +1276,25 @@ const transformSelectedFacet = ({
|
|
|
1288
1276
|
};
|
|
1289
1277
|
}
|
|
1290
1278
|
};
|
|
1291
|
-
const
|
|
1279
|
+
const findSlug = facets => {
|
|
1292
1280
|
var _facets$find$value, _facets$find;
|
|
1293
1281
|
|
|
1294
|
-
return (_facets$find$value = facets == null ? void 0 : (_facets$find = facets.find(x => x.key === '
|
|
1282
|
+
return (_facets$find$value = facets == null ? void 0 : (_facets$find = facets.find(x => x.key === 'slug')) == null ? void 0 : _facets$find.value) != null ? _facets$find$value : null;
|
|
1295
1283
|
};
|
|
1296
|
-
const
|
|
1284
|
+
const findSkuId = facets => {
|
|
1297
1285
|
var _facets$find$value2, _facets$find2;
|
|
1298
1286
|
|
|
1299
|
-
return (_facets$find$value2 = facets == null ? void 0 : (_facets$find2 = facets.find(
|
|
1287
|
+
return (_facets$find$value2 = facets == null ? void 0 : (_facets$find2 = facets.find(x => x.key === 'id')) == null ? void 0 : _facets$find2.value) != null ? _facets$find$value2 : null;
|
|
1288
|
+
};
|
|
1289
|
+
const findLocale = facets => {
|
|
1290
|
+
var _facets$find$value3, _facets$find3;
|
|
1291
|
+
|
|
1292
|
+
return (_facets$find$value3 = facets == null ? void 0 : (_facets$find3 = facets.find(x => x.key === 'locale')) == null ? void 0 : _facets$find3.value) != null ? _facets$find$value3 : null;
|
|
1293
|
+
};
|
|
1294
|
+
const findChannel = facets => {
|
|
1295
|
+
var _facets$find$value4, _facets$find4;
|
|
1296
|
+
|
|
1297
|
+
return (_facets$find$value4 = facets == null ? void 0 : (_facets$find4 = facets.find(facet => facet.key === 'channel')) == null ? void 0 : _facets$find4.value) != null ? _facets$find$value4 : null;
|
|
1300
1298
|
};
|
|
1301
1299
|
|
|
1302
1300
|
const SORT_MAP = {
|
|
@@ -1310,6 +1308,42 @@ const SORT_MAP = {
|
|
|
1310
1308
|
score_desc: ''
|
|
1311
1309
|
};
|
|
1312
1310
|
|
|
1311
|
+
/**
|
|
1312
|
+
* More info at: https://en.wikipedia.org/wiki/Order_statistic
|
|
1313
|
+
*/
|
|
1314
|
+
// O(n) search to find the max of an array
|
|
1315
|
+
const min = (array, cmp) => {
|
|
1316
|
+
let best = 0;
|
|
1317
|
+
|
|
1318
|
+
for (let curr = 1; curr < array.length; curr++) {
|
|
1319
|
+
if (cmp(array[best], array[curr]) > 0) {
|
|
1320
|
+
best = curr;
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
return array[best];
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1327
|
+
/**
|
|
1328
|
+
* This function implements Portal heuristics for returning the best sku for a product.
|
|
1329
|
+
*
|
|
1330
|
+
* The best sku is the one with the best (cheapest available) offer
|
|
1331
|
+
* */
|
|
1332
|
+
|
|
1333
|
+
const pickBestSku = skus => {
|
|
1334
|
+
const offersBySku = skus.flatMap(sku => sku.sellers.map(seller => ({
|
|
1335
|
+
offer: seller.commertialOffer,
|
|
1336
|
+
sku
|
|
1337
|
+
})));
|
|
1338
|
+
const best = min(offersBySku, ({
|
|
1339
|
+
offer: o1
|
|
1340
|
+
}, {
|
|
1341
|
+
offer: o2
|
|
1342
|
+
}) => bestOfferFirst(o1, o2));
|
|
1343
|
+
return best.sku;
|
|
1344
|
+
};
|
|
1345
|
+
const isValidSkuId = skuId => skuId !== '' && !Number.isNaN(Number(skuId));
|
|
1346
|
+
|
|
1313
1347
|
const Query = {
|
|
1314
1348
|
product: async (_, {
|
|
1315
1349
|
locator
|
|
@@ -1317,6 +1351,8 @@ const Query = {
|
|
|
1317
1351
|
// Insert channel in context for later usage
|
|
1318
1352
|
const channel = findChannel(locator);
|
|
1319
1353
|
const locale = findLocale(locator);
|
|
1354
|
+
const id = findSkuId(locator);
|
|
1355
|
+
const slug = findSlug(locator);
|
|
1320
1356
|
|
|
1321
1357
|
if (channel) {
|
|
1322
1358
|
mutateChannelContext(ctx, channel);
|
|
@@ -1329,9 +1365,50 @@ const Query = {
|
|
|
1329
1365
|
const {
|
|
1330
1366
|
loaders: {
|
|
1331
1367
|
skuLoader
|
|
1368
|
+
},
|
|
1369
|
+
clients: {
|
|
1370
|
+
commerce,
|
|
1371
|
+
search
|
|
1332
1372
|
}
|
|
1333
1373
|
} = ctx;
|
|
1334
|
-
|
|
1374
|
+
|
|
1375
|
+
try {
|
|
1376
|
+
var _ref;
|
|
1377
|
+
|
|
1378
|
+
const skuId = (_ref = id != null ? id : slug == null ? void 0 : slug.split('-').pop()) != null ? _ref : '';
|
|
1379
|
+
|
|
1380
|
+
if (!isValidSkuId(skuId)) {
|
|
1381
|
+
throw new Error('Invalid SkuId');
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
const sku = await skuLoader.load(skuId);
|
|
1385
|
+
return sku;
|
|
1386
|
+
} catch (err) {
|
|
1387
|
+
if (slug == null) {
|
|
1388
|
+
throw new BadRequestError('Missing slug or id');
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
const route = await commerce.catalog.portal.pagetype(`${slug}/p`);
|
|
1392
|
+
|
|
1393
|
+
if (route.pageType !== 'Product' || !route.id) {
|
|
1394
|
+
throw new NotFoundError(`No product found for slug ${slug}`);
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
const {
|
|
1398
|
+
products: [product]
|
|
1399
|
+
} = await search.products({
|
|
1400
|
+
page: 0,
|
|
1401
|
+
count: 1,
|
|
1402
|
+
query: `product:${route.id}`
|
|
1403
|
+
});
|
|
1404
|
+
|
|
1405
|
+
if (!product) {
|
|
1406
|
+
throw new NotFoundError(`No product found for id ${route.id}`);
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
const sku = pickBestSku(product.items);
|
|
1410
|
+
return enhanceSku(sku, product);
|
|
1411
|
+
}
|
|
1335
1412
|
},
|
|
1336
1413
|
collection: (_, {
|
|
1337
1414
|
slug
|
|
@@ -1576,8 +1653,10 @@ const StoreSeo = {
|
|
|
1576
1653
|
description: ({
|
|
1577
1654
|
description
|
|
1578
1655
|
}) => description != null ? description : '',
|
|
1579
|
-
|
|
1580
|
-
|
|
1656
|
+
canonical: ({
|
|
1657
|
+
canonical
|
|
1658
|
+
}) => canonical != null ? canonical : '',
|
|
1659
|
+
titleTemplate: () => ''
|
|
1581
1660
|
};
|
|
1582
1661
|
|
|
1583
1662
|
const ObjectOrString = /*#__PURE__*/new GraphQLScalarType({
|