@akinon/next 2.0.0-beta.1 → 2.0.0-beta.11
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/.eslintrc.js +12 -0
- package/CHANGELOG.md +56 -0
- package/__tests__/next-config.test.ts +83 -0
- package/__tests__/tsconfig.json +23 -0
- package/api/auth.ts +72 -5
- package/api/client.ts +18 -1
- package/babel.config.js +6 -0
- package/bin/pz-prebuild.js +1 -0
- package/bin/pz-run-tests.js +99 -0
- package/bin/run-prebuild-tests.js +46 -0
- package/components/accordion.tsx +1 -1
- package/components/button.tsx +51 -36
- package/components/client-root.tsx +20 -0
- package/components/input.tsx +1 -1
- package/components/modal.tsx +1 -1
- package/components/price.tsx +2 -2
- package/components/select.tsx +1 -1
- package/components/selected-payment-option-view.tsx +1 -1
- package/data/client/api.ts +2 -0
- package/data/client/basket.ts +27 -5
- package/data/client/checkout.ts +62 -7
- package/data/client/misc.ts +25 -1
- package/data/client/product.ts +19 -2
- package/data/client/user.ts +16 -8
- package/data/server/flatpage.ts +8 -4
- package/data/server/form.ts +12 -4
- package/data/server/landingpage.ts +8 -4
- package/data/server/menu.ts +7 -2
- package/data/server/product.ts +16 -5
- package/data/server/seo.ts +11 -4
- package/data/server/widget.ts +19 -4
- package/data/urls.ts +11 -3
- package/hooks/index.ts +1 -0
- package/hooks/use-localization.ts +24 -10
- package/hooks/use-router.ts +5 -2
- package/hooks/use-sentry-uncaught-errors.ts +24 -0
- package/instrumentation/index.ts +10 -0
- package/jest.config.js +19 -0
- package/lib/cache-handler.mjs +2 -2
- package/lib/cache.ts +4 -4
- package/localization/index.ts +2 -1
- package/middlewares/default.ts +31 -4
- package/middlewares/locale.ts +35 -11
- package/middlewares/url-redirection.ts +16 -0
- package/package.json +8 -4
- package/plugins.js +2 -1
- package/redux/middlewares/checkout.ts +30 -130
- package/redux/middlewares/index.ts +6 -2
- package/redux/middlewares/pre-order/address.ts +50 -0
- package/redux/middlewares/pre-order/attribute-based-shipping-option.ts +46 -0
- package/redux/middlewares/pre-order/data-source-shipping-option.ts +43 -0
- package/redux/middlewares/pre-order/delivery-option.ts +40 -0
- package/redux/middlewares/pre-order/index.ts +29 -0
- package/redux/middlewares/pre-order/installment-option.ts +42 -0
- package/redux/middlewares/pre-order/payment-option.ts +34 -0
- package/redux/middlewares/pre-order/pre-order-validation.ts +24 -0
- package/redux/middlewares/pre-order/redirection.ts +40 -0
- package/redux/middlewares/pre-order/set-pre-order.ts +22 -0
- package/redux/middlewares/pre-order/shipping-option.ts +44 -0
- package/redux/middlewares/pre-order/shipping-step.ts +38 -0
- package/redux/reducers/checkout.ts +8 -2
- package/redux/reducers/index.ts +5 -3
- package/redux/reducers/root.ts +7 -2
- package/sentry/index.ts +36 -17
- package/tailwind/content.js +16 -0
- package/types/commerce/account.ts +5 -1
- package/types/commerce/checkout.ts +23 -0
- package/types/index.ts +7 -2
- package/utils/get-root-hostname.ts +28 -0
- package/utils/index.ts +6 -2
- package/utils/localization.ts +4 -0
- package/utils/override-middleware.ts +25 -0
- package/views/error-page.tsx +93 -0
- package/with-pz-config.js +4 -3
package/data/urls.ts
CHANGED
|
@@ -74,7 +74,10 @@ export const address = {
|
|
|
74
74
|
|
|
75
75
|
export const basket = {
|
|
76
76
|
getBasket: '/baskets/basket/',
|
|
77
|
+
getMiniBasket: '/baskets/basket/mini/',
|
|
77
78
|
getBasketDetail: (namespace: string) => `/baskets/basket/${namespace}/`,
|
|
79
|
+
getMiniBasketDetail: (namespace: string) =>
|
|
80
|
+
`/baskets/basket/${namespace}/mini/`,
|
|
78
81
|
getAllBaskets: '/baskets/basket-list/',
|
|
79
82
|
removeBasket: (pk: number) => `/baskets/basket-list/${pk}/`,
|
|
80
83
|
selectMainBasket: (pk: number) => `/baskets/basket-list/id/${pk}/main/`,
|
|
@@ -137,7 +140,9 @@ export const checkout = {
|
|
|
137
140
|
'/orders/checkout/?page=AttributeBasedShippingOptionSelectionPage',
|
|
138
141
|
deliveryBagsPage: '/orders/checkout/?page=DeliveryBagsPage',
|
|
139
142
|
setOrderSelectionPage: '/orders/checkout/?page=OrderSelectionPage',
|
|
140
|
-
loyaltyCardPage: '/orders/checkout/?page=LoyaltyCardPage'
|
|
143
|
+
loyaltyCardPage: '/orders/checkout/?page=LoyaltyCardPage',
|
|
144
|
+
sendSmsPage: '/orders/checkout/?page=SendSmsPage',
|
|
145
|
+
verifySmsPage: '/orders/checkout/?page=VerifySmsPage'
|
|
141
146
|
};
|
|
142
147
|
|
|
143
148
|
export const flatpage = {
|
|
@@ -160,7 +165,8 @@ export const misc = {
|
|
|
160
165
|
parent ? `&parent=${parent}` : ''
|
|
161
166
|
}`,
|
|
162
167
|
cmsSeo: (slug: string | string[]) => `/cms/seo/?url=${slug ? slug : '/'}`,
|
|
163
|
-
setCurrency: '/users/activate-currency/'
|
|
168
|
+
setCurrency: '/users/activate-currency/',
|
|
169
|
+
bukalemunImageUrl: (params: string) => `/bukalemun/?${params}`
|
|
164
170
|
};
|
|
165
171
|
|
|
166
172
|
export const product = {
|
|
@@ -174,7 +180,9 @@ export const product = {
|
|
|
174
180
|
slug: (slug: string) => `/${slug}/`,
|
|
175
181
|
categoryUrl: (pk: number) => `/products/${pk}/category_nodes/?limit=1`,
|
|
176
182
|
breadcrumbUrl: (menuitemmodel: string) =>
|
|
177
|
-
`/menus/generate_breadcrumb/?item=${menuitemmodel}&generator_name=menu_item
|
|
183
|
+
`/menus/generate_breadcrumb/?item=${menuitemmodel}&generator_name=menu_item`,
|
|
184
|
+
bundleProduct: (productPk: string, queryString: string) =>
|
|
185
|
+
`/bundle-product/${productPk}/?${queryString}`
|
|
178
186
|
};
|
|
179
187
|
|
|
180
188
|
export const wishlist = {
|
package/hooks/index.ts
CHANGED
|
@@ -25,19 +25,33 @@ export const useLocalization = () => {
|
|
|
25
25
|
* @param locale Locale value defined in the settings.
|
|
26
26
|
*/
|
|
27
27
|
const setLocale = (locale: string) => {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
localeUrlStrategy !== LocaleUrlStrategy.ShowAllLocales
|
|
31
|
-
? ''
|
|
32
|
-
: `/${locale}`;
|
|
28
|
+
const { protocol, hostname, port, search, pathname } = location;
|
|
29
|
+
const pathnameWithoutLocale = pathname.replace(urlLocaleMatcherRegex, '');
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
let targetUrl;
|
|
32
|
+
|
|
33
|
+
if (localeUrlStrategy === LocaleUrlStrategy.Subdomain) {
|
|
34
|
+
const hostParts = hostname.split('.');
|
|
35
|
+
const subDomain = hostParts[0];
|
|
36
|
+
const isSubdomainLocale = locales.some((loc) => loc.value === subDomain);
|
|
37
|
+
const baseDomain = isSubdomainLocale
|
|
38
|
+
? hostParts.slice(1).join('.')
|
|
39
|
+
: hostname;
|
|
40
|
+
|
|
41
|
+
const formattedPort = port ? `:${port}` : '';
|
|
42
|
+
|
|
43
|
+
targetUrl = `${protocol}//${locale}.${baseDomain}${formattedPort}${pathnameWithoutLocale}${search}`;
|
|
44
|
+
} else {
|
|
45
|
+
const shouldHideLocale =
|
|
46
|
+
locale === defaultLocaleValue &&
|
|
47
|
+
localeUrlStrategy !== LocaleUrlStrategy.ShowAllLocales;
|
|
48
|
+
const localePath = shouldHideLocale ? '' : `/${locale}`;
|
|
49
|
+
|
|
50
|
+
targetUrl = `${localePath}${pathnameWithoutLocale}${search}`;
|
|
51
|
+
}
|
|
38
52
|
|
|
39
53
|
// router.push is not used because reloading the page also clears the client side cache.
|
|
40
|
-
location.href =
|
|
54
|
+
location.href = targetUrl;
|
|
41
55
|
};
|
|
42
56
|
|
|
43
57
|
/**
|
package/hooks/use-router.ts
CHANGED
|
@@ -27,8 +27,11 @@ export const useRouter = () => {
|
|
|
27
27
|
);
|
|
28
28
|
|
|
29
29
|
url.pathname = `${
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
localeUrlStrategy === LocaleUrlStrategy.Subdomain ||
|
|
31
|
+
(locale === defaultLocale?.value &&
|
|
32
|
+
[LocaleUrlStrategy.HideDefaultLocale].includes(
|
|
33
|
+
localeUrlStrategy as LocaleUrlStrategy
|
|
34
|
+
))
|
|
32
35
|
? ''
|
|
33
36
|
: `/${locale}`
|
|
34
37
|
}${pathnameWithoutLocale}`;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import * as Sentry from '@sentry/nextjs';
|
|
3
|
+
import { ClientLogType } from '@akinon/next/sentry';
|
|
4
|
+
|
|
5
|
+
export const useSentryUncaughtErrors = (error: Error & { digest?: string }) => {
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
Sentry.withScope(function (scope) {
|
|
8
|
+
scope.setLevel('fatal');
|
|
9
|
+
scope.setTags({
|
|
10
|
+
APP_TYPE: 'ProjectZeroNext',
|
|
11
|
+
TYPE: 'Client',
|
|
12
|
+
LOG_TYPE: ClientLogType.UNCAUGHT_ERROR_PAGE
|
|
13
|
+
});
|
|
14
|
+
scope.setExtra('error', error);
|
|
15
|
+
|
|
16
|
+
const error_ = new Error('FATAL: Uncaught client error');
|
|
17
|
+
error_.name = 'UNCAUGHT_ERROR_PAGE';
|
|
18
|
+
|
|
19
|
+
Sentry.captureException(error_, {
|
|
20
|
+
fingerprint: ['UNCAUGHT_ERROR_PAGE', error.digest]
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}, [error]);
|
|
24
|
+
};
|
package/instrumentation/index.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
+
import { initSentry } from '../sentry';
|
|
2
|
+
import * as Sentry from '@sentry/nextjs';
|
|
3
|
+
|
|
1
4
|
export async function register() {
|
|
2
5
|
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
3
6
|
await import('./node');
|
|
7
|
+
initSentry('Server');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (process.env.NEXT_RUNTIME === 'edge') {
|
|
11
|
+
initSentry('Edge');
|
|
4
12
|
}
|
|
5
13
|
}
|
|
14
|
+
|
|
15
|
+
export const onRequestError = Sentry.captureRequestError;
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
preset: 'ts-jest',
|
|
5
|
+
testEnvironment: 'node',
|
|
6
|
+
rootDir: path.resolve(__dirname),
|
|
7
|
+
roots: [],
|
|
8
|
+
testMatch: ['**/*.test.ts'],
|
|
9
|
+
testPathIgnorePatterns: [],
|
|
10
|
+
transformIgnorePatterns: [],
|
|
11
|
+
transform: {
|
|
12
|
+
'^.+\\.(tsx?|jsx?|mjs?)$': [
|
|
13
|
+
'ts-jest',
|
|
14
|
+
{
|
|
15
|
+
tsconfig: path.resolve(__dirname, '__tests__/tsconfig.json')
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
};
|
package/lib/cache-handler.mjs
CHANGED
|
@@ -23,10 +23,10 @@ CacheHandler.onCreation(async () => {
|
|
|
23
23
|
timeoutMs: 5000
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
const localHandler = createLruHandler();
|
|
26
|
+
// const localHandler = createLruHandler();
|
|
27
27
|
|
|
28
28
|
return {
|
|
29
|
-
handlers: [redisHandler
|
|
29
|
+
handlers: [redisHandler]
|
|
30
30
|
};
|
|
31
31
|
});
|
|
32
32
|
|
package/lib/cache.ts
CHANGED
|
@@ -156,10 +156,6 @@ export class Cache {
|
|
|
156
156
|
handler: () => Promise<T>,
|
|
157
157
|
options?: CacheOptions
|
|
158
158
|
): Promise<T> {
|
|
159
|
-
if (Settings.usePrettyUrlRoute) {
|
|
160
|
-
return await handler();
|
|
161
|
-
}
|
|
162
|
-
|
|
163
159
|
const requiredVariables = [
|
|
164
160
|
process.env.CACHE_HOST,
|
|
165
161
|
process.env.CACHE_PORT,
|
|
@@ -178,6 +174,10 @@ export class Cache {
|
|
|
178
174
|
const _options = Object.assign(defaultOptions, options);
|
|
179
175
|
const formattedKey = Cache.formatKey(key, locale);
|
|
180
176
|
|
|
177
|
+
if (Settings.usePrettyUrlRoute) {
|
|
178
|
+
_options.expire = 120;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
181
|
logger.debug('Cache wrap', { key, formattedKey, _options });
|
|
182
182
|
|
|
183
183
|
if (_options.cache) {
|
package/localization/index.ts
CHANGED
package/middlewares/default.ts
CHANGED
|
@@ -19,6 +19,8 @@ import withLocale from './locale';
|
|
|
19
19
|
import logger from '../utils/log';
|
|
20
20
|
import { user } from '../data/urls';
|
|
21
21
|
import { getUrlPathWithLocale } from '../utils/localization';
|
|
22
|
+
import getRootHostname from '../utils/get-root-hostname';
|
|
23
|
+
import { LocaleUrlStrategy } from '../localization';
|
|
22
24
|
|
|
23
25
|
const withPzDefault =
|
|
24
26
|
(middleware: NextMiddleware) =>
|
|
@@ -95,7 +97,9 @@ const withPzDefault =
|
|
|
95
97
|
|
|
96
98
|
if (
|
|
97
99
|
req.nextUrl.pathname.includes('/orders/hooks/') ||
|
|
98
|
-
req.nextUrl.pathname.includes('/orders/checkout-with-token/')
|
|
100
|
+
req.nextUrl.pathname.includes('/orders/checkout-with-token/') ||
|
|
101
|
+
req.nextUrl.pathname.includes('/hooks/cash_register/complete/') ||
|
|
102
|
+
req.nextUrl.pathname.includes('/hooks/cash_register/pre_order/')
|
|
99
103
|
) {
|
|
100
104
|
const queryString = searchParams.toString();
|
|
101
105
|
const currency = searchParams.get('currency')?.toLowerCase();
|
|
@@ -285,14 +289,16 @@ const withPzDefault =
|
|
|
285
289
|
url.pathname =
|
|
286
290
|
url.pathname +
|
|
287
291
|
(/\/$/.test(url.pathname) ? '' : '/') +
|
|
288
|
-
`searchparams|${
|
|
292
|
+
`searchparams|${encodeURIComponent(
|
|
293
|
+
url.searchParams.toString()
|
|
294
|
+
)}`;
|
|
289
295
|
}
|
|
290
296
|
|
|
291
297
|
if (
|
|
292
298
|
!req.middlewareParams.found &&
|
|
293
299
|
Settings.customNotFoundEnabled
|
|
294
300
|
) {
|
|
295
|
-
|
|
301
|
+
const pathname = url.pathname
|
|
296
302
|
.replace(/\/+$/, '')
|
|
297
303
|
.split('/');
|
|
298
304
|
url.pathname = url.pathname.replace(
|
|
@@ -337,6 +343,21 @@ const withPzDefault =
|
|
|
337
343
|
middlewareResult = NextResponse.rewrite(url);
|
|
338
344
|
}
|
|
339
345
|
|
|
346
|
+
const { localeUrlStrategy } =
|
|
347
|
+
Settings.localization;
|
|
348
|
+
|
|
349
|
+
const fallbackHost =
|
|
350
|
+
req.headers.get('x-forwarded-host') ||
|
|
351
|
+
req.headers.get('host');
|
|
352
|
+
const hostname =
|
|
353
|
+
process.env.NEXT_PUBLIC_URL ||
|
|
354
|
+
`https://${fallbackHost}`;
|
|
355
|
+
const rootHostname =
|
|
356
|
+
localeUrlStrategy ===
|
|
357
|
+
LocaleUrlStrategy.Subdomain
|
|
358
|
+
? getRootHostname(hostname)
|
|
359
|
+
: null;
|
|
360
|
+
|
|
340
361
|
if (
|
|
341
362
|
!url.pathname.startsWith(`/${currency}/orders`)
|
|
342
363
|
) {
|
|
@@ -346,6 +367,7 @@ const withPzDefault =
|
|
|
346
367
|
? locale
|
|
347
368
|
: defaultLocaleValue,
|
|
348
369
|
{
|
|
370
|
+
domain: rootHostname,
|
|
349
371
|
sameSite: 'none',
|
|
350
372
|
secure: true,
|
|
351
373
|
expires: new Date(
|
|
@@ -354,10 +376,12 @@ const withPzDefault =
|
|
|
354
376
|
}
|
|
355
377
|
);
|
|
356
378
|
}
|
|
379
|
+
|
|
357
380
|
middlewareResult.cookies.set(
|
|
358
381
|
'pz-currency',
|
|
359
382
|
currency,
|
|
360
383
|
{
|
|
384
|
+
domain: rootHostname,
|
|
361
385
|
sameSite: 'none',
|
|
362
386
|
secure: true,
|
|
363
387
|
expires: new Date(
|
|
@@ -406,7 +430,10 @@ const withPzDefault =
|
|
|
406
430
|
).json();
|
|
407
431
|
middlewareResult.cookies.set(
|
|
408
432
|
'csrftoken',
|
|
409
|
-
csrf_token
|
|
433
|
+
csrf_token,
|
|
434
|
+
{
|
|
435
|
+
domain: rootHostname
|
|
436
|
+
}
|
|
410
437
|
);
|
|
411
438
|
}
|
|
412
439
|
} catch (error) {
|
package/middlewares/locale.ts
CHANGED
|
@@ -4,17 +4,33 @@ import { PzNextRequest } from '.';
|
|
|
4
4
|
import { LocaleUrlStrategy } from '../localization';
|
|
5
5
|
import { urlLocaleMatcherRegex } from '../utils';
|
|
6
6
|
import logger from '../utils/log';
|
|
7
|
+
import { getUrlPathWithLocale } from '../utils/localization';
|
|
7
8
|
|
|
8
|
-
const getMatchedLocale = (pathname: string) => {
|
|
9
|
+
const getMatchedLocale = (pathname: string, req: PzNextRequest) => {
|
|
9
10
|
let matchedLocale = pathname.match(urlLocaleMatcherRegex)?.[0] ?? '';
|
|
10
11
|
matchedLocale = matchedLocale.replace('/', '');
|
|
11
12
|
|
|
13
|
+
const { localeUrlStrategy, defaultLocaleValue } = settings.localization;
|
|
14
|
+
|
|
15
|
+
if (localeUrlStrategy === LocaleUrlStrategy.Subdomain) {
|
|
16
|
+
const host =
|
|
17
|
+
req.headers.get('x-forwarded-host') || req.headers.get('host') || '';
|
|
18
|
+
|
|
19
|
+
if (host) {
|
|
20
|
+
const subDomain = host.split('.')[0] || '';
|
|
21
|
+
const subDomainLocaleMatched = `/${subDomain}`.match(
|
|
22
|
+
urlLocaleMatcherRegex
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
if (subDomainLocaleMatched && subDomainLocaleMatched[0]) {
|
|
26
|
+
matchedLocale = subDomainLocaleMatched[0].slice(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
12
31
|
if (!matchedLocale.length) {
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
LocaleUrlStrategy.ShowAllLocales
|
|
16
|
-
) {
|
|
17
|
-
matchedLocale = settings.localization.defaultLocaleValue;
|
|
32
|
+
if (localeUrlStrategy !== LocaleUrlStrategy.ShowAllLocales) {
|
|
33
|
+
matchedLocale = defaultLocaleValue;
|
|
18
34
|
}
|
|
19
35
|
}
|
|
20
36
|
|
|
@@ -28,8 +44,10 @@ const withLocale =
|
|
|
28
44
|
|
|
29
45
|
try {
|
|
30
46
|
const url = req.nextUrl.clone();
|
|
31
|
-
const matchedLocale = getMatchedLocale(url.pathname);
|
|
32
|
-
let { localeUrlStrategy
|
|
47
|
+
const matchedLocale = getMatchedLocale(url.pathname, req);
|
|
48
|
+
let { localeUrlStrategy } = settings.localization;
|
|
49
|
+
|
|
50
|
+
const { defaultLocaleValue, redirectToDefaultLocale } =
|
|
33
51
|
settings.localization;
|
|
34
52
|
|
|
35
53
|
localeUrlStrategy =
|
|
@@ -50,8 +68,15 @@ const withLocale =
|
|
|
50
68
|
redirectToDefaultLocale &&
|
|
51
69
|
req.method === 'GET'
|
|
52
70
|
) {
|
|
53
|
-
|
|
54
|
-
|
|
71
|
+
// Redirect to existing or default locale
|
|
72
|
+
|
|
73
|
+
url.pathname = getUrlPathWithLocale(
|
|
74
|
+
url.pathname,
|
|
75
|
+
req.cookies.get('pz-locale')?.value
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// Use 303 for POST requests
|
|
79
|
+
return NextResponse.redirect(url, 303);
|
|
55
80
|
}
|
|
56
81
|
|
|
57
82
|
req.middlewareParams.rewrites.locale = matchedLocale;
|
|
@@ -61,7 +86,6 @@ const withLocale =
|
|
|
61
86
|
ip
|
|
62
87
|
});
|
|
63
88
|
}
|
|
64
|
-
|
|
65
89
|
return middleware(req, event);
|
|
66
90
|
};
|
|
67
91
|
|
|
@@ -60,6 +60,22 @@ const withUrlRedirection =
|
|
|
60
60
|
|
|
61
61
|
const setCookies = request.headers.getSetCookie();
|
|
62
62
|
|
|
63
|
+
if (settings.commerceRedirectionIgnoreList) {
|
|
64
|
+
const shouldIgnoreRedirect =
|
|
65
|
+
settings.commerceRedirectionIgnoreList.some((ignorePath) =>
|
|
66
|
+
redirectUrl.pathname.startsWith(
|
|
67
|
+
getUrlPathWithLocale(
|
|
68
|
+
ignorePath,
|
|
69
|
+
req.middlewareParams.rewrites.locale
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (shouldIgnoreRedirect) {
|
|
75
|
+
return middleware(req, event);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
63
79
|
const response = NextResponse.redirect(redirectUrl.toString(), {
|
|
64
80
|
status: request.status
|
|
65
81
|
});
|
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": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.11",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -13,14 +13,18 @@
|
|
|
13
13
|
"pz-predev": "bin/pz-predev.js",
|
|
14
14
|
"pz-postdev": "bin/pz-postdev.js"
|
|
15
15
|
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "jest"
|
|
18
|
+
},
|
|
16
19
|
"dependencies": {
|
|
20
|
+
"@neshca/cache-handler": "1.5.1",
|
|
17
21
|
"@opentelemetry/exporter-trace-otlp-http": "0.46.0",
|
|
18
22
|
"@opentelemetry/resources": "1.19.0",
|
|
19
23
|
"@opentelemetry/sdk-node": "0.46.0",
|
|
20
24
|
"@opentelemetry/sdk-trace-node": "1.19.0",
|
|
21
25
|
"@opentelemetry/semantic-conventions": "1.19.0",
|
|
22
26
|
"@reduxjs/toolkit": "1.9.7",
|
|
23
|
-
"@
|
|
27
|
+
"@sentry/nextjs": "9.5.0",
|
|
24
28
|
"cross-spawn": "7.0.3",
|
|
25
29
|
"generic-pool": "3.9.0",
|
|
26
30
|
"react-redux": "8.1.3",
|
|
@@ -30,13 +34,13 @@
|
|
|
30
34
|
"set-cookie-parser": "2.6.0"
|
|
31
35
|
},
|
|
32
36
|
"devDependencies": {
|
|
33
|
-
"@akinon/eslint-plugin-projectzero": "2.0.0-beta.
|
|
37
|
+
"@akinon/eslint-plugin-projectzero": "2.0.0-beta.11",
|
|
34
38
|
"@types/react-redux": "7.1.30",
|
|
35
39
|
"@types/set-cookie-parser": "2.4.7",
|
|
36
40
|
"@typescript-eslint/eslint-plugin": "8.18.2",
|
|
37
41
|
"@typescript-eslint/parser": "8.18.2",
|
|
38
42
|
"eslint": "9.17.0",
|
|
39
|
-
"eslint-config-next": "15.
|
|
43
|
+
"eslint-config-next": "15.3.2",
|
|
40
44
|
"eslint-config-prettier": "9.1.0"
|
|
41
45
|
}
|
|
42
46
|
}
|
package/plugins.js
CHANGED
|
@@ -16,12 +16,11 @@ import {
|
|
|
16
16
|
setLoyaltyBalance,
|
|
17
17
|
setPaymentChoices,
|
|
18
18
|
setPaymentOptions,
|
|
19
|
-
setPreOrder,
|
|
20
19
|
setRetailStores,
|
|
21
20
|
setShippingOptions,
|
|
22
|
-
setShippingStepCompleted,
|
|
23
21
|
setHepsipayAvailability,
|
|
24
|
-
setWalletPaymentData
|
|
22
|
+
setWalletPaymentData,
|
|
23
|
+
setPayOnDeliveryOtpModalActive
|
|
25
24
|
} from '../../redux/reducers/checkout';
|
|
26
25
|
import { RootState, TypedDispatch } from 'redux/store';
|
|
27
26
|
import { checkoutApi } from '../../data/client/checkout';
|
|
@@ -37,6 +36,7 @@ interface CheckoutResult {
|
|
|
37
36
|
errors?: Record<string, string[]>;
|
|
38
37
|
pre_order?: PreOrder;
|
|
39
38
|
context_list?: CheckoutContext[];
|
|
39
|
+
redirect_url?: string;
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -58,142 +58,29 @@ export const errorMiddleware: Middleware = ({ dispatch }: MiddlewareParams) => {
|
|
|
58
58
|
};
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
export const
|
|
62
|
-
getState,
|
|
63
|
-
dispatch
|
|
64
|
-
}: MiddlewareParams) => {
|
|
61
|
+
export const redirectUrlMiddleware: Middleware = () => {
|
|
65
62
|
return (next) => (action) => {
|
|
66
63
|
const result: CheckoutResult = next(action);
|
|
67
|
-
const
|
|
64
|
+
const redirectUrl = result?.payload?.redirect_url;
|
|
68
65
|
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
action?.meta?.arg?.endpointName === 'guestLogin' ||
|
|
72
|
-
action?.meta?.arg?.endpointName === 'getCheckoutLoyaltyBalance'
|
|
73
|
-
) {
|
|
74
|
-
return result;
|
|
75
|
-
}
|
|
66
|
+
if (redirectUrl) {
|
|
67
|
+
const currentLocale = getCookie('pz-locale');
|
|
76
68
|
|
|
77
|
-
|
|
78
|
-
deliveryOptions,
|
|
79
|
-
addressList: addresses,
|
|
80
|
-
shippingOptions,
|
|
81
|
-
dataSourceShippingOptions,
|
|
82
|
-
paymentOptions,
|
|
83
|
-
installmentOptions,
|
|
84
|
-
attributeBasedShippingOptions
|
|
85
|
-
} = getState().checkout;
|
|
86
|
-
const { endpoints: apiEndpoints } = checkoutApi;
|
|
69
|
+
let url = redirectUrl;
|
|
87
70
|
|
|
88
|
-
|
|
89
|
-
|
|
71
|
+
if (currentLocale && !redirectUrl.includes('/orders/redirection')) {
|
|
72
|
+
const { defaultLocaleValue, localeUrlStrategy } = settings.localization;
|
|
90
73
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
dispatch(
|
|
97
|
-
apiEndpoints.setPaymentOption.initiate(preOrder.payment_option?.pk)
|
|
98
|
-
);
|
|
99
|
-
return;
|
|
74
|
+
url =
|
|
75
|
+
currentLocale === defaultLocaleValue &&
|
|
76
|
+
localeUrlStrategy !== LocaleUrlStrategy.ShowAllLocales
|
|
77
|
+
? redirectUrl
|
|
78
|
+
: `/${currentLocale}${redirectUrl}`;
|
|
100
79
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
dispatch(setPreOrder(preOrder));
|
|
104
80
|
|
|
105
|
-
|
|
106
|
-
dispatch(
|
|
107
|
-
apiEndpoints.setDeliveryOption.initiate(
|
|
108
|
-
deliveryOptions.find((opt) => opt.delivery_option_type === 'customer')
|
|
109
|
-
?.pk
|
|
110
|
-
)
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (
|
|
115
|
-
(!preOrder.shipping_address || !preOrder.billing_address) &&
|
|
116
|
-
addresses.length > 0 &&
|
|
117
|
-
(!preOrder.delivery_option ||
|
|
118
|
-
preOrder.delivery_option.delivery_option_type === 'customer')
|
|
119
|
-
) {
|
|
120
|
-
dispatch(
|
|
121
|
-
apiEndpoints.setAddresses.initiate({
|
|
122
|
-
shippingAddressPk: addresses[0].pk,
|
|
123
|
-
billingAddressPk: addresses[0].pk
|
|
124
|
-
})
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
shippingOptions.length > 0 &&
|
|
130
|
-
(!preOrder.shipping_option ||
|
|
131
|
-
!shippingOptions.find((opt) => opt.pk === preOrder.shipping_option?.pk))
|
|
132
|
-
) {
|
|
133
|
-
dispatch(apiEndpoints.setShippingOption.initiate(shippingOptions[0].pk));
|
|
81
|
+
window.location.href = url;
|
|
134
82
|
}
|
|
135
83
|
|
|
136
|
-
if (
|
|
137
|
-
dataSourceShippingOptions.length > 0 &&
|
|
138
|
-
!preOrder.data_source_shipping_options
|
|
139
|
-
) {
|
|
140
|
-
const selectedDataSourceShippingOptionsPks =
|
|
141
|
-
dataSourceShippingOptions.map(
|
|
142
|
-
(opt) => opt.data_source_shipping_options[0].pk
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
dispatch(
|
|
146
|
-
apiEndpoints.setDataSourceShippingOptions.initiate(
|
|
147
|
-
selectedDataSourceShippingOptionsPks
|
|
148
|
-
)
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
Object.keys(attributeBasedShippingOptions).length > 0 &&
|
|
154
|
-
!preOrder.attribute_based_shipping_options
|
|
155
|
-
) {
|
|
156
|
-
const initialSelectedOptions: Record<string, number> = Object.fromEntries(
|
|
157
|
-
Object.entries(attributeBasedShippingOptions).map(([key, options]) => [
|
|
158
|
-
key,
|
|
159
|
-
options.attribute_based_shipping_options[0].pk
|
|
160
|
-
])
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
dispatch(
|
|
164
|
-
apiEndpoints.setAttributeBasedShippingOptions.initiate(
|
|
165
|
-
initialSelectedOptions
|
|
166
|
-
)
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (!preOrder.payment_option && paymentOptions.length > 0) {
|
|
171
|
-
dispatch(apiEndpoints.setPaymentOption.initiate(paymentOptions[0].pk));
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (
|
|
175
|
-
!preOrder.installment &&
|
|
176
|
-
preOrder.payment_option?.payment_type !== 'saved_card' &&
|
|
177
|
-
installmentOptions.length > 0
|
|
178
|
-
) {
|
|
179
|
-
dispatch(
|
|
180
|
-
apiEndpoints.setInstallmentOption.initiate(installmentOptions[0].pk)
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
dispatch(
|
|
185
|
-
setShippingStepCompleted(
|
|
186
|
-
[
|
|
187
|
-
preOrder.delivery_option?.delivery_option_type === 'retail_store'
|
|
188
|
-
? true
|
|
189
|
-
: preOrder.shipping_address?.pk,
|
|
190
|
-
preOrder.billing_address?.pk,
|
|
191
|
-
preOrder.shipping_option?.pk,
|
|
192
|
-
addresses.length > 0
|
|
193
|
-
].every(Boolean)
|
|
194
|
-
)
|
|
195
|
-
);
|
|
196
|
-
|
|
197
84
|
return result;
|
|
198
85
|
};
|
|
199
86
|
};
|
|
@@ -203,8 +90,9 @@ export const contextListMiddleware: Middleware = ({
|
|
|
203
90
|
getState
|
|
204
91
|
}: MiddlewareParams) => {
|
|
205
92
|
return (next) => (action) => {
|
|
206
|
-
const { isMobileApp } = getState().root;
|
|
93
|
+
const { isMobileApp, userPhoneNumber } = getState().root;
|
|
207
94
|
const result: CheckoutResult = next(action);
|
|
95
|
+
const preOrder = result?.payload?.pre_order;
|
|
208
96
|
|
|
209
97
|
if (result?.payload?.context_list) {
|
|
210
98
|
result.payload.context_list.forEach((context) => {
|
|
@@ -323,6 +211,18 @@ export const contextListMiddleware: Middleware = ({
|
|
|
323
211
|
if (context.page_context.retail_stores) {
|
|
324
212
|
dispatch(setRetailStores(context.page_context.retail_stores));
|
|
325
213
|
}
|
|
214
|
+
|
|
215
|
+
if (context.page_name === 'SendSmsPage' && !preOrder?.phone_number) {
|
|
216
|
+
dispatch(
|
|
217
|
+
checkoutApi.endpoints.sendSms.initiate({
|
|
218
|
+
phone_number: userPhoneNumber ?? preOrder?.user_phone_number
|
|
219
|
+
})
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (context.page_name === 'VerifySmsPage') {
|
|
224
|
+
dispatch(setPayOnDeliveryOtpModalActive(true));
|
|
225
|
+
}
|
|
326
226
|
});
|
|
327
227
|
}
|
|
328
228
|
|