@akinon/next 1.2.0 → 1.4.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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @akinon/next
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Fix basket reset on mobile app checkout page
8
+ - Upgrade typescript to v5 and remove ts-expect-error lines
9
+ - Fix 3D payment with different currencies
10
+ - Support tailwind theming
11
+
12
+ ## 1.3.0
13
+
14
+ ### Minor Changes
15
+
16
+ - Refactor currency and locale selection
17
+ - Update TS types
18
+ - Fix 3D redirection middleware
19
+ - Refactor logging
20
+
3
21
  ## 1.2.0
4
22
 
5
23
  ### Minor Changes
package/api/auth.ts CHANGED
@@ -8,13 +8,16 @@ import { urlLocaleMatcherRegex } from '../utils';
8
8
  import logger from '@akinon/next/utils/log';
9
9
  import { AuthError } from '../types';
10
10
 
11
- async function getCurrentUser(sessionId: string) {
11
+ async function getCurrentUser(sessionId: string, currency = '') {
12
+ const headers = {
13
+ 'Content-Type': 'application/json',
14
+ Cookie: `osessionid=${sessionId}`,
15
+ 'x-currency': currency
16
+ };
17
+
12
18
  const currentUser = await (
13
19
  await fetch(URLS.user.currentUser, {
14
- headers: {
15
- 'Content-Type': 'application/json',
16
- Cookie: `osessionid=${sessionId}`
17
- }
20
+ headers
18
21
  })
19
22
  ).json();
20
23
 
@@ -51,7 +54,10 @@ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
51
54
  return null;
52
55
  }
53
56
 
54
- const currentUser = await getCurrentUser(sessionId);
57
+ const currentUser = await getCurrentUser(
58
+ sessionId,
59
+ req.cookies['pz-currency'] ?? ''
60
+ );
55
61
  return currentUser;
56
62
  }
57
63
  }),
@@ -78,6 +84,7 @@ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
78
84
  headers.set('Content-Type', 'application/json');
79
85
  headers.set('cookie', `${req.headers.cookie}`);
80
86
  headers.set('Accept-Language', `${language}`);
87
+ headers.set('x-currency', req.cookies['pz-currency'] ?? '');
81
88
 
82
89
  logger.debug('Trying to login/register', {
83
90
  formType: credentials.formType
@@ -160,7 +167,10 @@ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
160
167
  }
161
168
  }
162
169
 
163
- const currentUser = await getCurrentUser(sessionId);
170
+ const currentUser = await getCurrentUser(
171
+ sessionId,
172
+ req.cookies['pz-currency'] ?? ''
173
+ );
164
174
  return currentUser;
165
175
  }
166
176
  })
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const BASE_DIR =
7
+ path.resolve(__dirname, '../../../apps/projectzeropwa') || process.cwd();
8
+ const getFullPath = (relativePath) => path.join(BASE_DIR, relativePath);
9
+
10
+ const theme = require(getFullPath('src/theme.js'));
11
+
12
+ try {
13
+ const spawn = require('cross-spawn');
14
+ const tsConfigPath = getFullPath('tsconfig.json');
15
+
16
+ if (!fs.existsSync(tsConfigPath)) {
17
+ throw new Error(`tsconfig.json not found at ${tsConfigPath}`);
18
+ }
19
+
20
+ const tsConfigContent = fs.readFileSync(tsConfigPath, 'utf8');
21
+ const themePaths = ['"./*"'];
22
+
23
+ if (theme !== 'default') {
24
+ themePaths.splice(0, 0, `"themes/${theme}/*"`);
25
+ }
26
+
27
+ const newContent = tsConfigContent.replace(
28
+ /"@theme\/\*":\s\[.+\]/,
29
+ `"@theme/*": [${themePaths.join(', ')}]`
30
+ );
31
+
32
+ fs.writeFileSync(tsConfigPath, newContent);
33
+
34
+ if (fs.existsSync(getFullPath('../../turbo.json'))) {
35
+ spawn.sync('turbo', ['clean'], {
36
+ stdio: 'inherit'
37
+ });
38
+ }
39
+ } catch (error) {
40
+ console.error('Error:', error.message);
41
+ }
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ const spawn = require('cross-spawn');
4
+
5
+ spawn.sync('pz-install-plugins', [], { stdio: 'inherit' });
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ const spawn = require('cross-spawn');
4
+
5
+ spawn.sync('pz-install-theme', [], { stdio: 'inherit' });
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ const spawn = require('cross-spawn');
4
+
5
+ spawn.sync('pz-install-theme', [], { stdio: 'inherit' });
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -1,15 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { usePathname } from 'next/navigation';
4
- import { useEffect } from 'react';
5
- import { api } from '../data/client/api';
6
- import {
7
- useClearBasketMutation,
8
- useGetBasketQuery
9
- } from '../data/client/basket';
10
- import { useAppDispatch, useAppSelector } from '../redux/hooks';
11
- import { getCookie, removeCookie } from '../utils';
12
- import { useRouter } from '../hooks';
4
+ import { useAppSelector } from '../redux/hooks';
13
5
 
14
6
  export default function ClientRoot({
15
7
  children,
@@ -18,39 +10,8 @@ export default function ClientRoot({
18
10
  children: React.ReactNode;
19
11
  sessionId?: string;
20
12
  }) {
21
- const dispatch = useAppDispatch();
22
13
  const pathname = usePathname();
23
- const router = useRouter();
24
14
  const { isMobileApp } = useAppSelector((state) => state.root);
25
- const { data: basketData, isSuccess } = useGetBasketQuery();
26
- const [clearBasket] = useClearBasketMutation();
27
- const resetClientCache = getCookie('pz-reset-client-cache') === 'true';
28
- const resetBasket = getCookie('pz-reset-basket') === 'true';
29
-
30
- useEffect(() => {
31
- if (basketData?.basketitem_set.length && resetBasket) {
32
- dispatch(
33
- api.util.invalidateTags([
34
- 'Checkout',
35
- 'Product',
36
- 'Addresses',
37
- 'Favorite',
38
- 'Basket'
39
- ])
40
- );
41
-
42
- clearBasket();
43
- }
44
-
45
- removeCookie('pz-reset-basket');
46
- }, [resetBasket, isSuccess, basketData]);
47
-
48
- useEffect(() => {
49
- if (resetClientCache) {
50
- removeCookie('pz-reset-client-cache');
51
- location.reload();
52
- }
53
- }, [resetClientCache]);
54
15
 
55
16
  if (isMobileApp && pathname.includes('/orders/completed')) {
56
17
  ((window.parent || window) as any)?.ReactNativeWebView?.postMessage?.(
@@ -1,6 +1,7 @@
1
1
  import dynamic from 'next/dynamic';
2
2
  import plugins from 'plugins';
3
3
  import logger from '../utils/log';
4
+ import { useMemo } from 'react';
4
5
 
5
6
  enum Plugin {
6
7
  BasketGiftPack = 'pz-basket-gift-pack',
@@ -47,31 +48,35 @@ export default function PluginModule({
47
48
  return null;
48
49
  }
49
50
 
50
- const Component = dynamic(
51
- () => {
52
- let promise: any;
51
+ const Component = useMemo(
52
+ () =>
53
+ dynamic(
54
+ () => {
55
+ let promise: any;
53
56
 
54
- try {
55
- if (plugin === Plugin.BasketGiftPack) {
56
- promise = import(`${'pz-basket-gift-pack'}`);
57
- } else if (plugin === Plugin.ClickCollect) {
58
- promise = import(`${'pz-click-collect'}`);
59
- } else if (plugin === Plugin.OneClickCheckout) {
60
- promise = import(`${'pz-one-click-checkout'}`);
61
- } else if (plugin === Plugin.PayOnDelivery) {
62
- promise = import(`${'pz-pay-on-delivery'}`);
63
- } else if (plugin === Plugin.CheckoutGiftPack) {
64
- promise = import(`${'pz-checkout-gift-pack'}`);
65
- }
66
- } catch (error) {
67
- logger.error(error);
68
- }
57
+ try {
58
+ if (plugin === Plugin.BasketGiftPack) {
59
+ promise = import(`${'pz-basket-gift-pack'}`);
60
+ } else if (plugin === Plugin.ClickCollect) {
61
+ promise = import(`${'pz-click-collect'}`);
62
+ } else if (plugin === Plugin.OneClickCheckout) {
63
+ promise = import(`${'pz-one-click-checkout'}`);
64
+ } else if (plugin === Plugin.PayOnDelivery) {
65
+ promise = import(`${'pz-pay-on-delivery'}`);
66
+ } else if (plugin === Plugin.CheckoutGiftPack) {
67
+ promise = import(`${'pz-checkout-gift-pack'}`);
68
+ }
69
+ } catch (error) {
70
+ logger.error(error);
71
+ }
69
72
 
70
- return promise
71
- ? promise.then((mod) => mod[component]).catch(() => () => null)
72
- : new Promise<any>((resolve) => resolve(() => null));
73
- },
74
- { ssr: false }
73
+ return promise
74
+ ? promise.then((mod) => mod[component]).catch(() => () => null)
75
+ : new Promise<any>((resolve) => resolve(() => null));
76
+ },
77
+ { ssr: false }
78
+ ),
79
+ [plugin]
75
80
  );
76
81
 
77
82
  return <Component {...props} />;
@@ -70,13 +70,21 @@ const userApi = api.injectEndpoints({
70
70
  method: 'POST',
71
71
  body
72
72
  })
73
- })
73
+ }),
74
+ changeEmailVerification: build.query<void, string>({
75
+ query: (token) => ({
76
+ url: buildClientRequestUrl(user.changeEmailVerification(token), {
77
+ contentType: 'application/json'
78
+ })
79
+ })
80
+ }),
74
81
  }),
75
82
  overrideExisting: false
76
83
  });
77
84
 
78
85
  export const {
79
86
  useGetCaptchaQuery,
87
+ useChangeEmailVerificationQuery,
80
88
  useValidateCaptchaMutation,
81
89
  useLogoutMutation,
82
90
  useForgotPasswordMutation
package/data/urls.ts CHANGED
@@ -142,6 +142,7 @@ export const user = {
142
142
  captcha: '/users/pz-captcha',
143
143
  profiles: '/users/profile',
144
144
  forgotPassword: '/users/password/reset',
145
+ changeEmailVerification: (token: string) => `/users/email-set-primary/${token}`,
145
146
  csrfToken: '/csrf_token'
146
147
  };
147
148
 
@@ -15,11 +15,10 @@ export const withSegmentDefaults =
15
15
  options: SegmentDefaultsOptions
16
16
  ) =>
17
17
  (props: T) => {
18
- let componentProps = { ...props };
18
+ const componentProps = { ...props };
19
19
 
20
20
  return (
21
21
  <>
22
- {/* @ts-expect-error Server Component */}
23
22
  <Component {...componentProps} />
24
23
  </>
25
24
  );
@@ -35,7 +35,6 @@ export const withSegmentDefaults =
35
35
 
36
36
  return await (
37
37
  <>
38
- {/* @ts-expect-error Server Component */}
39
38
  <Component {...componentProps} />
40
39
  </>
41
40
  );
@@ -74,7 +73,10 @@ const checkRedisVariables = () => {
74
73
  process.env.CACHE_SECRET
75
74
  ];
76
75
 
77
- if (!requiredVariableValues.every((v) => v)) {
76
+ if (
77
+ !requiredVariableValues.every((v) => v) &&
78
+ process.env.NODE_ENV === 'production'
79
+ ) {
78
80
  logger.warn('Redis cache variables are not set', {
79
81
  requiredVariables: ['CACHE_HOST', 'CACHE_PORT', 'CACHE_SECRET'],
80
82
  values: requiredVariableValues
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { LocalizationContext } from '../localization/provider';
4
4
  import { useContext } from 'react';
5
- import { urlLocaleMatcherRegex } from '../utils';
5
+ import { setCookie, urlLocaleMatcherRegex } from '../utils';
6
6
  import { LocaleUrlStrategy } from '../localization';
7
7
  import { useRouter } from 'next/navigation';
8
8
 
@@ -36,7 +36,21 @@ export const useLocalization = () => {
36
36
  ''
37
37
  );
38
38
 
39
- router.push(`${localePath}${pathnameWithoutLocale}${location.search}`);
39
+ // router.push is not used because reloading the page also clears the client side cache.
40
+ location.href = `${localePath}${pathnameWithoutLocale}${location.search}`;
41
+ };
42
+
43
+ /**
44
+ * Sets the currency.
45
+ *
46
+ * If the currency is linked to the locale by using `getActiveCurrencyCode` function in the settings,
47
+ * you need to use `setLocale` instead of this.
48
+ * @param currency Currency code defined in the settings.
49
+ */
50
+ const setCurrency = (currency: string) => {
51
+ // It is a temp cookie to set currency in `currency` middleware.
52
+ setCookie('pz-set-currency', currency);
53
+ location.reload();
40
54
  };
41
55
 
42
56
  return {
@@ -52,12 +66,13 @@ export const useLocalization = () => {
52
66
  */
53
67
  t: (path: string) => translate(path),
54
68
  setLocale,
69
+ setCurrency,
55
70
  locale,
56
71
  currency,
57
72
  locales,
58
73
  currencies,
59
74
  defaultLocaleValue,
60
75
  defaultCurrencyCode,
61
- localeUrlStrategy,
76
+ localeUrlStrategy
62
77
  };
63
78
  };
package/lib/cache.ts CHANGED
@@ -140,7 +140,7 @@ export class Cache {
140
140
  }
141
141
  }
142
142
 
143
- logger.info('Redis cache miss. Setting new value...', { key });
143
+ logger.debug('Redis cache miss. Setting new value...', { key });
144
144
 
145
145
  const data = await handler();
146
146
 
@@ -1,8 +1,21 @@
1
1
  import { NextFetchEvent, NextMiddleware } from 'next/server';
2
- import { ROUTES } from 'routes';
3
2
  import settings from 'settings';
4
3
  import { PzNextRequest } from '.';
5
4
  import logger from '../utils/log';
5
+ import { basket } from '../data/urls';
6
+ import { urlLocaleMatcherRegex } from '../utils';
7
+
8
+ const resetBasket = async (req: PzNextRequest) => {
9
+ await fetch(`${settings.commerceUrl}${basket.getBasket}`, {
10
+ method: 'DELETE',
11
+ headers: {
12
+ Cookie: req.headers.get('cookie') || '',
13
+ 'Content-Type': 'application/json',
14
+ 'X-CSRFToken': req.cookies.get('csrftoken')?.value ?? '',
15
+ Referer: settings.commerceUrl
16
+ }
17
+ });
18
+ };
6
19
 
7
20
  const withCurrency =
8
21
  (middleware: NextMiddleware) =>
@@ -11,6 +24,7 @@ const withCurrency =
11
24
  const { currencies, defaultCurrencyCode, defaultLocaleValue } =
12
25
  settings.localization;
13
26
  const locale = req.middlewareParams.rewrites.locale ?? defaultLocaleValue;
27
+ const url = req.nextUrl.clone();
14
28
 
15
29
  if (!defaultCurrencyCode) {
16
30
  logger.error('Default currency code is not defined in settings.');
@@ -34,6 +48,10 @@ const withCurrency =
34
48
  defaultCurrencyCode
35
49
  });
36
50
 
51
+ if (req.cookies.get('pz-set-currency')) {
52
+ activeCurrency = req.cookies.get('pz-set-currency')?.value;
53
+ }
54
+
37
55
  if (
38
56
  !activeCurrency ||
39
57
  !currencies.find((c) => c.code === activeCurrency)
@@ -44,6 +62,22 @@ const withCurrency =
44
62
  activeCurrency = defaultCurrencyCode;
45
63
  }
46
64
 
65
+ if (
66
+ req.cookies.get('pz-currency') &&
67
+ req.cookies.get('pz-currency')?.value !== activeCurrency &&
68
+ url.pathname.match(urlLocaleMatcherRegex) &&
69
+ !url.search.includes('mobile_app=true') &&
70
+ !url.search.includes('page=CreditCardThreeDSecurePage')
71
+ ) {
72
+ logger.info('Currency changed. Resetting basket...', {
73
+ sessionid: req.cookies.get('osessionid')?.value ?? '',
74
+ oldCurrency: req.cookies.get('pz-currency')?.value,
75
+ newCurrency: activeCurrency
76
+ });
77
+
78
+ resetBasket(req);
79
+ }
80
+
47
81
  req.middlewareParams.rewrites.currency = activeCurrency;
48
82
  } catch (error) {
49
83
  logger.error('withCurrency error', error);
@@ -154,18 +154,6 @@ const withPzDefault =
154
154
  secure: true
155
155
  });
156
156
 
157
- if (
158
- req.cookies.get('pz-currency') &&
159
- req.cookies.get('pz-currency').value !== currency
160
- ) {
161
- logger.debug('Currency changed', {
162
- currency,
163
- oldCurrency: req.cookies.get('pz-currency')?.value
164
- });
165
-
166
- middlewareResult.cookies.set('pz-reset-basket', 'true');
167
- }
168
-
169
157
  if (
170
158
  req.cookies.get('pz-locale') &&
171
159
  req.cookies.get('pz-locale').value !== locale
@@ -174,11 +162,6 @@ const withPzDefault =
174
162
  locale,
175
163
  oldLocale: req.cookies.get('pz-locale')?.value
176
164
  });
177
-
178
- middlewareResult.cookies.set(
179
- 'pz-reset-client-cache',
180
- 'true'
181
- );
182
165
  }
183
166
 
184
167
  middlewareResult.headers.set(
@@ -186,6 +169,10 @@ const withPzDefault =
186
169
  req.nextUrl.toString()
187
170
  );
188
171
 
172
+ if (req.cookies.get('pz-set-currency')) {
173
+ middlewareResult.cookies.delete('pz-set-currency');
174
+ }
175
+
189
176
  if (process.env.ACC_APP_VERSION) {
190
177
  middlewareResult.headers.set(
191
178
  'acc-app-version',
@@ -18,7 +18,8 @@ const withOauthLogin =
18
18
 
19
19
  const headers = {
20
20
  'x-forwarded-host':
21
- req.headers.get('x-forwarded-host') || req.headers.get('host') || ''
21
+ req.headers.get('x-forwarded-host') || req.headers.get('host') || '',
22
+ 'x-currency': req.cookies.get('pz-currency')?.value ?? ''
22
23
  };
23
24
 
24
25
  if (loginUrlMatcherRegex.test(url.pathname)) {
@@ -55,7 +55,8 @@ const withRedirectionPayment =
55
55
  headers: {
56
56
  'X-Requested-With': 'XMLHttpRequest',
57
57
  'Content-Type': 'application/x-www-form-urlencoded',
58
- Cookie: req.headers.get('cookie') ?? ''
58
+ Cookie: req.headers.get('cookie') ?? '',
59
+ 'x-currency': req.cookies.get('pz-currency')?.value ?? ''
59
60
  },
60
61
  body
61
62
  });
@@ -37,86 +37,95 @@ const withThreeDRedirection =
37
37
  return middleware(req, event);
38
38
  }
39
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);
40
+ const requestUrl = `${Settings.commerceUrl}/orders/checkout/${url.search}`;
41
+ const requestHeaders = {
42
+ 'X-Requested-With': 'XMLHttpRequest',
43
+ 'Content-Type': 'application/x-www-form-urlencoded',
44
+ Cookie: `osessionid=${req.cookies.get('osessionid')?.value ?? ''}`,
45
+ 'x-currency': req.cookies.get('pz-currency')?.value ?? ''
46
+ };
47
47
 
48
- if (!encodedPzParams.length) {
49
- logger.warn('No pzparams found in 3D form params');
50
- return middleware(req, event);
51
- }
48
+ try {
49
+ const body = await streamToString(req.body);
52
50
 
53
- const pzParams = JSON.parse(decodeURIComponent(encodedPzParams)) as {
54
- session: string;
55
- locale: string;
56
- };
51
+ const request = await fetch(requestUrl, {
52
+ method: 'POST',
53
+ headers: requestHeaders,
54
+ body
55
+ });
57
56
 
58
- logger.debug('3D form extra params', pzParams);
57
+ logger.info('Complete 3D payment request', {
58
+ requestUrl,
59
+ status: request.status,
60
+ requestHeaders
61
+ });
59
62
 
60
- const requestUrl = `${Settings.commerceUrl}/orders/checkout/${url.search}`;
63
+ const response = await request.json();
61
64
 
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
- }
65
+ const { context_list: contextList } = response;
66
+ const redirectionContext = contextList?.find(
67
+ (context) => context.page_context?.redirect_url
96
68
  );
97
- return middleware(req, event);
98
- }
69
+ const redirectUrl = redirectionContext?.page_context?.redirect_url;
70
+
71
+ logger.info('Order success page context list', {
72
+ middleware: 'three-d-redirection',
73
+ contextList
74
+ });
99
75
 
100
- const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
101
- redirectUrl,
102
- req.cookies.get('pz-locale')?.value
103
- )}`;
76
+ if (!redirectUrl) {
77
+ logger.warn(
78
+ 'No redirection url for order success page found in page_context. Redirecting to checkout page.',
79
+ {
80
+ middleware: 'three-d-redirection',
81
+ requestHeaders,
82
+ response: JSON.stringify(response)
83
+ }
84
+ );
85
+
86
+ const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
87
+ '/orders/checkout/',
88
+ req.cookies.get('pz-locale')?.value
89
+ )}`;
90
+
91
+ return NextResponse.redirect(redirectUrlWithLocale, 303);
92
+ }
104
93
 
105
- logger.info('Redirecting to order success page', {
106
- middleware: 'three-d-redirection',
107
- redirectUrlWithLocale
108
- });
94
+ const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
95
+ redirectUrl,
96
+ req.cookies.get('pz-locale')?.value
97
+ )}`;
109
98
 
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);
99
+ logger.info('Redirecting to order success page', {
100
+ middleware: 'three-d-redirection',
101
+ redirectUrlWithLocale
102
+ });
103
+
104
+ // Using POST method while redirecting causes an error,
105
+ // So we use 303 status code to change the method to GET
106
+ const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
113
107
 
114
- nextResponse.headers.set(
115
- 'Set-Cookie',
116
- request.headers.get('set-cookie') ?? ''
117
- );
108
+ nextResponse.headers.set(
109
+ 'Set-Cookie',
110
+ request.headers.get('set-cookie') ?? ''
111
+ );
118
112
 
119
- return nextResponse;
113
+ return nextResponse;
114
+ } catch (error) {
115
+ logger.error('Error while completing 3D payment', {
116
+ middleware: 'three-d-redirection',
117
+ error,
118
+ requestHeaders
119
+ });
120
+
121
+ return NextResponse.redirect(
122
+ `${url.origin}${getUrlPathWithLocale(
123
+ '/orders/checkout/',
124
+ req.cookies.get('pz-locale')?.value
125
+ )}`,
126
+ 303
127
+ );
128
+ }
120
129
  };
121
130
 
122
131
  export default withThreeDRedirection;
package/package.json CHANGED
@@ -1,11 +1,17 @@
1
1
  {
2
2
  "name": "@akinon/next",
3
3
  "description": "Core package for Project Zero Next",
4
- "version": "1.2.0",
4
+ "version": "1.4.0",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
8
- "pz-install-plugins": "bin/pz-install-plugins.js"
8
+ "pz-postbuild": "bin/pz-postbuild.js",
9
+ "pz-prebuild": "bin/pz-prebuild.js",
10
+ "pz-postinstall": "bin/pz-postinstall.js",
11
+ "pz-prestart": "bin/pz-prestart.js",
12
+ "pz-poststart": "bin/pz-poststart.js",
13
+ "pz-predev": "bin/pz-predev.js",
14
+ "pz-postdev": "bin/pz-postdev.js"
9
15
  },
10
16
  "dependencies": {
11
17
  "@reduxjs/toolkit": "1.9.2",
@@ -42,18 +42,14 @@ export type AccountChangePasswordFormType = {
42
42
  };
43
43
 
44
44
  export type AccountProfileFormType = {
45
+ date_of_birth: string;
46
+ email_allowed: boolean;
45
47
  first_name: string;
48
+ gender: string;
46
49
  last_name: string;
47
50
  phone: string;
48
- email_allowed: boolean;
49
51
  sms_allowed: boolean;
50
- gender: string;
51
- email: string;
52
- birthdate_day: string;
53
- birthdate_month: string;
54
- birthdate_year: string;
55
- country_code: string;
56
- date_of_birth: string;
52
+ [key: string]: any;
57
53
  };
58
54
 
59
55
  export type ContactFormType = {
package/utils/index.ts CHANGED
@@ -35,6 +35,9 @@ export function removeCookie(name: string) {
35
35
  document.cookie = name + '=' + '; expires=' + date + '; path=/';
36
36
  }
37
37
 
38
+ /**
39
+ * @deprecated Use setCurrency method in useLocalization hook instead.
40
+ */
38
41
  export function setCurrency(currency: string) {
39
42
  if (getCookie('pz-currency') !== currency) {
40
43
  setCookie('pz-reset-basket', 'true');
package/utils/log.ts CHANGED
@@ -1,5 +1,3 @@
1
- import * as Sentry from '@sentry/nextjs';
2
-
3
1
  enum LogLevel {
4
2
  TRACE = 'trace',
5
3
  DEBUG = 'debug',
@@ -94,15 +92,6 @@ const error: LoggerFn = (message, payload) => {
94
92
  message,
95
93
  payload
96
94
  });
97
-
98
- Sentry.withScope(function (scope) {
99
- scope.setLevel('error');
100
-
101
- Sentry.captureException({
102
- message,
103
- extra: payload
104
- });
105
- });
106
95
  };
107
96
 
108
97
  const warn: LoggerFn = (message, payload) => {
@@ -111,15 +100,6 @@ const warn: LoggerFn = (message, payload) => {
111
100
  message,
112
101
  payload
113
102
  });
114
-
115
- Sentry.withScope(function (scope) {
116
- scope.setLevel('warning');
117
-
118
- Sentry.captureEvent({
119
- message,
120
- extra: payload
121
- });
122
- });
123
103
  };
124
104
 
125
105
  const debug: LoggerFn = (message, payload) => {