@base44/app-plugin-commerce 0.1.13 → 0.1.15

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.
@@ -264,13 +264,31 @@ export function priceRange(product, variations, selection = {}) {
264
264
  return { min: Math.min(...prices), max: Math.max(...prices), on_sale: onSale, count: prices.length };
265
265
  }
266
266
 
267
+ /**
268
+ * Normalize a stored image entry to the one shape the UI renders. Stored images
269
+ * are not uniform — product images carry `position`, variation images don't,
270
+ * and no sub-field is required by the schema — so this guarantees consumers
271
+ * `{src, name, alt}` with a non-empty `src`, or `null` when there is nothing
272
+ * renderable. Run gallery entries through it too: `product.images.map(normalizeImage)`.
273
+ *
274
+ * @param {object|null|undefined} img a stored image entry (`product.images[n]` or `variation.image`)
275
+ * @returns {{src: string, name: string, alt: string}|null}
276
+ */
277
+ export function normalizeImage(img) {
278
+ const src = typeof img?.src === "string" ? img.src.trim() : "";
279
+ if (!src) return null;
280
+ const name = img.name ?? "";
281
+ return { src, name, alt: img.alt || name };
282
+ }
283
+
267
284
  /**
268
285
  * The fields to display for the current state, resolved variation-first with a
269
286
  * fallback to the parent. `image` is the variation's own image when it has one
270
287
  * — highlight it in the gallery rather than replacing the gallery.
271
288
  *
272
- * `image` is `{src, name, alt}`, or `null` when the product has no images at all
273
- * — the one case needing a UI placeholder.
289
+ * `image` is **always** the normalized `{src, name, alt}` (never a raw stored
290
+ * entry — see `normalizeImage`), or `null` when neither the variation nor the
291
+ * product has a renderable image — the one case needing a UI placeholder.
274
292
  *
275
293
  * @returns {{price: number|null, regular_price: number|null, sale_price: number|null,
276
294
  * on_sale: boolean, sku: string, stock_status: string,
@@ -296,7 +314,7 @@ export function displayFields(product, variation) {
296
314
  ? (variation.manage_stock === "yes" ? (variation.stock_quantity ?? null) : (product?.stock_quantity ?? null))
297
315
  : (product?.stock_quantity ?? null),
298
316
  backorders: pick("backorders", "no"),
299
- image: variation?.image?.src ? variation.image : (product?.images?.[0] ?? null),
317
+ image: normalizeImage(variation?.image) ?? normalizeImage(product?.images?.[0]),
300
318
  weight: pick("weight"),
301
319
  dimensions: pick("dimensions"),
302
320
  description: variation?.description || product?.description || "",