@akinon/next 1.52.0 → 1.53.0-rc.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/CHANGELOG.md +489 -0
- package/api/client.ts +50 -17
- package/assets/styles/index.css +49 -0
- package/assets/styles/index.css.map +1 -0
- package/assets/styles/index.scss +50 -26
- package/bin/pz-generate-translations.js +41 -0
- package/bin/pz-prebuild.js +1 -0
- package/bin/pz-predev.js +1 -0
- package/components/file-input.tsx +8 -0
- package/components/index.ts +1 -0
- package/components/input.tsx +21 -7
- package/components/link.tsx +17 -13
- package/components/price.tsx +11 -4
- package/components/pz-root.tsx +15 -3
- package/components/selected-payment-option-view.tsx +26 -38
- package/data/client/account.ts +10 -9
- package/data/client/address.ts +32 -8
- package/data/client/api.ts +1 -1
- package/data/client/b2b.ts +35 -2
- package/data/client/basket.ts +6 -5
- package/data/client/checkout.ts +47 -4
- package/data/client/user.ts +3 -2
- package/data/client/wishlist.ts +1 -1
- package/data/server/category.ts +43 -19
- package/data/server/flatpage.ts +29 -7
- package/data/server/form.ts +29 -11
- package/data/server/landingpage.ts +26 -7
- package/data/server/list.ts +16 -6
- package/data/server/menu.ts +15 -2
- package/data/server/product.ts +46 -21
- package/data/server/seo.ts +17 -24
- package/data/server/special-page.ts +15 -5
- package/data/server/widget.ts +14 -7
- package/data/urls.ts +8 -1
- package/hocs/server/with-segment-defaults.tsx +4 -1
- package/hooks/index.ts +2 -1
- package/hooks/use-message-listener.ts +24 -0
- package/hooks/use-pagination.ts +2 -2
- package/hooks/use-payment-options.ts +2 -1
- package/lib/cache-handler.mjs +33 -0
- package/lib/cache.ts +8 -6
- package/middlewares/default.ts +87 -8
- package/middlewares/pretty-url.ts +11 -1
- package/middlewares/url-redirection.ts +4 -0
- package/package.json +4 -3
- package/plugins.d.ts +1 -0
- package/redux/middlewares/checkout.ts +70 -11
- package/redux/reducers/checkout.ts +24 -5
- package/redux/reducers/config.ts +2 -0
- package/routes/pretty-url.tsx +192 -0
- package/types/commerce/account.ts +1 -0
- package/types/commerce/address.ts +1 -1
- package/types/commerce/b2b.ts +12 -2
- package/types/commerce/checkout.ts +30 -0
- package/types/commerce/misc.ts +2 -0
- package/types/commerce/order.ts +5 -0
- package/types/index.ts +18 -2
- package/utils/app-fetch.ts +17 -8
- package/utils/generate-commerce-search-params.ts +3 -1
- package/utils/index.ts +27 -6
- package/utils/redirection-iframe.ts +85 -0
- package/utils/server-translation.ts +11 -1
- package/utils/server-variables.ts +2 -1
- package/with-pz-config.js +13 -2
package/data/server/seo.ts
CHANGED
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
import appFetch from '../../utils/app-fetch';
|
|
2
2
|
import { Cache, CacheKey } from '../../lib/cache';
|
|
3
3
|
import { misc } from '../../data/urls';
|
|
4
|
-
import
|
|
4
|
+
import { ServerVariables } from '../../utils/server-variables';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
try {
|
|
11
|
-
data = await appFetch<{ [key: string]: string }>(misc.cmsSeo('/'));
|
|
12
|
-
} catch (error) {
|
|
13
|
-
logger.error('Error while fetching root seo data', error);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return data;
|
|
17
|
-
};
|
|
6
|
+
interface SeoDataParams {
|
|
7
|
+
url: string;
|
|
8
|
+
locale?: string;
|
|
9
|
+
currency?: string;
|
|
18
10
|
}
|
|
19
11
|
|
|
20
|
-
function getSeoDataHandler(url:
|
|
12
|
+
function getSeoDataHandler({ url, locale, currency }: SeoDataParams) {
|
|
21
13
|
return async function () {
|
|
22
14
|
let data = {} as {
|
|
23
15
|
title: string;
|
|
@@ -27,7 +19,7 @@ function getSeoDataHandler(url: string) {
|
|
|
27
19
|
};
|
|
28
20
|
|
|
29
21
|
try {
|
|
30
|
-
data = await appFetch(misc.cmsSeo(url));
|
|
22
|
+
data = await appFetch({ url: misc.cmsSeo(url), locale, currency });
|
|
31
23
|
} catch (error) {
|
|
32
24
|
// logger.error('Error while fetching seo data', { url, error });
|
|
33
25
|
}
|
|
@@ -36,13 +28,14 @@ function getSeoDataHandler(url: string) {
|
|
|
36
28
|
};
|
|
37
29
|
}
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
31
|
+
export const getSeoData = async (
|
|
32
|
+
url,
|
|
33
|
+
locale = ServerVariables.locale,
|
|
34
|
+
currency = ServerVariables.currency
|
|
35
|
+
) => {
|
|
36
|
+
return Cache.wrap(
|
|
37
|
+
CacheKey.Seo(url),
|
|
38
|
+
locale,
|
|
39
|
+
getSeoDataHandler({ url, locale, currency })
|
|
40
|
+
);
|
|
48
41
|
};
|
|
@@ -4,25 +4,30 @@ import { GetCategoryResponse } from '../../types';
|
|
|
4
4
|
import { generateCommerceSearchParams } from '../../utils';
|
|
5
5
|
import appFetch from '../../utils/app-fetch';
|
|
6
6
|
import header from '../../redux/reducers/header';
|
|
7
|
+
import { ServerVariables } from '../../utils/server-variables';
|
|
7
8
|
|
|
8
9
|
const getSpecialPageDataHandler = (
|
|
9
10
|
pk: number,
|
|
11
|
+
locale: string,
|
|
12
|
+
currency: string,
|
|
10
13
|
searchParams: URLSearchParams,
|
|
11
14
|
headers?: Record<string, string>
|
|
12
15
|
) => {
|
|
13
16
|
return async function () {
|
|
14
17
|
const params = generateCommerceSearchParams(searchParams);
|
|
15
18
|
|
|
16
|
-
const data: GetCategoryResponse = await appFetch(
|
|
17
|
-
`${category.getSpecialPageByPk(pk)}${params}`,
|
|
18
|
-
|
|
19
|
+
const data: GetCategoryResponse = await appFetch({
|
|
20
|
+
url: `${category.getSpecialPageByPk(pk)}${params}`,
|
|
21
|
+
locale,
|
|
22
|
+
currency,
|
|
23
|
+
init: {
|
|
19
24
|
headers: {
|
|
20
25
|
Accept: 'application/json',
|
|
21
26
|
'Content-Type': 'application/json',
|
|
22
27
|
...(headers ?? {})
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
|
-
);
|
|
30
|
+
});
|
|
26
31
|
|
|
27
32
|
return data;
|
|
28
33
|
};
|
|
@@ -30,16 +35,21 @@ const getSpecialPageDataHandler = (
|
|
|
30
35
|
|
|
31
36
|
export const getSpecialPageData = async ({
|
|
32
37
|
pk,
|
|
38
|
+
locale = ServerVariables.locale,
|
|
39
|
+
currency = ServerVariables.currency,
|
|
33
40
|
searchParams,
|
|
34
41
|
headers
|
|
35
42
|
}: {
|
|
36
43
|
pk: number;
|
|
44
|
+
locale?: string;
|
|
45
|
+
currency?: string;
|
|
37
46
|
searchParams: URLSearchParams;
|
|
38
47
|
headers?: Record<string, string>;
|
|
39
48
|
}) => {
|
|
40
49
|
return Cache.wrap(
|
|
41
50
|
CacheKey.SpecialPage(pk, searchParams, headers),
|
|
42
|
-
|
|
51
|
+
locale,
|
|
52
|
+
getSpecialPageDataHandler(pk, locale, currency, searchParams, headers),
|
|
43
53
|
{
|
|
44
54
|
expire: 300
|
|
45
55
|
}
|
package/data/server/widget.ts
CHANGED
|
@@ -3,25 +3,32 @@ import 'server-only';
|
|
|
3
3
|
import { CacheOptions, WidgetResultType } from '../../types';
|
|
4
4
|
import appFetch from '../../utils/app-fetch';
|
|
5
5
|
import { widgets } from '../urls';
|
|
6
|
+
import { ServerVariables } from '../../utils/server-variables';
|
|
6
7
|
|
|
7
|
-
const getWidgetDataHandler =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const getWidgetDataHandler =
|
|
9
|
+
(slug: string, locale: string, currency: string) => async () => {
|
|
10
|
+
if (!slug) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
+
return await appFetch({ url: widgets.getWidget(slug), locale, currency });
|
|
15
|
+
};
|
|
14
16
|
|
|
15
17
|
export const getWidgetData = async <T>({
|
|
16
18
|
slug,
|
|
19
|
+
locale = ServerVariables.locale,
|
|
20
|
+
currency = ServerVariables.currency,
|
|
17
21
|
cacheOptions
|
|
18
22
|
}: {
|
|
19
23
|
slug: string;
|
|
24
|
+
locale?: string;
|
|
25
|
+
currency?: string;
|
|
20
26
|
cacheOptions?: CacheOptions;
|
|
21
27
|
}): Promise<WidgetResultType<T>> => {
|
|
22
28
|
return Cache.wrap(
|
|
23
29
|
CacheKey.Widget(slug),
|
|
24
|
-
|
|
30
|
+
locale,
|
|
31
|
+
getWidgetDataHandler(slug, locale, currency),
|
|
25
32
|
cacheOptions
|
|
26
33
|
);
|
|
27
34
|
};
|
package/data/urls.ts
CHANGED
|
@@ -83,6 +83,8 @@ export const checkout = {
|
|
|
83
83
|
setDeliveryOption: '/orders/checkout/?page=DeliveryOptionSelectionPage',
|
|
84
84
|
setAddresses: '/orders/checkout/?page=AddressSelectionPage',
|
|
85
85
|
setShippingOption: '/orders/checkout/?page=ShippingOptionSelectionPage',
|
|
86
|
+
setDataSourceShippingOption:
|
|
87
|
+
'/orders/checkout/?page=DataSourceShippingOptionSelectionPage',
|
|
86
88
|
setPaymentOption: '/orders/checkout/?page=PaymentOptionSelectionPage',
|
|
87
89
|
setBinNumber: '/orders/checkout/?page=BinNumberPage',
|
|
88
90
|
setMasterpassBinNumber: '/orders/checkout/?page=MasterpassBinNumberPage',
|
|
@@ -109,6 +111,8 @@ export const checkout = {
|
|
|
109
111
|
loyaltyMoneyUsage: '/orders/checkout/?page=LoyaltyMoneyUsagePage',
|
|
110
112
|
setOrderNote: '/orders/checkout/?page=OrderNotePage',
|
|
111
113
|
couponSelectionPage: '/orders/checkout/?page=CouponSelectionPage',
|
|
114
|
+
setAttributeBasedShippingOption:
|
|
115
|
+
'/orders/checkout/?page=AttributeBasedShippingOptionSelectionPage',
|
|
112
116
|
deliveryBagsPage: '/orders/checkout/?page=DeliveryBagsPage'
|
|
113
117
|
};
|
|
114
118
|
|
|
@@ -198,7 +202,10 @@ export const b2b = {
|
|
|
198
202
|
draftBaskets: '/b2b/basket/drafts/',
|
|
199
203
|
divisions: '/b2b/my-divisions/',
|
|
200
204
|
myQuotations: '/b2b/my-quotations/',
|
|
201
|
-
loadBasket: (id) => `/b2b/basket/${id}/load
|
|
205
|
+
loadBasket: (id) => `/b2b/basket/${id}/load/`,
|
|
206
|
+
statusBasket: (cacheKey) => `/b2b/basket/?status_cache_key=${cacheKey}`,
|
|
207
|
+
basketExport: (queryString) => `/b2b/basket/?upload=true&${queryString}`,
|
|
208
|
+
basketImport: '/b2b/basket/bulk-import/'
|
|
202
209
|
};
|
|
203
210
|
|
|
204
211
|
export const widgets = {
|
|
@@ -2,7 +2,6 @@ import settings from 'settings';
|
|
|
2
2
|
import { LayoutProps, PageProps, RootLayoutProps } from '../../types';
|
|
3
3
|
import { redirect } from 'next/navigation';
|
|
4
4
|
import { ServerVariables } from '../../utils/server-variables';
|
|
5
|
-
import { getTranslations } from '../../utils/server-translation';
|
|
6
5
|
import { ROUTES } from 'routes';
|
|
7
6
|
import logger from '../../utils/log';
|
|
8
7
|
|
|
@@ -50,7 +49,11 @@ const addRootLayoutProps = async (componentProps: RootLayoutProps) => {
|
|
|
50
49
|
return redirect(ROUTES.HOME);
|
|
51
50
|
}
|
|
52
51
|
|
|
52
|
+
const { getTranslations } = settings.useOptimizedTranslations
|
|
53
|
+
? require('translations')
|
|
54
|
+
: require('../../utils/server-translation');
|
|
53
55
|
const translations = await getTranslations(params.locale);
|
|
56
|
+
|
|
54
57
|
componentProps.translations = translations;
|
|
55
58
|
|
|
56
59
|
const locale = settings.localization.locales.find(
|
package/hooks/index.ts
CHANGED
|
@@ -8,4 +8,5 @@ export * from './use-media-query';
|
|
|
8
8
|
export * from './use-on-click-outside';
|
|
9
9
|
export * from './use-mobile-iframe-handler';
|
|
10
10
|
export * from './use-payment-options';
|
|
11
|
-
export * from './use-pagination';
|
|
11
|
+
export * from './use-pagination';
|
|
12
|
+
export * from './use-message-listener';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useMessageListener = () => {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
const handleMessage = (event: MessageEvent) => {
|
|
6
|
+
if (event.origin !== window.location.origin) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (event.data && typeof event.data === 'string') {
|
|
11
|
+
const messageData = JSON.parse(event.data);
|
|
12
|
+
if (messageData?.url) {
|
|
13
|
+
window.location.href = messageData.url;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
window.addEventListener('message', handleMessage);
|
|
19
|
+
|
|
20
|
+
return () => {
|
|
21
|
+
window.removeEventListener('message', handleMessage);
|
|
22
|
+
};
|
|
23
|
+
}, []);
|
|
24
|
+
};
|
package/hooks/use-pagination.ts
CHANGED
|
@@ -116,7 +116,7 @@ export default function usePagination(
|
|
|
116
116
|
urlSearchParams.set('page', (Number(state.page) - 1).toString());
|
|
117
117
|
return `${pathname}?${urlSearchParams.toString()}`;
|
|
118
118
|
}
|
|
119
|
-
return
|
|
119
|
+
return null;
|
|
120
120
|
}, [state.page, pathname, urlSearchParams]);
|
|
121
121
|
|
|
122
122
|
const next = useMemo(() => {
|
|
@@ -124,7 +124,7 @@ export default function usePagination(
|
|
|
124
124
|
urlSearchParams.set('page', (Number(state.page) + 1).toString());
|
|
125
125
|
return `${pathname}?${urlSearchParams.toString()}`;
|
|
126
126
|
}
|
|
127
|
-
return
|
|
127
|
+
return null;
|
|
128
128
|
}, [state.page, state.last, pathname, urlSearchParams]);
|
|
129
129
|
|
|
130
130
|
return {
|
|
@@ -18,7 +18,8 @@ export const usePaymentOptions = () => {
|
|
|
18
18
|
pay_on_delivery: 'pz-pay-on-delivery',
|
|
19
19
|
bkm_express: 'pz-bkm',
|
|
20
20
|
credit_payment: 'pz-credit-payment',
|
|
21
|
-
masterpass: 'pz-masterpass'
|
|
21
|
+
masterpass: 'pz-masterpass',
|
|
22
|
+
gpay: 'pz-gpay'
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
const isInitialTypeIncluded = (type: string) => initialTypes.has(type);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { CacheHandler } from '@neshca/cache-handler';
|
|
2
|
+
import createLruHandler from '@neshca/cache-handler/local-lru';
|
|
3
|
+
import createRedisHandler from '@neshca/cache-handler/redis-stack';
|
|
4
|
+
import { createClient } from 'redis';
|
|
5
|
+
|
|
6
|
+
CacheHandler.onCreation(async () => {
|
|
7
|
+
const redisUrl = `redis://${process.env.CACHE_HOST}:${
|
|
8
|
+
process.env.CACHE_PORT
|
|
9
|
+
}/${process.env.CACHE_BUCKET ?? '0'}`;
|
|
10
|
+
|
|
11
|
+
const client = createClient({
|
|
12
|
+
url: redisUrl
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
client.on('error', (error) => {
|
|
16
|
+
console.error('Redis client error', { redisUrl, error });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
await client.connect();
|
|
20
|
+
|
|
21
|
+
const redisHandler = await createRedisHandler({
|
|
22
|
+
client,
|
|
23
|
+
timeoutMs: 5000
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const localHandler = createLruHandler();
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
handlers: [redisHandler, localHandler]
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export default CacheHandler;
|
package/lib/cache.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { RedisClientType } from 'redis';
|
|
|
3
3
|
import Settings from 'settings';
|
|
4
4
|
import { CacheOptions } from '../types';
|
|
5
5
|
import logger from '../utils/log';
|
|
6
|
-
import { ServerVariables } from '../utils/server-variables';
|
|
7
6
|
|
|
8
7
|
const hashCacheKey = (object?: Record<string, string>) => {
|
|
9
8
|
if (!object) {
|
|
@@ -59,10 +58,8 @@ export const CacheKey = {
|
|
|
59
58
|
export class Cache {
|
|
60
59
|
static PROXY_URL = `${process.env.NEXT_PUBLIC_URL}/api/cache`;
|
|
61
60
|
|
|
62
|
-
static formatKey(key: string) {
|
|
63
|
-
return encodeURIComponent(
|
|
64
|
-
`${Settings.commerceUrl}_${ServerVariables.locale}_${key}`
|
|
65
|
-
);
|
|
61
|
+
static formatKey(key: string, locale: string) {
|
|
62
|
+
return encodeURIComponent(`${Settings.commerceUrl}_${locale}_${key}`);
|
|
66
63
|
}
|
|
67
64
|
|
|
68
65
|
static clientPool: Pool<RedisClientType> = createPool(
|
|
@@ -155,9 +152,14 @@ export class Cache {
|
|
|
155
152
|
|
|
156
153
|
static async wrap<T = any>(
|
|
157
154
|
key: string,
|
|
155
|
+
locale: string,
|
|
158
156
|
handler: () => Promise<T>,
|
|
159
157
|
options?: CacheOptions
|
|
160
158
|
): Promise<T> {
|
|
159
|
+
if (Settings.usePrettyUrlRoute) {
|
|
160
|
+
return await handler();
|
|
161
|
+
}
|
|
162
|
+
|
|
161
163
|
const requiredVariables = [
|
|
162
164
|
process.env.CACHE_HOST,
|
|
163
165
|
process.env.CACHE_PORT,
|
|
@@ -174,7 +176,7 @@ export class Cache {
|
|
|
174
176
|
};
|
|
175
177
|
|
|
176
178
|
const _options = Object.assign(defaultOptions, options);
|
|
177
|
-
const formattedKey = Cache.formatKey(key);
|
|
179
|
+
const formattedKey = Cache.formatKey(key, locale);
|
|
178
180
|
|
|
179
181
|
logger.debug('Cache wrap', { key, formattedKey, _options });
|
|
180
182
|
|
package/middlewares/default.ts
CHANGED
|
@@ -88,14 +88,44 @@ const withPzDefault =
|
|
|
88
88
|
req.nextUrl.pathname.includes('/orders/hooks/') ||
|
|
89
89
|
req.nextUrl.pathname.includes('/orders/checkout-with-token/')
|
|
90
90
|
) {
|
|
91
|
-
|
|
91
|
+
const segment = url.searchParams.get('segment');
|
|
92
|
+
const currency = url.searchParams.get('currency')?.toLowerCase();
|
|
93
|
+
|
|
94
|
+
const headers = {};
|
|
95
|
+
|
|
96
|
+
if (segment) {
|
|
97
|
+
headers['X-Segment-Id'] = segment;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (currency) {
|
|
101
|
+
headers['x-currency'] = currency;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const response = NextResponse.rewrite(
|
|
92
105
|
new URL(
|
|
93
106
|
`${Settings.commerceUrl}${req.nextUrl.pathname.replace(
|
|
94
107
|
urlLocaleMatcherRegex,
|
|
95
108
|
''
|
|
96
109
|
)}`
|
|
97
|
-
)
|
|
110
|
+
),
|
|
111
|
+
{
|
|
112
|
+
headers
|
|
113
|
+
}
|
|
98
114
|
);
|
|
115
|
+
|
|
116
|
+
if (segment) {
|
|
117
|
+
response.cookies.set('pz-segment', segment);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (currency) {
|
|
121
|
+
response.cookies.set('pz-currency', currency, {
|
|
122
|
+
sameSite: 'none',
|
|
123
|
+
secure: true,
|
|
124
|
+
expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7) // 7 days
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return response;
|
|
99
129
|
}
|
|
100
130
|
|
|
101
131
|
if (req.nextUrl.pathname.startsWith('/orders/redirection/')) {
|
|
@@ -189,10 +219,41 @@ const withPzDefault =
|
|
|
189
219
|
''
|
|
190
220
|
);
|
|
191
221
|
|
|
222
|
+
middlewareResult = (await middleware(
|
|
223
|
+
req,
|
|
224
|
+
event
|
|
225
|
+
)) as NextResponse | void;
|
|
226
|
+
|
|
227
|
+
let customRewriteUrlDiff = '';
|
|
228
|
+
|
|
229
|
+
if (
|
|
230
|
+
middlewareResult instanceof NextResponse &&
|
|
231
|
+
middlewareResult.headers.get(
|
|
232
|
+
'pz-override-response'
|
|
233
|
+
) &&
|
|
234
|
+
middlewareResult.headers.get(
|
|
235
|
+
'x-middleware-rewrite'
|
|
236
|
+
)
|
|
237
|
+
) {
|
|
238
|
+
const rewriteUrl = new URL(
|
|
239
|
+
middlewareResult.headers.get(
|
|
240
|
+
'x-middleware-rewrite'
|
|
241
|
+
)
|
|
242
|
+
);
|
|
243
|
+
const originalUrl = new URL(req.url);
|
|
244
|
+
customRewriteUrlDiff =
|
|
245
|
+
rewriteUrl.pathname.replace(
|
|
246
|
+
originalUrl.pathname,
|
|
247
|
+
''
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
192
251
|
url.basePath = `/${commerceUrl}`;
|
|
193
252
|
url.pathname = `/${
|
|
194
253
|
locale.length ? `${locale}/` : ''
|
|
195
|
-
}${currency}${
|
|
254
|
+
}${currency}/${customRewriteUrlDiff}${
|
|
255
|
+
prettyUrl ?? pathnameWithoutLocale
|
|
256
|
+
}`.replace(/\/+/g, '/');
|
|
196
257
|
|
|
197
258
|
if (
|
|
198
259
|
!req.middlewareParams.found &&
|
|
@@ -207,6 +268,20 @@ const withPzDefault =
|
|
|
207
268
|
);
|
|
208
269
|
}
|
|
209
270
|
|
|
271
|
+
if (
|
|
272
|
+
Settings.usePrettyUrlRoute &&
|
|
273
|
+
url.searchParams.toString().length > 0 &&
|
|
274
|
+
!Object.entries(ROUTES).find(([, value]) =>
|
|
275
|
+
new RegExp(`^${value}/?$`).test(
|
|
276
|
+
pathnameWithoutLocale
|
|
277
|
+
)
|
|
278
|
+
)
|
|
279
|
+
) {
|
|
280
|
+
url.pathname =
|
|
281
|
+
url.pathname +
|
|
282
|
+
`searchparams|${url.searchParams.toString()}`;
|
|
283
|
+
}
|
|
284
|
+
|
|
210
285
|
Settings.rewrites.forEach((rewrite) => {
|
|
211
286
|
url.pathname = url.pathname.replace(
|
|
212
287
|
rewrite.source,
|
|
@@ -214,11 +289,6 @@ const withPzDefault =
|
|
|
214
289
|
);
|
|
215
290
|
});
|
|
216
291
|
|
|
217
|
-
middlewareResult = (await middleware(
|
|
218
|
-
req,
|
|
219
|
-
event
|
|
220
|
-
)) as NextResponse | void;
|
|
221
|
-
|
|
222
292
|
// if middleware.ts has a return value for current url
|
|
223
293
|
if (middlewareResult instanceof NextResponse) {
|
|
224
294
|
// pz-override-response header is used to prevent 404 page for custom responses.
|
|
@@ -231,6 +301,15 @@ const withPzDefault =
|
|
|
231
301
|
'x-middleware-rewrite',
|
|
232
302
|
url.href
|
|
233
303
|
);
|
|
304
|
+
} else if (
|
|
305
|
+
middlewareResult.headers.get(
|
|
306
|
+
'x-middleware-rewrite'
|
|
307
|
+
) &&
|
|
308
|
+
middlewareResult.headers.get(
|
|
309
|
+
'pz-override-response'
|
|
310
|
+
) === 'true'
|
|
311
|
+
) {
|
|
312
|
+
middlewareResult = NextResponse.rewrite(url);
|
|
234
313
|
}
|
|
235
314
|
} else {
|
|
236
315
|
// if middleware.ts doesn't have a return value.
|
|
@@ -43,9 +43,14 @@ const resolvePrettyUrlHandler =
|
|
|
43
43
|
return prettyUrlResult;
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
const resolvePrettyUrl = async (
|
|
46
|
+
const resolvePrettyUrl = async (
|
|
47
|
+
pathname: string,
|
|
48
|
+
locale: string,
|
|
49
|
+
ip: string | null
|
|
50
|
+
) => {
|
|
47
51
|
return Cache.wrap(
|
|
48
52
|
CacheKey.PrettyUrl(pathname),
|
|
53
|
+
locale,
|
|
49
54
|
resolvePrettyUrlHandler(pathname, ip),
|
|
50
55
|
{
|
|
51
56
|
useProxy: true
|
|
@@ -56,6 +61,10 @@ const resolvePrettyUrl = async (pathname: string, ip: string | null) => {
|
|
|
56
61
|
const withPrettyUrl =
|
|
57
62
|
(middleware: NextMiddleware) =>
|
|
58
63
|
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
64
|
+
if (Settings.usePrettyUrlRoute) {
|
|
65
|
+
return middleware(req, event);
|
|
66
|
+
}
|
|
67
|
+
|
|
59
68
|
const url = req.nextUrl.clone();
|
|
60
69
|
const matchedLanguagePrefix = url.pathname.match(
|
|
61
70
|
urlLocaleMatcherRegex
|
|
@@ -84,6 +93,7 @@ const withPrettyUrl =
|
|
|
84
93
|
)
|
|
85
94
|
? url.pathname
|
|
86
95
|
: prettyUrlPathname,
|
|
96
|
+
matchedLanguagePrefix,
|
|
87
97
|
ip
|
|
88
98
|
);
|
|
89
99
|
|
|
@@ -11,6 +11,10 @@ import { ROUTES } from 'routes';
|
|
|
11
11
|
const withUrlRedirection =
|
|
12
12
|
(middleware: NextMiddleware) =>
|
|
13
13
|
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
14
|
+
if (settings.usePrettyUrlRoute) {
|
|
15
|
+
return middleware(req, event);
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
const url = req.nextUrl.clone();
|
|
15
19
|
const ip = req.headers.get('x-forwarded-for') ?? '';
|
|
16
20
|
const pathnameWithoutLocale = url.pathname.replace(
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/next",
|
|
3
3
|
"description": "Core package for Project Zero Next",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.53.0-rc.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -20,16 +20,17 @@
|
|
|
20
20
|
"@opentelemetry/sdk-trace-node": "1.19.0",
|
|
21
21
|
"@opentelemetry/semantic-conventions": "1.19.0",
|
|
22
22
|
"@reduxjs/toolkit": "1.9.7",
|
|
23
|
+
"@neshca/cache-handler": "1.5.1",
|
|
23
24
|
"cross-spawn": "7.0.3",
|
|
24
25
|
"generic-pool": "3.9.0",
|
|
25
26
|
"react-redux": "8.1.3",
|
|
26
27
|
"react-string-replace": "1.1.1",
|
|
27
|
-
"redis": "4.
|
|
28
|
+
"redis": "4.6.13",
|
|
28
29
|
"semver": "7.6.2",
|
|
29
30
|
"set-cookie-parser": "2.6.0"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
"@akinon/eslint-plugin-projectzero": "1.
|
|
33
|
+
"@akinon/eslint-plugin-projectzero": "1.53.0-rc.0",
|
|
33
34
|
"@types/react-redux": "7.1.30",
|
|
34
35
|
"@types/set-cookie-parser": "2.4.7",
|
|
35
36
|
"@typescript-eslint/eslint-plugin": "6.7.4",
|
package/plugins.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare module '@akinon/pz-masterpass/src/utils' {
|
|
|
12
12
|
declare module '@akinon/pz-masterpass/src/redux/reducer' {
|
|
13
13
|
export const setError: any;
|
|
14
14
|
export const setOtpModalVisible: any;
|
|
15
|
+
export const setCvcRequired: any;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
declare module '@akinon/pz-otp' {
|