@faststore/api 1.10.4 → 1.10.17
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 +30 -0
- package/dist/api.cjs.development.js +102 -4
- 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 +102 -4
- package/dist/api.esm.js.map +1 -1
- package/dist/platforms/vtex/clients/commerce/index.d.ts +13 -0
- package/dist/platforms/vtex/clients/commerce/types/Product.d.ts +174 -0
- package/dist/platforms/vtex/clients/commerce/types/SalesChannel.d.ts +24 -0
- package/dist/platforms/vtex/clients/index.d.ts +8 -0
- package/dist/platforms/vtex/loaders/index.d.ts +1 -0
- package/dist/platforms/vtex/loaders/salesChannel.d.ts +5 -0
- package/dist/platforms/vtex/resolvers/query.d.ts +3 -3
- package/dist/platforms/vtex/utils/facets.d.ts +14 -0
- package/package.json +3 -3
- package/src/platforms/vtex/clients/commerce/index.ts +27 -1
- package/src/platforms/vtex/clients/commerce/types/Product.ts +199 -0
- package/src/platforms/vtex/clients/commerce/types/SalesChannel.ts +25 -0
- package/src/platforms/vtex/loaders/index.ts +3 -0
- package/src/platforms/vtex/loaders/salesChannel.ts +15 -0
- package/src/platforms/vtex/resolvers/aggregateOffer.ts +10 -1
- package/src/platforms/vtex/resolvers/offer.ts +10 -1
- package/src/platforms/vtex/resolvers/query.ts +39 -14
- package/src/platforms/vtex/utils/facets.ts +41 -0
package/dist/api.esm.js
CHANGED
|
@@ -32,6 +32,7 @@ const VtexCommerce = ({
|
|
|
32
32
|
const base = `https://${account}.${environment}.com.br`;
|
|
33
33
|
return {
|
|
34
34
|
catalog: {
|
|
35
|
+
salesChannel: sc => fetchAPI(`${base}/api/catalog_system/pub/saleschannel/${sc}`),
|
|
35
36
|
brand: {
|
|
36
37
|
list: () => fetchAPI(`${base}/api/catalog_system/pub/brand/list`)
|
|
37
38
|
},
|
|
@@ -40,6 +41,19 @@ const VtexCommerce = ({
|
|
|
40
41
|
},
|
|
41
42
|
portal: {
|
|
42
43
|
pagetype: slug => fetchAPI(`${base}/api/catalog_system/pub/portal/pagetype/${slug}`)
|
|
44
|
+
},
|
|
45
|
+
products: {
|
|
46
|
+
crossselling: ({
|
|
47
|
+
type,
|
|
48
|
+
productId,
|
|
49
|
+
groupByProduct = true
|
|
50
|
+
}) => {
|
|
51
|
+
const params = new URLSearchParams({
|
|
52
|
+
sc: ctx.storage.channel.salesChannel,
|
|
53
|
+
groupByProduct: groupByProduct.toString()
|
|
54
|
+
});
|
|
55
|
+
return fetchAPI(`${base}/api/catalog_system/pub/products/crossselling/${type}/${productId}?${params}`);
|
|
56
|
+
}
|
|
43
57
|
}
|
|
44
58
|
},
|
|
45
59
|
checkout: {
|
|
@@ -309,6 +323,12 @@ const getClients = (options, ctx) => {
|
|
|
309
323
|
};
|
|
310
324
|
};
|
|
311
325
|
|
|
326
|
+
const getSalesChannelLoader = (_, clients) => {
|
|
327
|
+
const loader = async channels => Promise.all(channels.map(sc => clients.commerce.catalog.salesChannel(sc)));
|
|
328
|
+
|
|
329
|
+
return new DataLoader(loader);
|
|
330
|
+
};
|
|
331
|
+
|
|
312
332
|
const CONCURRENT_REQUESTS_MAX = 1;
|
|
313
333
|
const getSimulationLoader = (_, clients) => {
|
|
314
334
|
const limit = pLimit(CONCURRENT_REQUESTS_MAX);
|
|
@@ -446,10 +466,12 @@ const getLoaders = (options, {
|
|
|
446
466
|
const skuLoader = getSkuLoader(options, clients);
|
|
447
467
|
const simulationLoader = getSimulationLoader(options, clients);
|
|
448
468
|
const collectionLoader = getCollectionLoader(options, clients);
|
|
469
|
+
const salesChannelLoader = getSalesChannelLoader(options, clients);
|
|
449
470
|
return {
|
|
450
471
|
skuLoader,
|
|
451
472
|
simulationLoader,
|
|
452
|
-
collectionLoader
|
|
473
|
+
collectionLoader,
|
|
474
|
+
salesChannelLoader
|
|
453
475
|
};
|
|
454
476
|
};
|
|
455
477
|
|
|
@@ -490,7 +512,20 @@ const StoreAggregateOffer = {
|
|
|
490
512
|
return lowOffer ? price(lowOffer) : 0;
|
|
491
513
|
},
|
|
492
514
|
offerCount: offers => offers.length,
|
|
493
|
-
priceCurrency: () =>
|
|
515
|
+
priceCurrency: async (_, __, ctx) => {
|
|
516
|
+
var _sc$CurrencyCode;
|
|
517
|
+
|
|
518
|
+
const {
|
|
519
|
+
loaders: {
|
|
520
|
+
salesChannelLoader
|
|
521
|
+
},
|
|
522
|
+
storage: {
|
|
523
|
+
channel
|
|
524
|
+
}
|
|
525
|
+
} = ctx;
|
|
526
|
+
const sc = await salesChannelLoader.load(channel.salesChannel);
|
|
527
|
+
return (_sc$CurrencyCode = sc.CurrencyCode) != null ? _sc$CurrencyCode : '';
|
|
528
|
+
},
|
|
494
529
|
offers: offers => offers
|
|
495
530
|
};
|
|
496
531
|
|
|
@@ -637,6 +672,14 @@ class ChannelMarshal {
|
|
|
637
672
|
|
|
638
673
|
}
|
|
639
674
|
|
|
675
|
+
const FACET_CROSS_SELLING_MAP = {
|
|
676
|
+
buy: "whoboughtalsobought",
|
|
677
|
+
view: "whosawalsosaw",
|
|
678
|
+
similars: "similars",
|
|
679
|
+
viewAndBought: "whosawalsobought",
|
|
680
|
+
accessories: "accessories",
|
|
681
|
+
suggestions: "suggestions"
|
|
682
|
+
};
|
|
640
683
|
/**
|
|
641
684
|
* Transform facets from the store to VTEX platform facets.
|
|
642
685
|
* For instance, the channel in Store becomes trade-policy and regionId in VTEX's realm
|
|
@@ -678,6 +721,16 @@ const transformSelectedFacet = ({
|
|
|
678
721
|
};
|
|
679
722
|
}
|
|
680
723
|
|
|
724
|
+
case "buy":
|
|
725
|
+
case "view":
|
|
726
|
+
case "similars":
|
|
727
|
+
case "viewAndBought":
|
|
728
|
+
case "accessories":
|
|
729
|
+
case "suggestions":
|
|
730
|
+
{
|
|
731
|
+
return []; // remove this facet from search
|
|
732
|
+
}
|
|
733
|
+
|
|
681
734
|
default:
|
|
682
735
|
return {
|
|
683
736
|
key,
|
|
@@ -694,6 +747,18 @@ const parseRange = range => {
|
|
|
694
747
|
|
|
695
748
|
return splitted;
|
|
696
749
|
};
|
|
750
|
+
const isCrossSelling = x => typeof FACET_CROSS_SELLING_MAP[x] === "string";
|
|
751
|
+
const findCrossSelling = facets => {
|
|
752
|
+
var _filtered$;
|
|
753
|
+
|
|
754
|
+
const filtered = facets == null ? void 0 : facets.filter(x => isCrossSelling(x.key));
|
|
755
|
+
|
|
756
|
+
if (Array.isArray(filtered) && filtered.length > 1) {
|
|
757
|
+
throw new BadRequestError(`You passed ${filtered.length} cross selling facets but only one is allowed. Please leave one of the following facet: ${filtered.map(x => x.key).join(',')}`);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
return (_filtered$ = filtered == null ? void 0 : filtered[0]) != null ? _filtered$ : null;
|
|
761
|
+
};
|
|
697
762
|
const findSlug = facets => {
|
|
698
763
|
var _facets$find$value, _facets$find;
|
|
699
764
|
|
|
@@ -1155,7 +1220,20 @@ const isSearchItem = item => 'Price' in item && 'seller' in item && 'product' in
|
|
|
1155
1220
|
const isOrderFormItem = item => 'skuName' in item;
|
|
1156
1221
|
|
|
1157
1222
|
const StoreOffer = {
|
|
1158
|
-
priceCurrency: () =>
|
|
1223
|
+
priceCurrency: async (_, __, ctx) => {
|
|
1224
|
+
var _sc$CurrencyCode;
|
|
1225
|
+
|
|
1226
|
+
const {
|
|
1227
|
+
loaders: {
|
|
1228
|
+
salesChannelLoader
|
|
1229
|
+
},
|
|
1230
|
+
storage: {
|
|
1231
|
+
channel
|
|
1232
|
+
}
|
|
1233
|
+
} = ctx;
|
|
1234
|
+
const sc = await salesChannelLoader.load(channel.salesChannel);
|
|
1235
|
+
return (_sc$CurrencyCode = sc.CurrencyCode) != null ? _sc$CurrencyCode : '';
|
|
1236
|
+
},
|
|
1159
1237
|
priceValidUntil: root => {
|
|
1160
1238
|
if (isSearchItem(root)) {
|
|
1161
1239
|
var _root$PriceValidUntil;
|
|
@@ -1561,6 +1639,7 @@ const Query = {
|
|
|
1561
1639
|
// Insert channel in context for later usage
|
|
1562
1640
|
const channel = findChannel(selectedFacets);
|
|
1563
1641
|
const locale = findLocale(selectedFacets);
|
|
1642
|
+
const crossSelling = findCrossSelling(selectedFacets);
|
|
1564
1643
|
|
|
1565
1644
|
if (channel) {
|
|
1566
1645
|
mutateChannelContext(ctx, channel);
|
|
@@ -1570,11 +1649,30 @@ const Query = {
|
|
|
1570
1649
|
mutateLocaleContext(ctx, locale);
|
|
1571
1650
|
}
|
|
1572
1651
|
|
|
1652
|
+
let query = term;
|
|
1653
|
+
/**
|
|
1654
|
+
* In case we are using crossSelling, we need to modify the search
|
|
1655
|
+
* we will be performing on our search engine. The idea in here
|
|
1656
|
+
* is to use the cross selling API for fetching the productIds our
|
|
1657
|
+
* search will return for us.
|
|
1658
|
+
* Doing this two request workflow makes it possible to have cross
|
|
1659
|
+
* selling with Search features, like pagination, internationalization
|
|
1660
|
+
* etc
|
|
1661
|
+
*/
|
|
1662
|
+
|
|
1663
|
+
if (crossSelling) {
|
|
1664
|
+
const products = await ctx.clients.commerce.catalog.products.crossselling({
|
|
1665
|
+
type: FACET_CROSS_SELLING_MAP[crossSelling.key],
|
|
1666
|
+
productId: crossSelling.value
|
|
1667
|
+
});
|
|
1668
|
+
query = `product:${products.map(x => x.productId).slice(0, first).join(";")}`;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1573
1671
|
const after = maybeAfter ? Number(maybeAfter) : 0;
|
|
1574
1672
|
const searchArgs = {
|
|
1575
1673
|
page: Math.ceil(after / first),
|
|
1576
1674
|
count: first,
|
|
1577
|
-
query
|
|
1675
|
+
query,
|
|
1578
1676
|
sort: SORT_MAP[sort != null ? sort : 'score_desc'],
|
|
1579
1677
|
selectedFacets: (_selectedFacets$flatM = selectedFacets == null ? void 0 : selectedFacets.flatMap(transformSelectedFacet)) != null ? _selectedFacets$flatM : []
|
|
1580
1678
|
};
|