@akinon/next 1.94.0 → 1.95.0-snapshot-ZERO-3586-20250901132537
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/CHANGELOG.md +1330 -49
- package/__tests__/next-config.test.ts +1 -10
- package/__tests__/redirect.test.ts +319 -0
- package/api/cache.ts +41 -5
- package/api/image-proxy.ts +75 -0
- package/api/similar-product-list.ts +84 -0
- package/api/similar-products.ts +120 -0
- package/components/accordion.tsx +20 -5
- package/components/file-input.tsx +65 -3
- package/components/input.tsx +2 -0
- package/components/link.tsx +16 -12
- package/components/modal.tsx +32 -16
- package/components/plugin-module.tsx +30 -3
- package/data/client/checkout.ts +5 -4
- package/data/server/basket.ts +72 -0
- package/data/server/category.ts +52 -30
- package/data/server/flatpage.ts +20 -13
- package/data/server/form.ts +4 -1
- package/data/server/landingpage.ts +20 -13
- package/data/server/list.ts +25 -14
- package/data/server/menu.ts +4 -1
- package/data/server/product.ts +68 -40
- package/data/server/seo.ts +4 -1
- package/data/server/special-page.ts +18 -13
- package/data/server/widget.ts +4 -1
- package/data/urls.ts +5 -1
- package/hocs/server/with-segment-defaults.tsx +5 -2
- package/hooks/use-localization.ts +2 -3
- package/jest.config.js +7 -1
- package/lib/cache-handler.mjs +359 -85
- package/lib/cache.ts +254 -25
- package/middlewares/checkout-provider.ts +1 -1
- package/middlewares/complete-gpay.ts +2 -1
- package/middlewares/complete-masterpass.ts +2 -1
- package/middlewares/default.ts +50 -13
- package/middlewares/locale.ts +9 -1
- package/middlewares/pretty-url.ts +2 -1
- package/middlewares/redirection-payment.ts +2 -1
- package/middlewares/saved-card-redirection.ts +2 -1
- package/middlewares/three-d-redirection.ts +2 -1
- package/middlewares/url-redirection.ts +9 -15
- package/package.json +4 -3
- package/plugins.d.ts +8 -0
- package/plugins.js +3 -1
- package/redux/middlewares/checkout.ts +5 -1
- package/sentry/index.ts +54 -17
- package/types/commerce/order.ts +1 -0
- package/types/index.ts +43 -1
- package/utils/app-fetch.ts +7 -2
- package/utils/index.ts +34 -10
- package/utils/redirect-ignore.ts +35 -0
- package/utils/redirect.ts +31 -6
- package/with-pz-config.js +2 -5
package/components/accordion.tsx
CHANGED
|
@@ -7,15 +7,19 @@ import { AccordionProps } from '../types';
|
|
|
7
7
|
|
|
8
8
|
export const Accordion = ({
|
|
9
9
|
isCollapse = false,
|
|
10
|
+
collapseClassName,
|
|
10
11
|
title,
|
|
11
12
|
subTitle,
|
|
12
13
|
icons = ['chevron-up', 'chevron-down'],
|
|
13
14
|
iconSize = 16,
|
|
14
15
|
iconColor = 'fill-[#000000]',
|
|
15
16
|
children,
|
|
17
|
+
headerClassName,
|
|
16
18
|
className,
|
|
17
19
|
titleClassName,
|
|
18
|
-
|
|
20
|
+
subTitleClassName,
|
|
21
|
+
dataTestId,
|
|
22
|
+
contentClassName
|
|
19
23
|
}: AccordionProps) => {
|
|
20
24
|
const [collapse, setCollapse] = useState(isCollapse);
|
|
21
25
|
|
|
@@ -27,15 +31,22 @@ export const Accordion = ({
|
|
|
27
31
|
)}
|
|
28
32
|
>
|
|
29
33
|
<div
|
|
30
|
-
className=
|
|
34
|
+
className={twMerge(
|
|
35
|
+
'flex items-center justify-between cursor-pointer',
|
|
36
|
+
headerClassName
|
|
37
|
+
)}
|
|
31
38
|
onClick={() => setCollapse(!collapse)}
|
|
32
39
|
data-testid={dataTestId}
|
|
33
40
|
>
|
|
34
|
-
<div className=
|
|
41
|
+
<div className={twMerge('flex flex-col', contentClassName)}>
|
|
35
42
|
{title && (
|
|
36
43
|
<h3 className={twMerge('text-sm', titleClassName)}>{title}</h3>
|
|
37
44
|
)}
|
|
38
|
-
{subTitle &&
|
|
45
|
+
{subTitle && (
|
|
46
|
+
<h4 className={twMerge('text-xs text-gray-700', subTitleClassName)}>
|
|
47
|
+
{subTitle}
|
|
48
|
+
</h4>
|
|
49
|
+
)}
|
|
39
50
|
</div>
|
|
40
51
|
|
|
41
52
|
{icons && (
|
|
@@ -46,7 +57,11 @@ export const Accordion = ({
|
|
|
46
57
|
/>
|
|
47
58
|
)}
|
|
48
59
|
</div>
|
|
49
|
-
{collapse &&
|
|
60
|
+
{collapse && (
|
|
61
|
+
<div className={twMerge('mt-3 text-sm', collapseClassName)}>
|
|
62
|
+
{children}
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
50
65
|
</div>
|
|
51
66
|
);
|
|
52
67
|
};
|
|
@@ -1,8 +1,70 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
1
2
|
import { forwardRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
+
import { useLocalization } from '@akinon/next/hooks';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { FileInputProps } from '../types';
|
|
3
6
|
|
|
4
7
|
export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
|
|
5
|
-
function
|
|
6
|
-
|
|
8
|
+
function FileInput(
|
|
9
|
+
{
|
|
10
|
+
buttonClassName,
|
|
11
|
+
onChange,
|
|
12
|
+
fileClassName,
|
|
13
|
+
fileNameWrapperClassName,
|
|
14
|
+
fileInputClassName,
|
|
15
|
+
...props
|
|
16
|
+
},
|
|
17
|
+
ref
|
|
18
|
+
) {
|
|
19
|
+
const { t } = useLocalization();
|
|
20
|
+
const [fileNames, setFileNames] = useState<string[]>([]);
|
|
21
|
+
|
|
22
|
+
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
23
|
+
const files = Array.from(event.target.files || []);
|
|
24
|
+
setFileNames(files.map((file) => file.name));
|
|
25
|
+
|
|
26
|
+
if (onChange) {
|
|
27
|
+
onChange(event);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div className="relative">
|
|
33
|
+
<input
|
|
34
|
+
type="file"
|
|
35
|
+
{...props}
|
|
36
|
+
ref={ref}
|
|
37
|
+
className={twMerge(
|
|
38
|
+
'absolute inset-0 w-full h-full opacity-0 cursor-pointer',
|
|
39
|
+
fileInputClassName
|
|
40
|
+
)}
|
|
41
|
+
onChange={handleFileChange}
|
|
42
|
+
/>
|
|
43
|
+
<button
|
|
44
|
+
type="button"
|
|
45
|
+
className={twMerge(
|
|
46
|
+
'bg-primary text-white py-2 px-4 text-sm',
|
|
47
|
+
buttonClassName
|
|
48
|
+
)}
|
|
49
|
+
>
|
|
50
|
+
{t('common.file_input.select_file')}
|
|
51
|
+
</button>
|
|
52
|
+
<div
|
|
53
|
+
className={twMerge('mt-1 text-gray-500', fileNameWrapperClassName)}
|
|
54
|
+
>
|
|
55
|
+
{fileNames.length > 0 ? (
|
|
56
|
+
<ul className={twMerge('list-disc pl-4 text-xs', fileClassName)}>
|
|
57
|
+
{fileNames.map((name, index) => (
|
|
58
|
+
<li key={index}>{name}</li>
|
|
59
|
+
))}
|
|
60
|
+
</ul>
|
|
61
|
+
) : (
|
|
62
|
+
<span className={twMerge('text-xs', fileClassName)}>
|
|
63
|
+
{t('common.file_input.no_file')}
|
|
64
|
+
</span>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
7
69
|
}
|
|
8
70
|
);
|
package/components/input.tsx
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { forwardRef, FocusEvent, useState, Ref } from 'react';
|
|
3
3
|
import { Controller } from 'react-hook-form';
|
|
4
|
+
|
|
5
|
+
// @ts-ignore
|
|
4
6
|
import { PatternFormat, PatternFormatProps } from 'react-number-format';
|
|
5
7
|
import { InputProps } from '../types';
|
|
6
8
|
import { twMerge } from 'tailwind-merge';
|
package/components/link.tsx
CHANGED
|
@@ -10,7 +10,9 @@ type LinkProps = Omit<
|
|
|
10
10
|
React.AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
11
11
|
keyof NextLinkProps
|
|
12
12
|
> &
|
|
13
|
-
NextLinkProps
|
|
13
|
+
NextLinkProps & {
|
|
14
|
+
href: string;
|
|
15
|
+
};
|
|
14
16
|
|
|
15
17
|
export const Link = ({ children, href, ...rest }: LinkProps) => {
|
|
16
18
|
const { locale, defaultLocaleValue, localeUrlStrategy } = useLocalization();
|
|
@@ -26,19 +28,21 @@ export const Link = ({ children, href, ...rest }: LinkProps) => {
|
|
|
26
28
|
return href;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
if (typeof href === 'string' && !href.startsWith('http')) {
|
|
32
|
+
const pathnameWithoutLocale = href.replace(urlLocaleMatcherRegex, '');
|
|
33
|
+
const hrefWithLocale = `/${locale}${pathnameWithoutLocale}`;
|
|
34
|
+
|
|
35
|
+
if (localeUrlStrategy === LocaleUrlStrategy.ShowAllLocales) {
|
|
36
|
+
return hrefWithLocale;
|
|
37
|
+
} else if (
|
|
38
|
+
localeUrlStrategy === LocaleUrlStrategy.HideDefaultLocale &&
|
|
39
|
+
locale !== defaultLocaleValue
|
|
40
|
+
) {
|
|
41
|
+
return hrefWithLocale;
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
return href
|
|
45
|
+
return href;
|
|
42
46
|
}, [href, defaultLocaleValue, locale, localeUrlStrategy]);
|
|
43
47
|
|
|
44
48
|
return (
|
package/components/modal.tsx
CHANGED
|
@@ -4,16 +4,7 @@ import { ReactPortal } from './react-portal';
|
|
|
4
4
|
import { Icon } from './icon';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
6
6
|
import { useEffect } from 'react';
|
|
7
|
-
|
|
8
|
-
export interface ModalProps {
|
|
9
|
-
portalId: string;
|
|
10
|
-
children?: React.ReactNode;
|
|
11
|
-
open?: boolean;
|
|
12
|
-
setOpen?: (open: boolean) => void;
|
|
13
|
-
title?: React.ReactNode;
|
|
14
|
-
showCloseButton?: React.ReactNode;
|
|
15
|
-
className?: string;
|
|
16
|
-
}
|
|
7
|
+
import { ModalProps } from '../types';
|
|
17
8
|
|
|
18
9
|
export const Modal = (props: ModalProps) => {
|
|
19
10
|
const {
|
|
@@ -23,7 +14,14 @@ export const Modal = (props: ModalProps) => {
|
|
|
23
14
|
setOpen,
|
|
24
15
|
title = '',
|
|
25
16
|
showCloseButton = true,
|
|
26
|
-
className
|
|
17
|
+
className,
|
|
18
|
+
overlayClassName,
|
|
19
|
+
headerWrapperClassName,
|
|
20
|
+
titleClassName,
|
|
21
|
+
closeButtonClassName,
|
|
22
|
+
iconName = 'close',
|
|
23
|
+
iconSize = 16,
|
|
24
|
+
iconClassName
|
|
27
25
|
} = props;
|
|
28
26
|
|
|
29
27
|
useEffect(() => {
|
|
@@ -38,7 +36,12 @@ export const Modal = (props: ModalProps) => {
|
|
|
38
36
|
|
|
39
37
|
return (
|
|
40
38
|
<ReactPortal wrapperId={portalId}>
|
|
41
|
-
<div
|
|
39
|
+
<div
|
|
40
|
+
className={twMerge(
|
|
41
|
+
'fixed top-0 left-0 w-screen h-screen bg-primary bg-opacity-60 z-50',
|
|
42
|
+
overlayClassName
|
|
43
|
+
)}
|
|
44
|
+
/>
|
|
42
45
|
<section
|
|
43
46
|
className={twMerge(
|
|
44
47
|
'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 bg-white',
|
|
@@ -46,15 +49,28 @@ export const Modal = (props: ModalProps) => {
|
|
|
46
49
|
)}
|
|
47
50
|
>
|
|
48
51
|
{(showCloseButton || title) && (
|
|
49
|
-
<div
|
|
50
|
-
|
|
52
|
+
<div
|
|
53
|
+
className={twMerge(
|
|
54
|
+
'flex px-6 py-4 border-b border-gray-400',
|
|
55
|
+
headerWrapperClassName
|
|
56
|
+
)}
|
|
57
|
+
>
|
|
58
|
+
{title && (
|
|
59
|
+
<h3 className={twMerge('text-lg font-light', titleClassName)}>
|
|
60
|
+
{title}
|
|
61
|
+
</h3>
|
|
62
|
+
)}
|
|
51
63
|
{showCloseButton && (
|
|
52
64
|
<button
|
|
53
65
|
type="button"
|
|
54
66
|
onClick={() => setOpen(false)}
|
|
55
|
-
className=
|
|
67
|
+
className={twMerge('ml-auto', closeButtonClassName)}
|
|
56
68
|
>
|
|
57
|
-
<Icon
|
|
69
|
+
<Icon
|
|
70
|
+
name={iconName}
|
|
71
|
+
size={iconSize}
|
|
72
|
+
className={iconClassName}
|
|
73
|
+
/>
|
|
58
74
|
</button>
|
|
59
75
|
)}
|
|
60
76
|
</div>
|
|
@@ -21,7 +21,9 @@ enum Plugin {
|
|
|
21
21
|
Akifast = 'pz-akifast',
|
|
22
22
|
MultiBasket = 'pz-multi-basket',
|
|
23
23
|
SavedCard = 'pz-saved-card',
|
|
24
|
-
|
|
24
|
+
Hepsipay = 'pz-hepsipay',
|
|
25
|
+
FlowPayment = 'pz-flow-payment',
|
|
26
|
+
SimilarProducts = 'pz-similar-products'
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export enum Component {
|
|
@@ -47,7 +49,15 @@ export enum Component {
|
|
|
47
49
|
AkifastCheckoutButton = 'CheckoutButton',
|
|
48
50
|
MultiBasket = 'MultiBasket',
|
|
49
51
|
SavedCard = 'SavedCardOption',
|
|
50
|
-
|
|
52
|
+
Hepsipay = 'Hepsipay',
|
|
53
|
+
FlowPayment = 'FlowPayment',
|
|
54
|
+
SimilarProductsModal = 'SimilarProductsModal',
|
|
55
|
+
SimilarProductsFilterSidebar = 'SimilarProductsFilterSidebar',
|
|
56
|
+
SimilarProductsResultsGrid = 'SimilarProductsResultsGrid',
|
|
57
|
+
SimilarProductsPlugin = 'SimilarProductsPlugin',
|
|
58
|
+
ProductImageSearchFeature = 'ProductImageSearchFeature',
|
|
59
|
+
ImageSearchButton = 'ImageSearchButton',
|
|
60
|
+
HeaderImageSearchFeature = 'HeaderImageSearchFeature'
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
const PluginComponents = new Map([
|
|
@@ -81,7 +91,20 @@ const PluginComponents = new Map([
|
|
|
81
91
|
],
|
|
82
92
|
[Plugin.MultiBasket, [Component.MultiBasket]],
|
|
83
93
|
[Plugin.SavedCard, [Component.SavedCard]],
|
|
84
|
-
[Plugin.
|
|
94
|
+
[Plugin.Hepsipay, [Component.Hepsipay]],
|
|
95
|
+
[Plugin.FlowPayment, [Component.FlowPayment]],
|
|
96
|
+
[
|
|
97
|
+
Plugin.SimilarProducts,
|
|
98
|
+
[
|
|
99
|
+
Component.SimilarProductsModal,
|
|
100
|
+
Component.SimilarProductsFilterSidebar,
|
|
101
|
+
Component.SimilarProductsResultsGrid,
|
|
102
|
+
Component.SimilarProductsPlugin,
|
|
103
|
+
Component.ProductImageSearchFeature,
|
|
104
|
+
Component.ImageSearchButton,
|
|
105
|
+
Component.HeaderImageSearchFeature
|
|
106
|
+
]
|
|
107
|
+
]
|
|
85
108
|
]);
|
|
86
109
|
|
|
87
110
|
const getPlugin = (component: Component) => {
|
|
@@ -146,8 +169,12 @@ export default function PluginModule({
|
|
|
146
169
|
promise = import(`${'@akinon/pz-multi-basket'}`);
|
|
147
170
|
} else if (plugin === Plugin.SavedCard) {
|
|
148
171
|
promise = import(`${'@akinon/pz-saved-card'}`);
|
|
172
|
+
} else if (plugin === Plugin.Hepsipay) {
|
|
173
|
+
promise = import(`${'@akinon/pz-hepsipay'}`);
|
|
149
174
|
} else if (plugin === Plugin.FlowPayment) {
|
|
150
175
|
promise = import(`${'@akinon/pz-flow-payment'}`);
|
|
176
|
+
} else if (plugin === Plugin.SimilarProducts) {
|
|
177
|
+
promise = import(`${'@akinon/pz-similar-products'}`);
|
|
151
178
|
}
|
|
152
179
|
} catch (error) {
|
|
153
180
|
logger.error(error);
|
package/data/client/checkout.ts
CHANGED
|
@@ -35,8 +35,10 @@ import {
|
|
|
35
35
|
|
|
36
36
|
interface CheckoutResponse {
|
|
37
37
|
pre_order?: PreOrder;
|
|
38
|
-
errors
|
|
39
|
-
non_field_errors
|
|
38
|
+
errors?: {
|
|
39
|
+
non_field_errors?: string;
|
|
40
|
+
sample_products?: string[];
|
|
41
|
+
[key: string]: string | string[] | undefined;
|
|
40
42
|
};
|
|
41
43
|
context_list?: CheckoutContext[];
|
|
42
44
|
template_name?: string;
|
|
@@ -884,8 +886,7 @@ export const checkoutApi = api.injectEndpoints({
|
|
|
884
886
|
method: 'POST',
|
|
885
887
|
body: formData
|
|
886
888
|
};
|
|
887
|
-
}
|
|
888
|
-
invalidatesTags: ['Checkout']
|
|
889
|
+
}
|
|
889
890
|
})
|
|
890
891
|
}),
|
|
891
892
|
overrideExisting: false
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Cache, CacheKey } from '../../lib/cache';
|
|
2
|
+
import { basket } from '../../data/urls';
|
|
3
|
+
import { Basket } from '../../types';
|
|
4
|
+
import appFetch from '../../utils/app-fetch';
|
|
5
|
+
import { ServerVariables } from '../../utils/server-variables';
|
|
6
|
+
import logger from '../../utils/log';
|
|
7
|
+
|
|
8
|
+
type GetBasketParams = {
|
|
9
|
+
locale?: string;
|
|
10
|
+
currency?: string;
|
|
11
|
+
namespace?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const getBasketDataHandler = ({
|
|
15
|
+
locale,
|
|
16
|
+
currency,
|
|
17
|
+
namespace
|
|
18
|
+
}: GetBasketParams) => {
|
|
19
|
+
return async function () {
|
|
20
|
+
try {
|
|
21
|
+
const url = namespace
|
|
22
|
+
? basket.getBasketDetail(namespace)
|
|
23
|
+
: basket.getBasket;
|
|
24
|
+
|
|
25
|
+
const basketData = await appFetch<{ basket: Basket }>({
|
|
26
|
+
url,
|
|
27
|
+
locale,
|
|
28
|
+
currency,
|
|
29
|
+
init: {
|
|
30
|
+
headers: {
|
|
31
|
+
Accept: 'application/json',
|
|
32
|
+
'Content-Type': 'application/json'
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (!basketData?.basket) {
|
|
38
|
+
logger.warn('Basket data is undefined', {
|
|
39
|
+
handler: 'getBasketDataHandler',
|
|
40
|
+
namespace
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return basketData;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
logger.error('Error fetching basket data', {
|
|
47
|
+
handler: 'getBasketDataHandler',
|
|
48
|
+
error,
|
|
49
|
+
namespace
|
|
50
|
+
});
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const getBasketData = async ({
|
|
57
|
+
locale = ServerVariables.locale,
|
|
58
|
+
currency = ServerVariables.currency,
|
|
59
|
+
namespace
|
|
60
|
+
}: GetBasketParams = {}) => {
|
|
61
|
+
return Cache.wrap(
|
|
62
|
+
CacheKey.Basket(namespace),
|
|
63
|
+
locale,
|
|
64
|
+
getBasketDataHandler({ locale, currency, namespace }),
|
|
65
|
+
{
|
|
66
|
+
expire: 0,
|
|
67
|
+
cache: false
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
|
package/data/server/category.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { category, product } from '../urls';
|
|
|
5
5
|
import { Cache, CacheKey } from '../../lib/cache';
|
|
6
6
|
import { parse } from 'lossless-json';
|
|
7
7
|
import logger from '../../utils/log';
|
|
8
|
-
import { headers as nHeaders } from 'next/headers';
|
|
9
8
|
import { ServerVariables } from '../../utils/server-variables';
|
|
10
9
|
|
|
11
10
|
function getCategoryDataHandler(
|
|
@@ -18,19 +17,30 @@ function getCategoryDataHandler(
|
|
|
18
17
|
return async function () {
|
|
19
18
|
const params = generateCommerceSearchParams(searchParams);
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
let rawData: string;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
rawData = await appFetch<string>({
|
|
24
|
+
url: `${category.getCategoryByPk(pk)}${params ? params : ''}`,
|
|
25
|
+
locale,
|
|
26
|
+
currency,
|
|
27
|
+
init: {
|
|
28
|
+
headers: {
|
|
29
|
+
Accept: 'application/json',
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
...(headers ?? {})
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
responseType: FetchResponseType.TEXT
|
|
35
|
+
});
|
|
36
|
+
} catch (error) {
|
|
37
|
+
logger.error('Failed to fetch category data', {
|
|
38
|
+
handler: 'getCategoryDataHandler',
|
|
39
|
+
pk,
|
|
40
|
+
error: error.message
|
|
41
|
+
});
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
34
44
|
|
|
35
45
|
let data: GetCategoryResponse;
|
|
36
46
|
|
|
@@ -48,8 +58,8 @@ function getCategoryDataHandler(
|
|
|
48
58
|
logger.fatal('Error while parsing category data', {
|
|
49
59
|
handler: 'getCategoryDataHandler',
|
|
50
60
|
error,
|
|
51
|
-
rawData: rawData
|
|
52
|
-
? `${rawData
|
|
61
|
+
rawData: rawData?.startsWith?.('<!DOCTYPE html>')
|
|
62
|
+
? `${rawData?.substring(0, 50)}...`
|
|
53
63
|
: rawData
|
|
54
64
|
});
|
|
55
65
|
}
|
|
@@ -64,17 +74,27 @@ function getCategoryDataHandler(
|
|
|
64
74
|
return { data, breadcrumbData: undefined };
|
|
65
75
|
}
|
|
66
76
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
let breadcrumbData: { menu?: unknown } = {};
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
breadcrumbData = await appFetch<{ menu?: unknown }>({
|
|
81
|
+
url: product.breadcrumbUrl(menuItemModel),
|
|
82
|
+
locale,
|
|
83
|
+
currency,
|
|
84
|
+
init: {
|
|
85
|
+
headers: {
|
|
86
|
+
Accept: 'application/json',
|
|
87
|
+
'Content-Type': 'application/json'
|
|
88
|
+
}
|
|
75
89
|
}
|
|
76
|
-
}
|
|
77
|
-
})
|
|
90
|
+
});
|
|
91
|
+
} catch (error) {
|
|
92
|
+
logger.warn('Failed to fetch breadcrumb data', {
|
|
93
|
+
handler: 'getCategoryDataHandler',
|
|
94
|
+
pk,
|
|
95
|
+
error: error.message
|
|
96
|
+
});
|
|
97
|
+
}
|
|
78
98
|
|
|
79
99
|
return { data, breadcrumbData: breadcrumbData?.menu };
|
|
80
100
|
};
|
|
@@ -98,7 +118,8 @@ export const getCategoryData = ({
|
|
|
98
118
|
locale,
|
|
99
119
|
getCategoryDataHandler(pk, locale, currency, searchParams, headers),
|
|
100
120
|
{
|
|
101
|
-
expire: 300
|
|
121
|
+
expire: 300,
|
|
122
|
+
compressed: true
|
|
102
123
|
}
|
|
103
124
|
);
|
|
104
125
|
};
|
|
@@ -138,8 +159,8 @@ function getCategoryBySlugDataHandler(
|
|
|
138
159
|
logger.fatal('Error while parsing category data', {
|
|
139
160
|
handler: 'getCategoryBySlugDataHandler',
|
|
140
161
|
error,
|
|
141
|
-
rawData: rawData
|
|
142
|
-
? `${rawData
|
|
162
|
+
rawData: rawData?.startsWith?.('<!DOCTYPE html>')
|
|
163
|
+
? `${rawData?.substring(0, 50)}...`
|
|
143
164
|
: rawData
|
|
144
165
|
});
|
|
145
166
|
}
|
|
@@ -158,7 +179,8 @@ export const getCategoryBySlugData = async ({
|
|
|
158
179
|
locale,
|
|
159
180
|
getCategoryBySlugDataHandler(slug, locale, currency),
|
|
160
181
|
{
|
|
161
|
-
expire: 300
|
|
182
|
+
expire: 300,
|
|
183
|
+
compressed: true // Compress category data for memory savings
|
|
162
184
|
}
|
|
163
185
|
);
|
|
164
186
|
};
|
package/data/server/flatpage.ts
CHANGED
|
@@ -11,20 +11,24 @@ const getFlatPageDataHandler = (
|
|
|
11
11
|
headers?: Record<string, string>
|
|
12
12
|
) => {
|
|
13
13
|
return async function () {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
try {
|
|
15
|
+
const data = await appFetch<FlatPage>({
|
|
16
|
+
url: flatpage.getFlatPageByPk(pk),
|
|
17
|
+
locale,
|
|
18
|
+
currency,
|
|
19
|
+
init: {
|
|
20
|
+
headers: {
|
|
21
|
+
Accept: 'application/json',
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
...(headers ?? {})
|
|
24
|
+
}
|
|
23
25
|
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
+
});
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
return data;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
28
32
|
};
|
|
29
33
|
};
|
|
30
34
|
|
|
@@ -42,6 +46,9 @@ export const getFlatPageData = ({
|
|
|
42
46
|
return Cache.wrap(
|
|
43
47
|
CacheKey.FlatPage(pk),
|
|
44
48
|
locale,
|
|
45
|
-
getFlatPageDataHandler(pk, locale, currency, headers)
|
|
49
|
+
getFlatPageDataHandler(pk, locale, currency, headers),
|
|
50
|
+
{
|
|
51
|
+
compressed: true
|
|
52
|
+
}
|
|
46
53
|
);
|
|
47
54
|
};
|
package/data/server/form.ts
CHANGED
|
@@ -11,20 +11,24 @@ const getLandingPageHandler = (
|
|
|
11
11
|
headers?: Record<string, string>
|
|
12
12
|
) => {
|
|
13
13
|
return async function () {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
try {
|
|
15
|
+
const data = await appFetch<LandingPage>({
|
|
16
|
+
url: landingpage.getLandingPageByPk(pk),
|
|
17
|
+
locale,
|
|
18
|
+
currency,
|
|
19
|
+
init: {
|
|
20
|
+
headers: {
|
|
21
|
+
Accept: 'application/json',
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
...(headers ?? {})
|
|
24
|
+
}
|
|
23
25
|
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
+
});
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
return data;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
28
32
|
};
|
|
29
33
|
};
|
|
30
34
|
|
|
@@ -42,6 +46,9 @@ export const getLandingPageData = ({
|
|
|
42
46
|
return Cache.wrap(
|
|
43
47
|
CacheKey.LandingPage(pk),
|
|
44
48
|
locale,
|
|
45
|
-
getLandingPageHandler(pk, locale, currency, headers)
|
|
49
|
+
getLandingPageHandler(pk, locale, currency, headers),
|
|
50
|
+
{
|
|
51
|
+
compressed: true
|
|
52
|
+
}
|
|
46
53
|
);
|
|
47
54
|
};
|