Skip to content
Draft
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Added

- `state` parameter to `formatTranslatableStringV2` indicating if the label is already translated

## [1.85.1] - 2025-10-14

### Fixed
Expand Down
8 changes: 5 additions & 3 deletions node/clients/search.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {
AppClient,
CacheType,
InstanceOptions,
IOContext,
RequestConfig,
SegmentData,
CacheType,
} from '@vtex/api'
import { stringify } from 'qs'

import {
searchEncodeURI,
SearchCrossSellingTypes,
searchEncodeURI,
} from '../resolvers/search/utils'

interface AutocompleteArgs {
Expand Down Expand Up @@ -308,11 +308,13 @@ export class Search extends AppClient {
metric: 'search-category',
})

public crossSelling = (id: string, type: SearchCrossSellingTypes, groupByProduct = true) =>
public crossSelling = (id: string, type: SearchCrossSellingTypes, groupByProduct = true, acceptLanguage?: string) =>
this.get<SearchProduct[]>(
`/pub/products/crossselling/${type}/${id}?groupByProduct=${groupByProduct}`,
{
metric: 'search-crossSelling',
// This Accept Language header is used to request the cross selling products in the desired language from new dataplane endpoint
headers: acceptLanguage ? { 'Accept-Language': acceptLanguage } : {}
}
)

Expand Down
2 changes: 1 addition & 1 deletion node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Clients } from './clients'
import { schemaDirectives } from './directives'
import { resolvers } from './resolvers'
import {
setWorkspaceSearchParams,
getWorkspaceSearchParams,
setWorkspaceSearchParams,
} from './routes/workspaceSearchParams'

const TWO_SECONDS_MS = 2 * 1000
Expand Down
46 changes: 24 additions & 22 deletions node/resolvers/search/category.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { compose, last, prop, split } from 'ramda'

import { getCategoryInfo, logDegradedSearchError } from './utils'
import { formatTranslatableProp, shouldTranslateToBinding } from '../../utils/i18n'
import { Slugify } from '../../utils/slug'
import { APP_NAME } from './constants'
import { getCategoryInfo, logDegradedSearchError } from './utils'

const lastSegment = compose<string, string[], string>(
last,
Expand All @@ -14,6 +14,28 @@ function cleanUrl(url: string) {
return url.replace(/https:\/\/[A-z0-9]+\.vtexcommercestable\.com\.br/, '').toLowerCase()
}

export async function mountHrefRewritter({ url, id }: any, _: unknown, ctx: Context) {
const settings: AppSettings = await ctx.clients.apps.getAppSettings(APP_NAME)

if (shouldTranslateToBinding(ctx)) {
try {
const rewriterUrl = await ctx.clients.rewriter.getRoute(id.toString(), 'anyCategoryEntity', ctx.vtex.binding!.id!)
if (rewriterUrl) {
url = rewriterUrl
}
} catch (e) {
logDegradedSearchError(ctx.vtex.logger, {
service: 'Rewriter getRoute',
error: `Rewriter getRoute query returned an error for category ${id}. Category href may be incorrect.`,
errorStack: e,
})
}
}
const pathname = cleanUrl(url)

return settings.slugifyLinks ? Slugify(pathname) : pathname
}

/** This type has to be created because the Catlog API to get category by ID does not return the url or children for now.
* These fields only come if you get the category from the categroy tree api.
*/
Expand All @@ -29,27 +51,7 @@ export const resolvers = {

cacheId: prop('id'),

href: async ({ url, id }: SafeCategory, _: unknown, ctx: Context) => {
const settings: AppSettings = await ctx.clients.apps.getAppSettings(APP_NAME)

if (shouldTranslateToBinding(ctx)) {
try {
const rewriterUrl = await ctx.clients.rewriter.getRoute(id.toString(), 'anyCategoryEntity', ctx.vtex.binding!.id!)
if (rewriterUrl) {
url = rewriterUrl
}
} catch (e) {
logDegradedSearchError(ctx.vtex.logger, {
service: 'Rewriter getRoute',
error: `Rewriter getRoute query returned an error for category ${id}. Category href may be incorrect.`,
errorStack: e,
})
}
}
const pathname = cleanUrl(url)

return settings.slugifyLinks ? Slugify(pathname) : pathname
},
href: mountHrefRewritter,

metaTagDescription: formatTranslatableProp<SafeCategory, 'MetaTagDescription', 'id'>(
'MetaTagDescription',
Expand Down
28 changes: 18 additions & 10 deletions node/resolvers/search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,20 @@ import {
} from '../../commons/compatibility-layer'
import { getWorkspaceSearchParamsFromStorage } from '../../routes/workspaceSearchParams'
import {
buildVtexSegment,
fetchAutocompleteSuggestions,
fetchCorrection,
fetchSearchSuggestions,
fetchTopSearches,
} from '../../services/autocomplete'
import { fetchBanners } from '../../services/banners'
import {
ProductArgs,
ProductIdentifier,
buildVtexSegment,
resolveProduct,
} from '../../services/product'
import { fetchAppSettings } from '../../services/settings'
import { AdvertisementOptions, FacetsInput, ProductSearchInput, ProductsInput, SegmentData, SuggestionProductsArgs } from '../../typings/Search'
import { shouldTranslateToTenantLocale } from '../../utils/i18n'
import { resolvers as assemblyOptionResolvers } from './assemblyOption'
import { resolvers as autocompleteResolvers } from './autocomplete'
Expand Down Expand Up @@ -39,14 +48,6 @@ import {
getShippingOptionsFromSelectedFacets,
validMapAndQuery,
} from './utils'
import {
fetchAutocompleteSuggestions,
fetchTopSearches,
fetchSearchSuggestions,
fetchCorrection,
} from '../../services/autocomplete'
import { fetchBanners } from '../../services/banners'
import { AdvertisementOptions, FacetsInput, ProductSearchInput, ProductsInput, SegmentData, SuggestionProductsArgs } from '../../typings/Search'

enum CrossSellingInput {
view = 'view',
Expand Down Expand Up @@ -597,6 +598,8 @@ export const queries = {
if (identifier == null || type == null) {
throw new UserInputError('Wrong input provided')
}

const { shouldUseNewPDPEndpoint } = await fetchAppSettings(ctx)
const searchType = inputToSearchCrossSelling[type]
let productId = identifier.value
if (identifier.field !== 'id') {
Expand All @@ -607,10 +610,15 @@ export const queries = {
const groupByProduct =
groupBy === CrossSellingGroupByInput.PRODUCT ? true : false

if (shouldUseNewPDPEndpoint) {
ctx.translated = true
}

const products = await ctx.clients.search.crossSelling(
productId,
searchType,
groupByProduct
groupByProduct,
shouldUseNewPDPEndpoint ? ctx.vtex.locale : undefined
)

searchFirstElements(products, 0, ctx.clients.search)
Expand Down
19 changes: 15 additions & 4 deletions node/resolvers/search/product.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { compose, last, omit, pathOr, split, flatten } from 'ramda'
import { compose, flatten, last, omit, pathOr, split } from 'ramda'

import { fetchAppSettings } from '../../services/settings'
import {
addContextToTranslatableString,
formatTranslatableProp,
shouldTranslateToBinding,
shouldTranslateToUserLocale,
} from '../../utils/i18n'
import { getBenefits } from '../benefits'
import { mountHrefRewritter } from './category'
import { buildCategoryMap, logDegradedSearchError } from './utils'

type DynamicKey<T> = Record<string, T>
Expand Down Expand Up @@ -121,18 +123,27 @@ const findMainTree = (categoriesIds: string[], prodCategoryId: string) => {
}

const productCategoriesToCategoryTree = async (
{ categories, categoriesIds, categoryId: prodCategoryId }: SearchProduct,
// TODO categoryTree will be added
{ categories, categoriesIds, categoryId: prodCategoryId, categoryTree }: SearchProduct & { categoryTree: Array<{ id: number, name: string, href: string }> },
_: any,
{ clients: { search }, vtex: { platform } }: Context
ctx: Context
) => {
const { clients: { search }, vtex: { platform } } = ctx
const { shouldUseNewPDPEndpoint } = await fetchAppSettings(ctx)
if (!categories || !categoriesIds) {
return []
}

const mainTreeIds = findMainTree(categoriesIds, prodCategoryId)

if (platform === 'vtex') {
return mainTreeIds.map(categoryId => search.category(Number(categoryId)))
if (shouldUseNewPDPEndpoint) {
return categoryTree.map(category => ({ ...category, href: mountHrefRewritter(category, _, ctx) }))
}
return mainTreeIds.map(async categoryId => {
const category = await search.category(Number(categoryId))
return {...category,}
})
}
const categoriesTree = await search.categories(mainTreeIds.length)
const categoryMap = buildCategoryMap(categoriesTree)
Expand Down
3 changes: 2 additions & 1 deletion node/services/product.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fetchAppSettings } from './settings'
import type { SegmentData } from '../typings/Search'
import { fetchAppSettings } from './settings'

export type ProductIdentifier = {
field: 'id' | 'slug' | 'ean' | 'reference' | 'sku'
Expand Down Expand Up @@ -144,6 +144,7 @@ export async function fetchProduct(

// Check if current account should skip comparison and use intsch directly
if (shouldUseNewPDPEndpoint) {
ctx.translated = true
return fetchProductFromIntsch(ctx, args)
}

Expand Down
9 changes: 6 additions & 3 deletions node/utils/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
createMessagesLoader,
formatTranslatableStringV2,
parseTranslatableStringV2,
createMessagesLoader,
} from '@vtex/api'
import { logDegradedSearchError } from '../resolvers/search/utils'

Expand All @@ -28,13 +28,15 @@ export interface Message extends BaseMessage {
}

export const addContextToTranslatableString = (message: Message, ctx: Context) => {
const { vtex: { tenant } } = ctx
const { vtex: { tenant }, translated } = ctx
const { locale } = tenant!

if (!message.content) {
return message.content
}

const state = translated ? 'translated' : 'original'


try {
const {
Expand All @@ -45,7 +47,8 @@ export const addContextToTranslatableString = (message: Message, ctx: Context) =

const context = (originalContext || message.context)?.toString()
const from = originalFrom || message.from || locale
return formatTranslatableStringV2({ content, context, from })
// @ts-expect-error
return formatTranslatableStringV2({ content, context, from, state })
} catch (e) {
logDegradedSearchError(ctx.vtex.logger, {
service: 'node-vtex-api translation',
Expand Down