medusa-storefront-data 2.0.0 → 2.3.0
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/dist/server/customer.d.ts +1 -1
- package/dist/server/customer.d.ts.map +1 -1
- package/dist/server/customer.js +1 -0
- package/dist/server/dynamic-config.d.ts +78 -1
- package/dist/server/dynamic-config.d.ts.map +1 -1
- package/dist/server/dynamic-config.js +447 -38
- package/dist/server/fulfillment.d.ts +1 -1
- package/dist/server/fulfillment.d.ts.map +1 -1
- package/dist/server/home.d.ts +31 -4
- package/dist/server/home.d.ts.map +1 -1
- package/dist/server/home.js +89 -10
- package/dist/server/homepage-section-defaults.d.ts +155 -0
- package/dist/server/homepage-section-defaults.d.ts.map +1 -0
- package/dist/server/homepage-section-defaults.js +149 -0
- package/dist/server/swaps.d.ts +6 -5
- package/dist/server/swaps.d.ts.map +1 -1
- package/dist/server/swaps.js +1 -1
- package/dist/server/wishlist.js +1 -1
- package/package.json +2 -2
- package/src/server/customer.ts +6 -1
- package/src/server/dynamic-config.ts +545 -45
- package/src/server/home.ts +155 -12
- package/src/server/homepage-section-defaults.ts +160 -0
- package/src/server/swaps.ts +8 -6
- package/src/server/wishlist.ts +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { cache } from "react";
|
|
3
3
|
import { getAuthHeaders } from "../cookies";
|
|
4
|
+
import { DEFAULT_HOMEPAGE_SECTIONS, HOME_SECTION_COPY_ID_LIST, } from "./homepage-section-defaults";
|
|
4
5
|
export const getDynamicConfig = cache(async () => {
|
|
5
6
|
try {
|
|
6
7
|
const publishableKey = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY;
|
|
@@ -84,10 +85,10 @@ export const getHomeBannersFromConfig = async () => {
|
|
|
84
85
|
const banner = item["homepage-banner"];
|
|
85
86
|
return {
|
|
86
87
|
image: banner?.["homepage-banner-image"],
|
|
87
|
-
title: banner?.["homepage-banner-title"],
|
|
88
|
-
subtitle: banner?.["homepage-banner-subtitle"],
|
|
89
|
-
description: banner?.["homepage-banner-description"],
|
|
90
|
-
buttonName: banner?.["homepage-banner-button-name"],
|
|
88
|
+
title: normalizeCmsText(banner?.["homepage-banner-title"]),
|
|
89
|
+
subtitle: normalizeCmsText(banner?.["homepage-banner-subtitle"]),
|
|
90
|
+
description: normalizeCmsText(banner?.["homepage-banner-description"]),
|
|
91
|
+
buttonName: normalizeBannerButtonName(banner?.["homepage-banner-button-name"]),
|
|
91
92
|
buttonLink: banner?.["homepage-banner-button-link"],
|
|
92
93
|
};
|
|
93
94
|
});
|
|
@@ -107,10 +108,10 @@ export const getAppBannersFromConfig = async () => {
|
|
|
107
108
|
const banner = item["app-banner"];
|
|
108
109
|
return {
|
|
109
110
|
image: banner?.["app-banner-image"],
|
|
110
|
-
title: banner?.["app-banner-title"],
|
|
111
|
-
subtitle: banner?.["app-banner-subtitle"],
|
|
112
|
-
description: banner?.["app-banner-description"],
|
|
113
|
-
buttonName: banner?.["app-banner-button-name"],
|
|
111
|
+
title: normalizeCmsText(banner?.["app-banner-title"]),
|
|
112
|
+
subtitle: normalizeCmsText(banner?.["app-banner-subtitle"]),
|
|
113
|
+
description: normalizeCmsText(banner?.["app-banner-description"]),
|
|
114
|
+
buttonName: normalizeBannerButtonName(banner?.["app-banner-button-name"]),
|
|
114
115
|
buttonLink: banner?.["app-banner-button-link"],
|
|
115
116
|
};
|
|
116
117
|
});
|
|
@@ -137,27 +138,220 @@ export const getWebsiteDescriptionFromConfig = async () => {
|
|
|
137
138
|
return null;
|
|
138
139
|
}
|
|
139
140
|
};
|
|
141
|
+
/** Why choose us — defaults + `sections.whyChooseUs` override. */
|
|
140
142
|
export const getFeaturesFromConfig = async () => {
|
|
141
143
|
try {
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
const featuresRaw = homepageConfig["why-choose-us-features"] || [];
|
|
148
|
-
const features = featuresRaw.map((item) => {
|
|
149
|
-
const feature = item?.feature || item;
|
|
150
|
-
return {
|
|
151
|
-
name: feature?.["feature-name"] || "",
|
|
152
|
-
icon: feature?.["feature-icon"] || "",
|
|
153
|
-
};
|
|
154
|
-
}).filter((f) => f.name && f.icon);
|
|
144
|
+
const block = await getMergedSectionBlock("whyChooseUs");
|
|
145
|
+
const copy = parseSectionCopy(block);
|
|
146
|
+
const title = copy.title ?? copy.name ?? "";
|
|
147
|
+
const featuresRaw = block.features ?? block.items ?? [];
|
|
148
|
+
const features = parseFeatureIconList(featuresRaw);
|
|
155
149
|
return { title, features };
|
|
156
150
|
}
|
|
157
|
-
catch
|
|
158
|
-
|
|
151
|
+
catch {
|
|
152
|
+
const block = DEFAULT_HOMEPAGE_SECTIONS.whyChooseUs;
|
|
153
|
+
const copy = parseSectionCopy(block);
|
|
154
|
+
return {
|
|
155
|
+
title: copy.title ?? copy.name ?? "",
|
|
156
|
+
features: parseFeatureIconList(block.features ?? []),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
function parseFeatureIconList(raw) {
|
|
161
|
+
if (!Array.isArray(raw))
|
|
162
|
+
return [];
|
|
163
|
+
return raw
|
|
164
|
+
.map((item) => {
|
|
165
|
+
if (!item || typeof item !== "object")
|
|
166
|
+
return null;
|
|
167
|
+
const feature = item.feature ?? item;
|
|
168
|
+
const row = feature;
|
|
169
|
+
const name = normalizeCmsText(row["feature-name"] ?? row.name) ?? "";
|
|
170
|
+
const icon = normalizeCmsText(row["feature-icon"] ?? row.icon) ?? "";
|
|
171
|
+
return name && icon ? { name, icon } : null;
|
|
172
|
+
})
|
|
173
|
+
.filter(Boolean);
|
|
174
|
+
}
|
|
175
|
+
const EMAIL_PATTERN = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
176
|
+
/** Fix common UTF-8 mojibake from CMS copy-paste (e.g. em dash, apostrophe). */
|
|
177
|
+
function normalizeCmsText(value) {
|
|
178
|
+
if (typeof value !== "string" || !value.trim())
|
|
179
|
+
return undefined;
|
|
180
|
+
return value
|
|
181
|
+
.trim()
|
|
182
|
+
.replace(/ΓÇö/g, "—")
|
|
183
|
+
.replace(/ΓÇÖ/g, "'")
|
|
184
|
+
.replace(/ΓÇ£|ΓÇ¥/g, '"')
|
|
185
|
+
.replace(/≡ƒÿÄ≡ƒæòΓ£¿/g, " 👕✨");
|
|
186
|
+
}
|
|
187
|
+
const EMPTY_SECTION_COPY = {
|
|
188
|
+
title: null,
|
|
189
|
+
name: null,
|
|
190
|
+
text: null,
|
|
191
|
+
description: null,
|
|
192
|
+
subtitle: null,
|
|
193
|
+
eyebrow: null,
|
|
194
|
+
};
|
|
195
|
+
export function parseSectionCopy(block) {
|
|
196
|
+
if (!block || typeof block !== "object")
|
|
197
|
+
return { ...EMPTY_SECTION_COPY };
|
|
198
|
+
const row = block;
|
|
199
|
+
return {
|
|
200
|
+
title: normalizeCmsText(row.title) ?? null,
|
|
201
|
+
name: normalizeCmsText(row.name) ?? null,
|
|
202
|
+
text: normalizeCmsText(row.text) ?? null,
|
|
203
|
+
description: normalizeCmsText(row.description) ?? null,
|
|
204
|
+
subtitle: normalizeCmsText(row.subtitle) ?? null,
|
|
205
|
+
eyebrow: normalizeCmsText(row.eyebrow) ?? null,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const HOME_SECTION_COPY_IDS = new Set(HOME_SECTION_COPY_ID_LIST);
|
|
209
|
+
function sectionIdFromConfigKey(key) {
|
|
210
|
+
const id = key.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
211
|
+
return HOME_SECTION_COPY_IDS.has(id) ? id : null;
|
|
212
|
+
}
|
|
213
|
+
async function getHomepageSectionsRoot() {
|
|
214
|
+
const config = await getDynamicConfig();
|
|
215
|
+
const root = config?.["homepage-config"]?.sections;
|
|
216
|
+
return root && typeof root === "object"
|
|
217
|
+
? root
|
|
218
|
+
: {};
|
|
219
|
+
}
|
|
220
|
+
function findSectionBlock(root, id) {
|
|
221
|
+
for (const [key, value] of Object.entries(root)) {
|
|
222
|
+
if (sectionIdFromConfigKey(key) !== id)
|
|
223
|
+
continue;
|
|
224
|
+
if (value && typeof value === "object") {
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
if (typeof value === "string") {
|
|
228
|
+
return { text: value };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
/** Merge CMS section block onto package defaults (override wins when set). */
|
|
234
|
+
export function mergeSectionBlock(defaults, override) {
|
|
235
|
+
if (!override)
|
|
236
|
+
return { ...defaults };
|
|
237
|
+
const merged = { ...defaults };
|
|
238
|
+
for (const [key, value] of Object.entries(override)) {
|
|
239
|
+
if (value === undefined || value === null)
|
|
240
|
+
continue;
|
|
241
|
+
if (Array.isArray(value)) {
|
|
242
|
+
if (value.length > 0)
|
|
243
|
+
merged[key] = value;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (typeof value === "string") {
|
|
247
|
+
if (value.trim())
|
|
248
|
+
merged[key] = value.trim();
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (typeof value === "boolean" || typeof value === "number") {
|
|
252
|
+
merged[key] = value;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (typeof value === "object") {
|
|
256
|
+
const base = merged[key] && typeof merged[key] === "object" && !Array.isArray(merged[key])
|
|
257
|
+
? merged[key]
|
|
258
|
+
: {};
|
|
259
|
+
merged[key] = mergeSectionBlock(base, value);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return merged;
|
|
263
|
+
}
|
|
264
|
+
async function getMergedSectionBlock(id) {
|
|
265
|
+
const root = await getHomepageSectionsRoot();
|
|
266
|
+
const defaults = DEFAULT_HOMEPAGE_SECTIONS[id] ?? {};
|
|
267
|
+
const override = findSectionBlock(root, id);
|
|
268
|
+
return mergeSectionBlock({ ...defaults }, override);
|
|
269
|
+
}
|
|
270
|
+
function mergeSectionCopy(base, patch) {
|
|
271
|
+
const pick = (override, fallback) => override ?? fallback;
|
|
272
|
+
return {
|
|
273
|
+
title: pick(patch.title ?? patch.name, base.title ?? base.name),
|
|
274
|
+
name: pick(patch.name, base.name),
|
|
275
|
+
text: pick(patch.text, base.text),
|
|
276
|
+
description: pick(patch.description, base.description),
|
|
277
|
+
subtitle: pick(patch.subtitle, base.subtitle),
|
|
278
|
+
eyebrow: pick(patch.eyebrow, base.eyebrow),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function parseAnnouncementMessages(block) {
|
|
282
|
+
if (!block)
|
|
283
|
+
return [];
|
|
284
|
+
const raw = block.messages ?? block.items ?? block["announcement-messages"];
|
|
285
|
+
if (!Array.isArray(raw))
|
|
286
|
+
return [];
|
|
287
|
+
return raw
|
|
288
|
+
.map((item) => {
|
|
289
|
+
if (typeof item === "string")
|
|
290
|
+
return item.trim();
|
|
291
|
+
if (item && typeof item === "object") {
|
|
292
|
+
const row = item;
|
|
293
|
+
const nested = (row.message ?? row.text);
|
|
294
|
+
return typeof nested === "string" ? nested.trim() : "";
|
|
295
|
+
}
|
|
296
|
+
return "";
|
|
297
|
+
})
|
|
298
|
+
.filter(Boolean);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Merged section copy: package defaults + `homepage-config.sections` overrides.
|
|
302
|
+
*/
|
|
303
|
+
export const getHomeSectionsCopyFromConfig = async () => {
|
|
304
|
+
try {
|
|
305
|
+
const copy = {};
|
|
306
|
+
for (const id of HOME_SECTION_COPY_ID_LIST) {
|
|
307
|
+
const block = await getMergedSectionBlock(id);
|
|
308
|
+
copy[id] = parseSectionCopy(block);
|
|
309
|
+
}
|
|
310
|
+
return copy;
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
const fallback = {};
|
|
314
|
+
for (const id of HOME_SECTION_COPY_ID_LIST) {
|
|
315
|
+
fallback[id] = parseSectionCopy(DEFAULT_HOMEPAGE_SECTIONS[id]);
|
|
316
|
+
}
|
|
317
|
+
return fallback;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
/** Trust badge row — defaults + `sections.features` override. */
|
|
321
|
+
export const getTrustFeaturesFromConfig = async () => {
|
|
322
|
+
try {
|
|
323
|
+
const block = await getMergedSectionBlock("features");
|
|
324
|
+
const copy = parseSectionCopy(block);
|
|
325
|
+
const title = copy.title ?? copy.name;
|
|
326
|
+
const description = copy.description ?? copy.text;
|
|
327
|
+
const rawList = block.features ?? block.items ?? [];
|
|
328
|
+
const features = parseFeatureIconList(rawList);
|
|
329
|
+
return { title: title ?? null, description: description ?? null, features };
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
const block = DEFAULT_HOMEPAGE_SECTIONS.features;
|
|
333
|
+
const copy = parseSectionCopy(block);
|
|
334
|
+
return {
|
|
335
|
+
title: copy.title,
|
|
336
|
+
description: copy.description,
|
|
337
|
+
features: parseFeatureIconList(block.features ?? []),
|
|
338
|
+
};
|
|
159
339
|
}
|
|
160
340
|
};
|
|
341
|
+
function normalizeBannerButtonName(value) {
|
|
342
|
+
const text = normalizeCmsText(value);
|
|
343
|
+
if (!text)
|
|
344
|
+
return undefined;
|
|
345
|
+
if (/^shop\s+now\s*1$/i.test(text))
|
|
346
|
+
return "Shop Now";
|
|
347
|
+
return text;
|
|
348
|
+
}
|
|
349
|
+
function normalizeConfigEmail(value) {
|
|
350
|
+
if (typeof value !== "string")
|
|
351
|
+
return undefined;
|
|
352
|
+
const trimmed = value.trim();
|
|
353
|
+
return EMAIL_PATTERN.test(trimmed) ? trimmed : undefined;
|
|
354
|
+
}
|
|
161
355
|
export const getContactInfoFromConfig = async () => {
|
|
162
356
|
try {
|
|
163
357
|
const config = await getDynamicConfig();
|
|
@@ -167,10 +361,7 @@ export const getContactInfoFromConfig = async () => {
|
|
|
167
361
|
}
|
|
168
362
|
return {
|
|
169
363
|
phone: contactConfig["contact-phone"],
|
|
170
|
-
email:
|
|
171
|
-
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(contactConfig["contact-email"].trim())
|
|
172
|
-
? contactConfig["contact-email"].trim()
|
|
173
|
-
: undefined,
|
|
364
|
+
email: normalizeConfigEmail(contactConfig["contact-email"]),
|
|
174
365
|
address: contactConfig["contact-address"],
|
|
175
366
|
};
|
|
176
367
|
}
|
|
@@ -178,28 +369,84 @@ export const getContactInfoFromConfig = async () => {
|
|
|
178
369
|
return null;
|
|
179
370
|
}
|
|
180
371
|
};
|
|
372
|
+
function normalizeVideoStoryUrl(entry) {
|
|
373
|
+
if (typeof entry === "string" && entry.trim())
|
|
374
|
+
return entry.trim();
|
|
375
|
+
if (!entry || typeof entry !== "object")
|
|
376
|
+
return null;
|
|
377
|
+
const row = entry;
|
|
378
|
+
const nested = row["video-story"] ??
|
|
379
|
+
row["video_stories"] ??
|
|
380
|
+
row;
|
|
381
|
+
const url = nested["video-url"] ??
|
|
382
|
+
nested["video_url"] ??
|
|
383
|
+
nested.url ??
|
|
384
|
+
nested.src ??
|
|
385
|
+
nested.video;
|
|
386
|
+
return typeof url === "string" && url.trim() ? url.trim() : null;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Homepage video stories/reviews carousel (`homepage-config.video-stories`).
|
|
390
|
+
*/
|
|
391
|
+
export const getVideoStoriesFromConfig = async () => {
|
|
392
|
+
try {
|
|
393
|
+
const config = await getDynamicConfig();
|
|
394
|
+
const homepageConfig = config?.["homepage-config"];
|
|
395
|
+
if (!homepageConfig)
|
|
396
|
+
return null;
|
|
397
|
+
const block = await getMergedSectionBlock("videoStories");
|
|
398
|
+
const copy = parseSectionCopy(block);
|
|
399
|
+
const title = copy.title ?? copy.name ?? "";
|
|
400
|
+
const raw = block["video-urls"] ??
|
|
401
|
+
block.videoUrls ??
|
|
402
|
+
block.videos ??
|
|
403
|
+
block["video-stories"] ??
|
|
404
|
+
homepageConfig["video-stories"] ??
|
|
405
|
+
homepageConfig["video-stories-array"] ??
|
|
406
|
+
homepageConfig["video_stories"] ??
|
|
407
|
+
[];
|
|
408
|
+
const list = Array.isArray(raw) ? raw : [raw];
|
|
409
|
+
const videoUrls = list
|
|
410
|
+
.map(normalizeVideoStoryUrl)
|
|
411
|
+
.filter((url) => Boolean(url));
|
|
412
|
+
return { title, videoUrls };
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
const block = DEFAULT_HOMEPAGE_SECTIONS.videoStories;
|
|
416
|
+
const copy = parseSectionCopy(block);
|
|
417
|
+
return {
|
|
418
|
+
title: copy.title ?? copy.name ?? "",
|
|
419
|
+
videoUrls: [],
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
};
|
|
181
423
|
export const getTestimonialsFromConfig = async () => {
|
|
182
424
|
try {
|
|
183
425
|
const config = await getDynamicConfig();
|
|
184
426
|
const homepageConfig = config?.["homepage-config"];
|
|
185
427
|
if (!homepageConfig)
|
|
186
428
|
return null;
|
|
187
|
-
const
|
|
429
|
+
const block = await getMergedSectionBlock("testimonials");
|
|
430
|
+
const copy = parseSectionCopy(block);
|
|
431
|
+
const title = copy.title ?? copy.name ?? "";
|
|
188
432
|
const ratings = homepageConfig["ratings"] || [];
|
|
189
|
-
|
|
190
|
-
const
|
|
433
|
+
let testimonials = (Array.isArray(ratings) ? ratings : []).map((item, index) => {
|
|
434
|
+
const row = item;
|
|
435
|
+
const review = (row?.review ?? row);
|
|
191
436
|
return {
|
|
192
437
|
id: `review-${index}`,
|
|
193
|
-
text: review?.["review-description"]
|
|
194
|
-
name: review?.["review-user-name"]
|
|
195
|
-
rating: parseFloat(review?.["review-rating"]
|
|
196
|
-
avatar: review?.["review-profile-image"]
|
|
438
|
+
text: String(review?.["review-description"] ?? "").trim(),
|
|
439
|
+
name: String(review?.["review-user-name"] ?? "").trim(),
|
|
440
|
+
rating: parseFloat(String(review?.["review-rating"] ?? "5")),
|
|
441
|
+
avatar: review?.["review-profile-image"],
|
|
197
442
|
};
|
|
198
443
|
}).filter((t) => t.text && t.name);
|
|
199
444
|
return { title, testimonials };
|
|
200
445
|
}
|
|
201
|
-
catch
|
|
202
|
-
|
|
446
|
+
catch {
|
|
447
|
+
const block = DEFAULT_HOMEPAGE_SECTIONS.testimonials;
|
|
448
|
+
const copy = parseSectionCopy(block);
|
|
449
|
+
return { title: copy.title ?? copy.name ?? "", testimonials: [] };
|
|
203
450
|
}
|
|
204
451
|
};
|
|
205
452
|
export const getSocialLinksFromConfig = async () => {
|
|
@@ -249,15 +496,177 @@ export const getFaqsFromConfig = async () => {
|
|
|
249
496
|
return null;
|
|
250
497
|
}
|
|
251
498
|
};
|
|
499
|
+
export const getAnnouncementMessagesFromConfig = async () => {
|
|
500
|
+
try {
|
|
501
|
+
const block = await getMergedSectionBlock("promoAnnouncements");
|
|
502
|
+
return parseAnnouncementMessages(block);
|
|
503
|
+
}
|
|
504
|
+
catch {
|
|
505
|
+
return parseAnnouncementMessages(DEFAULT_HOMEPAGE_SECTIONS.promoAnnouncements);
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
export const getAboutBrandFromConfig = async () => {
|
|
509
|
+
try {
|
|
510
|
+
const config = await getDynamicConfig();
|
|
511
|
+
const merged = await getMergedSectionBlock("aboutBrand");
|
|
512
|
+
const legacy = config?.["homepage-config"]?.["about-brand"] ??
|
|
513
|
+
config?.["homepage-config"]?.["who-we-are"];
|
|
514
|
+
const b = mergeSectionBlock(merged, legacy && typeof legacy === "object"
|
|
515
|
+
? legacy
|
|
516
|
+
: null);
|
|
517
|
+
const statsRaw = (b.stats ?? b["about-stats"] ?? []);
|
|
518
|
+
const stats = Array.isArray(statsRaw)
|
|
519
|
+
? statsRaw
|
|
520
|
+
.map((s) => {
|
|
521
|
+
if (!s || typeof s !== "object")
|
|
522
|
+
return null;
|
|
523
|
+
const row = s;
|
|
524
|
+
const label = String(row.label ?? row.name ?? "").trim();
|
|
525
|
+
const value = String(row.value ?? "").trim();
|
|
526
|
+
return label && value ? { label, value } : null;
|
|
527
|
+
})
|
|
528
|
+
.filter(Boolean)
|
|
529
|
+
: [];
|
|
530
|
+
const copy = parseSectionCopy(b);
|
|
531
|
+
return {
|
|
532
|
+
eyebrow: copy.eyebrow ?? "",
|
|
533
|
+
title: copy.title ?? copy.name ?? "",
|
|
534
|
+
description: copy.description ?? copy.text ?? "",
|
|
535
|
+
readMoreHref: String(b.readMoreHref ?? b["read-more-link"] ?? "/about"),
|
|
536
|
+
stats,
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
const b = DEFAULT_HOMEPAGE_SECTIONS.aboutBrand;
|
|
541
|
+
const copy = parseSectionCopy(b);
|
|
542
|
+
return {
|
|
543
|
+
eyebrow: copy.eyebrow ?? "",
|
|
544
|
+
title: copy.title ?? copy.name ?? "",
|
|
545
|
+
description: copy.description ?? copy.text ?? "",
|
|
546
|
+
readMoreHref: String(b.readMoreHref ?? "/about"),
|
|
547
|
+
stats: (b.stats ?? []),
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
export const getBrandPillarsFromConfig = async () => {
|
|
552
|
+
try {
|
|
553
|
+
const block = await getMergedSectionBlock("brandPillars");
|
|
554
|
+
const copy = parseSectionCopy(block);
|
|
555
|
+
const sectionTitle = copy.title ?? copy.name ?? "";
|
|
556
|
+
const raw = block.pillars ?? block["brand-pillars"] ?? [];
|
|
557
|
+
const pillars = (Array.isArray(raw) ? raw : [])
|
|
558
|
+
.map((item) => {
|
|
559
|
+
if (!item || typeof item !== "object")
|
|
560
|
+
return null;
|
|
561
|
+
const row = item["pillar"] ?? item;
|
|
562
|
+
const p = row;
|
|
563
|
+
const title = String(p.title ?? p.name ?? "").trim();
|
|
564
|
+
const description = String(p.description ?? p.text ?? "").trim();
|
|
565
|
+
const image = (p.image ?? p.icon);
|
|
566
|
+
return title && description ? { title, description, image } : null;
|
|
567
|
+
})
|
|
568
|
+
.filter(Boolean);
|
|
569
|
+
return { sectionTitle, pillars };
|
|
570
|
+
}
|
|
571
|
+
catch {
|
|
572
|
+
const block = DEFAULT_HOMEPAGE_SECTIONS.brandPillars;
|
|
573
|
+
const copy = parseSectionCopy(block);
|
|
574
|
+
const raw = block.pillars ?? [];
|
|
575
|
+
return {
|
|
576
|
+
sectionTitle: copy.title ?? copy.name ?? "",
|
|
577
|
+
pillars: [...(Array.isArray(raw) ? raw : [])],
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
export const getBlogPostsFromConfig = async () => {
|
|
582
|
+
try {
|
|
583
|
+
const block = await getMergedSectionBlock("blogPosts");
|
|
584
|
+
const raw = block.posts ?? block["blog-posts"] ?? block["blog-array"] ?? [];
|
|
585
|
+
const posts = (Array.isArray(raw) ? raw : [])
|
|
586
|
+
.map((item) => {
|
|
587
|
+
if (!item || typeof item !== "object")
|
|
588
|
+
return null;
|
|
589
|
+
const row = item["blog"] ?? item;
|
|
590
|
+
const b = row;
|
|
591
|
+
const title = String(b.title ?? "").trim();
|
|
592
|
+
const href = String(b.href ?? b.link ?? b.url ?? "").trim();
|
|
593
|
+
if (!title || !href)
|
|
594
|
+
return null;
|
|
595
|
+
return {
|
|
596
|
+
title,
|
|
597
|
+
href,
|
|
598
|
+
excerpt: String(b.excerpt ?? b.description ?? "").trim() || undefined,
|
|
599
|
+
category: String(b.category ?? b.tag ?? "").trim() || undefined,
|
|
600
|
+
date: String(b.date ?? "").trim() || undefined,
|
|
601
|
+
image: (b.image ?? b.thumbnail),
|
|
602
|
+
};
|
|
603
|
+
})
|
|
604
|
+
.filter(Boolean);
|
|
605
|
+
return posts;
|
|
606
|
+
}
|
|
607
|
+
catch {
|
|
608
|
+
const block = DEFAULT_HOMEPAGE_SECTIONS.blogPosts;
|
|
609
|
+
const raw = block.posts ?? [];
|
|
610
|
+
return (Array.isArray(raw) ? raw : [])
|
|
611
|
+
.map((item) => {
|
|
612
|
+
if (!item || typeof item !== "object")
|
|
613
|
+
return null;
|
|
614
|
+
const b = item;
|
|
615
|
+
const title = String(b.title ?? "").trim();
|
|
616
|
+
const href = String(b.href ?? b.link ?? "").trim();
|
|
617
|
+
if (!title || !href)
|
|
618
|
+
return null;
|
|
619
|
+
return { title, href };
|
|
620
|
+
})
|
|
621
|
+
.filter(Boolean);
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
function readPromoCountdownBlock(block) {
|
|
625
|
+
if (!block || typeof block !== "object") {
|
|
626
|
+
return { code: null, message: null, endAt: null, active: undefined };
|
|
627
|
+
}
|
|
628
|
+
const row = block;
|
|
629
|
+
const code = normalizeCmsText(row["promo-code"] ?? row.code ?? row["coupon-code"]) ?? null;
|
|
630
|
+
const message = normalizeCmsText(row["promo-text"] ?? row.message ?? row.text) ?? null;
|
|
631
|
+
const endAtRaw = row["end-at"] ?? row.endAt ?? row["ends-at"];
|
|
632
|
+
const endAt = typeof endAtRaw === "string" && endAtRaw.trim() ? endAtRaw.trim() : null;
|
|
633
|
+
const activeRaw = row["promo-active"] ?? row.active;
|
|
634
|
+
const active = typeof activeRaw === "boolean" ? activeRaw : undefined;
|
|
635
|
+
return { code, message, endAt, active };
|
|
636
|
+
}
|
|
637
|
+
/** Promo countdown — defaults + `sections.promoCountdown` override. */
|
|
638
|
+
export const getPromoCountdownFromConfig = async () => {
|
|
639
|
+
try {
|
|
640
|
+
const block = await getMergedSectionBlock("promoCountdown");
|
|
641
|
+
const fromBlock = readPromoCountdownBlock(block);
|
|
642
|
+
const defaults = readPromoCountdownBlock(DEFAULT_HOMEPAGE_SECTIONS.promoCountdown);
|
|
643
|
+
return {
|
|
644
|
+
code: fromBlock.code ?? defaults.code,
|
|
645
|
+
message: fromBlock.message ?? defaults.message,
|
|
646
|
+
endAt: fromBlock.endAt ?? defaults.endAt,
|
|
647
|
+
active: fromBlock.active ?? defaults.active ?? false,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
catch {
|
|
651
|
+
const defaults = readPromoCountdownBlock(DEFAULT_HOMEPAGE_SECTIONS.promoCountdown);
|
|
652
|
+
return {
|
|
653
|
+
code: defaults.code,
|
|
654
|
+
message: defaults.message,
|
|
655
|
+
endAt: defaults.endAt,
|
|
656
|
+
active: defaults.active ?? false,
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
export { DEFAULT_HOMEPAGE_SECTIONS } from "./homepage-section-defaults";
|
|
252
661
|
export const getPromoBarConfig = async () => {
|
|
253
662
|
try {
|
|
254
663
|
const config = await getDynamicConfig();
|
|
255
664
|
const promoConfig = config?.["homepage-config"]?.["promo-bar"];
|
|
256
665
|
return {
|
|
257
|
-
text: promoConfig?.["promo-text"] || null,
|
|
666
|
+
text: normalizeCmsText(promoConfig?.["promo-text"]) || null,
|
|
258
667
|
code: promoConfig?.["promo-code"] || null,
|
|
259
668
|
value: promoConfig?.["promo-value"] || null,
|
|
260
|
-
active: promoConfig?.["promo-active"] ?? false
|
|
669
|
+
active: promoConfig?.["promo-active"] ?? false,
|
|
261
670
|
};
|
|
262
671
|
}
|
|
263
672
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpTypes } from "@medusajs/types";
|
|
2
2
|
export declare const listCartShippingMethods: (cartId: string) => Promise<HttpTypes.StoreCartShippingOptionWithServiceZone[] | null>;
|
|
3
3
|
export declare const calculatePriceForShippingOption: (optionId: string, cartId: string, data?: Record<string, unknown>) => Promise<HttpTypes.StoreCartShippingOption | null>;
|
|
4
|
-
export declare const getShiprocketServiceability: (pincode: string, variant_id: string, cod?: number) => Promise<
|
|
4
|
+
export declare const getShiprocketServiceability: (pincode: string, variant_id: string, cod?: number) => Promise<import("medusa-services/fulfillment").ShiprocketServiceabilityResult | null>;
|
|
5
5
|
//# sourceMappingURL=fulfillment.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fulfillment.d.ts","sourceRoot":"","sources":["../../src/server/fulfillment.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAQ3C,eAAO,MAAM,uBAAuB,GAAU,QAAQ,MAAM,uEA0B3D,CAAA;AAED,eAAO,MAAM,+BAA+B,GAC1C,UAAU,MAAM,EAChB,QAAQ,MAAM,EACd,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,sDAc/B,CAAA;AAED,eAAO,MAAM,2BAA2B,GAAU,SAAS,MAAM,EAAE,YAAY,MAAM,EAAE,MAAK,MAAU,
|
|
1
|
+
{"version":3,"file":"fulfillment.d.ts","sourceRoot":"","sources":["../../src/server/fulfillment.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAQ3C,eAAO,MAAM,uBAAuB,GAAU,QAAQ,MAAM,uEA0B3D,CAAA;AAED,eAAO,MAAM,+BAA+B,GAC1C,UAAU,MAAM,EAChB,QAAQ,MAAM,EACd,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,sDAc/B,CAAA;AAED,eAAO,MAAM,2BAA2B,GAAU,SAAS,MAAM,EAAE,YAAY,MAAM,EAAE,MAAK,MAAU,yFAWrG,CAAA"}
|
package/dist/server/home.d.ts
CHANGED
|
@@ -1,15 +1,42 @@
|
|
|
1
|
+
import { HttpTypes } from "@medusajs/types";
|
|
1
2
|
import { getRegion } from "./regions";
|
|
3
|
+
import { type AboutBrandConfig, type BrandPillarConfig, type BlogPostConfig, type HomeSectionsCopy, type TrustFeaturesConfig } from "./dynamic-config";
|
|
2
4
|
export type HomePageData = {
|
|
3
5
|
region: Awaited<ReturnType<typeof getRegion>>;
|
|
4
6
|
collections: Array<Record<string, unknown>>;
|
|
5
|
-
categories:
|
|
6
|
-
newArrivals:
|
|
7
|
-
bestsellers:
|
|
7
|
+
categories: HttpTypes.StoreProductCategory[];
|
|
8
|
+
newArrivals: HttpTypes.StoreProduct[];
|
|
9
|
+
bestsellers: HttpTypes.StoreProduct[];
|
|
8
10
|
testimonials: unknown | null;
|
|
9
11
|
ratings: unknown[];
|
|
12
|
+
videoStories: {
|
|
13
|
+
title: string;
|
|
14
|
+
videoUrls: string[];
|
|
15
|
+
} | null;
|
|
16
|
+
announcementMessages: string[];
|
|
17
|
+
promoCountdown: {
|
|
18
|
+
code: string | null;
|
|
19
|
+
message: string | null;
|
|
20
|
+
endAt: string | null;
|
|
21
|
+
active: boolean;
|
|
22
|
+
};
|
|
23
|
+
luxeFavourites: HttpTypes.StoreProduct[];
|
|
24
|
+
celebrityProduct: HttpTypes.StoreProduct | null;
|
|
25
|
+
baptismGirl: HttpTypes.StoreProduct[];
|
|
26
|
+
baptismBoy: HttpTypes.StoreProduct[];
|
|
27
|
+
baptismPicks: HttpTypes.StoreProduct[];
|
|
28
|
+
themeProducts: HttpTypes.StoreProduct[];
|
|
29
|
+
aboutBrand: AboutBrandConfig;
|
|
30
|
+
brandPillars: {
|
|
31
|
+
sectionTitle: string;
|
|
32
|
+
pillars: BrandPillarConfig[];
|
|
33
|
+
};
|
|
34
|
+
blogPosts: BlogPostConfig[];
|
|
35
|
+
sectionsCopy: HomeSectionsCopy;
|
|
36
|
+
trustFeatures: TrustFeaturesConfig;
|
|
10
37
|
};
|
|
11
38
|
/**
|
|
12
|
-
* Parallel home page data loader
|
|
39
|
+
* Parallel home page data loader for full storefront homepage sections.
|
|
13
40
|
*/
|
|
14
41
|
export declare function loadHomePageData(countryCode: string): Promise<HomePageData | null>;
|
|
15
42
|
//# sourceMappingURL=home.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../src/server/home.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../src/server/home.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAUL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAC;AAiC1B,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC;IAC9C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5C,UAAU,EAAE,SAAS,CAAC,oBAAoB,EAAE,CAAC;IAC7C,WAAW,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;IACtC,WAAW,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;IACtC,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5D,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,cAAc,EAAE;QACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,cAAc,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;IACzC,gBAAgB,EAAE,SAAS,CAAC,YAAY,GAAG,IAAI,CAAC;IAChD,WAAW,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;IACtC,UAAU,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;IACrC,YAAY,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;IACvC,aAAa,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;IACxC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,YAAY,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,iBAAiB,EAAE,CAAA;KAAE,CAAC;IACrE,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,mBAAmB,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA2HxF"}
|