@akinon/next 1.17.1 → 1.19.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 +19 -0
- package/components/index.ts +2 -0
- package/components/link.tsx +52 -0
- package/components/pagination.tsx +194 -0
- package/components/plugin-module.tsx +40 -6
- package/components/selected-payment-option-view.tsx +4 -0
- package/data/client/account.ts +5 -2
- package/data/client/checkout.ts +153 -13
- package/data/urls.ts +6 -2
- package/hooks/index.ts +1 -0
- package/hooks/use-pagination.ts +136 -0
- package/hooks/use-payment-options.ts +1 -0
- package/middlewares/complete-masterpass.ts +159 -0
- package/middlewares/default.ts +105 -93
- package/middlewares/index.ts +3 -1
- package/package.json +2 -2
- package/plugins.d.ts +3 -0
- package/plugins.js +2 -0
- package/redux/reducers/index.ts +6 -2
- package/types/commerce/checkout.ts +1 -0
- package/types/commerce/product.ts +2 -2
- package/utils/get-currency-label.ts +9 -0
- package/utils/get-currency.ts +4 -2
- package/utils/index.ts +1 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useMemo, useReducer } from 'react';
|
|
4
|
+
import { usePathname, useSearchParams } from 'next/navigation';
|
|
5
|
+
|
|
6
|
+
export type UsePaginationType = ReturnType<typeof usePagination>;
|
|
7
|
+
|
|
8
|
+
type InitialState = {
|
|
9
|
+
page: number;
|
|
10
|
+
last: number;
|
|
11
|
+
limit: number;
|
|
12
|
+
total: number;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type ACTIONTYPE =
|
|
16
|
+
| { type: 'setPage'; payload: number }
|
|
17
|
+
| { type: 'setTotal'; payload: number }
|
|
18
|
+
| { type: 'setLimit'; payload: number };
|
|
19
|
+
|
|
20
|
+
function reducer(state: InitialState, action: ACTIONTYPE) {
|
|
21
|
+
switch (action.type) {
|
|
22
|
+
case 'setTotal':
|
|
23
|
+
return {
|
|
24
|
+
...state,
|
|
25
|
+
total: action.payload,
|
|
26
|
+
last: Math.ceil(action.payload / state.limit)
|
|
27
|
+
};
|
|
28
|
+
case 'setPage':
|
|
29
|
+
return { ...state, page: action.payload };
|
|
30
|
+
case 'setLimit':
|
|
31
|
+
return { ...state, limit: action.payload };
|
|
32
|
+
default:
|
|
33
|
+
throw new Error();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default function usePagination(
|
|
38
|
+
_total = 0,
|
|
39
|
+
_limit = 12,
|
|
40
|
+
_page: number | undefined,
|
|
41
|
+
_last: number | undefined
|
|
42
|
+
) {
|
|
43
|
+
const pathname = usePathname();
|
|
44
|
+
const searchParams = useSearchParams();
|
|
45
|
+
const urlSearchParams = useMemo(
|
|
46
|
+
() => new URLSearchParams(searchParams.toString()),
|
|
47
|
+
[searchParams]
|
|
48
|
+
);
|
|
49
|
+
const { page, limit } = useMemo(
|
|
50
|
+
() => ({
|
|
51
|
+
page: _page || Number(searchParams.get('page')) || 1,
|
|
52
|
+
limit: _limit || Number(searchParams.get('limit'))
|
|
53
|
+
}),
|
|
54
|
+
[searchParams, _page, _limit]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const initialState: InitialState = {
|
|
58
|
+
page,
|
|
59
|
+
limit,
|
|
60
|
+
last: _last || Math.ceil(_total / limit) || 1,
|
|
61
|
+
total: _total
|
|
62
|
+
};
|
|
63
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
64
|
+
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
dispatch({ type: 'setPage', payload: page });
|
|
67
|
+
}, [page]);
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
dispatch({ type: 'setLimit', payload: limit });
|
|
71
|
+
}, [limit]);
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
window.scrollTo(0, 0);
|
|
75
|
+
}, [state.page, state.limit]);
|
|
76
|
+
|
|
77
|
+
const setTotal = useCallback(
|
|
78
|
+
(total: number) => {
|
|
79
|
+
dispatch({ type: 'setTotal', payload: total });
|
|
80
|
+
},
|
|
81
|
+
[dispatch]
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const setPage = useCallback(
|
|
85
|
+
(page: number) => {
|
|
86
|
+
if (page > 0 && page <= state.total) {
|
|
87
|
+
dispatch({ type: 'setPage', payload: page });
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
[dispatch, state.total]
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const setLimit = useCallback(
|
|
94
|
+
(limit: number) => {
|
|
95
|
+
dispatch({ type: 'setLimit', payload: limit });
|
|
96
|
+
},
|
|
97
|
+
[dispatch]
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const pageList = useMemo(() => {
|
|
101
|
+
return Array.from({ length: state.last }, (_, i) => {
|
|
102
|
+
urlSearchParams.set('page', (i + 1).toString());
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
page: i + 1,
|
|
106
|
+
url: `${pathname}?${urlSearchParams.toString()}`
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}, [state.last, pathname, urlSearchParams]);
|
|
110
|
+
|
|
111
|
+
const prev = useMemo(() => {
|
|
112
|
+
if (state.page > 1) {
|
|
113
|
+
urlSearchParams.set('page', (Number(state.page) - 1).toString());
|
|
114
|
+
return `${pathname}?${urlSearchParams.toString()}`;
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}, [state.page, pathname, urlSearchParams]);
|
|
118
|
+
|
|
119
|
+
const next = useMemo(() => {
|
|
120
|
+
if (Number(state.page) < Number(state.last)) {
|
|
121
|
+
urlSearchParams.set('page', (Number(state.page) + 1).toString());
|
|
122
|
+
return `${pathname}?${urlSearchParams.toString()}`;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}, [state.page, state.last, pathname, urlSearchParams]);
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
...state,
|
|
129
|
+
setTotal,
|
|
130
|
+
setPage,
|
|
131
|
+
setLimit,
|
|
132
|
+
pageList,
|
|
133
|
+
prev,
|
|
134
|
+
next
|
|
135
|
+
};
|
|
136
|
+
}
|
|
@@ -18,6 +18,7 @@ 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
22
|
};
|
|
22
23
|
|
|
23
24
|
const isInitialTypeIncluded = (type: string) => initialTypes.has(type);
|
|
@@ -0,0 +1,159 @@
|
|
|
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: 'complete-masterpass',
|
|
22
|
+
error
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const withCompleteMasterpass =
|
|
32
|
+
(middleware: NextMiddleware) =>
|
|
33
|
+
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
34
|
+
const url = req.nextUrl.clone();
|
|
35
|
+
const ip = req.headers.get('x-forwarded-for') ?? '';
|
|
36
|
+
|
|
37
|
+
if (url.search.indexOf('MasterpassCompletePage') === -1) {
|
|
38
|
+
return middleware(req, event);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const requestUrl = `${Settings.commerceUrl}/orders/checkout/${url.search}`;
|
|
42
|
+
const requestHeaders = {
|
|
43
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
44
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
45
|
+
Cookie: `osessionid=${req.cookies.get('osessionid')?.value ?? ''}`,
|
|
46
|
+
'x-currency': req.cookies.get('pz-currency')?.value ?? ''
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const body = await streamToString(req.body);
|
|
51
|
+
|
|
52
|
+
const request = await fetch(requestUrl, {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: requestHeaders,
|
|
55
|
+
body
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
logger.info('Complete Masterpass payment request', {
|
|
59
|
+
requestUrl,
|
|
60
|
+
status: request.status,
|
|
61
|
+
requestHeaders,
|
|
62
|
+
ip
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const response = await request.json();
|
|
66
|
+
|
|
67
|
+
const { context_list: contextList, errors } = response;
|
|
68
|
+
const redirectionContext = contextList?.find(
|
|
69
|
+
(context) => context.page_context?.redirect_url
|
|
70
|
+
);
|
|
71
|
+
const redirectUrl = redirectionContext?.page_context?.redirect_url;
|
|
72
|
+
|
|
73
|
+
if (errors && Object.keys(errors).length) {
|
|
74
|
+
logger.error('Error while completing Masterpass payment', {
|
|
75
|
+
middleware: 'complete-masterpass',
|
|
76
|
+
errors,
|
|
77
|
+
requestHeaders,
|
|
78
|
+
ip
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return NextResponse.redirect(
|
|
82
|
+
`${url.origin}${getUrlPathWithLocale(
|
|
83
|
+
'/orders/checkout/',
|
|
84
|
+
req.cookies.get('pz-locale')?.value
|
|
85
|
+
)}`,
|
|
86
|
+
{
|
|
87
|
+
status: 303,
|
|
88
|
+
headers: {
|
|
89
|
+
'Set-Cookie': `pz-pos-error=${JSON.stringify(errors)}; path=/;`
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
logger.info('Order success page context list', {
|
|
96
|
+
middleware: 'complete-masterpass',
|
|
97
|
+
contextList,
|
|
98
|
+
ip
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (!redirectUrl) {
|
|
102
|
+
logger.warn(
|
|
103
|
+
'No redirection url for order success page found in page_context. Redirecting to checkout page.',
|
|
104
|
+
{
|
|
105
|
+
middleware: 'complete-masterpass',
|
|
106
|
+
requestHeaders,
|
|
107
|
+
response: JSON.stringify(response),
|
|
108
|
+
ip
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
|
|
113
|
+
'/orders/checkout/',
|
|
114
|
+
req.cookies.get('pz-locale')?.value
|
|
115
|
+
)}`;
|
|
116
|
+
|
|
117
|
+
return NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
|
|
121
|
+
redirectUrl,
|
|
122
|
+
req.cookies.get('pz-locale')?.value
|
|
123
|
+
)}`;
|
|
124
|
+
|
|
125
|
+
logger.info('Redirecting to order success page', {
|
|
126
|
+
middleware: 'complete-masterpass',
|
|
127
|
+
redirectUrlWithLocale,
|
|
128
|
+
ip
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Using POST method while redirecting causes an error,
|
|
132
|
+
// So we use 303 status code to change the method to GET
|
|
133
|
+
const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
134
|
+
|
|
135
|
+
nextResponse.headers.set(
|
|
136
|
+
'Set-Cookie',
|
|
137
|
+
request.headers.get('set-cookie') ?? ''
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
return nextResponse;
|
|
141
|
+
} catch (error) {
|
|
142
|
+
logger.error('Error while completing Masterpass payment', {
|
|
143
|
+
middleware: 'complete-masterpass',
|
|
144
|
+
error,
|
|
145
|
+
requestHeaders,
|
|
146
|
+
ip
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return NextResponse.redirect(
|
|
150
|
+
`${url.origin}${getUrlPathWithLocale(
|
|
151
|
+
'/orders/checkout/',
|
|
152
|
+
req.cookies.get('pz-locale')?.value
|
|
153
|
+
)}`,
|
|
154
|
+
303
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export default withCompleteMasterpass;
|
package/middlewares/default.ts
CHANGED
|
@@ -3,6 +3,7 @@ import Settings from 'settings';
|
|
|
3
3
|
import {
|
|
4
4
|
PzNextRequest,
|
|
5
5
|
withCompleteGpay,
|
|
6
|
+
withCompleteMasterpass,
|
|
6
7
|
withOauthLogin,
|
|
7
8
|
withPrettyUrl,
|
|
8
9
|
withRedirectionPayment,
|
|
@@ -124,61 +125,74 @@ const withPzDefault =
|
|
|
124
125
|
withThreeDRedirection(
|
|
125
126
|
withUrlRedirection(
|
|
126
127
|
withCompleteGpay(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
NextResponse
|
|
128
|
+
withCompleteMasterpass(
|
|
129
|
+
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
130
|
+
let middlewareResult: NextResponse | void =
|
|
131
|
+
NextResponse.next();
|
|
130
132
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
url.basePath = `/${commerceUrl}`;
|
|
142
|
-
url.pathname = `/${
|
|
143
|
-
locale.length ? `${locale}/` : ''
|
|
144
|
-
}${currency}${prettyUrl ?? pathnameWithoutLocale}`;
|
|
145
|
-
|
|
146
|
-
Settings.rewrites.forEach((rewrite) => {
|
|
147
|
-
url.pathname = url.pathname.replace(
|
|
148
|
-
rewrite.source,
|
|
149
|
-
rewrite.destination
|
|
133
|
+
try {
|
|
134
|
+
const { locale, prettyUrl, currency } =
|
|
135
|
+
req.middlewareParams.rewrites;
|
|
136
|
+
const { defaultLocaleValue } = Settings.localization;
|
|
137
|
+
const url = req.nextUrl.clone();
|
|
138
|
+
const pathnameWithoutLocale = url.pathname.replace(
|
|
139
|
+
urlLocaleMatcherRegex,
|
|
140
|
+
''
|
|
150
141
|
);
|
|
151
|
-
});
|
|
152
142
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
143
|
+
url.basePath = `/${commerceUrl}`;
|
|
144
|
+
url.pathname = `/${
|
|
145
|
+
locale.length ? `${locale}/` : ''
|
|
146
|
+
}${currency}${prettyUrl ?? pathnameWithoutLocale}`;
|
|
157
147
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
middlewareResult.headers.get(
|
|
163
|
-
'pz-override-response'
|
|
164
|
-
) !== 'true'
|
|
165
|
-
) {
|
|
166
|
-
middlewareResult.headers.set(
|
|
167
|
-
'x-middleware-rewrite',
|
|
168
|
-
url.href
|
|
148
|
+
Settings.rewrites.forEach((rewrite) => {
|
|
149
|
+
url.pathname = url.pathname.replace(
|
|
150
|
+
rewrite.source,
|
|
151
|
+
rewrite.destination
|
|
169
152
|
);
|
|
170
|
-
}
|
|
171
|
-
} else {
|
|
172
|
-
// if middleware.ts doesn't have a return value.
|
|
173
|
-
// e.g. NextResponse.next() doesn't exist in middleware.ts
|
|
153
|
+
});
|
|
174
154
|
|
|
175
|
-
middlewareResult =
|
|
176
|
-
|
|
155
|
+
middlewareResult = (await middleware(
|
|
156
|
+
req,
|
|
157
|
+
event
|
|
158
|
+
)) as NextResponse | void;
|
|
177
159
|
|
|
178
|
-
|
|
160
|
+
// if middleware.ts has a return value for current url
|
|
161
|
+
if (middlewareResult instanceof NextResponse) {
|
|
162
|
+
// pz-override-response header is used to prevent 404 page for custom responses.
|
|
163
|
+
if (
|
|
164
|
+
middlewareResult.headers.get(
|
|
165
|
+
'pz-override-response'
|
|
166
|
+
) !== 'true'
|
|
167
|
+
) {
|
|
168
|
+
middlewareResult.headers.set(
|
|
169
|
+
'x-middleware-rewrite',
|
|
170
|
+
url.href
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
// if middleware.ts doesn't have a return value.
|
|
175
|
+
// e.g. NextResponse.next() doesn't exist in middleware.ts
|
|
176
|
+
|
|
177
|
+
middlewareResult = NextResponse.rewrite(url);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (!url.pathname.startsWith(`/${currency}/orders`)) {
|
|
181
|
+
middlewareResult.cookies.set(
|
|
182
|
+
'pz-locale',
|
|
183
|
+
locale?.length > 0 ? locale : defaultLocaleValue,
|
|
184
|
+
{
|
|
185
|
+
sameSite: 'none',
|
|
186
|
+
secure: true,
|
|
187
|
+
expires: new Date(
|
|
188
|
+
Date.now() + 1000 * 60 * 60 * 24 * 7
|
|
189
|
+
) // 7 days
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
}
|
|
179
193
|
middlewareResult.cookies.set(
|
|
180
|
-
'pz-
|
|
181
|
-
|
|
194
|
+
'pz-currency',
|
|
195
|
+
currency,
|
|
182
196
|
{
|
|
183
197
|
sameSite: 'none',
|
|
184
198
|
secure: true,
|
|
@@ -187,65 +201,63 @@ const withPzDefault =
|
|
|
187
201
|
) // 7 days
|
|
188
202
|
}
|
|
189
203
|
);
|
|
190
|
-
}
|
|
191
|
-
middlewareResult.cookies.set('pz-currency', currency, {
|
|
192
|
-
sameSite: 'none',
|
|
193
|
-
secure: true,
|
|
194
|
-
expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7) // 7 days
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
req.cookies.get('pz-locale') &&
|
|
199
|
-
req.cookies.get('pz-locale').value !== locale
|
|
200
|
-
) {
|
|
201
|
-
logger.debug('Locale changed', {
|
|
202
|
-
locale,
|
|
203
|
-
oldLocale: req.cookies.get('pz-locale')?.value,
|
|
204
|
-
ip
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
middlewareResult.headers.set(
|
|
209
|
-
'pz-url',
|
|
210
|
-
req.nextUrl.toString()
|
|
211
|
-
);
|
|
212
204
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
205
|
+
if (
|
|
206
|
+
req.cookies.get('pz-locale') &&
|
|
207
|
+
req.cookies.get('pz-locale').value !== locale
|
|
208
|
+
) {
|
|
209
|
+
logger.debug('Locale changed', {
|
|
210
|
+
locale,
|
|
211
|
+
oldLocale: req.cookies.get('pz-locale')?.value,
|
|
212
|
+
ip
|
|
213
|
+
});
|
|
214
|
+
}
|
|
216
215
|
|
|
217
|
-
if (process.env.ACC_APP_VERSION) {
|
|
218
216
|
middlewareResult.headers.set(
|
|
219
|
-
'
|
|
220
|
-
|
|
217
|
+
'pz-url',
|
|
218
|
+
req.nextUrl.toString()
|
|
221
219
|
);
|
|
222
|
-
}
|
|
223
220
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
221
|
+
if (req.cookies.get('pz-set-currency')) {
|
|
222
|
+
middlewareResult.cookies.delete('pz-set-currency');
|
|
223
|
+
}
|
|
227
224
|
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
225
|
+
if (process.env.ACC_APP_VERSION) {
|
|
226
|
+
middlewareResult.headers.set(
|
|
227
|
+
'acc-app-version',
|
|
228
|
+
process.env.ACC_APP_VERSION
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Set CSRF token if not set
|
|
233
|
+
try {
|
|
234
|
+
const url = `${Settings.commerceUrl}${user.csrfToken}`;
|
|
235
|
+
|
|
236
|
+
if (!req.cookies.get('csrftoken')) {
|
|
237
|
+
const { csrf_token } = await (
|
|
238
|
+
await fetch(url)
|
|
239
|
+
).json();
|
|
240
|
+
middlewareResult.cookies.set(
|
|
241
|
+
'csrftoken',
|
|
242
|
+
csrf_token
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
} catch (error) {
|
|
246
|
+
logger.error('CSRF Error', {
|
|
247
|
+
error,
|
|
248
|
+
ip
|
|
249
|
+
});
|
|
233
250
|
}
|
|
234
251
|
} catch (error) {
|
|
235
|
-
logger.error('
|
|
252
|
+
logger.error('withPzDefault Error', {
|
|
236
253
|
error,
|
|
237
254
|
ip
|
|
238
255
|
});
|
|
239
256
|
}
|
|
240
|
-
} catch (error) {
|
|
241
|
-
logger.error('withPzDefault Error', {
|
|
242
|
-
error,
|
|
243
|
-
ip
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
257
|
|
|
247
|
-
|
|
248
|
-
|
|
258
|
+
return middlewareResult;
|
|
259
|
+
}
|
|
260
|
+
)
|
|
249
261
|
)
|
|
250
262
|
)
|
|
251
263
|
)
|
package/middlewares/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import withLocale from './locale';
|
|
|
6
6
|
import withOauthLogin from './oauth-login';
|
|
7
7
|
import withUrlRedirection from './url-redirection';
|
|
8
8
|
import withCompleteGpay from './complete-gpay';
|
|
9
|
+
import withCompleteMasterpass from './complete-masterpass';
|
|
9
10
|
import { NextRequest } from 'next/server';
|
|
10
11
|
|
|
11
12
|
export {
|
|
@@ -16,7 +17,8 @@ export {
|
|
|
16
17
|
withLocale,
|
|
17
18
|
withOauthLogin,
|
|
18
19
|
withUrlRedirection,
|
|
19
|
-
withCompleteGpay
|
|
20
|
+
withCompleteGpay,
|
|
21
|
+
withCompleteMasterpass
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export interface PzNextRequest extends NextRequest {
|
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.19.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@typescript-eslint/eslint-plugin": "6.7.4",
|
|
32
32
|
"@typescript-eslint/parser": "6.7.4",
|
|
33
33
|
"eslint": "^8.14.0",
|
|
34
|
-
"@akinon/eslint-plugin-projectzero": "1.
|
|
34
|
+
"@akinon/eslint-plugin-projectzero": "1.19.0",
|
|
35
35
|
"eslint-config-prettier": "8.5.0"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/plugins.d.ts
ADDED
package/plugins.js
CHANGED
package/redux/reducers/index.ts
CHANGED
|
@@ -4,12 +4,16 @@ import configReducer from './config';
|
|
|
4
4
|
import headerReducer from './header';
|
|
5
5
|
import { api } from '../../data/client/api';
|
|
6
6
|
|
|
7
|
+
// Plugin reducers
|
|
8
|
+
import { masterpassReducer } from '@akinon/pz-masterpass';
|
|
9
|
+
|
|
7
10
|
const reducers = {
|
|
8
11
|
[api.reducerPath]: api.reducer,
|
|
9
12
|
root: rootReducer,
|
|
10
13
|
checkout: checkoutReducer,
|
|
11
14
|
config: configReducer,
|
|
12
|
-
header: headerReducer
|
|
15
|
+
header: headerReducer,
|
|
16
|
+
masterpass: masterpassReducer
|
|
13
17
|
};
|
|
14
18
|
|
|
15
|
-
export default reducers;
|
|
19
|
+
export default reducers;
|
|
@@ -10,14 +10,14 @@ export interface Product {
|
|
|
10
10
|
};
|
|
11
11
|
attributes_kwargs: any;
|
|
12
12
|
base_code: string;
|
|
13
|
-
basket_offers: {
|
|
13
|
+
basket_offers: Array<{
|
|
14
14
|
kwargs: { show_benefit_products: boolean };
|
|
15
15
|
label: string;
|
|
16
16
|
listing_kwargs: {
|
|
17
17
|
[key: string]: any;
|
|
18
18
|
};
|
|
19
19
|
pk: number;
|
|
20
|
-
}
|
|
20
|
+
}>;
|
|
21
21
|
currency_type: string;
|
|
22
22
|
data_source: null;
|
|
23
23
|
extra_attributes: {
|
package/utils/get-currency.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import getSymbolFromCurrency from 'currency-symbol-map';
|
|
4
|
+
import { getCurrencyLabel } from './get-currency-label';
|
|
4
5
|
|
|
5
6
|
type GetCurrencyType = {
|
|
6
7
|
currencyCode: string;
|
|
@@ -17,10 +18,11 @@ export const getCurrency = (args: GetCurrencyType) => {
|
|
|
17
18
|
useCurrencySpace = true
|
|
18
19
|
} = args;
|
|
19
20
|
|
|
21
|
+
const currencyLabel = getCurrencyLabel(currencyCode);
|
|
20
22
|
const currencySpace = useCurrencySpace ? ' ' : '';
|
|
21
23
|
const currency = useCurrencySymbol
|
|
22
|
-
? `${getSymbolFromCurrency(
|
|
23
|
-
:
|
|
24
|
+
? `${getSymbolFromCurrency(currencyLabel)}`
|
|
25
|
+
: currencyLabel;
|
|
24
26
|
const currencyAfterPrice = useCurrencyAfterPrice
|
|
25
27
|
? `${currencySpace}${currency}`
|
|
26
28
|
: `${currency}${currencySpace}`;
|
package/utils/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { CDNOptions, ClientRequestOptions } from '../types';
|
|
|
5
5
|
export * from './get-currency';
|
|
6
6
|
export * from './menu-generator';
|
|
7
7
|
export * from './generate-commerce-search-params';
|
|
8
|
+
export * from './get-currency-label';
|
|
8
9
|
|
|
9
10
|
export function getCookie(name: string) {
|
|
10
11
|
if (typeof document === 'undefined') {
|