@faststore/api 1.7.30 → 1.7.33
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 +27 -0
- package/dist/api.cjs.development.js +313 -181
- 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 +313 -181
- package/dist/api.esm.js.map +1 -1
- package/dist/index.d.ts +27 -13
- package/dist/platforms/vtex/clients/index.d.ts +4 -1
- package/dist/platforms/vtex/clients/search/index.d.ts +3 -3
- package/dist/platforms/vtex/clients/search/types/AttributeSearchResult.d.ts +25 -51
- package/dist/platforms/vtex/clients/search/types/FacetSearchResult.d.ts +31 -0
- package/dist/platforms/vtex/clients/search/types/ProductSearchResult.d.ts +146 -154
- package/dist/platforms/vtex/clients/sp/index.d.ts +13 -0
- package/dist/platforms/vtex/index.d.ts +28 -14
- package/dist/platforms/vtex/resolvers/aggregateOffer.d.ts +10 -6
- package/dist/platforms/vtex/resolvers/facet.d.ts +2 -2
- package/dist/platforms/vtex/resolvers/facetValue.d.ts +2 -2
- package/dist/platforms/vtex/resolvers/offer.d.ts +7 -6
- package/dist/platforms/vtex/resolvers/product.d.ts +11 -2
- package/dist/platforms/vtex/resolvers/productGroup.d.ts +5 -2
- package/dist/platforms/vtex/utils/enhanceSku.d.ts +3 -3
- package/dist/platforms/vtex/utils/price.d.ts +2 -0
- package/dist/platforms/vtex/utils/productStock.d.ts +5 -0
- package/dist/typings/index.d.ts +2 -0
- package/package.json +2 -2
- package/src/platforms/vtex/clients/fetch.ts +1 -1
- package/src/platforms/vtex/clients/index.ts +3 -0
- package/src/platforms/vtex/clients/search/index.ts +6 -6
- package/src/platforms/vtex/clients/search/types/AttributeSearchResult.ts +24 -53
- package/src/platforms/vtex/clients/search/types/FacetSearchResult.ts +33 -0
- package/src/platforms/vtex/clients/search/types/ProductSearchResult.ts +135 -164
- package/src/platforms/vtex/clients/sp/index.ts +67 -0
- package/src/platforms/vtex/index.ts +2 -2
- package/src/platforms/vtex/loaders/sku.ts +2 -2
- package/src/platforms/vtex/resolvers/aggregateOffer.ts +17 -35
- package/src/platforms/vtex/resolvers/facet.ts +5 -5
- package/src/platforms/vtex/resolvers/facetValue.ts +7 -6
- package/src/platforms/vtex/resolvers/offer.ts +107 -17
- package/src/platforms/vtex/resolvers/product.ts +55 -73
- package/src/platforms/vtex/resolvers/productGroup.ts +22 -13
- package/src/platforms/vtex/resolvers/query.ts +3 -3
- package/src/platforms/vtex/resolvers/searchResult.ts +24 -12
- package/src/platforms/vtex/utils/enhanceSku.ts +4 -4
- package/src/platforms/vtex/utils/facets.ts +8 -2
- package/src/platforms/vtex/utils/price.ts +10 -0
- package/src/platforms/vtex/utils/productStock.ts +25 -0
- package/src/typings/index.ts +4 -0
|
@@ -15,7 +15,7 @@ const fetchAPI = async (info, init) => {
|
|
|
15
15
|
const response = await fetch(info, init);
|
|
16
16
|
|
|
17
17
|
if (response.ok) {
|
|
18
|
-
return response.json();
|
|
18
|
+
return response.status !== 204 ? response.json() : undefined;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
console.error(info, init, response);
|
|
@@ -112,7 +112,7 @@ const IntelligentSearch = ({
|
|
|
112
112
|
environment,
|
|
113
113
|
hideUnavailableItems
|
|
114
114
|
}, ctx) => {
|
|
115
|
-
const base = `
|
|
115
|
+
const base = `https://${account}.${environment}.com.br/api/io`;
|
|
116
116
|
const policyFacet = {
|
|
117
117
|
key: 'trade-policy',
|
|
118
118
|
value: ctx.storage.channel.salesChannel
|
|
@@ -148,14 +148,14 @@ const IntelligentSearch = ({
|
|
|
148
148
|
});
|
|
149
149
|
|
|
150
150
|
if (hideUnavailableItems !== undefined) {
|
|
151
|
-
params.append('
|
|
151
|
+
params.append('hideUnavailableItems', hideUnavailableItems.toString());
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
const pathname = addDefaultFacets(selectedFacets).map(({
|
|
155
155
|
key,
|
|
156
156
|
value
|
|
157
157
|
}) => `${key}/${value}`).join('/');
|
|
158
|
-
return fetchAPI(`${base}/api/
|
|
158
|
+
return fetchAPI(`${base}/_v/api/intelligent-search/${type}/${pathname}?${params.toString()}`);
|
|
159
159
|
};
|
|
160
160
|
|
|
161
161
|
const products = args => search({ ...args,
|
|
@@ -163,7 +163,7 @@ const IntelligentSearch = ({
|
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
const facets = args => search({ ...args,
|
|
166
|
-
type: '
|
|
166
|
+
type: 'facets'
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
return {
|
|
@@ -172,12 +172,66 @@ const IntelligentSearch = ({
|
|
|
172
172
|
};
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Client for SP, Intelligent search's analytics event API
|
|
177
|
+
* More info at: https://www.notion.so/vtexhandbook/Event-API-Documentation-48eee26730cf4d7f80f8fd7262231f84
|
|
178
|
+
*/
|
|
179
|
+
const THIRTY_MINUTES_S = 30 * 60;
|
|
180
|
+
const ONE_YEAR_S = 365 * 24 * 3600;
|
|
181
|
+
|
|
182
|
+
const randomUUID = () => (Math.random() * 1e6).toFixed(0);
|
|
183
|
+
|
|
184
|
+
const timelapsed = past => (Date.now() - past) / 1e3;
|
|
185
|
+
|
|
186
|
+
const createId = expiresSecond => {
|
|
187
|
+
let payload = randomUUID();
|
|
188
|
+
let createdAt = Date.now();
|
|
189
|
+
return () => {
|
|
190
|
+
if (timelapsed(createdAt) > expiresSecond) {
|
|
191
|
+
payload = randomUUID();
|
|
192
|
+
createdAt = Date.now();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return payload;
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const user = {
|
|
200
|
+
anonymous: /*#__PURE__*/createId(ONE_YEAR_S),
|
|
201
|
+
session: /*#__PURE__*/createId(THIRTY_MINUTES_S)
|
|
202
|
+
};
|
|
203
|
+
const SP = ({
|
|
204
|
+
account
|
|
205
|
+
}, _) => {
|
|
206
|
+
const base = `https://sp.vtex.com/event-api/v1/${account}/event`;
|
|
207
|
+
|
|
208
|
+
const sendEvent = options => {
|
|
209
|
+
return fetchAPI(base, {
|
|
210
|
+
method: 'POST',
|
|
211
|
+
body: JSON.stringify({ ...options,
|
|
212
|
+
agent: '@faststore/api',
|
|
213
|
+
anonymous: user.anonymous(),
|
|
214
|
+
session: user.session()
|
|
215
|
+
}),
|
|
216
|
+
headers: {
|
|
217
|
+
'content-type': 'application/json'
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
sendEvent
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
|
|
175
227
|
const getClients = (options, ctx) => {
|
|
176
228
|
const search = IntelligentSearch(options, ctx);
|
|
177
229
|
const commerce = VtexCommerce(options, ctx);
|
|
230
|
+
const sp = SP(options);
|
|
178
231
|
return {
|
|
179
232
|
search,
|
|
180
|
-
commerce
|
|
233
|
+
commerce,
|
|
234
|
+
sp
|
|
181
235
|
};
|
|
182
236
|
};
|
|
183
237
|
|
|
@@ -229,7 +283,7 @@ class NotFoundError extends Error {
|
|
|
229
283
|
|
|
230
284
|
}
|
|
231
285
|
|
|
232
|
-
const enhanceSku = (
|
|
286
|
+
const enhanceSku = (item, product) => ({ ...item,
|
|
233
287
|
isVariantOf: product
|
|
234
288
|
});
|
|
235
289
|
|
|
@@ -254,8 +308,8 @@ const getSkuLoader = (_, clients) => {
|
|
|
254
308
|
count: skuIds.length
|
|
255
309
|
});
|
|
256
310
|
const skuBySkuId = products.reduce((acc, product) => {
|
|
257
|
-
for (const sku of product.
|
|
258
|
-
acc[sku.
|
|
311
|
+
for (const sku of product.items) {
|
|
312
|
+
acc[sku.itemId] = enhanceSku(sku, product);
|
|
259
313
|
}
|
|
260
314
|
|
|
261
315
|
return acc;
|
|
@@ -312,38 +366,18 @@ const getLoaders = (options, {
|
|
|
312
366
|
};
|
|
313
367
|
};
|
|
314
368
|
|
|
315
|
-
const inStock = item => item.availability === 'available'; // Smallest Available Selling Price First
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const sortOfferByPrice = items => items.sort((a, b) => {
|
|
319
|
-
if (inStock(a) && !inStock(b)) {
|
|
320
|
-
return -1;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (!inStock(a) && inStock(b)) {
|
|
324
|
-
return 1;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
return a.sellingPrice - b.sellingPrice;
|
|
328
|
-
});
|
|
329
369
|
const StoreAggregateOffer = {
|
|
330
370
|
highPrice: ({
|
|
331
|
-
|
|
371
|
+
product
|
|
332
372
|
}) => {
|
|
333
|
-
var
|
|
373
|
+
var _product$isVariantOf$;
|
|
334
374
|
|
|
335
|
-
|
|
336
|
-
const highPrice = (_availableItems$pop = availableItems.pop()) == null ? void 0 : _availableItems$pop.sellingPrice;
|
|
337
|
-
return (highPrice != null ? highPrice : 0) / 1e2;
|
|
375
|
+
return (_product$isVariantOf$ = product.isVariantOf.priceRange.sellingPrice.highPrice) != null ? _product$isVariantOf$ : 0;
|
|
338
376
|
},
|
|
339
|
-
lowPrice:
|
|
340
|
-
|
|
341
|
-
}) => {
|
|
342
|
-
var _availableItems$;
|
|
377
|
+
lowPrice: root => {
|
|
378
|
+
var _root$product$isVaria;
|
|
343
379
|
|
|
344
|
-
|
|
345
|
-
const lowPrice = (_availableItems$ = availableItems[0]) == null ? void 0 : _availableItems$.sellingPrice;
|
|
346
|
-
return (lowPrice != null ? lowPrice : 0) / 1e2;
|
|
380
|
+
return (_root$product$isVaria = root.product.isVariantOf.priceRange.sellingPrice.lowPrice) != null ? _root$product$isVaria : 0;
|
|
347
381
|
},
|
|
348
382
|
offerCount: ({
|
|
349
383
|
items
|
|
@@ -481,33 +515,36 @@ const StoreCollection = {
|
|
|
481
515
|
const StoreFacet = {
|
|
482
516
|
key: ({
|
|
483
517
|
key
|
|
484
|
-
}) => key,
|
|
518
|
+
}) => key != null ? key : '',
|
|
485
519
|
label: ({
|
|
486
|
-
|
|
487
|
-
}) =>
|
|
520
|
+
name
|
|
521
|
+
}) => name != null ? name : 'unknown',
|
|
488
522
|
values: ({
|
|
489
523
|
values
|
|
490
524
|
}) => values,
|
|
491
525
|
type: ({
|
|
492
526
|
type
|
|
493
|
-
}) => type === '
|
|
527
|
+
}) => type === 'TEXT' ? 'BOOLEAN' : 'RANGE'
|
|
494
528
|
};
|
|
495
529
|
|
|
496
530
|
const StoreFacetValue = {
|
|
497
531
|
value: ({
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
532
|
+
value,
|
|
533
|
+
range
|
|
534
|
+
}) => {
|
|
535
|
+
var _range$from, _range$to;
|
|
536
|
+
|
|
537
|
+
return value != null ? value : `${(_range$from = range == null ? void 0 : range.from) != null ? _range$from : ''}-to-${(_range$to = range == null ? void 0 : range.to) != null ? _range$to : ''}`;
|
|
538
|
+
},
|
|
502
539
|
label: ({
|
|
503
|
-
|
|
504
|
-
}) =>
|
|
540
|
+
name
|
|
541
|
+
}) => name || 'unknown',
|
|
505
542
|
selected: ({
|
|
506
|
-
|
|
507
|
-
}) =>
|
|
543
|
+
selected
|
|
544
|
+
}) => selected,
|
|
508
545
|
quantity: ({
|
|
509
|
-
|
|
510
|
-
}) =>
|
|
546
|
+
quantity
|
|
547
|
+
}) => quantity
|
|
511
548
|
};
|
|
512
549
|
|
|
513
550
|
const getId = item => [item.itemOffered.sku, item.seller.identifier, item.price].join('::');
|
|
@@ -710,40 +747,132 @@ const Mutation = {
|
|
|
710
747
|
updateSession
|
|
711
748
|
};
|
|
712
749
|
|
|
750
|
+
const getItemPriceByKey = (item, key) => {
|
|
751
|
+
var _getFirstSeller$comme, _getFirstSeller;
|
|
752
|
+
|
|
753
|
+
return (_getFirstSeller$comme = (_getFirstSeller = getFirstSeller(item.sellers)) == null ? void 0 : _getFirstSeller.commertialOffer[key]) != null ? _getFirstSeller$comme : 0;
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
const inStock = item => item.sellers.find(seller => seller.commertialOffer.AvailableQuantity > 0);
|
|
757
|
+
const getFirstSeller = sellers => sellers[0]; // Smallest Available Selling Price First
|
|
758
|
+
|
|
759
|
+
const sortOfferByPrice = items => items.sort((a, b) => {
|
|
760
|
+
if (inStock(a) && !inStock(b)) {
|
|
761
|
+
return -1;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
if (!inStock(a) && inStock(b)) {
|
|
765
|
+
return 1;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
return getItemPriceByKey(a, 'Price') - getItemPriceByKey(b, 'Price');
|
|
769
|
+
});
|
|
770
|
+
const inStockOrderFormItem = availability => availability === 'available';
|
|
771
|
+
|
|
772
|
+
const isSearchItem = item => 'sellers' in item;
|
|
773
|
+
|
|
774
|
+
const isOrderFormItem = item => 'skuName' in item;
|
|
775
|
+
|
|
776
|
+
const getAvailability = available => available ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock';
|
|
777
|
+
|
|
713
778
|
const StoreOffer = {
|
|
714
779
|
priceCurrency: () => '',
|
|
715
|
-
priceValidUntil:
|
|
716
|
-
|
|
717
|
-
|
|
780
|
+
priceValidUntil: item => {
|
|
781
|
+
if (isSearchItem(item)) {
|
|
782
|
+
var _getFirstSeller$comme, _getFirstSeller;
|
|
783
|
+
|
|
784
|
+
return (_getFirstSeller$comme = (_getFirstSeller = getFirstSeller(item.sellers)) == null ? void 0 : _getFirstSeller.commertialOffer.PriceValidUntil) != null ? _getFirstSeller$comme : '';
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
if (isOrderFormItem(item)) {
|
|
788
|
+
var _item$priceValidUntil;
|
|
789
|
+
|
|
790
|
+
return (_item$priceValidUntil = item.priceValidUntil) != null ? _item$priceValidUntil : '';
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
return null;
|
|
794
|
+
},
|
|
718
795
|
itemCondition: () => 'https://schema.org/NewCondition',
|
|
719
|
-
availability:
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
796
|
+
availability: async item => {
|
|
797
|
+
if (isSearchItem(item)) {
|
|
798
|
+
return getAvailability(!!inStock(item));
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (isOrderFormItem(item)) {
|
|
802
|
+
return getAvailability(inStockOrderFormItem(item.availability));
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
return null;
|
|
806
|
+
},
|
|
807
|
+
seller: item => {
|
|
808
|
+
if (isSearchItem(item)) {
|
|
809
|
+
var _getFirstSeller$selle, _getFirstSeller2;
|
|
810
|
+
|
|
811
|
+
return {
|
|
812
|
+
identifier: (_getFirstSeller$selle = (_getFirstSeller2 = getFirstSeller(item.sellers)) == null ? void 0 : _getFirstSeller2.sellerId) != null ? _getFirstSeller$selle : ''
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
if (isOrderFormItem(item)) {
|
|
817
|
+
return {
|
|
818
|
+
identifier: item.seller
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
return null;
|
|
823
|
+
},
|
|
824
|
+
price: item => {
|
|
825
|
+
if (isSearchItem(item)) {
|
|
826
|
+
return getItemPriceByKey(item, 'spotPrice');
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (isOrderFormItem(item)) {
|
|
830
|
+
return item.price / 1e2;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
return null;
|
|
834
|
+
},
|
|
835
|
+
sellingPrice: item => {
|
|
836
|
+
if (isSearchItem(item)) {
|
|
837
|
+
return getItemPriceByKey(item, 'Price');
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (isOrderFormItem(item)) {
|
|
841
|
+
return item.sellingPrice / 1e2;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
return null;
|
|
845
|
+
},
|
|
846
|
+
listPrice: item => {
|
|
847
|
+
if (isSearchItem(item)) {
|
|
848
|
+
return getItemPriceByKey(item, 'ListPrice');
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
if (isOrderFormItem(item)) {
|
|
852
|
+
return item.listPrice / 1e2;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
return null;
|
|
856
|
+
},
|
|
736
857
|
itemOffered: ({
|
|
737
858
|
product
|
|
738
859
|
}) => product,
|
|
739
|
-
quantity:
|
|
740
|
-
|
|
741
|
-
|
|
860
|
+
quantity: item => {
|
|
861
|
+
if (isSearchItem(item)) {
|
|
862
|
+
return item.sellers.reduce((quantity, seller) => quantity + seller.commertialOffer.AvailableQuantity, 0);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
if (isOrderFormItem(item)) {
|
|
866
|
+
return item.quantity;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
return null;
|
|
870
|
+
}
|
|
742
871
|
};
|
|
743
872
|
|
|
744
873
|
const DEFAULT_IMAGE = {
|
|
745
|
-
|
|
746
|
-
|
|
874
|
+
imageText: 'image',
|
|
875
|
+
imageUrl: 'https://storecomponents.vtexassets.com/assets/faststore/images/image___117a6d3e229a96ad0e0d0876352566e2.svg'
|
|
747
876
|
};
|
|
748
877
|
|
|
749
878
|
const getSlug = (link, id) => `${link}-${id}`;
|
|
@@ -754,18 +883,18 @@ const nonEmptyArray = array => Array.isArray(array) && array.length > 0 ? array
|
|
|
754
883
|
|
|
755
884
|
const StoreProduct = {
|
|
756
885
|
productID: ({
|
|
757
|
-
|
|
758
|
-
}) =>
|
|
886
|
+
itemId
|
|
887
|
+
}) => itemId,
|
|
759
888
|
name: ({
|
|
760
889
|
isVariantOf,
|
|
761
890
|
name
|
|
762
|
-
}) => name != null ? name : isVariantOf.
|
|
891
|
+
}) => name != null ? name : isVariantOf.productName,
|
|
763
892
|
slug: ({
|
|
764
893
|
isVariantOf: {
|
|
765
|
-
|
|
894
|
+
linkText
|
|
766
895
|
},
|
|
767
|
-
|
|
768
|
-
}) => getSlug(
|
|
896
|
+
itemId
|
|
897
|
+
}) => getSlug(linkText, itemId),
|
|
769
898
|
description: ({
|
|
770
899
|
isVariantOf: {
|
|
771
900
|
description
|
|
@@ -773,11 +902,11 @@ const StoreProduct = {
|
|
|
773
902
|
}) => description,
|
|
774
903
|
seo: ({
|
|
775
904
|
isVariantOf: {
|
|
776
|
-
|
|
777
|
-
|
|
905
|
+
description,
|
|
906
|
+
productName
|
|
778
907
|
}
|
|
779
908
|
}) => ({
|
|
780
|
-
title:
|
|
909
|
+
title: productName,
|
|
781
910
|
description
|
|
782
911
|
}),
|
|
783
912
|
brand: ({
|
|
@@ -789,86 +918,61 @@ const StoreProduct = {
|
|
|
789
918
|
}),
|
|
790
919
|
breadcrumbList: ({
|
|
791
920
|
isVariantOf: {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
921
|
+
categories,
|
|
922
|
+
productName,
|
|
923
|
+
linkText
|
|
795
924
|
},
|
|
796
|
-
|
|
797
|
-
}) =>
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
925
|
+
itemId
|
|
926
|
+
}) => {
|
|
927
|
+
return {
|
|
928
|
+
itemListElement: [...categories.reverse().map((categoryPath, index) => {
|
|
929
|
+
const categoryNames = categoryPath.split('/');
|
|
930
|
+
return {
|
|
931
|
+
name: categoryNames[categoryNames.length - 2],
|
|
932
|
+
item: categoryPath.toLowerCase(),
|
|
933
|
+
position: index + 1
|
|
934
|
+
};
|
|
935
|
+
}), {
|
|
936
|
+
name: productName,
|
|
937
|
+
item: getPath(linkText, itemId),
|
|
938
|
+
position: categories.length + 1
|
|
939
|
+
}],
|
|
940
|
+
numberOfItems: categories.length
|
|
941
|
+
};
|
|
942
|
+
},
|
|
811
943
|
image: ({
|
|
812
|
-
isVariantOf,
|
|
813
944
|
images
|
|
814
945
|
}) => {
|
|
815
|
-
var
|
|
946
|
+
var _nonEmptyArray;
|
|
816
947
|
|
|
817
|
-
return ((
|
|
818
|
-
|
|
819
|
-
|
|
948
|
+
return ((_nonEmptyArray = nonEmptyArray(images)) != null ? _nonEmptyArray : [DEFAULT_IMAGE]).map(({
|
|
949
|
+
imageUrl,
|
|
950
|
+
imageText
|
|
820
951
|
}) => ({
|
|
821
|
-
alternateName:
|
|
822
|
-
url:
|
|
952
|
+
alternateName: imageText != null ? imageText : '',
|
|
953
|
+
url: imageUrl.replace('vteximg.com.br', 'vtexassets.com')
|
|
823
954
|
}));
|
|
824
955
|
},
|
|
825
956
|
sku: ({
|
|
826
|
-
|
|
827
|
-
}) =>
|
|
957
|
+
itemId
|
|
958
|
+
}) => itemId,
|
|
828
959
|
gtin: ({
|
|
829
|
-
|
|
830
|
-
}) =>
|
|
960
|
+
referenceId
|
|
961
|
+
}) => {
|
|
962
|
+
var _referenceId$0$Value, _referenceId$;
|
|
963
|
+
|
|
964
|
+
return (_referenceId$0$Value = (_referenceId$ = referenceId[0]) == null ? void 0 : _referenceId$.Value) != null ? _referenceId$0$Value : '';
|
|
965
|
+
},
|
|
831
966
|
review: () => [],
|
|
832
967
|
aggregateRating: () => ({}),
|
|
833
|
-
offers:
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
const {
|
|
837
|
-
loaders: {
|
|
838
|
-
simulationLoader
|
|
839
|
-
},
|
|
840
|
-
storage: {
|
|
841
|
-
channel
|
|
842
|
-
}
|
|
843
|
-
} = ctx;
|
|
844
|
-
const {
|
|
845
|
-
id,
|
|
846
|
-
policies
|
|
847
|
-
} = product;
|
|
848
|
-
const sellers = (_policies$find = policies.find(policy => policy.id === channel.salesChannel)) == null ? void 0 : _policies$find.sellers;
|
|
849
|
-
|
|
850
|
-
if (sellers === null || sellers === undefined) {
|
|
851
|
-
// This error will likely happen when you forget to forward the channel somewhere in your code.
|
|
852
|
-
// Make sure all queries that lead to a product are forwarding the channel in context corectly
|
|
853
|
-
throw new Error(`Product with id ${id} has no sellers for sales channel ${channel.salesChannel}.`);
|
|
854
|
-
} // Unique seller ids
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
const sellerIds = sellers.map(seller => seller.id);
|
|
858
|
-
const items = Array.from(new Set(sellerIds)).map(seller => ({
|
|
859
|
-
quantity: 1,
|
|
860
|
-
seller,
|
|
861
|
-
id
|
|
862
|
-
}));
|
|
863
|
-
const simulation = await simulationLoader.load(items);
|
|
864
|
-
return { ...simulation,
|
|
865
|
-
items: sortOfferByPrice(simulation.items),
|
|
968
|
+
offers: product => {
|
|
969
|
+
return {
|
|
970
|
+
items: sortOfferByPrice(product.isVariantOf.items),
|
|
866
971
|
product
|
|
867
972
|
};
|
|
868
973
|
},
|
|
869
|
-
isVariantOf:
|
|
870
|
-
|
|
871
|
-
}) => isVariantOf,
|
|
974
|
+
isVariantOf: root => root,
|
|
975
|
+
// TODO: get this value. Fix any type
|
|
872
976
|
additionalProperty: ({
|
|
873
977
|
attributes = []
|
|
874
978
|
}) => attributes.map(attribute => ({
|
|
@@ -877,24 +981,31 @@ const StoreProduct = {
|
|
|
877
981
|
}))
|
|
878
982
|
};
|
|
879
983
|
|
|
984
|
+
const BLOCKED_PROPERTIES = {
|
|
985
|
+
sellerId: true
|
|
986
|
+
};
|
|
880
987
|
const StoreProductGroup = {
|
|
881
|
-
hasVariant: root => root.
|
|
988
|
+
hasVariant: root => root.isVariantOf.items.map(item => enhanceSku(item, root.isVariantOf)),
|
|
882
989
|
productGroupID: ({
|
|
883
|
-
|
|
884
|
-
}) =>
|
|
990
|
+
isVariantOf
|
|
991
|
+
}) => isVariantOf.productId,
|
|
885
992
|
name: ({
|
|
886
|
-
|
|
887
|
-
}) =>
|
|
993
|
+
isVariantOf
|
|
994
|
+
}) => isVariantOf.productName,
|
|
888
995
|
additionalProperty: ({
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
996
|
+
isVariantOf: {
|
|
997
|
+
properties
|
|
998
|
+
}
|
|
999
|
+
}) => properties.flatMap(property => {
|
|
1000
|
+
if (BLOCKED_PROPERTIES[property.name]) {
|
|
1001
|
+
return [];
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
return property.values.map(propertyValue => ({
|
|
1005
|
+
name: property.name,
|
|
1006
|
+
value: propertyValue
|
|
896
1007
|
}));
|
|
897
|
-
}
|
|
1008
|
+
})
|
|
898
1009
|
};
|
|
899
1010
|
|
|
900
1011
|
/**
|
|
@@ -909,12 +1020,20 @@ const transformSelectedFacet = ({
|
|
|
909
1020
|
switch (key) {
|
|
910
1021
|
case 'channel':
|
|
911
1022
|
{
|
|
912
|
-
const channel = ChannelMarshal.parse(value);
|
|
913
|
-
|
|
914
|
-
return [{
|
|
1023
|
+
const channel = ChannelMarshal.parse(value);
|
|
1024
|
+
const channelFacets = [{
|
|
915
1025
|
key: 'trade-policy',
|
|
916
1026
|
value: channel.salesChannel
|
|
917
1027
|
}];
|
|
1028
|
+
|
|
1029
|
+
if (channel.regionId) {
|
|
1030
|
+
channelFacets.push({
|
|
1031
|
+
key: 'region-id',
|
|
1032
|
+
value: channel.regionId
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
return channelFacets;
|
|
918
1037
|
}
|
|
919
1038
|
|
|
920
1039
|
default:
|
|
@@ -1006,14 +1125,14 @@ const Query = {
|
|
|
1006
1125
|
page: Math.ceil(after / first),
|
|
1007
1126
|
count: first
|
|
1008
1127
|
});
|
|
1009
|
-
const skus = products.products.map(product => product.
|
|
1128
|
+
const skus = products.products.map(product => product.items.map(sku => enhanceSku(sku, product))).flat().filter(sku => sku.sellers.length > 0);
|
|
1010
1129
|
return {
|
|
1011
1130
|
pageInfo: {
|
|
1012
1131
|
hasNextPage: products.pagination.after.length > 0,
|
|
1013
1132
|
hasPreviousPage: products.pagination.before.length > 0,
|
|
1014
1133
|
startCursor: '0',
|
|
1015
|
-
endCursor: products.
|
|
1016
|
-
totalCount: products.
|
|
1134
|
+
endCursor: products.recordsFiltered.toString(),
|
|
1135
|
+
totalCount: products.recordsFiltered
|
|
1017
1136
|
},
|
|
1018
1137
|
// after + index is bigger than after+first itself because of the array flat() above
|
|
1019
1138
|
edges: skus.map((sku, index) => ({
|
|
@@ -1100,17 +1219,30 @@ const StoreReview = {
|
|
|
1100
1219
|
})
|
|
1101
1220
|
};
|
|
1102
1221
|
|
|
1103
|
-
const REMOVED_FACETS_FROM_COLLECTION_PAGE = ['departamento'];
|
|
1222
|
+
const REMOVED_FACETS_FROM_COLLECTION_PAGE = ['departamento', 'Departamento'];
|
|
1104
1223
|
const StoreSearchResult = {
|
|
1105
1224
|
products: async (searchArgs, _, ctx) => {
|
|
1106
1225
|
const {
|
|
1107
1226
|
clients: {
|
|
1108
|
-
search
|
|
1227
|
+
search,
|
|
1228
|
+
sp
|
|
1109
1229
|
}
|
|
1110
1230
|
} = ctx;
|
|
1111
|
-
const products = await search.products(searchArgs);
|
|
1231
|
+
const products = await search.products(searchArgs); // Raise event on search's analytics API when performing
|
|
1232
|
+
// a full text search.
|
|
1233
|
+
|
|
1234
|
+
if (searchArgs.query) {
|
|
1235
|
+
sp.sendEvent({
|
|
1236
|
+
type: 'search.query',
|
|
1237
|
+
text: searchArgs.query,
|
|
1238
|
+
misspelled: products.correction.misspelled,
|
|
1239
|
+
match: products.recordsFiltered,
|
|
1240
|
+
operator: products.operator
|
|
1241
|
+
}).catch(console.error);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1112
1244
|
const skus = products.products.map(product => {
|
|
1113
|
-
const [maybeSku] = product.
|
|
1245
|
+
const [maybeSku] = product.items;
|
|
1114
1246
|
return maybeSku && enhanceSku(maybeSku, product);
|
|
1115
1247
|
}).filter(sku => !!sku);
|
|
1116
1248
|
return {
|
|
@@ -1118,8 +1250,8 @@ const StoreSearchResult = {
|
|
|
1118
1250
|
hasNextPage: products.pagination.after.length > 0,
|
|
1119
1251
|
hasPreviousPage: products.pagination.before.length > 0,
|
|
1120
1252
|
startCursor: '0',
|
|
1121
|
-
endCursor: products.
|
|
1122
|
-
totalCount: products.
|
|
1253
|
+
endCursor: products.recordsFiltered.toString(),
|
|
1254
|
+
totalCount: products.recordsFiltered
|
|
1123
1255
|
},
|
|
1124
1256
|
edges: skus.map((sku, index) => ({
|
|
1125
1257
|
node: sku,
|
|
@@ -1128,17 +1260,17 @@ const StoreSearchResult = {
|
|
|
1128
1260
|
};
|
|
1129
1261
|
},
|
|
1130
1262
|
facets: async (searchArgs, _, ctx) => {
|
|
1131
|
-
var _facets$attributes;
|
|
1132
|
-
|
|
1133
1263
|
const {
|
|
1134
1264
|
clients: {
|
|
1135
1265
|
search: is
|
|
1136
1266
|
}
|
|
1137
1267
|
} = ctx;
|
|
1138
|
-
const
|
|
1268
|
+
const {
|
|
1269
|
+
facets
|
|
1270
|
+
} = await is.facets(searchArgs);
|
|
1139
1271
|
const isCollectionPage = !searchArgs.query;
|
|
1140
|
-
const filteredFacets = facets == null ? void 0 :
|
|
1141
|
-
const shouldFilterFacet = REMOVED_FACETS_FROM_COLLECTION_PAGE.includes(currentFacet.
|
|
1272
|
+
const filteredFacets = facets == null ? void 0 : facets.reduce((acc, currentFacet) => {
|
|
1273
|
+
const shouldFilterFacet = REMOVED_FACETS_FROM_COLLECTION_PAGE.includes(currentFacet.name);
|
|
1142
1274
|
const shouldRemoveFacetFromCollectionPage = isCollectionPage && shouldFilterFacet;
|
|
1143
1275
|
|
|
1144
1276
|
if (shouldRemoveFacetFromCollectionPage) {
|
|
@@ -1146,10 +1278,10 @@ const StoreSearchResult = {
|
|
|
1146
1278
|
}
|
|
1147
1279
|
|
|
1148
1280
|
currentFacet.values.sort((a, b) => {
|
|
1149
|
-
var _a$
|
|
1281
|
+
var _a$name, _b$name;
|
|
1150
1282
|
|
|
1151
|
-
const firstItemLabel = (_a$
|
|
1152
|
-
const secondItemLabel = (_b$
|
|
1283
|
+
const firstItemLabel = (_a$name = a.name) != null ? _a$name : '';
|
|
1284
|
+
const secondItemLabel = (_b$name = b.name) != null ? _b$name : '';
|
|
1153
1285
|
return firstItemLabel.localeCompare(secondItemLabel);
|
|
1154
1286
|
});
|
|
1155
1287
|
acc.push(currentFacet);
|