Skip to content

Commit

Permalink
Merge branch 'main' into links
Browse files Browse the repository at this point in the history
  • Loading branch information
maxakuru committed Nov 21, 2024
2 parents 5966284 + e94c004 commit 116ee55
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 45 deletions.
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
# [1.7.0](https://github.com/adobe-rnd/helix-commerce-api/compare/v1.6.7...v1.7.0) (2024-11-21)


### Features

* use content-source-location ([#52](https://github.com/adobe-rnd/helix-commerce-api/issues/52)) ([d6527be](https://github.com/adobe-rnd/helix-commerce-api/commit/d6527be6bf32a4ce93af444cc4ef479b152afebe))

## [1.6.7](https://github.com/adobe-rnd/helix-commerce-api/compare/v1.6.6...v1.6.7) (2024-11-19)


### Bug Fixes

* don't assume uppercase skus ([#51](https://github.com/adobe-rnd/helix-commerce-api/issues/51)) ([a3d1dc7](https://github.com/adobe-rnd/helix-commerce-api/commit/a3d1dc7dd757c473bf503bb628b4a01bbb3b864d))

## [1.6.6](https://github.com/adobe-rnd/helix-commerce-api/compare/v1.6.5...v1.6.6) (2024-11-19)


### Bug Fixes

* json-ld tweaks ([#49](https://github.com/adobe-rnd/helix-commerce-api/issues/49)) ([45971c6](https://github.com/adobe-rnd/helix-commerce-api/commit/45971c69e65b43984d24397cbf0d3367d195e0f1))

## [1.6.5](https://github.com/adobe-rnd/helix-commerce-api/compare/v1.6.4...v1.6.5) (2024-11-18)


### Bug Fixes

* throw if no price range on product or variant ([#50](https://github.com/adobe-rnd/helix-commerce-api/issues/50)) ([8469058](https://github.com/adobe-rnd/helix-commerce-api/commit/8469058c82dace3cc843afbb5b89d6e5d13e57e5))

## [1.6.4](https://github.com/adobe-rnd/helix-commerce-api/compare/v1.6.3...v1.6.4) (2024-11-15)


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "helix-commerce-api",
"version": "1.6.4",
"version": "1.7.0",
"private": true,
"description": "API for markup content and a commerce graphql commerce proxy",
"main": "src/index.js",
Expand Down
33 changes: 22 additions & 11 deletions src/content/adobe-commerce.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ async function fetchProduct(sku, config) {
const product = productAdapter(config, productData);
return product;
} catch (e) {
console.error('failed to parse product: ', e);
if (e.response) {
throw errorWithResponse(e.response.status, e.message);
}
throw errorWithResponse(500, 'failed to parse product response');
}
}
Expand Down Expand Up @@ -102,7 +104,9 @@ async function fetchVariants(sku, config) {
const { variants } = json?.data?.variants ?? {};
return variantsAdapter(config, variants);
} catch (e) {
console.error('failed to parse variants: ', e);
if (e.response) {
throw errorWithResponse(e.response.status, e.message);
}
throw errorWithResponse(500, 'failed to parse variants response');
}
}
Expand Down Expand Up @@ -147,6 +151,9 @@ async function lookupProductSKU(urlkey, config) {
return product.sku;
} catch (e) {
console.error('failed to parse product sku: ', e);
if (e.response) {
throw errorWithResponse(e.response.status, e.message);
}
throw errorWithResponse(500, 'failed to parse product sku response');
}
}
Expand All @@ -160,22 +167,26 @@ export async function handle(ctx) {
const { urlkey } = config.params;
let { sku } = config.params;

if (!sku && !urlkey) {
return errorResponse(404, 'missing sku or urlkey');
} else if (!sku && !config.coreEndpoint) {
return errorResponse(400, 'missing sku and coreEndpoint');
const cslParams = new URLSearchParams(ctx.info.headers['x-content-source-location'] ?? '');
if (cslParams.has('sku')) {
// prefer sku from content-source-location
sku = cslParams.get('sku');
} else if (urlkey && config.coreEndpoint) {
// lookup sku by urlkey with core
sku = await lookupProductSKU(urlkey, config);
}

if (!sku && !config.coreEndpoint) {
return errorResponse(400, 'missing sku and coreEndpoint');
}
if (!sku) {
// lookup sku by urlkey with core
// TODO: test if livesearch if enabled
sku = await lookupProductSKU(urlkey, config);
return errorResponse(404, 'could not find sku');
}

// const product = await fetchProductCore({ sku }, config);
const [product, variants] = await Promise.all([
fetchProduct(sku.toUpperCase(), config),
fetchVariants(sku.toUpperCase(), config),
fetchProduct(sku, config),
fetchVariants(sku, config),
]);
const html = htmlTemplateFromContext(ctx, product, variants).render();
return new Response(html, {
Expand Down
6 changes: 5 additions & 1 deletion src/content/queries/cs-product.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/

import { forceImagesHTTPS } from '../../utils/http.js';
import { errorWithResponse, forceImagesHTTPS } from '../../utils/http.js';
import { gql, parseRating, parseSpecialToDate } from '../../utils/product.js';

/**
Expand Down Expand Up @@ -91,6 +91,10 @@ export const adapter = (config, productData) => {
} : null,
};

if (!minPrice && !maxPrice) {
throw errorWithResponse(400, 'no product price range found');
}

if (config.attributeOverrides?.product) {
Object.entries(config.attributeOverrides.product).forEach(([key, value]) => {
product.attributeMap[key] = product.attributeMap[value] ?? product[key];
Expand Down
22 changes: 13 additions & 9 deletions src/content/queries/cs-variants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/

import { forceImagesHTTPS } from '../../utils/http.js';
import { errorWithResponse, forceImagesHTTPS } from '../../utils/http.js';
import { gql, parseRating, parseSpecialToDate } from '../../utils/product.js';

/**
Expand All @@ -37,22 +37,26 @@ export const adapter = (config, variants) => variants.map(({ selections, product
prices: {
regular: {
// TODO: determine whether to use min or max
amount: minPrice.regular.amount.value,
currency: minPrice.regular.amount.currency,
maximumAmount: maxPrice.regular.amount.value,
minimumAmount: minPrice.regular.amount.value,
amount: minPrice?.regular.amount.value,
currency: minPrice?.regular.amount.currency,
maximumAmount: maxPrice?.regular.amount.value,
minimumAmount: minPrice?.regular.amount.value,
},
final: {
// TODO: determine whether to use min or max
amount: minPrice.final.amount.value,
currency: minPrice.final.amount.currency,
maximumAmount: maxPrice.final.amount.value,
minimumAmount: minPrice.final.amount.value,
amount: minPrice?.final.amount.value,
currency: minPrice?.final.amount.currency,
maximumAmount: maxPrice?.final.amount.value,
minimumAmount: minPrice?.final.amount.value,
},
},
selections: (selections ?? []).sort(),
};

if (!minPrice && !maxPrice) {
throw errorWithResponse(400, 'no variant price range found');
}

if (config.attributeOverrides?.variant) {
Object.entries(config.attributeOverrides.variant).forEach(([key, value]) => {
variant.attributeMap[key] = variant.attributeMap[value] ?? variant[key];
Expand Down
5 changes: 4 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ export function makeContext(pctx, req, env) {
ctx.log = console;
ctx.info = {
method: req.method,
headers: Object.fromEntries(req.headers),
headers: Object.fromEntries(
[...req.headers.entries()]
.map(([k, v]) => [k.toLowerCase(), v]),
),
};
return ctx;
}
Expand Down
2 changes: 1 addition & 1 deletion src/templates/json/JSONTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class JSONTemplate {
if (variant) {
const offerVariantURLTemplate = matchedPathConfig?.offerVariantURLTemplate;
if (!offerVariantURLTemplate) {
return `${productUrl}/?optionsUIDs=${encodeURIComponent(variant.selections.join(','))}`;
return `${productUrl}?optionsUIDs=${encodeURIComponent(variant.selections.join(','))}`;
}

const variantPath = offerVariantURLTemplate
Expand Down
3 changes: 2 additions & 1 deletion src/templates/json/overrides/wilson-ecommerce--wilson.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export default class extends JSONTemplate {
* @param {Variant} [variant]
*/
constructMPN(variant) {
return variant ? variant.sku : this.product.sku;
// only include mpn on product-level
return variant ? undefined : this.product.sku;
}

renderOffers() {
Expand Down
30 changes: 15 additions & 15 deletions test/fixtures/post-deploy/bella-tank.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
{
"@type": "Offer",
"sku": "WT01-L-Black",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzI%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzI%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-black_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -55,7 +55,7 @@
{
"@type": "Offer",
"sku": "WT01-L-Blue",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzI%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzI%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-blue_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -64,7 +64,7 @@
{
"@type": "Offer",
"sku": "WT01-L-Orange",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzI%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzI%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-orange_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -73,7 +73,7 @@
{
"@type": "Offer",
"sku": "WT01-M-Black",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81Mjk%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81Mjk%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-black_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -82,7 +82,7 @@
{
"@type": "Offer",
"sku": "WT01-M-Blue",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81Mjk%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81Mjk%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-blue_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -91,7 +91,7 @@
{
"@type": "Offer",
"sku": "WT01-M-Orange",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81Mjk%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81Mjk%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-orange_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -100,7 +100,7 @@
{
"@type": "Offer",
"sku": "WT01-S-Black",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjY%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjY%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-black_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -109,7 +109,7 @@
{
"@type": "Offer",
"sku": "WT01-S-Blue",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjY%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjY%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-blue_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -118,7 +118,7 @@
{
"@type": "Offer",
"sku": "WT01-S-Orange",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjY%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjY%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-orange_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -127,7 +127,7 @@
{
"@type": "Offer",
"sku": "WT01-XL-Black",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzU%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzU%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-black_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -136,7 +136,7 @@
{
"@type": "Offer",
"sku": "WT01-XL-Blue",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzU%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzU%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-blue_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -145,7 +145,7 @@
{
"@type": "Offer",
"sku": "WT01-XL-Orange",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzU%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81MzU%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-orange_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -154,7 +154,7 @@
{
"@type": "Offer",
"sku": "WT01-XS-Black",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjM%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzI%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjM%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-black_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -163,7 +163,7 @@
{
"@type": "Offer",
"sku": "WT01-XS-Blue",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjM%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xNzU%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjM%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-blue_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand All @@ -172,7 +172,7 @@
{
"@type": "Offer",
"sku": "WT01-XS-Orange",
"url": "https://example.test/products/bella-tank/wt01/?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjM%3D",
"url": "https://example.test/products/bella-tank/wt01?optionsUIDs=Y29uZmlndXJhYmxlLzI3Ny8xOTM%3D%2CY29uZmlndXJhYmxlLzU1Ni81MjM%3D",
"image": "https://www.aemshop.net/media/catalog/product/w/t/wt01-orange_main_1.jpg",
"availability": "InStock",
"price": 29,
Expand Down
6 changes: 3 additions & 3 deletions test/templates/json/JSONTemplate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ describe('JSONTemplate', () => {

// @ts-ignore
const url = template.constructProductURL(variant1);
const expectedUrl = 'https://www.example.com/products/utopia-small-pendant/kw5531/?optionsUIDs=Y29uZmlndXJhYmxlLzE2NTEvODI3MQ%3D%3D';
const expectedUrl = 'https://www.example.com/products/utopia-small-pendant/kw5531?optionsUIDs=Y29uZmlndXJhYmxlLzE2NTEvODI3MQ%3D%3D';
assert.strictEqual(url, expectedUrl, 'Variant URL without offerVariantURLTemplate does not match expected URL');
});

Expand All @@ -97,7 +97,7 @@ describe('JSONTemplate', () => {

// @ts-ignore
const url = template.constructProductURL(variantWithSpecialSelections);
const expectedUrl = 'https://www.example.com/products/summer-sun/kw%2055%2F31/?optionsUIDs=Y29uZmlndXJhYmxlLzE2NTEvODI3MQ%3D%3D%2CY29uZmlndXJhYmxlLzI0NjEvMzYzNDE%3D';
const expectedUrl = 'https://www.example.com/products/summer-sun/kw%2055%2F31?optionsUIDs=Y29uZmlndXJhYmxlLzE2NTEvODI3MQ%3D%3D%2CY29uZmlndXJhYmxlLzI0NjEvMzYzNDE%3D';
assert.strictEqual(url, expectedUrl, 'Variant URL with special characters does not match expected URL');
});

Expand All @@ -114,7 +114,7 @@ describe('JSONTemplate', () => {
}), product1, [variantEmptySelections]);
// @ts-ignore
const url = template.constructProductURL(variantEmptySelections);
const expectedUrl = 'https://www.example.com/products/utopia-small-pendant/kw5531/?optionsUIDs=';
const expectedUrl = 'https://www.example.com/products/utopia-small-pendant/kw5531?optionsUIDs=';
assert.strictEqual(url, expectedUrl, 'URL with empty variant selections does not match expected URL');
});

Expand Down

0 comments on commit 116ee55

Please sign in to comment.