|
11 | 11 | import { Page as MakeswiftPage } from '@makeswift/runtime/next'; |
12 | 12 | import { ComponentPropsWithoutRef } from 'react'; |
13 | 13 |
|
| 14 | +type MetadataValue = string | number | boolean | MetadataObject | MetadataValue[] | null | undefined; |
| 15 | +type MetadataObject = { [key: string]: MetadataValue }; |
| 16 | + |
14 | 17 | /** |
15 | 18 | * Filters metadata to only include meaningful values while preserving structure. |
16 | 19 | * - Always disables favicon to prefer the store favicon from /favicon.ico |
17 | 20 | * - Removes falsy values (empty strings, null, undefined) to use BigCommerce defaults |
18 | 21 | * - Preserves nested objects and meaningful boolean values |
| 22 | + * @param metadata - The metadata object to filter |
| 23 | + * @returns The filtered metadata object with meaningful values only |
19 | 24 | */ |
20 | | -function filterMetadata(metadata: any): any { |
| 25 | +function filterMetadata(metadata: MetadataValue): MetadataObject | false { |
21 | 26 | if (metadata === false) { |
22 | 27 | return false; |
23 | 28 | } |
24 | | - |
25 | | - if (!metadata || typeof metadata !== 'object') { |
| 29 | + |
| 30 | + if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) { |
26 | 31 | return { favicon: false }; |
27 | 32 | } |
28 | 33 |
|
29 | | - const filtered: any = { favicon: false }; |
| 34 | + const filtered: MetadataObject = { favicon: false }; |
| 35 | + const entries = Object.entries(metadata); |
30 | 36 |
|
31 | | - for (const [key, value] of Object.entries(metadata)) { |
| 37 | + const processedEntries = entries.reduce<MetadataObject>((acc, [key, value]) => { |
| 38 | + // Always disable favicon to use store favicon |
32 | 39 | if (key === 'favicon') { |
33 | | - // Always disable favicon to use store favicon |
34 | | - continue; |
| 40 | + return acc; |
35 | 41 | } |
36 | 42 |
|
| 43 | + // Skip null/undefined values to use BigCommerce defaults |
37 | 44 | if (value === null || value === undefined) { |
38 | | - // Skip null/undefined values to use BigCommerce defaults |
39 | | - continue; |
| 45 | + return acc; |
40 | 46 | } |
41 | 47 |
|
| 48 | + // Skip empty strings to use BigCommerce defaults |
42 | 49 | if (typeof value === 'string' && value.trim() === '') { |
43 | | - // Skip empty strings to use BigCommerce defaults |
44 | | - continue; |
| 50 | + return acc; |
45 | 51 | } |
46 | 52 |
|
| 53 | + // Preserve arrays as-is |
47 | 54 | if (Array.isArray(value)) { |
48 | | - // Preserve arrays as-is |
49 | | - filtered[key] = value; |
50 | | - continue; |
| 55 | + acc[key] = value; |
| 56 | + return acc; |
51 | 57 | } |
52 | 58 |
|
| 59 | + // Recursively filter nested objects (but not arrays) |
53 | 60 | if (typeof value === 'object' && value !== null) { |
54 | | - // Recursively filter nested objects (but not arrays) |
55 | 61 | const filteredNested = filterMetadata(value); |
| 62 | + |
56 | 63 | if (filteredNested !== false && Object.keys(filteredNested).length > 1) { |
57 | 64 | // Only include nested objects if they have more than just the favicon property |
58 | | - filtered[key] = filteredNested; |
| 65 | + acc[key] = filteredNested; |
59 | 66 | } |
60 | | - continue; |
| 67 | + |
| 68 | + return acc; |
61 | 69 | } |
62 | 70 |
|
63 | 71 | // Include all other meaningful values (non-empty strings, numbers, booleans) |
64 | | - filtered[key] = value; |
65 | | - } |
| 72 | + acc[key] = value; |
| 73 | + return acc; |
| 74 | + }, {}); |
66 | 75 |
|
67 | | - return filtered; |
| 76 | + return { ...filtered, ...processedEntries }; |
68 | 77 | } |
69 | 78 |
|
70 | 79 | export function MakeswiftPageShim(props: ComponentPropsWithoutRef<typeof MakeswiftPage>) { |
71 | 80 | const metadata = filterMetadata(props.metadata); |
72 | | - |
| 81 | + |
73 | 82 | return <MakeswiftPage {...props} metadata={metadata} />; |
74 | 83 | } |
0 commit comments