medusa-storefront-data 2.4.0 → 2.5.1
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.
- package/HOMEPAGE_CONFIG.md +38 -4
- package/dist/src/dynamic-config-schema/index.d.ts +103 -0
- package/dist/src/dynamic-config-schema/index.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/index.js +172 -0
- package/dist/src/dynamic-config-schema/sections/about-brand.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/about-brand.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/about-brand.js +30 -0
- package/dist/src/dynamic-config-schema/sections/baptism-picks.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/baptism-picks.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/baptism-picks.js +17 -0
- package/dist/src/dynamic-config-schema/sections/baptism.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/baptism.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/baptism.js +4 -0
- package/dist/src/dynamic-config-schema/sections/blog-posts.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/blog-posts.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/blog-posts.js +31 -0
- package/dist/src/dynamic-config-schema/sections/brand-marquee.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/brand-marquee.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/brand-marquee.js +9 -0
- package/dist/src/dynamic-config-schema/sections/brand-pillars.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/brand-pillars.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/brand-pillars.js +29 -0
- package/dist/src/dynamic-config-schema/sections/category-pills.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/category-pills.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/category-pills.js +4 -0
- package/dist/src/dynamic-config-schema/sections/celebrity-trust.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/celebrity-trust.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/celebrity-trust.js +4 -0
- package/dist/src/dynamic-config-schema/sections/features.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/features.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/features.js +12 -0
- package/dist/src/dynamic-config-schema/sections/hero.d.ts +6 -0
- package/dist/src/dynamic-config-schema/sections/hero.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/hero.js +9 -0
- package/dist/src/dynamic-config-schema/sections/index.d.ts +24 -0
- package/dist/src/dynamic-config-schema/sections/index.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/index.js +23 -0
- package/dist/src/dynamic-config-schema/sections/instagram-posts.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/instagram-posts.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/instagram-posts.js +30 -0
- package/dist/src/dynamic-config-schema/sections/loved-by-moms.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/loved-by-moms.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/loved-by-moms.js +4 -0
- package/dist/src/dynamic-config-schema/sections/luxe-favourites.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/luxe-favourites.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/luxe-favourites.js +4 -0
- package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.js +12 -0
- package/dist/src/dynamic-config-schema/sections/new-arrivals.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/new-arrivals.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/new-arrivals.js +12 -0
- package/dist/src/dynamic-config-schema/sections/promo-announcements.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/promo-announcements.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/promo-announcements.js +16 -0
- package/dist/src/dynamic-config-schema/sections/promo-countdown.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/promo-countdown.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/promo-countdown.js +16 -0
- package/dist/src/dynamic-config-schema/sections/shop-by-age.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/shop-by-age.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/shop-by-age.js +4 -0
- package/dist/src/dynamic-config-schema/sections/shop-by-category.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/shop-by-category.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/shop-by-category.js +4 -0
- package/dist/src/dynamic-config-schema/sections/testimonials.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/testimonials.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/testimonials.js +9 -0
- package/dist/src/dynamic-config-schema/sections/theme-dresses.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/theme-dresses.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/theme-dresses.js +4 -0
- package/dist/src/dynamic-config-schema/sections/video-stories.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/video-stories.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/video-stories.js +24 -0
- package/dist/src/dynamic-config-schema/sections/why-choose-us.d.ts +5 -0
- package/dist/src/dynamic-config-schema/sections/why-choose-us.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/sections/why-choose-us.js +9 -0
- package/dist/src/dynamic-config-schema/shared.d.ts +35 -0
- package/dist/src/dynamic-config-schema/shared.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/shared.js +99 -0
- package/dist/src/dynamic-config-schema/site-configs.d.ts +11 -0
- package/dist/src/dynamic-config-schema/site-configs.d.ts.map +1 -0
- package/dist/src/dynamic-config-schema/site-configs.js +70 -0
- package/dist/src/server/brand-pillars-from-categories.d.ts +8 -0
- package/dist/src/server/brand-pillars-from-categories.d.ts.map +1 -0
- package/dist/src/server/brand-pillars-from-categories.js +92 -0
- package/dist/src/server/cart.js +20 -20
- package/dist/src/server/customer.js +11 -11
- package/dist/src/server/dynamic-config-api.d.ts +11 -0
- package/dist/src/server/dynamic-config-api.d.ts.map +1 -0
- package/dist/src/server/dynamic-config-api.js +46 -0
- package/dist/src/server/dynamic-config.d.ts +1 -84
- package/dist/src/server/dynamic-config.d.ts.map +1 -1
- package/dist/src/server/dynamic-config.js +0 -130
- package/dist/src/server/fulfillment.js +3 -3
- package/dist/src/server/home.d.ts +4 -15
- package/dist/src/server/home.d.ts.map +1 -1
- package/dist/src/server/home.js +1 -122
- package/dist/src/server/normalize-homepage-config.d.ts +7 -0
- package/dist/src/server/normalize-homepage-config.d.ts.map +1 -0
- package/dist/src/server/normalize-homepage-config.js +213 -0
- package/dist/src/server/orders.js +6 -6
- package/dist/src/server/page-input.d.ts.map +1 -1
- package/dist/src/server/page-input.js +3 -1
- package/dist/src/server/payment-details.js +5 -5
- package/dist/src/server/payment.js +2 -2
- package/dist/src/server/regions.js +2 -2
- package/dist/src/server/shoppable-looks.js +1 -1
- package/dist/src/util/store-client.d.ts +0 -2
- package/dist/src/util/store-client.d.ts.map +1 -1
- package/dist/src/util/store-client.js +0 -2
- package/package.json +1 -156
- package/src/server/brand-pillars-from-categories.ts +156 -0
- package/src/server/cart.ts +20 -20
- package/src/server/customer.ts +11 -11
- package/src/server/dynamic-config.ts +1 -172
- package/src/server/fulfillment.ts +3 -3
- package/src/server/home.ts +36 -211
- package/src/server/normalize-homepage-config.ts +240 -0
- package/src/server/orders.ts +6 -6
- package/src/server/page-input.ts +3 -1
- package/src/server/payment-details.ts +5 -5
- package/src/server/payment.ts +2 -2
- package/src/server/regions.ts +2 -2
- package/src/server/shoppable-looks.ts +1 -1
- package/src/util/store-client.ts +0 -3
|
@@ -42,42 +42,6 @@ export function getLogoFromPageInput(pageInput) {
|
|
|
42
42
|
const config = resolvePageInput(pageInput);
|
|
43
43
|
return config.logo || null;
|
|
44
44
|
}
|
|
45
|
-
/** @deprecated Fetch in main project; pass `pageInput` into layout/pages instead. */
|
|
46
|
-
export const getLogoFromConfig = async () => {
|
|
47
|
-
const config = await getDynamicConfig();
|
|
48
|
-
return getLogoFromPageInput(config?.["homepage-config"] ?? null);
|
|
49
|
-
};
|
|
50
|
-
export const getBannerImageFromConfig = async () => {
|
|
51
|
-
try {
|
|
52
|
-
const config = await getDynamicConfig();
|
|
53
|
-
const bannerArray = config?.["homepage-config"]?.["homepage-banner-array"];
|
|
54
|
-
if (bannerArray && bannerArray.length > 0) {
|
|
55
|
-
const firstBanner = bannerArray[0];
|
|
56
|
-
const image = firstBanner?.["homepage-banner"]?.["homepage-banner-image"];
|
|
57
|
-
return image || null;
|
|
58
|
-
}
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
export const getMobileBannerFromConfig = async () => {
|
|
66
|
-
try {
|
|
67
|
-
const config = await getDynamicConfig();
|
|
68
|
-
const bannerArray = config?.["homepage-config"]?.["app-banner-array"];
|
|
69
|
-
if (bannerArray && bannerArray.length > 0) {
|
|
70
|
-
const firstBanner = bannerArray[0];
|
|
71
|
-
const image = firstBanner?.["app-banner"]?.["app-banner-image"] || null;
|
|
72
|
-
const link = firstBanner?.["app-banner"]?.["app-banner-button-link"] || firstBanner?.["app-banner"]?.["app-banner-link"] || null;
|
|
73
|
-
return { image, link };
|
|
74
|
-
}
|
|
75
|
-
return { image: null, link: null };
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
return { image: null, link: null };
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
45
|
export function getHomeBannersFromPageInput(pageInput) {
|
|
82
46
|
const config = resolvePageInput(pageInput);
|
|
83
47
|
const bannerArray = config["homepage-banner-array"];
|
|
@@ -114,31 +78,12 @@ export function getAppBannersFromPageInput(pageInput) {
|
|
|
114
78
|
}
|
|
115
79
|
return null;
|
|
116
80
|
}
|
|
117
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
118
|
-
export const getHomeBannersFromConfig = async () => {
|
|
119
|
-
const config = await getDynamicConfig();
|
|
120
|
-
return getHomeBannersFromPageInput(config?.["homepage-config"] ?? null);
|
|
121
|
-
};
|
|
122
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
123
|
-
export const getAppBannersFromConfig = async () => {
|
|
124
|
-
const config = await getDynamicConfig();
|
|
125
|
-
return getAppBannersFromPageInput(config?.["homepage-config"] ?? null);
|
|
126
|
-
};
|
|
127
81
|
// Legacy function for backward compatibility
|
|
128
|
-
export const getMobileBannerImageFromConfig = async () => {
|
|
129
|
-
const { image } = await getMobileBannerFromConfig();
|
|
130
|
-
return image;
|
|
131
|
-
};
|
|
132
82
|
export function getWebsiteDescriptionFromPageInput(pageInput) {
|
|
133
83
|
const config = resolvePageInput(pageInput);
|
|
134
84
|
const desc = config["website-description"] || config["website_description"];
|
|
135
85
|
return desc || null;
|
|
136
86
|
}
|
|
137
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
138
|
-
export const getWebsiteDescriptionFromConfig = async () => {
|
|
139
|
-
const config = await getDynamicConfig();
|
|
140
|
-
return getWebsiteDescriptionFromPageInput(config?.["homepage-config"] ?? null);
|
|
141
|
-
};
|
|
142
87
|
/** Why choose us — defaults + `sections.whyChooseUs` override. */
|
|
143
88
|
export function getFeaturesFromPageInput(pageInput) {
|
|
144
89
|
const block = getMergedSectionBlock("whyChooseUs", pageInput);
|
|
@@ -148,11 +93,6 @@ export function getFeaturesFromPageInput(pageInput) {
|
|
|
148
93
|
const features = parseFeatureIconList(featuresRaw);
|
|
149
94
|
return { title, features };
|
|
150
95
|
}
|
|
151
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
152
|
-
export const getFeaturesFromConfig = async () => {
|
|
153
|
-
const config = await getDynamicConfig();
|
|
154
|
-
return getFeaturesFromPageInput(config?.["homepage-config"] ?? null);
|
|
155
|
-
};
|
|
156
96
|
function parseFeatureIconList(raw) {
|
|
157
97
|
if (!Array.isArray(raw))
|
|
158
98
|
return [];
|
|
@@ -280,11 +220,6 @@ export function getHomeSectionsCopyFromPageInput(pageInput) {
|
|
|
280
220
|
}
|
|
281
221
|
return copy;
|
|
282
222
|
}
|
|
283
|
-
/** @deprecated Pass `pageInput` from main project instead of fetching here. */
|
|
284
|
-
export const getHomeSectionsCopyFromConfig = async () => {
|
|
285
|
-
const config = await getDynamicConfig();
|
|
286
|
-
return getHomeSectionsCopyFromPageInput(config?.["homepage-config"] ?? null);
|
|
287
|
-
};
|
|
288
223
|
/** Trust badge row — defaults + `sections.features` override. */
|
|
289
224
|
export function getTrustFeaturesFromPageInput(pageInput) {
|
|
290
225
|
const block = getMergedSectionBlock("features", pageInput);
|
|
@@ -295,11 +230,6 @@ export function getTrustFeaturesFromPageInput(pageInput) {
|
|
|
295
230
|
const features = parseFeatureIconList(rawList);
|
|
296
231
|
return { title: title ?? null, description: description ?? null, features };
|
|
297
232
|
}
|
|
298
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
299
|
-
export const getTrustFeaturesFromConfig = async () => {
|
|
300
|
-
const config = await getDynamicConfig();
|
|
301
|
-
return getTrustFeaturesFromPageInput(config?.["homepage-config"] ?? null);
|
|
302
|
-
};
|
|
303
233
|
function normalizeBannerButtonName(value) {
|
|
304
234
|
const text = normalizeCmsText(value);
|
|
305
235
|
if (!text)
|
|
@@ -325,11 +255,6 @@ export function getContactInfoFromPageInput(pageInput) {
|
|
|
325
255
|
address: contactConfig["contact-address"],
|
|
326
256
|
};
|
|
327
257
|
}
|
|
328
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
329
|
-
export const getContactInfoFromConfig = async () => {
|
|
330
|
-
const config = await getDynamicConfig();
|
|
331
|
-
return getContactInfoFromPageInput(config?.["homepage-config"] ?? null);
|
|
332
|
-
};
|
|
333
258
|
function normalizeVideoStoryUrl(entry) {
|
|
334
259
|
if (typeof entry === "string" && entry.trim())
|
|
335
260
|
return entry.trim();
|
|
@@ -368,11 +293,6 @@ export function getVideoStoriesFromPageInput(pageInput) {
|
|
|
368
293
|
.filter((url) => Boolean(url));
|
|
369
294
|
return { title, videoUrls };
|
|
370
295
|
}
|
|
371
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
372
|
-
export const getVideoStoriesFromConfig = async () => {
|
|
373
|
-
const config = await getDynamicConfig();
|
|
374
|
-
return getVideoStoriesFromPageInput(config?.["homepage-config"] ?? null);
|
|
375
|
-
};
|
|
376
296
|
function parseTestimonialRow(item, index) {
|
|
377
297
|
if (!item || typeof item !== "object")
|
|
378
298
|
return null;
|
|
@@ -430,11 +350,6 @@ export function getTestimonialsFromPageInput(pageInput) {
|
|
|
430
350
|
}
|
|
431
351
|
return { title, subtitle, testimonials };
|
|
432
352
|
}
|
|
433
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
434
|
-
export const getTestimonialsFromConfig = async () => {
|
|
435
|
-
const config = await getDynamicConfig();
|
|
436
|
-
return getTestimonialsFromPageInput(config?.["homepage-config"] ?? null);
|
|
437
|
-
};
|
|
438
353
|
export function getSocialLinksFromPageInput(pageInput) {
|
|
439
354
|
const config = resolvePageInput(pageInput);
|
|
440
355
|
const socialLinksRaw = config["social-links"] || [];
|
|
@@ -450,11 +365,6 @@ export function getSocialLinksFromPageInput(pageInput) {
|
|
|
450
365
|
.filter((l) => l.name && l.url);
|
|
451
366
|
return socialLinks.length > 0 ? socialLinks : null;
|
|
452
367
|
}
|
|
453
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
454
|
-
export const getSocialLinksFromConfig = async () => {
|
|
455
|
-
const config = await getDynamicConfig();
|
|
456
|
-
return getSocialLinksFromPageInput(config?.["homepage-config"] ?? null);
|
|
457
|
-
};
|
|
458
368
|
export function getFaqsFromPageInput(pageInput) {
|
|
459
369
|
const config = resolvePageInput(pageInput);
|
|
460
370
|
const faqsRaw = config["faq-array"] || [];
|
|
@@ -480,20 +390,10 @@ export function getFaqsFromPageInput(pageInput) {
|
|
|
480
390
|
}));
|
|
481
391
|
return faqs.length > 0 ? faqs : null;
|
|
482
392
|
}
|
|
483
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
484
|
-
export const getFaqsFromConfig = async () => {
|
|
485
|
-
const config = await getDynamicConfig();
|
|
486
|
-
return getFaqsFromPageInput(config?.["homepage-config"] ?? null);
|
|
487
|
-
};
|
|
488
393
|
export function getAnnouncementMessagesFromPageInput(pageInput) {
|
|
489
394
|
const block = getMergedSectionBlock("promoAnnouncements", pageInput);
|
|
490
395
|
return parseAnnouncementMessages(block);
|
|
491
396
|
}
|
|
492
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
493
|
-
export const getAnnouncementMessagesFromConfig = async () => {
|
|
494
|
-
const config = await getDynamicConfig();
|
|
495
|
-
return getAnnouncementMessagesFromPageInput(config?.["homepage-config"] ?? null);
|
|
496
|
-
};
|
|
497
397
|
export function getAboutBrandFromPageInput(pageInput) {
|
|
498
398
|
const homepageConfig = resolvePageInput(pageInput);
|
|
499
399
|
const merged = getMergedSectionBlock("aboutBrand", pageInput);
|
|
@@ -523,11 +423,6 @@ export function getAboutBrandFromPageInput(pageInput) {
|
|
|
523
423
|
stats,
|
|
524
424
|
};
|
|
525
425
|
}
|
|
526
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
527
|
-
export const getAboutBrandFromConfig = async () => {
|
|
528
|
-
const config = await getDynamicConfig();
|
|
529
|
-
return getAboutBrandFromPageInput(config?.["homepage-config"] ?? null);
|
|
530
|
-
};
|
|
531
426
|
export function getBrandPillarsFromPageInput(pageInput) {
|
|
532
427
|
const block = getMergedSectionBlock("brandPillars", pageInput);
|
|
533
428
|
const copy = parseSectionCopy(block);
|
|
@@ -547,11 +442,6 @@ export function getBrandPillarsFromPageInput(pageInput) {
|
|
|
547
442
|
.filter(Boolean);
|
|
548
443
|
return { sectionTitle, pillars };
|
|
549
444
|
}
|
|
550
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
551
|
-
export const getBrandPillarsFromConfig = async () => {
|
|
552
|
-
const config = await getDynamicConfig();
|
|
553
|
-
return getBrandPillarsFromPageInput(config?.["homepage-config"] ?? null);
|
|
554
|
-
};
|
|
555
445
|
export function getBlogPostsFromPageInput(pageInput) {
|
|
556
446
|
const block = getMergedSectionBlock("blogPosts", pageInput);
|
|
557
447
|
const raw = block.posts ?? block["blog-posts"] ?? block["blog-array"] ?? [];
|
|
@@ -576,11 +466,6 @@ export function getBlogPostsFromPageInput(pageInput) {
|
|
|
576
466
|
})
|
|
577
467
|
.filter(Boolean);
|
|
578
468
|
}
|
|
579
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
580
|
-
export const getBlogPostsFromConfig = async () => {
|
|
581
|
-
const config = await getDynamicConfig();
|
|
582
|
-
return getBlogPostsFromPageInput(config?.["homepage-config"] ?? null);
|
|
583
|
-
};
|
|
584
469
|
function readPromoCountdownBlock(block) {
|
|
585
470
|
if (!block || typeof block !== "object") {
|
|
586
471
|
return {
|
|
@@ -617,11 +502,6 @@ export function getPromoCountdownFromPageInput(pageInput) {
|
|
|
617
502
|
ctaHref: fromBlock.ctaHref ?? defaults.ctaHref,
|
|
618
503
|
};
|
|
619
504
|
}
|
|
620
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
621
|
-
export const getPromoCountdownFromConfig = async () => {
|
|
622
|
-
const config = await getDynamicConfig();
|
|
623
|
-
return getPromoCountdownFromPageInput(config?.["homepage-config"] ?? null);
|
|
624
|
-
};
|
|
625
505
|
function parseInstagramPostRow(item, index) {
|
|
626
506
|
if (!item || typeof item !== "object")
|
|
627
507
|
return null;
|
|
@@ -680,11 +560,6 @@ export function getInstagramPostsFromPageInput(pageInput) {
|
|
|
680
560
|
posts,
|
|
681
561
|
};
|
|
682
562
|
}
|
|
683
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
684
|
-
export const getInstagramPostsFromConfig = async () => {
|
|
685
|
-
const config = await getDynamicConfig();
|
|
686
|
-
return getInstagramPostsFromPageInput(config?.["homepage-config"] ?? null);
|
|
687
|
-
};
|
|
688
563
|
export { DEFAULT_HOMEPAGE_SECTIONS, } from "./homepage-section-defaults";
|
|
689
564
|
export { HOMEPAGE_SECTION_IDS } from "./homepage-config.types";
|
|
690
565
|
export function getPromoBarFromPageInput(pageInput) {
|
|
@@ -696,8 +571,3 @@ export function getPromoBarFromPageInput(pageInput) {
|
|
|
696
571
|
const active = Boolean(promoConfig?.["promo-active"]);
|
|
697
572
|
return { text, code, value, active };
|
|
698
573
|
}
|
|
699
|
-
/** @deprecated Pass `pageInput` from main project. */
|
|
700
|
-
export const getPromoBarConfig = async () => {
|
|
701
|
-
const config = await getDynamicConfig();
|
|
702
|
-
return getPromoBarFromPageInput(config?.["homepage-config"] ?? null);
|
|
703
|
-
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { sdk } from "../config";
|
|
3
3
|
import { getAuthHeaders, getCacheOptions } from "../cookies";
|
|
4
4
|
import { medusaShippingOptionCalculate, medusaShiprocketServiceability, } from "medusa-services/fulfillment";
|
|
5
|
-
import {
|
|
5
|
+
import { getStoreClientOptions } from "../util/store-client";
|
|
6
6
|
export const listCartShippingMethods = async (cartId) => {
|
|
7
7
|
const headers = {
|
|
8
8
|
...(await getAuthHeaders()),
|
|
@@ -27,7 +27,7 @@ export const listCartShippingMethods = async (cartId) => {
|
|
|
27
27
|
};
|
|
28
28
|
export const calculatePriceForShippingOption = async (optionId, cartId, data) => {
|
|
29
29
|
try {
|
|
30
|
-
const options = await
|
|
30
|
+
const options = await getStoreClientOptions();
|
|
31
31
|
const { shipping_option } = await medusaShippingOptionCalculate(optionId, cartId, options, data);
|
|
32
32
|
return shipping_option;
|
|
33
33
|
}
|
|
@@ -37,7 +37,7 @@ export const calculatePriceForShippingOption = async (optionId, cartId, data) =>
|
|
|
37
37
|
};
|
|
38
38
|
export const getShiprocketServiceability = async (pincode, variant_id, cod = 0) => {
|
|
39
39
|
try {
|
|
40
|
-
const options = await
|
|
40
|
+
const options = await getStoreClientOptions();
|
|
41
41
|
return await medusaShiprocketServiceability({ pincode, variant_id, cod }, options);
|
|
42
42
|
}
|
|
43
43
|
catch {
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import "
|
|
2
|
-
import { HttpTypes } from "@medusajs/types";
|
|
3
|
-
import { getRegion } from "./regions";
|
|
4
|
-
import type { HomepageConfig } from "./homepage-config.types";
|
|
1
|
+
import type { HttpTypes } from "@medusajs/types";
|
|
5
2
|
import type { InstagramPostsData, AboutBrandConfig, BrandPillarConfig, BlogPostConfig, HomeSectionsCopy, TrustFeaturesConfig, HomepageBanner } from "./dynamic-config";
|
|
6
|
-
import {
|
|
3
|
+
import type { ShoppableLook } from "./shoppable-looks";
|
|
4
|
+
/** Shape returned by the legacy `loadHomePageData` loader (removed — use per-section loaders). */
|
|
7
5
|
export type HomePageData = {
|
|
8
|
-
region:
|
|
6
|
+
region: HttpTypes.StoreRegion | null;
|
|
9
7
|
collections: Array<Record<string, unknown>>;
|
|
10
8
|
categories: HttpTypes.StoreProductCategory[];
|
|
11
9
|
newArrivals: HttpTypes.StoreProduct[];
|
|
@@ -50,13 +48,4 @@ export type HomePageData = {
|
|
|
50
48
|
}>;
|
|
51
49
|
};
|
|
52
50
|
};
|
|
53
|
-
export type LoadHomePageDataOptions = {
|
|
54
|
-
/** Merged `homepage-config` from main project (fetched via dynamic-config API there). */
|
|
55
|
-
pageInput?: HomepageConfig | null;
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* Parallel home page data loader. Catalog APIs run here; segment copy comes from
|
|
59
|
-
* `pageInput` (or package JSON defaults) — no dynamic-config fetch in this package.
|
|
60
|
-
*/
|
|
61
|
-
export declare function loadHomePageData(countryCode: string, options?: LoadHomePageDataOptions): Promise<HomePageData | null>;
|
|
62
51
|
//# sourceMappingURL=home.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/server/home.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/server/home.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEtD,kGAAkG;AAClG,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAA;IACpC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAC3C,UAAU,EAAE,SAAS,CAAC,oBAAoB,EAAE,CAAA;IAC5C,WAAW,EAAE,SAAS,CAAC,YAAY,EAAE,CAAA;IACrC,WAAW,EAAE,SAAS,CAAC,YAAY,EAAE,CAAA;IACrC,YAAY,EAAE,OAAO,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,OAAO,EAAE,CAAA;IAClB,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAA;IAC3D,oBAAoB,EAAE,MAAM,EAAE,CAAA;IAC9B,cAAc,EAAE;QACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;QACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;QACpB,MAAM,EAAE,OAAO,CAAA;QACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KACvB,CAAA;IACD,cAAc,EAAE,SAAS,CAAC,YAAY,EAAE,CAAA;IACxC,gBAAgB,EAAE,SAAS,CAAC,YAAY,GAAG,IAAI,CAAA;IAC/C,WAAW,EAAE,SAAS,CAAC,YAAY,EAAE,CAAA;IACrC,UAAU,EAAE,SAAS,CAAC,YAAY,EAAE,CAAA;IACpC,YAAY,EAAE,aAAa,EAAE,CAAA;IAC7B,aAAa,EAAE,SAAS,CAAC,YAAY,EAAE,CAAA;IACvC,UAAU,EAAE,gBAAgB,CAAA;IAC5B,YAAY,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,iBAAiB,EAAE,CAAA;KAAE,CAAA;IACpE,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,cAAc,EAAE,kBAAkB,CAAA;IAClC,YAAY,EAAE,gBAAgB,CAAA;IAC9B,aAAa,EAAE,mBAAmB,CAAA;IAClC,WAAW,EAAE,cAAc,EAAE,GAAG,IAAI,CAAA;IACpC,UAAU,EAAE,cAAc,EAAE,GAAG,IAAI,CAAA;IACnC,mBAAmB,EAAE;QACnB,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAChD,CAAA;CACF,CAAA"}
|
package/dist/src/server/home.js
CHANGED
|
@@ -1,122 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { listCollections } from "./collections";
|
|
3
|
-
import { listCategories } from "./categories";
|
|
4
|
-
import { listProductsWithSort, getProductsByTag, listProducts } from "./products";
|
|
5
|
-
import { getRegion } from "./regions";
|
|
6
|
-
import { fetchRatings } from "medusa-reviews-logic/server";
|
|
7
|
-
import { getBaptismPicksLooks, } from "./shoppable-looks";
|
|
8
|
-
import { resolveHomeSegmentConfigData } from "./resolve-home-segment-data";
|
|
9
|
-
async function productsForCategoryIds(countryCode, categoryIds, limit) {
|
|
10
|
-
if (!categoryIds.length)
|
|
11
|
-
return [];
|
|
12
|
-
try {
|
|
13
|
-
const { response } = await listProducts({
|
|
14
|
-
countryCode,
|
|
15
|
-
queryParams: {
|
|
16
|
-
category_id: categoryIds,
|
|
17
|
-
limit,
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
return response.products ?? [];
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return [];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function categoryIdsMatching(categories, pattern) {
|
|
27
|
-
return categories
|
|
28
|
-
.filter((c) => pattern.test((c.name || c.handle || "").toLowerCase()))
|
|
29
|
-
.map((c) => c.id)
|
|
30
|
-
.filter(Boolean);
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Parallel home page data loader. Catalog APIs run here; segment copy comes from
|
|
34
|
-
* `pageInput` (or package JSON defaults) — no dynamic-config fetch in this package.
|
|
35
|
-
*/
|
|
36
|
-
export async function loadHomePageData(countryCode, options) {
|
|
37
|
-
const pageInput = options?.pageInput ?? null;
|
|
38
|
-
const segmentConfig = resolveHomeSegmentConfigData(pageInput);
|
|
39
|
-
const region = await getRegion(countryCode);
|
|
40
|
-
if (!region)
|
|
41
|
-
return null;
|
|
42
|
-
const [collectionsResult, categoriesResult, newArrivalsResult, bestsellersResult, allRatings, themeByTag, baptismByTag,] = await Promise.all([
|
|
43
|
-
listCollections({ fields: "id, handle, title, metadata" }).catch(() => ({
|
|
44
|
-
collections: [],
|
|
45
|
-
})),
|
|
46
|
-
listCategories({
|
|
47
|
-
limit: 100,
|
|
48
|
-
fields: "id,handle,name,metadata,parent_category_id,*parent_category,*parent_category.parent_category",
|
|
49
|
-
}).catch(() => []),
|
|
50
|
-
listProductsWithSort({
|
|
51
|
-
page: 1,
|
|
52
|
-
queryParams: { limit: 12 },
|
|
53
|
-
sortBy: "created_at",
|
|
54
|
-
countryCode,
|
|
55
|
-
}).catch(() => ({ response: { products: [] } })),
|
|
56
|
-
getProductsByTag({
|
|
57
|
-
tagValue: "bestseller",
|
|
58
|
-
limit: 10,
|
|
59
|
-
countryCode,
|
|
60
|
-
}).catch(() => []),
|
|
61
|
-
fetchRatings(),
|
|
62
|
-
getProductsByTag({ tagValue: "theme", limit: 8, countryCode }).catch(() => []),
|
|
63
|
-
getProductsByTag({ tagValue: "baptism", limit: 12, countryCode }).catch(() => []),
|
|
64
|
-
]);
|
|
65
|
-
const categories = (categoriesResult ?? []);
|
|
66
|
-
const collections = collectionsResult.collections ?? [];
|
|
67
|
-
const newArrivals = newArrivalsResult
|
|
68
|
-
.response?.products ?? [];
|
|
69
|
-
const bestsellers = (bestsellersResult ?? []);
|
|
70
|
-
const girlIds = categoryIdsMatching(categories, /baptism.*girl|girl.*baptism|^girl$/);
|
|
71
|
-
const boyIds = categoryIdsMatching(categories, /baptism.*boy|boy.*baptism|^boy$/);
|
|
72
|
-
const baptismIds = categoryIdsMatching(categories, /baptism/);
|
|
73
|
-
const [baptismGirl, baptismBoy] = await Promise.all([
|
|
74
|
-
girlIds.length
|
|
75
|
-
? productsForCategoryIds(countryCode, girlIds, 8)
|
|
76
|
-
: baptismByTag.filter((p) => /girl/i.test(p.title || "")).slice(0, 8),
|
|
77
|
-
boyIds.length
|
|
78
|
-
? productsForCategoryIds(countryCode, boyIds, 8)
|
|
79
|
-
: baptismByTag.filter((p) => /boy/i.test(p.title || "")).slice(0, 8),
|
|
80
|
-
]);
|
|
81
|
-
let baptismFallback = [];
|
|
82
|
-
if (baptismGirl.length === 0 && baptismBoy.length === 0) {
|
|
83
|
-
baptismFallback =
|
|
84
|
-
baptismIds.length > 0
|
|
85
|
-
? await productsForCategoryIds(countryCode, baptismIds, 12)
|
|
86
|
-
: baptismByTag;
|
|
87
|
-
}
|
|
88
|
-
const resolvedBaptismGirl = baptismGirl.length > 0 ? baptismGirl : baptismFallback.slice(0, 8);
|
|
89
|
-
const resolvedBaptismBoy = baptismBoy.length > 0 ? baptismBoy : baptismFallback.slice(0, 8);
|
|
90
|
-
const themeProducts = themeByTag.length > 0
|
|
91
|
-
? themeByTag
|
|
92
|
-
: await productsForCategoryIds(countryCode, categoryIdsMatching(categories, /theme/), 8);
|
|
93
|
-
const baptismPicksFallback = (baptismByTag.length ? baptismByTag : baptismFallback).slice(0, 8);
|
|
94
|
-
const baptismPicks = await getBaptismPicksLooks(countryCode, baptismPicksFallback, pageInput);
|
|
95
|
-
return {
|
|
96
|
-
region,
|
|
97
|
-
collections: collections,
|
|
98
|
-
categories,
|
|
99
|
-
newArrivals,
|
|
100
|
-
bestsellers,
|
|
101
|
-
testimonials: segmentConfig.testimonials,
|
|
102
|
-
ratings: allRatings ?? [],
|
|
103
|
-
videoStories: segmentConfig.videoStories,
|
|
104
|
-
announcementMessages: segmentConfig.announcementMessages,
|
|
105
|
-
promoCountdown: segmentConfig.promoCountdown,
|
|
106
|
-
luxeFavourites: bestsellers.slice(0, 4),
|
|
107
|
-
celebrityProduct: bestsellers[0] ?? newArrivals[0] ?? null,
|
|
108
|
-
baptismGirl: resolvedBaptismGirl,
|
|
109
|
-
baptismBoy: resolvedBaptismBoy,
|
|
110
|
-
baptismPicks,
|
|
111
|
-
themeProducts,
|
|
112
|
-
aboutBrand: segmentConfig.aboutBrand,
|
|
113
|
-
brandPillars: segmentConfig.brandPillars,
|
|
114
|
-
blogPosts: segmentConfig.blogPosts,
|
|
115
|
-
instagramPosts: segmentConfig.instagramPosts,
|
|
116
|
-
sectionsCopy: segmentConfig.sectionsCopy,
|
|
117
|
-
trustFeatures: segmentConfig.trustFeatures,
|
|
118
|
-
homeBanners: segmentConfig.homeBanners,
|
|
119
|
-
appBanners: segmentConfig.appBanners,
|
|
120
|
-
whyChooseUsFeatures: segmentConfig.whyChooseUsFeatures,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HomepageConfig } from "./homepage-config.types";
|
|
2
|
+
/**
|
|
3
|
+
* Accepts simplified `homepage-config` (site / banners / sections) or legacy shape.
|
|
4
|
+
* Storefront always receives the legacy `HomepageConfig` it already parses.
|
|
5
|
+
*/
|
|
6
|
+
export declare function normalizeHomepageConfig(input: unknown): HomepageConfig;
|
|
7
|
+
//# sourceMappingURL=normalize-homepage-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-homepage-config.d.ts","sourceRoot":"","sources":["../../../src/server/normalize-homepage-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAwM7D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAmCtE"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
function asObject(v) {
|
|
2
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
3
|
+
}
|
|
4
|
+
function asArray(v) {
|
|
5
|
+
return Array.isArray(v) ? v : [];
|
|
6
|
+
}
|
|
7
|
+
/** Map simplified banner row → legacy `homepage-banner` / `app-banner` entry. */
|
|
8
|
+
function legacyBannerEntry(row, prefix) {
|
|
9
|
+
const r = asObject(row);
|
|
10
|
+
if (!r)
|
|
11
|
+
return null;
|
|
12
|
+
const image = r.image ?? r[`${prefix}-image`];
|
|
13
|
+
if (!image)
|
|
14
|
+
return null;
|
|
15
|
+
return {
|
|
16
|
+
[prefix]: {
|
|
17
|
+
[`${prefix}-image`]: image,
|
|
18
|
+
[`${prefix}-title`]: r.title ?? r[`${prefix}-title`],
|
|
19
|
+
[`${prefix}-subtitle`]: r.subtitle ?? r[`${prefix}-subtitle`],
|
|
20
|
+
[`${prefix}-description`]: r.description ?? r[`${prefix}-description`],
|
|
21
|
+
[`${prefix}-button-name`]: r.buttonText ?? r.buttonName ?? r[`${prefix}-button-name`],
|
|
22
|
+
[`${prefix}-button-link`]: r.buttonLink ?? r[`${prefix}-button-link`],
|
|
23
|
+
...(prefix === "app-banner" && r.link != null
|
|
24
|
+
? { "app-banner-link": r.link }
|
|
25
|
+
: {}),
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function normalizeBanners(site) {
|
|
30
|
+
const banners = asObject(site?.banners) ?? asObject(site);
|
|
31
|
+
const desktopRaw = banners?.desktop ?? banners?.["homepage-banner-array"] ?? site?.["homepage-banner-array"];
|
|
32
|
+
const mobileRaw = banners?.mobile ?? banners?.["app-banner-array"] ?? site?.["app-banner-array"];
|
|
33
|
+
const desktop = asArray(desktopRaw)
|
|
34
|
+
.map((row) => legacyBannerEntry(row, "homepage-banner"))
|
|
35
|
+
.filter(Boolean);
|
|
36
|
+
const mobile = asArray(mobileRaw)
|
|
37
|
+
.map((row) => legacyBannerEntry(row, "app-banner"))
|
|
38
|
+
.filter(Boolean);
|
|
39
|
+
return { desktop, mobile };
|
|
40
|
+
}
|
|
41
|
+
function normalizeContact(site) {
|
|
42
|
+
const c = asObject(site?.contact) ?? asObject(site?.["contact-us"]);
|
|
43
|
+
if (!c)
|
|
44
|
+
return undefined;
|
|
45
|
+
return {
|
|
46
|
+
"contact-phone": c.phone ?? c["contact-phone"],
|
|
47
|
+
"contact-email": c.email ?? c["contact-email"],
|
|
48
|
+
"contact-whatsapp": c.whatsapp ?? c["contact-whatsapp"],
|
|
49
|
+
"contact-address": c.address ?? c["contact-address"],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function normalizeSocial(site) {
|
|
53
|
+
const raw = site?.social ?? site?.["social-links"];
|
|
54
|
+
return asArray(raw).map((item) => {
|
|
55
|
+
const row = asObject(item?.["social-link"]) ?? asObject(item);
|
|
56
|
+
if (!row)
|
|
57
|
+
return null;
|
|
58
|
+
return {
|
|
59
|
+
"social-link": {
|
|
60
|
+
"social-platform-name": row.name ?? row["social-platform-name"],
|
|
61
|
+
"social-platform-url": row.url ?? row["social-platform-url"],
|
|
62
|
+
"social-platform-icon": row.icon ?? row["social-platform-icon"],
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}).filter(Boolean);
|
|
66
|
+
}
|
|
67
|
+
function normalizeFaqs(site) {
|
|
68
|
+
const raw = site?.faqs ?? site?.["faq-array"];
|
|
69
|
+
return asArray(raw).map((item) => {
|
|
70
|
+
const f = asObject(item?.faq) ?? asObject(item);
|
|
71
|
+
if (!f)
|
|
72
|
+
return null;
|
|
73
|
+
return {
|
|
74
|
+
faq: {
|
|
75
|
+
"faq-category": f.category ?? f["faq-category"],
|
|
76
|
+
"faq-question": f.question ?? f["faq-question"],
|
|
77
|
+
"faq-answer": f.answer ?? f["faq-answer"],
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}).filter(Boolean);
|
|
81
|
+
}
|
|
82
|
+
function normalizeTestimonialItem(item) {
|
|
83
|
+
const r = asObject(item?.testimonial) ?? asObject(item);
|
|
84
|
+
if (!r)
|
|
85
|
+
return null;
|
|
86
|
+
const text = String(r.text ?? r.description ?? "").trim();
|
|
87
|
+
const name = String(r.name ?? "").trim();
|
|
88
|
+
if (!text || !name)
|
|
89
|
+
return null;
|
|
90
|
+
return { text, name, avatar: r.avatar, rating: r.rating };
|
|
91
|
+
}
|
|
92
|
+
function normalizeSections(sections) {
|
|
93
|
+
const out = { ...sections };
|
|
94
|
+
const promoAnnouncements = asObject(sections.promoAnnouncements);
|
|
95
|
+
if (promoAnnouncements?.messages) {
|
|
96
|
+
const messages = asArray(promoAnnouncements.messages)
|
|
97
|
+
.map((m) => {
|
|
98
|
+
if (typeof m === "string")
|
|
99
|
+
return m.trim();
|
|
100
|
+
const row = asObject(m);
|
|
101
|
+
return String(row?.message ?? row?.text ?? "").trim();
|
|
102
|
+
})
|
|
103
|
+
.filter(Boolean);
|
|
104
|
+
out.promoAnnouncements = { ...promoAnnouncements, messages };
|
|
105
|
+
}
|
|
106
|
+
const testimonials = asObject(sections.testimonials);
|
|
107
|
+
if (testimonials) {
|
|
108
|
+
const items = testimonials.items ??
|
|
109
|
+
testimonials.testimonials ??
|
|
110
|
+
testimonials.reviews;
|
|
111
|
+
if (Array.isArray(items)) {
|
|
112
|
+
out.testimonials = {
|
|
113
|
+
...testimonials,
|
|
114
|
+
items: items.map(normalizeTestimonialItem).filter(Boolean),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const promo = asObject(sections.promoCountdown);
|
|
119
|
+
if (promo) {
|
|
120
|
+
out.promoCountdown = {
|
|
121
|
+
code: promo.code ?? promo["promo-code"],
|
|
122
|
+
text: promo.text ?? promo.message ?? promo["promo-text"],
|
|
123
|
+
"end-at": promo.endAt ?? promo["end-at"],
|
|
124
|
+
active: promo.active ?? promo["promo-active"],
|
|
125
|
+
"cta-label": promo.ctaLabel ?? promo["cta-label"],
|
|
126
|
+
"cta-href": promo.ctaHref ?? promo["cta-href"],
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const baptism = asObject(sections.baptismPicks);
|
|
130
|
+
if (baptism?.looks) {
|
|
131
|
+
out.baptismPicks = {
|
|
132
|
+
title: baptism.title,
|
|
133
|
+
looks: asArray(baptism.looks).map((look) => {
|
|
134
|
+
const L = asObject(look?.look) ?? asObject(look);
|
|
135
|
+
if (!L)
|
|
136
|
+
return null;
|
|
137
|
+
return {
|
|
138
|
+
image: L.image,
|
|
139
|
+
"product-ids": L.productIds ?? L["product-ids"],
|
|
140
|
+
"product-handles": L.productHandles ?? L["product-handles"],
|
|
141
|
+
};
|
|
142
|
+
}).filter(Boolean),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const ig = asObject(sections.instagramPosts);
|
|
146
|
+
if (ig) {
|
|
147
|
+
out.instagramPosts = {
|
|
148
|
+
title: ig.title,
|
|
149
|
+
handle: ig.handle,
|
|
150
|
+
"profile-url": ig.profileUrl ?? ig["profile-url"],
|
|
151
|
+
"profile-image": ig.profileImage ?? ig["profile-image"],
|
|
152
|
+
posts: asArray(ig.posts).map((p) => {
|
|
153
|
+
const row = asObject(p?.post) ?? asObject(p);
|
|
154
|
+
return row ? { image: row.image, url: row.url ?? row.link } : null;
|
|
155
|
+
}).filter(Boolean),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const about = asObject(sections.aboutBrand);
|
|
159
|
+
if (about) {
|
|
160
|
+
out.aboutBrand = {
|
|
161
|
+
eyebrow: about.eyebrow,
|
|
162
|
+
title: about.title,
|
|
163
|
+
description: about.description ?? about.text,
|
|
164
|
+
readMoreHref: about.readMoreHref ?? about["read-more-link"],
|
|
165
|
+
stats: about.stats,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
// brandPillars: title only in simplified CMS (cards from categories in storefront)
|
|
169
|
+
const pillars = asObject(sections.brandPillars);
|
|
170
|
+
if (pillars && !pillars.pillars) {
|
|
171
|
+
out.brandPillars = {
|
|
172
|
+
title: pillars.title,
|
|
173
|
+
description: pillars.description,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Accepts simplified `homepage-config` (site / banners / sections) or legacy shape.
|
|
180
|
+
* Storefront always receives the legacy `HomepageConfig` it already parses.
|
|
181
|
+
*/
|
|
182
|
+
export function normalizeHomepageConfig(input) {
|
|
183
|
+
if (!input || typeof input !== "object")
|
|
184
|
+
return {};
|
|
185
|
+
const raw = input;
|
|
186
|
+
const site = asObject(raw.site);
|
|
187
|
+
const hasSimplifiedSite = Boolean(site);
|
|
188
|
+
if (!hasSimplifiedSite) {
|
|
189
|
+
return raw;
|
|
190
|
+
}
|
|
191
|
+
const { desktop, mobile } = normalizeBanners(raw);
|
|
192
|
+
const sections = normalizeSections(asObject(raw.sections) ?? {});
|
|
193
|
+
const legacy = {
|
|
194
|
+
logo: site?.logo ?? raw.logo,
|
|
195
|
+
"website-description": site?.description ??
|
|
196
|
+
raw["website-description"],
|
|
197
|
+
sections: sections,
|
|
198
|
+
};
|
|
199
|
+
if (desktop.length)
|
|
200
|
+
legacy["homepage-banner-array"] = desktop;
|
|
201
|
+
if (mobile.length)
|
|
202
|
+
legacy["app-banner-array"] = mobile;
|
|
203
|
+
const contact = normalizeContact(site);
|
|
204
|
+
if (contact)
|
|
205
|
+
legacy["contact-us"] = contact;
|
|
206
|
+
const social = normalizeSocial(site);
|
|
207
|
+
if (social.length)
|
|
208
|
+
legacy["social-links"] = social;
|
|
209
|
+
const faqs = normalizeFaqs(site);
|
|
210
|
+
if (faqs.length)
|
|
211
|
+
legacy["faq-array"] = faqs;
|
|
212
|
+
return legacy;
|
|
213
|
+
}
|