@akinon/next 1.0.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/.prettierrc +13 -0
- package/api/auth.ts +217 -0
- package/api/cache.ts +44 -0
- package/api/client.ts +157 -0
- package/api/logout.ts +42 -0
- package/assets/styles/index.scss +24 -0
- package/bin/pz-install-plugins.js +33 -0
- package/components/client-root.tsx +69 -0
- package/components/image.tsx +133 -0
- package/components/mobile-app-toggler.tsx +15 -0
- package/components/oauth-login.tsx +24 -0
- package/components/plugin-module.tsx +78 -0
- package/components/pz-providers.tsx +24 -0
- package/components/pz-root.tsx +21 -0
- package/components/redirect-three-d/content/index.tsx +64 -0
- package/components/redirect-three-d/index.tsx +17 -0
- package/components/selected-payment-option-view.tsx +66 -0
- package/components/trans.tsx +39 -0
- package/data/client/account.ts +188 -0
- package/data/client/address.ts +107 -0
- package/data/client/api.ts +42 -0
- package/data/client/basket.ts +85 -0
- package/data/client/checkout.ts +477 -0
- package/data/client/misc.ts +101 -0
- package/data/client/product.ts +90 -0
- package/data/client/user.ts +83 -0
- package/data/client/wishlist.ts +79 -0
- package/data/server/category.ts +121 -0
- package/data/server/flatpage.ts +21 -0
- package/data/server/index.ts +8 -0
- package/data/server/list.ts +56 -0
- package/data/server/menu.ts +35 -0
- package/data/server/product.ts +86 -0
- package/data/server/seo.ts +48 -0
- package/data/server/special-page.ts +42 -0
- package/data/server/widget.ts +27 -0
- package/data/urls.ts +184 -0
- package/hocs/client/index.ts +1 -0
- package/hocs/client/with-segment-defaults.tsx +26 -0
- package/hocs/server/index.ts +1 -0
- package/hocs/server/with-segment-defaults.tsx +83 -0
- package/hooks/index.ts +8 -0
- package/hooks/use-captcha.tsx +76 -0
- package/hooks/use-common-product-attributes.ts +36 -0
- package/hooks/use-debounce.ts +20 -0
- package/hooks/use-localization.ts +63 -0
- package/hooks/use-media-query.ts +36 -0
- package/hooks/use-on-click-outside.tsx +28 -0
- package/hooks/use-router.ts +45 -0
- package/hooks/use-translation.ts +14 -0
- package/lib/cache.ts +185 -0
- package/localization/index.ts +5 -0
- package/localization/provider.tsx +58 -0
- package/middlewares/currency.ts +55 -0
- package/middlewares/default.ts +224 -0
- package/middlewares/index.ts +29 -0
- package/middlewares/locale.ts +61 -0
- package/middlewares/oauth-login.ts +78 -0
- package/middlewares/pretty-url.ts +94 -0
- package/middlewares/redirection-payment.ts +117 -0
- package/middlewares/three-d-redirection.ts +122 -0
- package/middlewares/url-redirection.ts +61 -0
- package/package.json +20 -0
- package/plugins.js +7 -0
- package/redux/hooks.ts +7 -0
- package/redux/middlewares/checkout.ts +231 -0
- package/redux/middlewares/index.ts +50 -0
- package/redux/reducers/checkout.ts +164 -0
- package/redux/reducers/config.ts +28 -0
- package/redux/reducers/header.ts +59 -0
- package/redux/reducers/index.ts +15 -0
- package/redux/reducers/root.ts +61 -0
- package/tailwind/rtl.js +137 -0
- package/types/commerce/account.ts +68 -0
- package/types/commerce/address.ts +94 -0
- package/types/commerce/basket.ts +43 -0
- package/types/commerce/category.ts +114 -0
- package/types/commerce/checkout.ts +132 -0
- package/types/commerce/flatpage.ts +7 -0
- package/types/commerce/index.ts +10 -0
- package/types/commerce/misc.ts +127 -0
- package/types/commerce/order.ts +108 -0
- package/types/commerce/product.ts +110 -0
- package/types/commerce/widget.ts +28 -0
- package/types/gtm.ts +16 -0
- package/types/index.ts +207 -0
- package/types/next-auth.d.ts +24 -0
- package/utils/app-fetch.ts +62 -0
- package/utils/generate-commerce-search-params.ts +22 -0
- package/utils/get-currency.ts +29 -0
- package/utils/image-loader.ts +31 -0
- package/utils/index.ts +132 -0
- package/utils/localization.ts +29 -0
- package/utils/log.ts +138 -0
- package/utils/menu-generator.ts +27 -0
- package/utils/mobile-3d-iframe.ts +58 -0
- package/utils/server-translation.ts +57 -0
- package/utils/server-variables.ts +9 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NextFetchEvent,
|
|
3
|
+
NextMiddleware,
|
|
4
|
+
NextRequest,
|
|
5
|
+
NextResponse
|
|
6
|
+
} from 'next/server';
|
|
7
|
+
import Settings from 'settings';
|
|
8
|
+
import { getUrlPathWithLocale } from '../utils/localization';
|
|
9
|
+
|
|
10
|
+
const withOauthLogin =
|
|
11
|
+
(middleware: NextMiddleware) =>
|
|
12
|
+
async (req: NextRequest, event: NextFetchEvent) => {
|
|
13
|
+
const url = req.nextUrl.clone();
|
|
14
|
+
const loginUrlMatcherRegex = new RegExp(/^\/(\w+)\/login\/?$/);
|
|
15
|
+
const loginCallbackUrlMatcherRegex = new RegExp(
|
|
16
|
+
/^\/(\w+)\/login\/callback\/?$/
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const headers = {
|
|
20
|
+
'x-forwarded-host':
|
|
21
|
+
req.headers.get('x-forwarded-host') || req.headers.get('host') || ''
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (loginUrlMatcherRegex.test(url.pathname)) {
|
|
25
|
+
const provider = url.pathname.match(loginUrlMatcherRegex)[1];
|
|
26
|
+
const response = NextResponse.rewrite(
|
|
27
|
+
`${Settings.commerceUrl}/${provider}/login/`,
|
|
28
|
+
{
|
|
29
|
+
headers
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (req.headers.get('referer')) {
|
|
34
|
+
response.cookies.set(
|
|
35
|
+
'pz-oauth-callback-url',
|
|
36
|
+
req.headers.get('referer')
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return response;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (loginCallbackUrlMatcherRegex.test(url.pathname)) {
|
|
44
|
+
const provider = url.pathname.match(loginCallbackUrlMatcherRegex)[1];
|
|
45
|
+
|
|
46
|
+
return NextResponse.rewrite(
|
|
47
|
+
`${Settings.commerceUrl}/${provider}/login/callback/${url.search}`,
|
|
48
|
+
{
|
|
49
|
+
headers
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!url.pathname.startsWith('/baskets/basket')) {
|
|
55
|
+
return middleware(req, event);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (req.cookies.get('messages')?.value.includes('Successfully signed in')) {
|
|
59
|
+
let redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
|
|
60
|
+
'/auth/oauth-login',
|
|
61
|
+
req.cookies.get('pz-locale')?.value
|
|
62
|
+
)}`;
|
|
63
|
+
let callbackUrl = req.cookies.get('pz-oauth-callback-url')?.value ?? '';
|
|
64
|
+
|
|
65
|
+
if (callbackUrl.length) {
|
|
66
|
+
redirectUrlWithLocale += `?next=${encodeURIComponent(callbackUrl)}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const response = NextResponse.redirect(redirectUrlWithLocale);
|
|
70
|
+
response.cookies.delete('messages');
|
|
71
|
+
response.cookies.delete('pz-oauth-callback-url');
|
|
72
|
+
return response;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return middleware(req, event);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default withOauthLogin;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Cache, CacheKey } from '../lib/cache';
|
|
2
|
+
import { NextFetchEvent, NextMiddleware, NextRequest } from 'next/server';
|
|
3
|
+
import { ROUTES } from 'routes';
|
|
4
|
+
import { URLS } from '../data/urls';
|
|
5
|
+
import Settings from 'settings';
|
|
6
|
+
import { urlLocaleMatcherRegex } from '../utils';
|
|
7
|
+
import { PzNextRequest } from '.';
|
|
8
|
+
import logger from '../utils/log';
|
|
9
|
+
|
|
10
|
+
type PrettyUrlResult = {
|
|
11
|
+
matched: boolean;
|
|
12
|
+
path?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const resolvePrettyUrlHandler = (pathname: string) => async () => {
|
|
16
|
+
let results = <{ old_path: string }[]>[];
|
|
17
|
+
let prettyUrlResult: PrettyUrlResult = {
|
|
18
|
+
matched: false
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const requestUrl = URLS.misc.prettyUrls(pathname);
|
|
23
|
+
|
|
24
|
+
logger.debug(`Resolving pretty url`, { pathname, requestUrl });
|
|
25
|
+
|
|
26
|
+
const apiResponse = await fetch(requestUrl);
|
|
27
|
+
const data = await apiResponse.json();
|
|
28
|
+
({ results } = data);
|
|
29
|
+
|
|
30
|
+
const matched = results.length > 0;
|
|
31
|
+
const [{ old_path: path } = { old_path: '' }] = results;
|
|
32
|
+
prettyUrlResult = {
|
|
33
|
+
matched,
|
|
34
|
+
path
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
logger.trace('Pretty url result', prettyUrlResult);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
logger.error('Error resolving pretty url', { error, pathname });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return prettyUrlResult;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const resolvePrettyUrl = async (pathname: string) => {
|
|
46
|
+
return Cache.wrap(
|
|
47
|
+
CacheKey.PrettyUrl(pathname),
|
|
48
|
+
resolvePrettyUrlHandler(pathname),
|
|
49
|
+
{
|
|
50
|
+
useProxy: true
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const withPrettyUrl =
|
|
56
|
+
(middleware: NextMiddleware) =>
|
|
57
|
+
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
58
|
+
const url = req.nextUrl.clone();
|
|
59
|
+
const matchedLanguagePrefix = url.pathname.match(
|
|
60
|
+
urlLocaleMatcherRegex
|
|
61
|
+
)?.[0];
|
|
62
|
+
const prettyUrlPathname = url.pathname.replace(matchedLanguagePrefix, '');
|
|
63
|
+
const isValidPrettyUrlPath = (pathname: string) => {
|
|
64
|
+
return (
|
|
65
|
+
new RegExp(/^\/[a-zA-Z0-9/]+(?:-[a-zA-Z0-9/]+)*$/).test(pathname) &&
|
|
66
|
+
!Object.entries(ROUTES).find(([, value]) =>
|
|
67
|
+
new RegExp(`^${value}$`).test(pathname)
|
|
68
|
+
)
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
if (
|
|
73
|
+
!isValidPrettyUrlPath(prettyUrlPathname) ||
|
|
74
|
+
Settings.commerceUrl === 'default'
|
|
75
|
+
) {
|
|
76
|
+
return middleware(req, event);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const prettyUrlResult = await resolvePrettyUrl(prettyUrlPathname);
|
|
80
|
+
|
|
81
|
+
if (prettyUrlResult.matched) {
|
|
82
|
+
req.middlewareParams.rewrites.prettyUrl = prettyUrlResult.path;
|
|
83
|
+
logger.debug('Resolved pretty url', {
|
|
84
|
+
source: prettyUrlPathname,
|
|
85
|
+
dest: prettyUrlResult.path
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return middleware(req, event);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return middleware(req, event);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export default withPrettyUrl;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
import { NextFetchEvent, NextMiddleware, NextResponse } from 'next/server';
|
|
3
|
+
import Settings from 'settings';
|
|
4
|
+
import logger from '../utils/log';
|
|
5
|
+
import { PzNextRequest } from '.';
|
|
6
|
+
import { getUrlPathWithLocale } from '../utils/localization';
|
|
7
|
+
import { urlLocaleMatcherRegex } from '../utils';
|
|
8
|
+
|
|
9
|
+
const streamToString = async (stream: ReadableStream<Uint8Array> | null) => {
|
|
10
|
+
if (stream) {
|
|
11
|
+
const chunks = [];
|
|
12
|
+
let result = '';
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
for await (const chunk of stream as any) {
|
|
16
|
+
chunks.push(Buffer.from(chunk));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
result = Buffer.concat(chunks).toString('utf-8');
|
|
20
|
+
} catch (error) {
|
|
21
|
+
logger.error('Error while reading body stream', {
|
|
22
|
+
middleware: 'redirection-payment',
|
|
23
|
+
error
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const withRedirectionPayment =
|
|
33
|
+
(middleware: NextMiddleware) =>
|
|
34
|
+
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
35
|
+
const url = req.nextUrl.clone();
|
|
36
|
+
const pathnameWithoutLocale = url.pathname.replace(
|
|
37
|
+
urlLocaleMatcherRegex,
|
|
38
|
+
''
|
|
39
|
+
);
|
|
40
|
+
const searchParams = new URLSearchParams(url.search);
|
|
41
|
+
|
|
42
|
+
if (
|
|
43
|
+
!pathnameWithoutLocale.startsWith('/orders') ||
|
|
44
|
+
searchParams.get('page') !== 'RedirectionPageCompletePage' ||
|
|
45
|
+
req.method !== 'POST'
|
|
46
|
+
) {
|
|
47
|
+
return middleware(req, event);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const body = await streamToString(req.body);
|
|
51
|
+
const requestUrl = `${Settings.commerceUrl}/orders/checkout/${url.search}`;
|
|
52
|
+
|
|
53
|
+
const request = await fetch(requestUrl, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: {
|
|
56
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
57
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
58
|
+
Cookie: req.headers.get('cookie') ?? ''
|
|
59
|
+
},
|
|
60
|
+
body
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
logger.info('Complete redirection payment request', {
|
|
64
|
+
requestUrl,
|
|
65
|
+
status: request.status
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const response = await request.json();
|
|
69
|
+
|
|
70
|
+
const { context_list: contextList } = response;
|
|
71
|
+
const redirectionContext = contextList?.find(
|
|
72
|
+
(context) => context.page_context?.redirect_url
|
|
73
|
+
);
|
|
74
|
+
const redirectUrl = redirectionContext?.page_context?.redirect_url;
|
|
75
|
+
|
|
76
|
+
if (!redirectUrl) {
|
|
77
|
+
logger.info('Order success page context list', {
|
|
78
|
+
middleware: 'redirection-payment',
|
|
79
|
+
contextList
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
logger.warn(
|
|
83
|
+
'No redirection url for order success page found in page_context',
|
|
84
|
+
{ middleware: 'redirection-payment' }
|
|
85
|
+
);
|
|
86
|
+
return NextResponse.redirect(
|
|
87
|
+
`${url.origin}${getUrlPathWithLocale(
|
|
88
|
+
`/orders/checkout?${searchParams.toString()}`,
|
|
89
|
+
req.cookies.get('pz-locale')?.value
|
|
90
|
+
)}`,
|
|
91
|
+
303
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
|
|
96
|
+
redirectUrl,
|
|
97
|
+
req.cookies.get('pz-locale')?.value
|
|
98
|
+
)}`;
|
|
99
|
+
|
|
100
|
+
logger.info('Redirecting to order success page', {
|
|
101
|
+
middleware: 'redirection-payment',
|
|
102
|
+
redirectUrlWithLocale
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Using POST method while redirecting causes an error,
|
|
106
|
+
// So we use 303 status code to change the method to GET
|
|
107
|
+
const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
108
|
+
|
|
109
|
+
nextResponse.headers.set(
|
|
110
|
+
'Set-Cookie',
|
|
111
|
+
request.headers.get('set-cookie') ?? ''
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return nextResponse;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export default withRedirectionPayment;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { NextFetchEvent, NextMiddleware, NextResponse } from 'next/server';
|
|
2
|
+
import Settings from 'settings';
|
|
3
|
+
import { Buffer } from 'buffer';
|
|
4
|
+
import logger from '../utils/log';
|
|
5
|
+
import { getUrlPathWithLocale } from '../utils/localization';
|
|
6
|
+
import { PzNextRequest } from '.';
|
|
7
|
+
|
|
8
|
+
const streamToString = async (stream: ReadableStream<Uint8Array> | null) => {
|
|
9
|
+
if (stream) {
|
|
10
|
+
const chunks = [];
|
|
11
|
+
let result = '';
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
for await (const chunk of stream as any) {
|
|
15
|
+
chunks.push(Buffer.from(chunk));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
result = Buffer.concat(chunks).toString('utf-8');
|
|
19
|
+
} catch (error) {
|
|
20
|
+
logger.error('Error while reading body stream', {
|
|
21
|
+
middleware: 'three-d-redirection',
|
|
22
|
+
error
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const withThreeDRedirection =
|
|
32
|
+
(middleware: NextMiddleware) =>
|
|
33
|
+
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
34
|
+
const url = req.nextUrl.clone();
|
|
35
|
+
|
|
36
|
+
if (url.search.indexOf('CreditCardThreeDSecurePage') === -1) {
|
|
37
|
+
return middleware(req, event);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const body = await streamToString(req.body);
|
|
41
|
+
const params = body.split('&');
|
|
42
|
+
const encodedPzParams = decodeURIComponent(
|
|
43
|
+
params.find((param) => param.startsWith('pzparams'))?.split('=')[1] ?? ''
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
logger.debug('Encoded 3D form extra params', encodedPzParams);
|
|
47
|
+
|
|
48
|
+
if (!encodedPzParams.length) {
|
|
49
|
+
logger.warn('No pzparams found in 3D form params');
|
|
50
|
+
return middleware(req, event);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const pzParams = JSON.parse(decodeURIComponent(encodedPzParams)) as {
|
|
54
|
+
session: string;
|
|
55
|
+
locale: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
logger.debug('3D form extra params', pzParams);
|
|
59
|
+
|
|
60
|
+
const requestUrl = `${Settings.commerceUrl}/orders/checkout/${url.search}`;
|
|
61
|
+
|
|
62
|
+
const request = await fetch(requestUrl, {
|
|
63
|
+
method: 'POST',
|
|
64
|
+
headers: {
|
|
65
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
66
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
67
|
+
Cookie: `osessionid=${pzParams.session}`
|
|
68
|
+
},
|
|
69
|
+
body
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
logger.info('Complete 3D payment request', {
|
|
73
|
+
requestUrl,
|
|
74
|
+
status: request.status
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const response = await request.json();
|
|
78
|
+
|
|
79
|
+
const { context_list: contextList } = response;
|
|
80
|
+
const redirectionContext = contextList?.find(
|
|
81
|
+
(context) => context.page_context?.redirect_url
|
|
82
|
+
);
|
|
83
|
+
const redirectUrl = redirectionContext?.page_context?.redirect_url;
|
|
84
|
+
|
|
85
|
+
logger.info('Order success page context list', {
|
|
86
|
+
middleware: 'three-d-redirection',
|
|
87
|
+
contextList
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (!redirectUrl) {
|
|
91
|
+
logger.warn(
|
|
92
|
+
'No redirection url for order success page found in page_context',
|
|
93
|
+
{
|
|
94
|
+
middleware: 'three-d-redirection'
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
return middleware(req, event);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
|
|
101
|
+
redirectUrl,
|
|
102
|
+
req.cookies.get('pz-locale')?.value
|
|
103
|
+
)}`;
|
|
104
|
+
|
|
105
|
+
logger.info('Redirecting to order success page', {
|
|
106
|
+
middleware: 'three-d-redirection',
|
|
107
|
+
redirectUrlWithLocale
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Using POST method while redirecting causes an error,
|
|
111
|
+
// So we use 303 status code to change the method to GET
|
|
112
|
+
const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
113
|
+
|
|
114
|
+
nextResponse.headers.set(
|
|
115
|
+
'Set-Cookie',
|
|
116
|
+
request.headers.get('set-cookie') ?? ''
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
return nextResponse;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export default withThreeDRedirection;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { NextFetchEvent, NextMiddleware } from 'next/server';
|
|
2
|
+
import settings from 'settings';
|
|
3
|
+
import { PzNextRequest } from '.';
|
|
4
|
+
import logger from '../utils/log';
|
|
5
|
+
import { urlLocaleMatcherRegex } from '../utils';
|
|
6
|
+
import { getUrlPathWithLocale } from '../utils/localization';
|
|
7
|
+
import { ROUTES } from 'routes';
|
|
8
|
+
|
|
9
|
+
// This middleware is used to handle url redirections set in Omnitron
|
|
10
|
+
|
|
11
|
+
const withUrlRedirection =
|
|
12
|
+
(middleware: NextMiddleware) =>
|
|
13
|
+
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
14
|
+
const url = req.nextUrl.clone();
|
|
15
|
+
const pathnameWithoutLocale = url.pathname.replace(
|
|
16
|
+
urlLocaleMatcherRegex,
|
|
17
|
+
''
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
if (
|
|
21
|
+
Object.entries(ROUTES).find(([, value]) =>
|
|
22
|
+
new RegExp(`^${value}$`).test(pathnameWithoutLocale)
|
|
23
|
+
) ||
|
|
24
|
+
pathnameWithoutLocale.startsWith('/orders')
|
|
25
|
+
) {
|
|
26
|
+
return middleware(req, event);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const request = await fetch(
|
|
31
|
+
`${settings.commerceUrl}${pathnameWithoutLocale}${url.search}`,
|
|
32
|
+
{
|
|
33
|
+
redirect: 'manual',
|
|
34
|
+
next: {
|
|
35
|
+
revalidate: 0
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (request.headers.get('location')) {
|
|
41
|
+
const location = request.headers.get('location');
|
|
42
|
+
const redirectUrl = new URL(
|
|
43
|
+
request.headers.get('location'),
|
|
44
|
+
location.startsWith('http') ? '' : process.env.NEXT_PUBLIC_URL
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
redirectUrl.pathname = getUrlPathWithLocale(
|
|
48
|
+
redirectUrl.pathname,
|
|
49
|
+
req.middlewareParams.rewrites.locale
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return Response.redirect(redirectUrl.toString(), request.status);
|
|
53
|
+
}
|
|
54
|
+
} catch (error) {
|
|
55
|
+
logger.error('withUrlRedirection error', error);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return middleware(req, event);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default withUrlRedirection;
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@akinon/next",
|
|
3
|
+
"description": "Core package for Project Zero Next",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"private": false,
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"pz-install-plugins": "bin/pz-install-plugins.js"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@reduxjs/toolkit": "1.9.2",
|
|
12
|
+
"cross-spawn": "7.0.3",
|
|
13
|
+
"react-redux": "8.0.5",
|
|
14
|
+
"react-string-replace": "1.1.1",
|
|
15
|
+
"redis": "4.5.1"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/react-redux": "7.1.23"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/plugins.js
ADDED
package/redux/hooks.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
|
|
4
|
+
import type { RootState, TypedDispatch } from 'redux/store';
|
|
5
|
+
|
|
6
|
+
export const useAppDispatch = () => useDispatch<TypedDispatch>();
|
|
7
|
+
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|