diff --git a/CHANGELOG.md b/CHANGELOG.md index d6edf16a..51e40258 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `groupByProduct` param to `productRecommendations` query. - `quantity` param to `Recommendation.similars` resolver. +## [1.67.1] - 2023-10-18 + +## [1.67.0] - 2023-08-22 + +### Added +- `sponsoredProducts` query. + +## [1.66.1] - 2023-08-18 + +### Fixed +- Retrieve translated text-based product specification values ("properties") when using the `productSearch` and `products` queries. + +## [1.66.0] - 2023-08-01 + +### Fixed +- Version bump to reset circuit breaker ## [1.65.1] - 2023-04-24 ### Fixed diff --git a/manifest.json b/manifest.json index 35fd9ecc..21596a3b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "vendor": "vtex", "name": "search-resolver", - "version": "1.65.1", + "version": "1.67.1", "title": "GraphQL resolver for the VTEX store APIs", "description": "GraphQL resolvers for the VTEX API for the catalog and orders.", "credentialType": "absolute", diff --git a/node/clients/intelligent-search-api.ts b/node/clients/intelligent-search-api.ts index 959044f0..73c10f0b 100644 --- a/node/clients/intelligent-search-api.ts +++ b/node/clients/intelligent-search-api.ts @@ -127,4 +127,25 @@ export class IntelligentSearchApi extends ExternalClient { }, }) } + + public async sponsoredProducts(params: SearchResultArgs, path: string, shippingHeader?: string[]) { + const {query, leap, searchState} = params + if (isPathTraversal(path)) { + throw new Error("Malformed URL") + } + + return this.http.get(`/sponsored_products/${path}`, { + params: { + query: query && decodeQuery(query), + locale: this.locale, + bgy_leap: leap ? true : undefined, + ...parseState(searchState), + ...params, + }, + metric: 'product-search', + headers: { + 'x-vtex-shipping-options': shippingHeader ?? '', + }, + }) + } } diff --git a/node/package.json b/node/package.json index 6d1df3a4..fbbf4ea3 100644 --- a/node/package.json +++ b/node/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "@gocommerce/utils": "^0.6.11", - "@vtex/vtexis-compatibility-layer": "^0.2.5", + "@vtex/vtexis-compatibility-layer": "^1.2.13", "atob": "^2.1.2", "axios": "^0.21.2", "camelcase": "^5.0.0", @@ -33,7 +33,7 @@ "slugify": "^1.6.4", "typescript": "3.9.7", "unescape": "^1.0.1", - "vtex.search-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.46.0/public" + "vtex.search-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.54.0-beta.1/public" }, "devDependencies": { "@types/atob": "^2.1.2", @@ -46,7 +46,7 @@ "@types/node": "^12.0.0", "@types/qs": "^6.5.1", "@types/ramda": "^0.26.21", - "@vtex/api": "6.45.15", + "@vtex/api": "6.45.22", "@vtex/tsconfig": "^0.6.0", "eslint": "^5.15.3", "eslint-config-vtex": "^10.1.0", @@ -59,5 +59,5 @@ "vtex.rewriter": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rewriter@1.53.4/public/@types/vtex.rewriter", "vtex.search-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.46.0/public/@types/vtex.search-graphql" }, - "version": "1.65.1" + "version": "1.67.1" } diff --git a/node/resolvers/search/index.ts b/node/resolvers/search/index.ts index 1f3bc484..3b08a149 100644 --- a/node/resolvers/search/index.ts +++ b/node/resolvers/search/index.ts @@ -37,7 +37,6 @@ import { convertOrderBy, } from '../../commons/compatibility-layer' import { getWorkspaceSearchParamsFromStorage } from '../../routes/workspaceSearchParams' - interface ProductIndentifier { field: 'id' | 'slug' | 'ean' | 'reference' | 'sku' value: string @@ -540,6 +539,51 @@ export const queries = { } }, + sponsoredProducts: async (_: any, args: ProductSearchInput, ctx: any) => { + const [shippingOptions, facets] = getShippingOptionsFromSelectedFacets(args.selectedFacets) + args.selectedFacets = facets + + args = (await getCompatibilityArgsFromSelectedFacets( + ctx, + args + )) as ProductSearchInput + + if (!validMapAndQuery(args.query, args.map)) { + ctx.vtex.logger.warn({ + message: 'Invalid map or query', + query: args.query, + map: args.map + }) + } + + const { intelligentSearchApi } = ctx.clients + const { + selectedFacets, + fullText + } = args + + const workspaceSearchParams = await getWorkspaceSearchParamsFromStorage(ctx) + + const biggyArgs: {[key:string]: any} = { + ...args, + query: fullText, + sort: convertOrderBy(args.orderBy), + ...args.options, + ...workspaceSearchParams, + } + + // unnecessary field. It's is an object and breaks the @vtex/api cache + delete biggyArgs.selectedFacets + + const result = await intelligentSearchApi.sponsoredProducts({...biggyArgs}, buildAttributePath(selectedFacets), shippingOptions) + + if (ctx.vtex.tenant && !args.productOriginVtex) { + ctx.translated = result.translated + } + + return result + }, + productRecommendations: async ( _: any, { identifier, type, groupByProduct = true }: ProductRecommendationArg, diff --git a/node/resolvers/search/product.ts b/node/resolvers/search/product.ts index 35f518d4..d9fec90a 100644 --- a/node/resolvers/search/product.ts +++ b/node/resolvers/search/product.ts @@ -209,14 +209,17 @@ export const resolvers = { }, properties: async (product: SearchProduct, _: unknown, ctx: Context) => { + let valuesUntranslated = [] + if (product.origin === 'intelligent-search') { - return product.properties + valuesUntranslated = product.properties ?? [] + } else { + valuesUntranslated = (product.allSpecifications ?? []).map((name: string) => { + const value = (product as unknown as DynamicKey)[name] + return { name, originalName: name, values: value } + }) } - const valuesUntranslated = (product.allSpecifications ?? []).map((name: string) => { - const value = (product as unknown as DynamicKey)[name] - return { name, originalName: name, values: value } - }) if (!shouldTranslateToUserLocale(ctx)) { return valuesUntranslated } diff --git a/node/tsconfig.json b/node/tsconfig.json index cd249d19..8b85e768 100644 --- a/node/tsconfig.json +++ b/node/tsconfig.json @@ -1,7 +1,14 @@ { "extends": "@vtex/tsconfig", - "include": ["./typings/*.d.ts", "./**/*.tsx", "./**/*.ts"], + "include": [ + "./typings/*.d.ts", + "./**/*.tsx", + "./**/*.ts" + ], "compilerOptions": { - "types": ["node", "jest"] + "types": [ + "node", + "jest" + ] } } diff --git a/node/utils/i18n.ts b/node/utils/i18n.ts index a2c2b9b7..4df3e1e5 100644 --- a/node/utils/i18n.ts +++ b/node/utils/i18n.ts @@ -3,6 +3,7 @@ import { parseTranslatableStringV2, createMessagesLoader, } from '@vtex/api' +import { logDegradedSearchError } from '../resolvers/search/utils' export const formatTranslatableProp = (prop: P, idProp: I) => (root: R, _: unknown, ctx: Context) => addContextToTranslatableString( @@ -34,16 +35,25 @@ export const addContextToTranslatableString = (message: Message, ctx: Context) = return message.content } - const { - content, - context: originalContext, - from: originalFrom - } = parseTranslatableStringV2(message.content) - const context = (originalContext || message.context)?.toString() - const from = originalFrom || message.from || locale - - return formatTranslatableStringV2({ content, context, from }) + try { + const { + content, + context: originalContext, + from: originalFrom + } = parseTranslatableStringV2(message.content) + + const context = (originalContext || message.context)?.toString() + const from = originalFrom || message.from || locale + return formatTranslatableStringV2({ content, context, from }) + } catch (e) { + logDegradedSearchError(ctx.vtex.logger, { + service: 'node-vtex-api translation', + error: 'Error when trying to add context to translatable string', + errorStack: e, + }) + return message.content + } } export const translateToCurrentLanguage = (message: MessageWithContext, ctx: Context) => { @@ -78,4 +88,4 @@ export const shouldTranslateToBinding = ({ translated, vtex: { binding, tenant } binding && binding?.locale !== tenant?.locale && (!translated || ignoreIndexedTranslation) export const shouldTranslateToTenantLocale = ({ vtex: { locale, tenant } }: Context) => - Boolean(tenant?.locale && locale && tenant.locale !== locale) \ No newline at end of file + Boolean(tenant?.locale && locale && tenant.locale !== locale) diff --git a/node/yarn.lock b/node/yarn.lock index 3750f875..7abe0a79 100644 --- a/node/yarn.lock +++ b/node/yarn.lock @@ -780,10 +780,10 @@ lodash.unescape "4.0.1" semver "5.5.0" -"@vtex/api@6.45.15": - version "6.45.15" - resolved "https://registry.yarnpkg.com/@vtex/api/-/api-6.45.15.tgz#aa987d22f7df16ce2861130deda6ffd63156817b" - integrity sha512-Rg1VGDzJ4hHUNp1vSidMdGGPojr1PikMTptlZsJ3oNZVdEo4cPx2l8ZcAEwHWORL7QjPjXaEgmeA5ZOSf+boCQ== +"@vtex/api@6.45.22": + version "6.45.22" + resolved "https://registry.yarnpkg.com/@vtex/api/-/api-6.45.22.tgz#fa9bbfde1a4d4fbbaf6cce9f6dbc9bb9ee929ba3" + integrity sha512-g5cGUDhF4FADgSMpQmce/bnIZumwGlPG2cabwbQKIQ+cCFMZqOEM/n+YQb1+S8bCyHkzW3u/ZABoyCKi5/nxxg== dependencies: "@types/koa" "^2.11.0" "@types/koa-compose" "^3.2.3" @@ -803,7 +803,7 @@ fs-extra "^7.0.0" graphql "^14.5.8" graphql-tools "^4.0.6" - graphql-upload "^8.1.0" + graphql-upload "^13.0.0" jaeger-client "^3.18.0" js-base64 "^2.5.1" koa "^2.11.0" @@ -814,7 +814,7 @@ mime-types "^2.1.12" opentracing "^0.14.4" p-limit "^2.2.0" - prom-client "^12.0.0" + prom-client "^14.2.0" qs "^6.5.1" querystring "^0.2.0" ramda "^0.26.0" @@ -838,10 +838,10 @@ resolved "https://registry.yarnpkg.com/@vtex/tsconfig/-/tsconfig-0.6.0.tgz#c9dfffc95d2ef55195237411f9c15269ca30b2a5" integrity sha512-SVQBxaSdEVdpJFja1aVTIiZBgpQKePyYOUWGzcYq6LYkSWqSbz2LoC7TuLUsmfweYmVkv8+4eVuxcDpQVEpq1A== -"@vtex/vtexis-compatibility-layer@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@vtex/vtexis-compatibility-layer/-/vtexis-compatibility-layer-0.2.5.tgz#74875544688fb0f22ecf3e72b6391e149cd2c83c" - integrity sha512-7oz/JziJYIPGBx4Of1H88JLsU4KIMYvmcWKRSwfB6+Ao0ZLA0uPDmO8sUo40DOuZQdRHVeBJTMWtRV5+c6dtSQ== +"@vtex/vtexis-compatibility-layer@^1.2.13": + version "1.2.13" + resolved "https://registry.yarnpkg.com/@vtex/vtexis-compatibility-layer/-/vtexis-compatibility-layer-1.2.13.tgz#0f9154451b34fd90faa5e2e7018315f7c5def823" + integrity sha512-3nH/zHzZEGXh9mo+FVJXaV8PbIatbVoYZZRtVWvYsFwzUkBPOYEiXCjYBlWt/AVWxlyJtqBRXMKrqTiVq46fng== dependencies: ramda "^0.27.1" @@ -2311,10 +2311,10 @@ fresh@~0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -fs-capacitor@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-2.0.4.tgz#5a22e72d40ae5078b4fe64fe4d08c0d3fc88ad3c" - integrity sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA== +fs-capacitor@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-6.2.0.tgz#fa79ac6576629163cb84561995602d8999afb7f5" + integrity sha512-nKcE1UduoSKX27NSZlg879LdQc94OtbOsEmKMN2MBNudXREvijRKx2GEBsTMTfws+BrbkJoEuynbGSVRSpauvw== fs-constants@^1.0.0: version "1.0.0" @@ -2429,15 +2429,15 @@ graphql-tools@^4.0.6: iterall "^1.1.3" uuid "^3.1.0" -graphql-upload@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/graphql-upload/-/graphql-upload-8.1.0.tgz#6d0ab662db5677a68bfb1f2c870ab2544c14939a" - integrity sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q== +graphql-upload@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/graphql-upload/-/graphql-upload-13.0.0.tgz#1a255b64d3cbf3c9f9171fa62a8fb0b9b59bb1d9" + integrity sha512-YKhx8m/uOtKu4Y1UzBFJhbBGJTlk7k4CydlUUiNrtxnwZv0WigbRHP+DVhRNKt7u7DXOtcKZeYJlGtnMXvreXA== dependencies: busboy "^0.3.1" - fs-capacitor "^2.0.4" - http-errors "^1.7.3" - object-path "^0.11.4" + fs-capacitor "^6.2.0" + http-errors "^1.8.1" + object-path "^0.11.8" graphql@*, graphql@^14.5.8, graphql@^14.7.0: version "14.7.0" @@ -2547,7 +2547,7 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.7.2" -http-errors@1.7.3, http-errors@^1.3.1, http-errors@^1.6.3, http-errors@^1.7.3, http-errors@~1.7.2: +http-errors@1.7.3, http-errors@^1.3.1, http-errors@^1.6.3, http-errors@~1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== @@ -2558,6 +2558,17 @@ http-errors@1.7.3, http-errors@^1.3.1, http-errors@^1.6.3, http-errors@^1.7.3, h statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +http-errors@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -3864,10 +3875,10 @@ object-keys@^1.0.12: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-path@^0.11.4: - version "0.11.4" - resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949" - integrity sha1-NwrnUvvzfePqcKhhwju6iRVpGUk= +object-path@^0.11.8: + version "0.11.8" + resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.8.tgz#ed002c02bbdd0070b78a27455e8ae01fc14d4742" + integrity sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA== object-visit@^1.0.0: version "1.0.1" @@ -4123,10 +4134,10 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -prom-client@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-12.0.0.tgz#9689379b19bd3f6ab88a9866124db9da3d76c6ed" - integrity sha512-JbzzHnw0VDwCvoqf8y1WDtq4wSBAbthMB1pcVI/0lzdqHGJI3KBJDXle70XK+c7Iv93Gihqo0a5LlOn+g8+DrQ== +prom-client@^14.2.0: + version "14.2.0" + resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-14.2.0.tgz#ca94504e64156f6506574c25fb1c34df7812cf11" + integrity sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA== dependencies: tdigest "^0.1.1" @@ -4496,6 +4507,11 @@ setprototypeof@1.1.1: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -4668,7 +4684,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -stats-lite@vtex/node-stats-lite#dist: +"stats-lite@github:vtex/node-stats-lite#dist": version "2.2.0" resolved "https://codeload.github.com/vtex/node-stats-lite/tar.gz/1b0d39cc41ef7aaecfd541191f877887a2044797" dependencies: @@ -4944,6 +4960,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + tokenbucket@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/tokenbucket/-/tokenbucket-0.3.2.tgz#8172b2b58e3083acc8d914426fed15162a3a8e90" @@ -5228,9 +5249,9 @@ verror@1.10.0: version "1.53.4" resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rewriter@1.53.4/public/@types/vtex.rewriter#6348993efde4106196bca60fd40dba00b3a354b6" -"vtex.search-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.46.0/public": +"vtex.search-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.54.0-beta.1/public": version "0.0.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.46.0/public#9ebc3c5137c43b94205c6e8a9b7b0262fc7c0eff" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.54.0-beta.1/public#0804c2c849202332395756f4601f281a54390268" w3c-hr-time@^1.0.1: version "1.0.1"