@faststore/api 3.22.2 → 3.25.5
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/dist/cjs/package.json +1 -1
- package/dist/cjs/src/index.d.ts +1 -1
- package/dist/cjs/src/platforms/vtex/clients/search/types/ProductSearchResult.d.ts +2 -0
- package/dist/cjs/src/platforms/vtex/index.d.ts +1 -1
- package/dist/cjs/src/platforms/vtex/resolvers/product.d.ts +3 -3
- package/dist/cjs/src/platforms/vtex/resolvers/product.js +35 -10
- package/dist/cjs/src/platforms/vtex/resolvers/product.js.map +1 -1
- package/dist/cjs/src/platforms/vtex/resolvers/seo.d.ts +4 -4
- package/dist/cjs/src/platforms/vtex/resolvers/seo.js.map +1 -1
- package/dist/esm/package.json +1 -1
- package/dist/esm/src/index.d.ts +1 -1
- package/dist/esm/src/platforms/vtex/clients/search/types/ProductSearchResult.d.ts +2 -0
- package/dist/esm/src/platforms/vtex/index.d.ts +1 -1
- package/dist/esm/src/platforms/vtex/resolvers/product.d.ts +3 -3
- package/dist/esm/src/platforms/vtex/resolvers/product.js +35 -10
- package/dist/esm/src/platforms/vtex/resolvers/product.js.map +1 -1
- package/dist/esm/src/platforms/vtex/resolvers/seo.d.ts +4 -4
- package/dist/esm/src/platforms/vtex/resolvers/seo.js.map +1 -1
- package/package.json +2 -2
- package/src/platforms/vtex/clients/search/types/ProductSearchResult.ts +2 -0
- package/src/platforms/vtex/resolvers/product.ts +50 -17
- package/src/platforms/vtex/resolvers/seo.ts +5 -1
package/dist/cjs/package.json
CHANGED
package/dist/cjs/src/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare const getResolvers: (options: Options) => {
|
|
|
16
16
|
isVariantOf: import("./platforms/vtex").Resolver<import("./platforms/vtex/resolvers/product").Root, any, import("./platforms/vtex/resolvers/product").Root>;
|
|
17
17
|
image: import("./platforms/vtex").Resolver<import("./platforms/vtex/resolvers/product").Root, any, import("./__generated__/schema").StoreImage[]>;
|
|
18
18
|
};
|
|
19
|
-
StoreSeo: Record<string, import("./platforms/vtex").Resolver<
|
|
19
|
+
StoreSeo: Record<string, import("./platforms/vtex").Resolver<any>>;
|
|
20
20
|
StoreFacet: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/resolvers/facet").Root>>;
|
|
21
21
|
StoreFacetBoolean: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").Facet<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueBoolean>>>;
|
|
22
22
|
StoreFacetRange: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").Facet<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueRange>>>;
|
|
@@ -60,6 +60,7 @@ export interface Search {
|
|
|
60
60
|
export interface Product {
|
|
61
61
|
productId: string;
|
|
62
62
|
productName: string;
|
|
63
|
+
productTitle: string;
|
|
63
64
|
brand: string;
|
|
64
65
|
brandId: number;
|
|
65
66
|
cacheId?: string;
|
|
@@ -72,6 +73,7 @@ export interface Product {
|
|
|
72
73
|
categoriesIds: string[];
|
|
73
74
|
link: string;
|
|
74
75
|
description: string;
|
|
76
|
+
metaTagDescription: string;
|
|
75
77
|
/**
|
|
76
78
|
* @description Product SKUs.
|
|
77
79
|
*/
|
|
@@ -48,7 +48,7 @@ export declare const getResolvers: (_: Options) => {
|
|
|
48
48
|
isVariantOf: Resolver<import("./resolvers/product").Root, any, import("./resolvers/product").Root>;
|
|
49
49
|
image: Resolver<import("./resolvers/product").Root, any, import("../..").StoreImage[]>;
|
|
50
50
|
};
|
|
51
|
-
StoreSeo: Record<string, Resolver<
|
|
51
|
+
StoreSeo: Record<string, Resolver<any>>;
|
|
52
52
|
StoreFacet: Record<string, Resolver<import("./resolvers/facet").Root>>;
|
|
53
53
|
StoreFacetBoolean: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").Facet<import("./clients/search/types/FacetSearchResult").FacetValueBoolean>>>;
|
|
54
54
|
StoreFacetRange: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").Facet<import("./clients/search/types/FacetSearchResult").FacetValueRange>>>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { EnhancedCommercialOffer } from '../utils/enhanceCommercialOffer';
|
|
2
1
|
import type { Resolver } from '..';
|
|
2
|
+
import type { StoreImage } from '../../..';
|
|
3
3
|
import type { PromiseType } from '../../../typings';
|
|
4
|
-
import type { Query } from './query';
|
|
5
4
|
import type { Attachment } from '../clients/commerce/types/OrderForm';
|
|
6
|
-
import type {
|
|
5
|
+
import type { EnhancedCommercialOffer } from '../utils/enhanceCommercialOffer';
|
|
6
|
+
import type { Query } from './query';
|
|
7
7
|
type QueryProduct = PromiseType<ReturnType<typeof Query.product>>;
|
|
8
8
|
export type Root = QueryProduct & {
|
|
9
9
|
attachmentsValues?: Attachment[];
|
|
@@ -4,8 +4,8 @@ exports.StoreProduct = void 0;
|
|
|
4
4
|
const canonical_1 = require("../utils/canonical");
|
|
5
5
|
const enhanceCommercialOffer_1 = require("../utils/enhanceCommercialOffer");
|
|
6
6
|
const productStock_1 = require("../utils/productStock");
|
|
7
|
-
const slugify_1 = require("../utils/slugify");
|
|
8
7
|
const propertyValue_1 = require("../utils/propertyValue");
|
|
8
|
+
const slugify_1 = require("../utils/slugify");
|
|
9
9
|
const DEFAULT_IMAGE = {
|
|
10
10
|
imageText: 'image',
|
|
11
11
|
imageUrl: 'https://storecomponents.vtexassets.com/assets/faststore/images/image___117a6d3e229a96ad0e0d0876352566e2.svg',
|
|
@@ -14,25 +14,50 @@ const DEFAULT_IMAGE = {
|
|
|
14
14
|
const getSlug = (link, id) => `${link}-${id}`;
|
|
15
15
|
const getPath = (link, id) => `/${getSlug(link, id)}/p`;
|
|
16
16
|
const nonEmptyArray = (array) => Array.isArray(array) && array.length > 0 ? array : null;
|
|
17
|
+
function removeTrailingSlashes(path) {
|
|
18
|
+
return path.replace(/^\/+|\/+$/g, '');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Finds the index of the main category tree that matches the given category ID.
|
|
22
|
+
* This avoids including similar categories in the breadcrumb list.
|
|
23
|
+
* If Intelligent Search starts providing the list without similar categories, we'll have direct access to the main tree
|
|
24
|
+
* and we won't need this logic. Hopefully in the future we can remove this.
|
|
25
|
+
*
|
|
26
|
+
* @param categoriesIds - An array of category IDs representing different category trees.
|
|
27
|
+
* @param categoryId - The category ID to find within the category trees.
|
|
28
|
+
* @returns The index of the main category tree that contains the given category ID.
|
|
29
|
+
* If the category ID is not found, returns 0 - it should always be found, but the fallback was added for safety.
|
|
30
|
+
*/
|
|
31
|
+
const findMainTreeIndex = (categoriesIds, categoryId) => {
|
|
32
|
+
const mainTreeIndex = categoriesIds.findIndex((idsTree) => {
|
|
33
|
+
const lastId = removeTrailingSlashes(idsTree).split('/').at(-1);
|
|
34
|
+
return lastId === categoryId;
|
|
35
|
+
});
|
|
36
|
+
return mainTreeIndex < 0 ? 0 : mainTreeIndex;
|
|
37
|
+
};
|
|
17
38
|
exports.StoreProduct = {
|
|
18
39
|
productID: ({ itemId }) => itemId,
|
|
19
40
|
name: ({ isVariantOf, name }) => name ?? isVariantOf.productName,
|
|
20
41
|
slug: ({ isVariantOf: { linkText }, itemId }) => getSlug(linkText, itemId),
|
|
21
42
|
description: ({ isVariantOf: { description } }) => description,
|
|
22
43
|
seo: ({ isVariantOf }) => ({
|
|
23
|
-
title: isVariantOf.productName,
|
|
24
|
-
description: isVariantOf.description,
|
|
44
|
+
title: isVariantOf.productTitle || isVariantOf.productName,
|
|
45
|
+
description: isVariantOf.metaTagDescription || isVariantOf.description,
|
|
25
46
|
canonical: (0, canonical_1.canonicalFromProduct)(isVariantOf),
|
|
26
47
|
}),
|
|
27
48
|
brand: ({ isVariantOf: { brand } }) => ({ name: brand }),
|
|
28
49
|
unitMultiplier: ({ unitMultiplier }) => unitMultiplier,
|
|
29
|
-
breadcrumbList: ({ isVariantOf: { categories, productName, linkText }, itemId, }) => {
|
|
50
|
+
breadcrumbList: ({ isVariantOf: { categories, productName, linkText, categoryId, categoriesIds, }, itemId, }) => {
|
|
51
|
+
const mainTreeIndex = findMainTreeIndex(categoriesIds, categoryId);
|
|
52
|
+
const mainTree = categories[mainTreeIndex];
|
|
53
|
+
const splittedCategories = removeTrailingSlashes(mainTree).split('/');
|
|
30
54
|
return {
|
|
31
55
|
itemListElement: [
|
|
32
|
-
...
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
56
|
+
...splittedCategories.map((name, index) => {
|
|
57
|
+
const item = `/${splittedCategories
|
|
58
|
+
.slice(0, index + 1)
|
|
59
|
+
.map(slugify_1.slugify)
|
|
60
|
+
.join('/')}/`;
|
|
36
61
|
return {
|
|
37
62
|
name,
|
|
38
63
|
item,
|
|
@@ -42,10 +67,10 @@ exports.StoreProduct = {
|
|
|
42
67
|
{
|
|
43
68
|
name: productName,
|
|
44
69
|
item: getPath(linkText, itemId),
|
|
45
|
-
position:
|
|
70
|
+
position: splittedCategories.length + 1,
|
|
46
71
|
},
|
|
47
72
|
],
|
|
48
|
-
numberOfItems:
|
|
73
|
+
numberOfItems: splittedCategories.length,
|
|
49
74
|
};
|
|
50
75
|
},
|
|
51
76
|
image: ({ images }, args) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product.js","sourceRoot":"","sources":["../../../../../../src/platforms/vtex/resolvers/product.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"product.js","sourceRoot":"","sources":["../../../../../../src/platforms/vtex/resolvers/product.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Resolver } from '..';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import type { PromiseType } from '../../../typings';
|
|
3
|
+
import type { StoreProduct } from './product';
|
|
4
|
+
export type Root = PromiseType<ReturnType<typeof StoreProduct.seo>> & {
|
|
5
|
+
titleTemplate?: string;
|
|
6
6
|
};
|
|
7
7
|
export declare const StoreSeo: Record<string, Resolver<Root>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seo.js","sourceRoot":"","sources":["../../../../../../src/platforms/vtex/resolvers/seo.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"seo.js","sourceRoot":"","sources":["../../../../../../src/platforms/vtex/resolvers/seo.ts"],"names":[],"mappings":";;;AAQa,QAAA,QAAQ,GAAmC;IACtD,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE;IACjC,WAAW,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,WAAW,IAAI,EAAE;IACnD,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,SAAS,IAAI,EAAE;IAC7C,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;CACxB,CAAA"}
|
package/dist/esm/package.json
CHANGED
package/dist/esm/src/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare const getResolvers: (options: Options) => {
|
|
|
16
16
|
isVariantOf: import("./platforms/vtex").Resolver<import("./platforms/vtex/resolvers/product").Root, any, import("./platforms/vtex/resolvers/product").Root>;
|
|
17
17
|
image: import("./platforms/vtex").Resolver<import("./platforms/vtex/resolvers/product").Root, any, import("./__generated__/schema").StoreImage[]>;
|
|
18
18
|
};
|
|
19
|
-
StoreSeo: Record<string, import("./platforms/vtex").Resolver<
|
|
19
|
+
StoreSeo: Record<string, import("./platforms/vtex").Resolver<any>>;
|
|
20
20
|
StoreFacet: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/resolvers/facet").Root>>;
|
|
21
21
|
StoreFacetBoolean: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").Facet<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueBoolean>>>;
|
|
22
22
|
StoreFacetRange: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").Facet<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueRange>>>;
|
|
@@ -60,6 +60,7 @@ export interface Search {
|
|
|
60
60
|
export interface Product {
|
|
61
61
|
productId: string;
|
|
62
62
|
productName: string;
|
|
63
|
+
productTitle: string;
|
|
63
64
|
brand: string;
|
|
64
65
|
brandId: number;
|
|
65
66
|
cacheId?: string;
|
|
@@ -72,6 +73,7 @@ export interface Product {
|
|
|
72
73
|
categoriesIds: string[];
|
|
73
74
|
link: string;
|
|
74
75
|
description: string;
|
|
76
|
+
metaTagDescription: string;
|
|
75
77
|
/**
|
|
76
78
|
* @description Product SKUs.
|
|
77
79
|
*/
|
|
@@ -48,7 +48,7 @@ export declare const getResolvers: (_: Options) => {
|
|
|
48
48
|
isVariantOf: Resolver<import("./resolvers/product").Root, any, import("./resolvers/product").Root>;
|
|
49
49
|
image: Resolver<import("./resolvers/product").Root, any, import("../..").StoreImage[]>;
|
|
50
50
|
};
|
|
51
|
-
StoreSeo: Record<string, Resolver<
|
|
51
|
+
StoreSeo: Record<string, Resolver<any>>;
|
|
52
52
|
StoreFacet: Record<string, Resolver<import("./resolvers/facet").Root>>;
|
|
53
53
|
StoreFacetBoolean: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").Facet<import("./clients/search/types/FacetSearchResult").FacetValueBoolean>>>;
|
|
54
54
|
StoreFacetRange: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").Facet<import("./clients/search/types/FacetSearchResult").FacetValueRange>>>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { EnhancedCommercialOffer } from '../utils/enhanceCommercialOffer';
|
|
2
1
|
import type { Resolver } from '..';
|
|
2
|
+
import type { StoreImage } from '../../..';
|
|
3
3
|
import type { PromiseType } from '../../../typings';
|
|
4
|
-
import type { Query } from './query';
|
|
5
4
|
import type { Attachment } from '../clients/commerce/types/OrderForm';
|
|
6
|
-
import type {
|
|
5
|
+
import type { EnhancedCommercialOffer } from '../utils/enhanceCommercialOffer';
|
|
6
|
+
import type { Query } from './query';
|
|
7
7
|
type QueryProduct = PromiseType<ReturnType<typeof Query.product>>;
|
|
8
8
|
export type Root = QueryProduct & {
|
|
9
9
|
attachmentsValues?: Attachment[];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { canonicalFromProduct } from '../utils/canonical';
|
|
2
2
|
import { enhanceCommercialOffer } from '../utils/enhanceCommercialOffer';
|
|
3
3
|
import { bestOfferFirst } from '../utils/productStock';
|
|
4
|
-
import { slugify } from '../utils/slugify';
|
|
5
4
|
import { attachmentToPropertyValue, attributeToPropertyValue, VALUE_REFERENCES, } from '../utils/propertyValue';
|
|
5
|
+
import { slugify } from '../utils/slugify';
|
|
6
6
|
const DEFAULT_IMAGE = {
|
|
7
7
|
imageText: 'image',
|
|
8
8
|
imageUrl: 'https://storecomponents.vtexassets.com/assets/faststore/images/image___117a6d3e229a96ad0e0d0876352566e2.svg',
|
|
@@ -11,25 +11,50 @@ const DEFAULT_IMAGE = {
|
|
|
11
11
|
const getSlug = (link, id) => `${link}-${id}`;
|
|
12
12
|
const getPath = (link, id) => `/${getSlug(link, id)}/p`;
|
|
13
13
|
const nonEmptyArray = (array) => Array.isArray(array) && array.length > 0 ? array : null;
|
|
14
|
+
function removeTrailingSlashes(path) {
|
|
15
|
+
return path.replace(/^\/+|\/+$/g, '');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Finds the index of the main category tree that matches the given category ID.
|
|
19
|
+
* This avoids including similar categories in the breadcrumb list.
|
|
20
|
+
* If Intelligent Search starts providing the list without similar categories, we'll have direct access to the main tree
|
|
21
|
+
* and we won't need this logic. Hopefully in the future we can remove this.
|
|
22
|
+
*
|
|
23
|
+
* @param categoriesIds - An array of category IDs representing different category trees.
|
|
24
|
+
* @param categoryId - The category ID to find within the category trees.
|
|
25
|
+
* @returns The index of the main category tree that contains the given category ID.
|
|
26
|
+
* If the category ID is not found, returns 0 - it should always be found, but the fallback was added for safety.
|
|
27
|
+
*/
|
|
28
|
+
const findMainTreeIndex = (categoriesIds, categoryId) => {
|
|
29
|
+
const mainTreeIndex = categoriesIds.findIndex((idsTree) => {
|
|
30
|
+
const lastId = removeTrailingSlashes(idsTree).split('/').at(-1);
|
|
31
|
+
return lastId === categoryId;
|
|
32
|
+
});
|
|
33
|
+
return mainTreeIndex < 0 ? 0 : mainTreeIndex;
|
|
34
|
+
};
|
|
14
35
|
export const StoreProduct = {
|
|
15
36
|
productID: ({ itemId }) => itemId,
|
|
16
37
|
name: ({ isVariantOf, name }) => name ?? isVariantOf.productName,
|
|
17
38
|
slug: ({ isVariantOf: { linkText }, itemId }) => getSlug(linkText, itemId),
|
|
18
39
|
description: ({ isVariantOf: { description } }) => description,
|
|
19
40
|
seo: ({ isVariantOf }) => ({
|
|
20
|
-
title: isVariantOf.productName,
|
|
21
|
-
description: isVariantOf.description,
|
|
41
|
+
title: isVariantOf.productTitle || isVariantOf.productName,
|
|
42
|
+
description: isVariantOf.metaTagDescription || isVariantOf.description,
|
|
22
43
|
canonical: canonicalFromProduct(isVariantOf),
|
|
23
44
|
}),
|
|
24
45
|
brand: ({ isVariantOf: { brand } }) => ({ name: brand }),
|
|
25
46
|
unitMultiplier: ({ unitMultiplier }) => unitMultiplier,
|
|
26
|
-
breadcrumbList: ({ isVariantOf: { categories, productName, linkText }, itemId, }) => {
|
|
47
|
+
breadcrumbList: ({ isVariantOf: { categories, productName, linkText, categoryId, categoriesIds, }, itemId, }) => {
|
|
48
|
+
const mainTreeIndex = findMainTreeIndex(categoriesIds, categoryId);
|
|
49
|
+
const mainTree = categories[mainTreeIndex];
|
|
50
|
+
const splittedCategories = removeTrailingSlashes(mainTree).split('/');
|
|
27
51
|
return {
|
|
28
52
|
itemListElement: [
|
|
29
|
-
...
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
53
|
+
...splittedCategories.map((name, index) => {
|
|
54
|
+
const item = `/${splittedCategories
|
|
55
|
+
.slice(0, index + 1)
|
|
56
|
+
.map(slugify)
|
|
57
|
+
.join('/')}/`;
|
|
33
58
|
return {
|
|
34
59
|
name,
|
|
35
60
|
item,
|
|
@@ -39,10 +64,10 @@ export const StoreProduct = {
|
|
|
39
64
|
{
|
|
40
65
|
name: productName,
|
|
41
66
|
item: getPath(linkText, itemId),
|
|
42
|
-
position:
|
|
67
|
+
position: splittedCategories.length + 1,
|
|
43
68
|
},
|
|
44
69
|
],
|
|
45
|
-
numberOfItems:
|
|
70
|
+
numberOfItems: splittedCategories.length,
|
|
46
71
|
};
|
|
47
72
|
},
|
|
48
73
|
image: ({ images }, args) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product.js","sourceRoot":"","sources":["../../../../../../src/platforms/vtex/resolvers/product.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"product.js","sourceRoot":"","sources":["../../../../../../src/platforms/vtex/resolvers/product.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Resolver } from '..';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import type { PromiseType } from '../../../typings';
|
|
3
|
+
import type { StoreProduct } from './product';
|
|
4
|
+
export type Root = PromiseType<ReturnType<typeof StoreProduct.seo>> & {
|
|
5
|
+
titleTemplate?: string;
|
|
6
6
|
};
|
|
7
7
|
export declare const StoreSeo: Record<string, Resolver<Root>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seo.js","sourceRoot":"","sources":["../../../../../../src/platforms/vtex/resolvers/seo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"seo.js","sourceRoot":"","sources":["../../../../../../src/platforms/vtex/resolvers/seo.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,QAAQ,GAAmC;IACtD,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE;IACjC,WAAW,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,WAAW,IAAI,EAAE;IACnD,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,SAAS,IAAI,EAAE;IAC7C,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;CACxB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/api",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/cjs/src/index.js",
|
|
6
6
|
"typings": "dist/esm/src/index.d.ts",
|
|
@@ -79,5 +79,5 @@
|
|
|
79
79
|
"volta": {
|
|
80
80
|
"extends": "../../package.json"
|
|
81
81
|
},
|
|
82
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "d5a9bff0eb24b8b6c388b6dc4494ff3d586f297e"
|
|
83
83
|
}
|
|
@@ -70,6 +70,7 @@ export interface Search {
|
|
|
70
70
|
export interface Product {
|
|
71
71
|
productId: string
|
|
72
72
|
productName: string
|
|
73
|
+
productTitle: string
|
|
73
74
|
brand: string
|
|
74
75
|
brandId: number
|
|
75
76
|
cacheId?: string
|
|
@@ -82,6 +83,7 @@ export interface Product {
|
|
|
82
83
|
categoriesIds: string[]
|
|
83
84
|
link: string
|
|
84
85
|
description: string
|
|
86
|
+
metaTagDescription: string
|
|
85
87
|
/**
|
|
86
88
|
* @description Product SKUs.
|
|
87
89
|
*/
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
import type { Resolver } from '..'
|
|
2
|
+
import type { StoreImage, StoreProductImageArgs } from '../../..'
|
|
3
|
+
import type { PromiseType } from '../../../typings'
|
|
4
|
+
import type { Attachment } from '../clients/commerce/types/OrderForm'
|
|
1
5
|
import { canonicalFromProduct } from '../utils/canonical'
|
|
6
|
+
import type { EnhancedCommercialOffer } from '../utils/enhanceCommercialOffer'
|
|
2
7
|
import { enhanceCommercialOffer } from '../utils/enhanceCommercialOffer'
|
|
3
8
|
import { bestOfferFirst } from '../utils/productStock'
|
|
4
|
-
import { slugify } from '../utils/slugify'
|
|
5
|
-
import type { EnhancedCommercialOffer } from '../utils/enhanceCommercialOffer'
|
|
6
|
-
import type { Resolver } from '..'
|
|
7
|
-
import type { PromiseType } from '../../../typings'
|
|
8
|
-
import type { Query } from './query'
|
|
9
9
|
import {
|
|
10
10
|
attachmentToPropertyValue,
|
|
11
11
|
attributeToPropertyValue,
|
|
12
12
|
VALUE_REFERENCES,
|
|
13
13
|
} from '../utils/propertyValue'
|
|
14
|
-
import
|
|
15
|
-
import type {
|
|
14
|
+
import { slugify } from '../utils/slugify'
|
|
15
|
+
import type { Query } from './query'
|
|
16
16
|
|
|
17
17
|
type QueryProduct = PromiseType<ReturnType<typeof Query.product>>
|
|
18
18
|
|
|
@@ -33,6 +33,29 @@ const getPath = (link: string, id: string) => `/${getSlug(link, id)}/p`
|
|
|
33
33
|
const nonEmptyArray = <T>(array: T[] | null | undefined) =>
|
|
34
34
|
Array.isArray(array) && array.length > 0 ? array : null
|
|
35
35
|
|
|
36
|
+
function removeTrailingSlashes(path: string) {
|
|
37
|
+
return path.replace(/^\/+|\/+$/g, '')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Finds the index of the main category tree that matches the given category ID.
|
|
42
|
+
* This avoids including similar categories in the breadcrumb list.
|
|
43
|
+
* If Intelligent Search starts providing the list without similar categories, we'll have direct access to the main tree
|
|
44
|
+
* and we won't need this logic. Hopefully in the future we can remove this.
|
|
45
|
+
*
|
|
46
|
+
* @param categoriesIds - An array of category IDs representing different category trees.
|
|
47
|
+
* @param categoryId - The category ID to find within the category trees.
|
|
48
|
+
* @returns The index of the main category tree that contains the given category ID.
|
|
49
|
+
* If the category ID is not found, returns 0 - it should always be found, but the fallback was added for safety.
|
|
50
|
+
*/
|
|
51
|
+
const findMainTreeIndex = (categoriesIds: string[], categoryId: string) => {
|
|
52
|
+
const mainTreeIndex = categoriesIds.findIndex((idsTree) => {
|
|
53
|
+
const lastId = removeTrailingSlashes(idsTree).split('/').at(-1)
|
|
54
|
+
return lastId === categoryId
|
|
55
|
+
})
|
|
56
|
+
return mainTreeIndex < 0 ? 0 : mainTreeIndex
|
|
57
|
+
}
|
|
58
|
+
|
|
36
59
|
export const StoreProduct: Record<string, Resolver<Root>> & {
|
|
37
60
|
offers: Resolver<
|
|
38
61
|
Root,
|
|
@@ -49,23 +72,33 @@ export const StoreProduct: Record<string, Resolver<Root>> & {
|
|
|
49
72
|
slug: ({ isVariantOf: { linkText }, itemId }) => getSlug(linkText, itemId),
|
|
50
73
|
description: ({ isVariantOf: { description } }) => description,
|
|
51
74
|
seo: ({ isVariantOf }) => ({
|
|
52
|
-
title: isVariantOf.productName,
|
|
53
|
-
description: isVariantOf.description,
|
|
75
|
+
title: isVariantOf.productTitle || isVariantOf.productName,
|
|
76
|
+
description: isVariantOf.metaTagDescription || isVariantOf.description,
|
|
54
77
|
canonical: canonicalFromProduct(isVariantOf),
|
|
55
78
|
}),
|
|
56
79
|
brand: ({ isVariantOf: { brand } }) => ({ name: brand }),
|
|
57
80
|
unitMultiplier: ({ unitMultiplier }) => unitMultiplier,
|
|
58
81
|
breadcrumbList: ({
|
|
59
|
-
isVariantOf: {
|
|
82
|
+
isVariantOf: {
|
|
83
|
+
categories,
|
|
84
|
+
productName,
|
|
85
|
+
linkText,
|
|
86
|
+
categoryId,
|
|
87
|
+
categoriesIds,
|
|
88
|
+
},
|
|
60
89
|
itemId,
|
|
61
90
|
}) => {
|
|
91
|
+
const mainTreeIndex = findMainTreeIndex(categoriesIds, categoryId)
|
|
92
|
+
const mainTree = categories[mainTreeIndex]
|
|
93
|
+
const splittedCategories = removeTrailingSlashes(mainTree).split('/')
|
|
94
|
+
|
|
62
95
|
return {
|
|
63
96
|
itemListElement: [
|
|
64
|
-
...
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
97
|
+
...splittedCategories.map((name, index) => {
|
|
98
|
+
const item = `/${splittedCategories
|
|
99
|
+
.slice(0, index + 1)
|
|
100
|
+
.map(slugify)
|
|
101
|
+
.join('/')}/`
|
|
69
102
|
return {
|
|
70
103
|
name,
|
|
71
104
|
item,
|
|
@@ -75,10 +108,10 @@ export const StoreProduct: Record<string, Resolver<Root>> & {
|
|
|
75
108
|
{
|
|
76
109
|
name: productName,
|
|
77
110
|
item: getPath(linkText, itemId),
|
|
78
|
-
position:
|
|
111
|
+
position: splittedCategories.length + 1,
|
|
79
112
|
},
|
|
80
113
|
],
|
|
81
|
-
numberOfItems:
|
|
114
|
+
numberOfItems: splittedCategories.length,
|
|
82
115
|
}
|
|
83
116
|
},
|
|
84
117
|
image: ({ images }, args) => {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Resolver } from '..'
|
|
2
|
+
import type { PromiseType } from '../../../typings'
|
|
3
|
+
import type { StoreProduct } from './product'
|
|
2
4
|
|
|
3
|
-
export type Root =
|
|
5
|
+
export type Root = PromiseType<ReturnType<typeof StoreProduct.seo>> & {
|
|
6
|
+
titleTemplate?: string
|
|
7
|
+
}
|
|
4
8
|
|
|
5
9
|
export const StoreSeo: Record<string, Resolver<Root>> = {
|
|
6
10
|
title: ({ title }) => title ?? '',
|