Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Enhance Product Data Handling in DecoCX Schema.org Transformation #996

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion vtex/loaders/intelligentSearch/productDetailsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import { pageTypesToSeo } from "../../utils/legacy.ts";
import { getSegmentFromBag, withSegmentCookie } from "../../utils/segment.ts";
import { withIsSimilarTo } from "../../utils/similars.ts";
import { pickSku, toProductPage } from "../../utils/transform.ts";
import type { PageType, Product as VTEXProduct } from "../../utils/types.ts";
import type {
AdvancedLoaderConfig,
PageType,
Product as VTEXProduct,
} from "../../utils/types.ts";
import PDPDefaultPath from "../paths/PDPDefaultPath.ts";

export interface Props {
Expand All @@ -26,6 +30,11 @@ export interface Props {
* @description Index of product pages with the `skuId` parameter
*/
indexingSkus?: boolean;
/**
* @title Advanced Configuration
* @description Further change loader behaviour
*/
advancedConfigs?: AdvancedLoaderConfig;
}

/**
Expand Down Expand Up @@ -130,6 +139,7 @@ const loader = async (
const page = toProductPage(product, sku, kitItems, {
baseUrl,
priceCurrency: segment?.payload?.currencyCode ?? "BRL",
includeOriginalAttributes: props.advancedConfigs?.includeOriginalAttributes,
});

const isPageProduct = pageType.pageType === "Product";
Expand Down
8 changes: 8 additions & 0 deletions vtex/loaders/intelligentSearch/productListingPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
toProduct,
} from "../../utils/transform.ts";
import type {
AdvancedLoaderConfig,
Facet,
Fuzzy,
PageType,
Expand Down Expand Up @@ -142,6 +143,11 @@ export interface Props {
* @title Include price in facets
*/
priceFacets?: boolean;
/**
* @title Advanced Configuration
* @description Further change loader behaviour
*/
advancedConfigs?: AdvancedLoaderConfig;
}
const searchArgsOf = (props: Props, url: URL) => {
const hideUnavailableItems = props.hideUnavailableItems;
Expand Down Expand Up @@ -362,6 +368,8 @@ const loader = async (
toProduct(p, p.items.find(getFirstItemAvailable) || p.items[0], 0, {
baseUrl: baseUrl,
priceCurrency: segment?.payload?.currencyCode ?? "BRL",
includeOriginalAttributes: props.advancedConfigs
?.includeOriginalAttributes,
})
)
.map((product) =>
Expand Down
7 changes: 7 additions & 0 deletions vtex/loaders/intelligentSearch/suggestions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { getSegmentFromBag, withSegmentCookie } from "../../utils/segment.ts";
import { withIsSimilarTo } from "../../utils/similars.ts";
import { toProduct } from "../../utils/transform.ts";
import type { AdvancedLoaderConfig } from "../../utils/types.ts";

export interface Props {
query?: string;
Expand All @@ -23,6 +24,11 @@ export interface Props {
* @deprecated Use product extensions instead
*/
similars?: boolean;
/**
* @title Advanced Configuration
* @description Further change loader behaviour
*/
advancedConfigs?: AdvancedLoaderConfig;
}

/**
Expand Down Expand Up @@ -79,6 +85,7 @@ const loaders = async (
const options = {
baseUrl: url,
priceCurrency: segment?.payload?.currencyCode ?? "BRL",
includeOriginalAttributes: props.advancedConfigs?.includeOriginalAttributes,
};

return {
Expand Down
8 changes: 7 additions & 1 deletion vtex/loaders/legacy/productDetailsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { toSegmentParams } from "../../utils/legacy.ts";
import { getSegmentFromBag, withSegmentCookie } from "../../utils/segment.ts";
import { withIsSimilarTo } from "../../utils/similars.ts";
import { pickSku, toProductPage } from "../../utils/transform.ts";
import type { LegacyProduct } from "../../utils/types.ts";
import type { AdvancedLoaderConfig, LegacyProduct } from "../../utils/types.ts";
import PDPDefaultPath from "../paths/PDPDefaultPath.ts";

export interface Props {
Expand All @@ -22,6 +22,11 @@ export interface Props {
* @description Index of product pages with the `skuId` parameter
*/
indexingSkus?: boolean;
/**
* @title Advanced Configuration
* @description Further change loader behaviour
*/
advancedConfigs?: AdvancedLoaderConfig;
}

/**
Expand Down Expand Up @@ -86,6 +91,7 @@ async function loader(
const page = toProductPage(product, sku, kitItems, {
baseUrl,
priceCurrency: segment?.payload?.currencyCode ?? "BRL",
includeOriginalAttributes: props.advancedConfigs?.includeOriginalAttributes,
});

return {
Expand Down
9 changes: 9 additions & 0 deletions vtex/loaders/legacy/productListingPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { withIsSimilarTo } from "../../utils/similars.ts";
import { parsePageType } from "../../utils/transform.ts";
import { legacyFacetToFilter, toProduct } from "../../utils/transform.ts";
import type {
AdvancedLoaderConfig,
Item,
LegacyFacet,
LegacyProduct,
Expand Down Expand Up @@ -92,6 +93,12 @@ export interface Props {
* @title Ignore case by checking for selected filter
*/
ignoreCaseSelected?: boolean;

/**
* @title Advanced Configuration
* @description Further change loader behaviour
*/
advancedConfigs?: AdvancedLoaderConfig;
}

export const sortOptions = [
Expand Down Expand Up @@ -277,6 +284,8 @@ const loader = async (
{
baseUrl,
priceCurrency: segment?.payload?.currencyCode ?? "BRL",
includeOriginalAttributes: props.advancedConfigs
?.includeOriginalAttributes,
},
)
)
Expand Down
30 changes: 30 additions & 0 deletions vtex/utils/pickAndOmit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export function pick<
T extends object,
K extends keyof T = keyof T,
>(
keys: K[],
obj: T | null | undefined,
): Pick<T, K> | null {
if (!keys.length || !obj) {
return null;
}

const entries = keys.map((key) => [key, obj[key]]);

return Object.fromEntries(entries);
}

export function omit<T extends object, K extends keyof T>(
keys: K[],
obj: T | null | undefined,
): Omit<T, K> | null {
if (!keys.length || !obj) {
return null;
}

const pickedKeys = (Object.keys(obj) as K[]).filter(
(key) => !keys.includes(key),
);

return pick(pickedKeys, obj) as unknown as Omit<T, K>;
}
36 changes: 35 additions & 1 deletion vtex/utils/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
import { DEFAULT_IMAGE } from "../../commerce/utils/constants.ts";
import { formatRange } from "../../commerce/utils/filters.ts";
import type { PickupPoint as PickupPointVCS } from "./openapi/vcs.openapi.gen.ts";
import { pick } from "./pickAndOmit.ts";
import { slugify } from "./slugify.ts";
import type {
Brand as BrandVTEX,
Expand All @@ -29,7 +30,9 @@ import type {
Item as SkuVTEX,
LegacyFacet,
LegacyItem as LegacySkuVTEX,
LegacyProduct,
LegacyProduct as LegacyProductVTEX,
Maybe,
OrderForm,
PageType as PageTypeVTEX,
PickupHolidays,
Expand Down Expand Up @@ -81,6 +84,8 @@ interface ProductOptions {
/** Price coded currency, e.g.: USD, BRL */
priceCurrency: string;
imagesByKey?: Map<string, string>;
/** Original attributes to be included in the transformed product */
includeOriginalAttributes?: string[];
}

/** Returns first available sku */
Expand Down Expand Up @@ -363,6 +368,11 @@ export const toProduct = <P extends LegacyProductVTEX | ProductVTEX>(
const groupAdditionalProperty = isLegacyProduct(product)
? legacyToProductGroupAdditionalProperties(product)
: toProductGroupAdditionalProperties(product);
const originalAttributesAdditionalProperties =
toOriginalAttributesAdditionalProperties(
options.includeOriginalAttributes,
product,
);
const specificationsAdditionalProperty = isLegacySku(sku)
? toAdditionalPropertiesLegacy(sku)
: toAdditionalProperties(sku);
Expand All @@ -383,7 +393,10 @@ export const toProduct = <P extends LegacyProductVTEX | ProductVTEX>(
),
url: getProductGroupURL(baseUrl, product).href,
name: product.productName,
additionalProperty: groupAdditionalProperty,
additionalProperty: [
...groupAdditionalProperty,
...originalAttributesAdditionalProperties,
],
model: productReference,
} satisfies ProductGroup)
: undefined;
Expand Down Expand Up @@ -554,6 +567,27 @@ const toProductGroupAdditionalProperties = (
)
);

const toOriginalAttributesAdditionalProperties = (
originalAttributes: Maybe<string[]>,
product: ProductVTEX | LegacyProduct,
) => {
if (!originalAttributes) {
return [];
}

const attributes =
pick(originalAttributes as Array<keyof typeof product>, product) ?? {};

return Object.entries(attributes).map(([name, value]) =>
({
"@type": "PropertyValue",
name,
value,
valueReference: "ORIGINAL_PROPERTY" as string,
}) as const
) as unknown as PropertyValue[];
};

const toAdditionalProperties = (sku: SkuVTEX): PropertyValue[] =>
sku.variations?.flatMap(({ name, values }) =>
values.map((value) => toAdditionalPropertySpecification({ name, value }))
Expand Down
7 changes: 7 additions & 0 deletions vtex/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1514,3 +1514,10 @@ export interface Promotion {
maxNumberOfAffectedItems: number;
maxNumberOfAffectedItemsGroupKey: string;
}

export interface AdvancedLoaderConfig {
/** @description Specifies an array of attribute names from the original object to be directly included in the transformed object. */
includeOriginalAttributes: string[];
}

export type Maybe<T> = T | null | undefined;
Loading