@akinon/next 2.0.150-beta.0 → 2.0.150-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,7 +18,11 @@ import {
18
18
  withBfcacheHeaders
19
19
  } from '.';
20
20
  import { getCsrfCookieFlags, urlLocaleMatcherRegex } from '../utils';
21
- import { getPzSegmentsConfig, encodePzValue, isLegacyMode } from '../utils/pz-segments';
21
+ import {
22
+ getPzSegmentsConfig,
23
+ encodePzValue,
24
+ isLegacyMode
25
+ } from '../utils/pz-segments';
22
26
  import withCurrency from './currency';
23
27
  import withLocale from './locale';
24
28
  import logger from '../utils/log';
@@ -343,98 +347,98 @@ const withPzDefault =
343
347
  req: PzNextRequest,
344
348
  event: NextFetchEvent
345
349
  ) => {
346
- let middlewareResult: NextResponse | void =
347
- NextResponse.next();
348
-
349
- try {
350
- const { locale, prettyUrl, currency } =
351
- req.middlewareParams.rewrites;
352
- const { defaultLocaleValue } =
353
- Settings.localization;
354
- const url = req.nextUrl.clone();
355
- const pathnameWithoutLocale =
356
- url.pathname.replace(
357
- urlLocaleMatcherRegex,
358
- ''
359
- );
350
+ let middlewareResult: NextResponse | void =
351
+ NextResponse.next();
352
+
353
+ try {
354
+ const { locale, prettyUrl, currency } =
355
+ req.middlewareParams.rewrites;
356
+ const { defaultLocaleValue } =
357
+ Settings.localization;
358
+ const url = req.nextUrl.clone();
359
+ const pathnameWithoutLocale =
360
+ url.pathname.replace(
361
+ urlLocaleMatcherRegex,
362
+ ''
363
+ );
360
364
 
361
- middlewareResult = (await middleware(
362
- req,
363
- event
364
- )) as NextResponse | void;
365
-
366
- let customRewriteUrlDiff = '';
367
-
368
- if (
369
- middlewareResult instanceof
370
- NextResponse &&
371
- middlewareResult.headers.get(
372
- 'pz-override-response'
373
- ) &&
374
- middlewareResult.headers.get(
375
- 'x-middleware-rewrite'
376
- )
377
- ) {
378
- const rewriteUrl = new URL(
365
+ middlewareResult = (await middleware(
366
+ req,
367
+ event
368
+ )) as NextResponse | void;
369
+
370
+ let customRewriteUrlDiff = '';
371
+
372
+ if (
373
+ middlewareResult instanceof
374
+ NextResponse &&
375
+ middlewareResult.headers.get(
376
+ 'pz-override-response'
377
+ ) &&
379
378
  middlewareResult.headers.get(
380
379
  'x-middleware-rewrite'
381
380
  )
382
- );
383
- const originalUrl = new URL(req.url);
384
- customRewriteUrlDiff =
385
- rewriteUrl.pathname.replace(
386
- originalUrl.pathname,
387
- ''
381
+ ) {
382
+ const rewriteUrl = new URL(
383
+ middlewareResult.headers.get(
384
+ 'x-middleware-rewrite'
385
+ )
388
386
  );
389
- }
387
+ const originalUrl = new URL(req.url);
388
+ customRewriteUrlDiff =
389
+ rewriteUrl.pathname.replace(
390
+ originalUrl.pathname,
391
+ ''
392
+ );
393
+ }
390
394
 
391
- let ordersPrefix: string;
395
+ let ordersPrefix: string;
392
396
 
393
- if (isLegacyMode(Settings)) {
394
- url.basePath = `/${commerceUrl}`;
395
- url.pathname =
396
- `/${locale.length ? `${locale}/` : ''}${currency}/${customRewriteUrlDiff}${
397
- prettyUrl ?? pathnameWithoutLocale
398
- }`.replace(/\/+/g, '/');
399
- ordersPrefix = `/${currency}/orders`;
400
- } else {
401
- const pzConfig =
402
- getPzSegmentsConfig(Settings);
403
- const fullUrlPath =
404
- `${customRewriteUrlDiff}${
397
+ if (isLegacyMode(Settings)) {
398
+ url.basePath = `/${commerceUrl}`;
399
+ url.pathname = `/${
400
+ locale.length ? `${locale}/` : ''
401
+ }${currency}/${customRewriteUrlDiff}${
405
402
  prettyUrl ?? pathnameWithoutLocale
406
403
  }`.replace(/\/+/g, '/');
407
- const fullUrl = `${req.nextUrl.origin}${fullUrlPath}`;
408
- const resolvedLocale =
409
- locale?.length > 0
410
- ? locale
411
- : Settings.localization
412
- .defaultLocaleValue;
413
- const resolveContext = {
414
- req,
415
- event,
416
- url,
417
- locale: resolvedLocale,
418
- currency,
419
- pathname: pathnameWithoutLocale
420
- };
421
- const customSegments = pzConfig.segments
422
- .filter(
423
- (seg) =>
424
- seg.name !== 'locale' &&
425
- seg.name !== 'currency' &&
426
- seg.name !== 'url'
427
- );
428
- const segmentValues: Record<
429
- string,
430
- string
431
- > = {
432
- locale: resolvedLocale,
433
- currency,
434
- url: encodeURIComponent(fullUrl),
435
- ...Object.fromEntries(
436
- customSegments
437
- .map((seg) => [
404
+ ordersPrefix = `/${currency}/orders`;
405
+ } else {
406
+ const pzConfig =
407
+ getPzSegmentsConfig(Settings);
408
+ const fullUrlPath =
409
+ `${customRewriteUrlDiff}${
410
+ prettyUrl ?? pathnameWithoutLocale
411
+ }`.replace(/\/+/g, '/');
412
+ const fullUrl = `${req.nextUrl.origin}${fullUrlPath}`;
413
+ const resolvedLocale =
414
+ locale?.length > 0
415
+ ? locale
416
+ : Settings.localization
417
+ .defaultLocaleValue;
418
+ const resolveContext = {
419
+ req,
420
+ event,
421
+ url,
422
+ locale: resolvedLocale,
423
+ currency,
424
+ pathname: pathnameWithoutLocale
425
+ };
426
+ const customSegments =
427
+ pzConfig.segments.filter(
428
+ (seg) =>
429
+ seg.name !== 'locale' &&
430
+ seg.name !== 'currency' &&
431
+ seg.name !== 'url'
432
+ );
433
+ const segmentValues: Record<
434
+ string,
435
+ string
436
+ > = {
437
+ locale: resolvedLocale,
438
+ currency,
439
+ url: encodeURIComponent(fullUrl),
440
+ ...Object.fromEntries(
441
+ customSegments.map((seg) => [
438
442
  seg.name,
439
443
  req.middlewareParams.rewrites[
440
444
  seg.name
@@ -443,105 +447,121 @@ const withPzDefault =
443
447
  ? seg.resolve(resolveContext)
444
448
  : '')
445
449
  ])
446
- )
447
- };
448
-
449
- const pzValue = encodePzValue(
450
- segmentValues,
451
- pzConfig
452
- );
450
+ )
451
+ };
453
452
 
454
- url.pathname =
455
- `/${pzValue}/${fullUrlPath}`.replace(
456
- /\/+/g,
457
- '/'
453
+ const pzValue = encodePzValue(
454
+ segmentValues,
455
+ pzConfig
458
456
  );
459
- ordersPrefix = `/${pzValue}/orders`;
460
- }
461
457
 
462
- if (
463
- Settings.usePrettyUrlRoute &&
464
- url.searchParams.toString().length > 0 &&
465
- !Object.entries(ROUTES).find(
466
- ([, value]) =>
467
- new RegExp(`^${value}/?$`).test(
468
- pathnameWithoutLocale
469
- )
470
- )
471
- ) {
472
- url.pathname =
473
- url.pathname +
474
- (/\/$/.test(url.pathname) ? '' : '/') +
475
- `searchparams|${encodeURIComponent(
476
- url.searchParams.toString()
477
- )}`;
478
- }
479
-
480
- Settings.rewrites.forEach((rewrite) => {
481
- url.pathname = url.pathname.replace(
482
- rewrite.source,
483
- rewrite.destination
484
- );
485
- });
458
+ url.pathname =
459
+ `/${pzValue}/${fullUrlPath}`.replace(
460
+ /\/+/g,
461
+ '/'
462
+ );
463
+ ordersPrefix = `/${pzValue}/orders`;
464
+ }
486
465
 
487
- // if middleware.ts has a return value for current url
488
- if (
489
- middlewareResult instanceof NextResponse
490
- ) {
491
- // pz-override-response header is used to prevent 404 page for custom responses.
492
466
  if (
493
- middlewareResult.headers.get(
494
- 'pz-override-response'
495
- ) !== 'true'
467
+ Settings.usePrettyUrlRoute &&
468
+ url.searchParams.toString().length >
469
+ 0 &&
470
+ !Object.entries(ROUTES).find(
471
+ ([, value]) =>
472
+ new RegExp(`^${value}/?$`).test(
473
+ pathnameWithoutLocale
474
+ )
475
+ )
496
476
  ) {
497
- middlewareResult.headers.set(
498
- 'x-middleware-rewrite',
499
- url.href
477
+ url.pathname =
478
+ url.pathname +
479
+ (/\/$/.test(url.pathname)
480
+ ? ''
481
+ : '/') +
482
+ `searchparams|${encodeURIComponent(
483
+ url.searchParams.toString()
484
+ )}`;
485
+ }
486
+
487
+ Settings.rewrites.forEach((rewrite) => {
488
+ url.pathname = url.pathname.replace(
489
+ rewrite.source,
490
+ rewrite.destination
500
491
  );
501
- } else if (
502
- middlewareResult.headers.get(
503
- 'x-middleware-rewrite'
504
- ) &&
505
- middlewareResult.headers.get(
506
- 'pz-override-response'
507
- ) === 'true'
492
+ });
493
+
494
+ // if middleware.ts has a return value for current url
495
+ if (
496
+ middlewareResult instanceof NextResponse
508
497
  ) {
498
+ // pz-override-response header is used to prevent 404 page for custom responses.
499
+ if (
500
+ middlewareResult.headers.get(
501
+ 'pz-override-response'
502
+ ) !== 'true'
503
+ ) {
504
+ middlewareResult.headers.set(
505
+ 'x-middleware-rewrite',
506
+ url.href
507
+ );
508
+ } else if (
509
+ middlewareResult.headers.get(
510
+ 'x-middleware-rewrite'
511
+ ) &&
512
+ middlewareResult.headers.get(
513
+ 'pz-override-response'
514
+ ) === 'true'
515
+ ) {
516
+ middlewareResult =
517
+ NextResponse.rewrite(url);
518
+ }
519
+ } else {
520
+ // if middleware.ts doesn't have a return value.
521
+ // e.g. NextResponse.next() doesn't exist in middleware.ts
522
+
509
523
  middlewareResult =
510
524
  NextResponse.rewrite(url);
511
525
  }
512
- } else {
513
- // if middleware.ts doesn't have a return value.
514
- // e.g. NextResponse.next() doesn't exist in middleware.ts
515
526
 
516
- middlewareResult =
517
- NextResponse.rewrite(url);
518
- }
527
+ const { localeUrlStrategy } =
528
+ Settings.localization;
529
+
530
+ const fallbackHost =
531
+ req.headers.get('x-forwarded-host') ||
532
+ req.headers.get('host');
533
+ const hostname =
534
+ process.env.NEXT_PUBLIC_URL ||
535
+ `https://${fallbackHost}`;
536
+ const rootHostname =
537
+ localeUrlStrategy ===
538
+ LocaleUrlStrategy.Subdomain
539
+ ? getRootHostname(hostname)
540
+ : null;
541
+
542
+ if (
543
+ !url.pathname.startsWith(ordersPrefix)
544
+ ) {
545
+ middlewareResult.cookies.set(
546
+ 'pz-locale',
547
+ locale?.length > 0
548
+ ? locale
549
+ : defaultLocaleValue,
550
+ {
551
+ domain: rootHostname,
552
+ sameSite: 'none',
553
+ secure: true,
554
+ expires: new Date(
555
+ Date.now() +
556
+ 1000 * 60 * 60 * 24 * 7
557
+ ) // 7 days
558
+ }
559
+ );
560
+ }
519
561
 
520
- const { localeUrlStrategy } =
521
- Settings.localization;
522
-
523
- const fallbackHost =
524
- req.headers.get('x-forwarded-host') ||
525
- req.headers.get('host');
526
- const hostname =
527
- process.env.NEXT_PUBLIC_URL ||
528
- `https://${fallbackHost}`;
529
- const rootHostname =
530
- localeUrlStrategy ===
531
- LocaleUrlStrategy.Subdomain
532
- ? getRootHostname(hostname)
533
- : null;
534
-
535
- if (
536
- !url.pathname.startsWith(
537
- ordersPrefix
538
- )
539
- ) {
540
562
  middlewareResult.cookies.set(
541
- 'pz-locale',
542
- locale?.length > 0
543
- ? locale
544
- : defaultLocaleValue,
563
+ 'pz-currency',
564
+ currency,
545
565
  {
546
566
  domain: rootHostname,
547
567
  sameSite: 'none',
@@ -551,102 +571,89 @@ const withPzDefault =
551
571
  ) // 7 days
552
572
  }
553
573
  );
554
- }
555
574
 
556
- middlewareResult.cookies.set(
557
- 'pz-currency',
558
- currency,
559
- {
560
- domain: rootHostname,
561
- sameSite: 'none',
562
- secure: true,
563
- expires: new Date(
564
- Date.now() + 1000 * 60 * 60 * 24 * 7
565
- ) // 7 days
575
+ if (
576
+ req.cookies.get('pz-locale') &&
577
+ req.cookies.get('pz-locale').value !==
578
+ locale
579
+ ) {
580
+ logger.debug('Locale changed', {
581
+ locale,
582
+ oldLocale:
583
+ req.cookies.get('pz-locale')?.value,
584
+ ip
585
+ });
566
586
  }
567
- );
568
-
569
- if (
570
- req.cookies.get('pz-locale') &&
571
- req.cookies.get('pz-locale').value !==
572
- locale
573
- ) {
574
- logger.debug('Locale changed', {
575
- locale,
576
- oldLocale:
577
- req.cookies.get('pz-locale')?.value,
578
- ip
579
- });
580
- }
581
-
582
- middlewareResult.headers.set(
583
- 'pz-url',
584
- req.nextUrl.toString()
585
- );
586
587
 
587
- if (req.cookies.get('pz-set-currency')) {
588
- middlewareResult.cookies.delete(
589
- 'pz-set-currency'
588
+ middlewareResult.headers.set(
589
+ 'pz-url',
590
+ req.nextUrl.toString()
590
591
  );
591
- }
592
592
 
593
- if (
594
- req.cookies.get('pz-post-checkout-flow')
595
- ) {
596
- if (
597
- pathnameWithoutLocale.startsWith(
598
- '/orders/completed/'
599
- ) ||
600
- pathnameWithoutLocale.startsWith(
601
- '/basket'
602
- )
603
- ) {
593
+ if (req.cookies.get('pz-set-currency')) {
604
594
  middlewareResult.cookies.delete(
605
- 'pz-post-checkout-flow'
595
+ 'pz-set-currency'
606
596
  );
607
597
  }
608
- }
609
-
610
- if (process.env.ACC_APP_VERSION) {
611
- middlewareResult.headers.set(
612
- 'acc-app-version',
613
- process.env.ACC_APP_VERSION
614
- );
615
- }
616
598
 
617
- // Set CSRF token if not set
618
- try {
619
- const url = `${Settings.commerceUrl}${user.csrfToken}`;
599
+ if (
600
+ req.cookies.get('pz-post-checkout-flow')
601
+ ) {
602
+ if (
603
+ pathnameWithoutLocale.startsWith(
604
+ '/orders/completed/'
605
+ ) ||
606
+ pathnameWithoutLocale.startsWith(
607
+ '/basket'
608
+ )
609
+ ) {
610
+ middlewareResult.cookies.delete(
611
+ 'pz-post-checkout-flow'
612
+ );
613
+ }
614
+ }
620
615
 
621
- if (!req.cookies.get('csrftoken')) {
622
- const { csrf_token } = await (
623
- await fetch(url)
624
- ).json();
625
- middlewareResult.cookies.set(
626
- 'csrftoken',
627
- csrf_token,
628
- {
629
- path: '/',
630
- domain: rootHostname,
631
- ...getCsrfCookieFlags()
632
- }
616
+ if (process.env.ACC_APP_VERSION) {
617
+ middlewareResult.headers.set(
618
+ 'acc-app-version',
619
+ process.env.ACC_APP_VERSION
633
620
  );
634
621
  }
622
+
623
+ // Set CSRF token if not set
624
+ try {
625
+ const url = `${Settings.commerceUrl}${user.csrfToken}`;
626
+
627
+ if (!req.cookies.get('csrftoken')) {
628
+ const { csrf_token } = await (
629
+ await fetch(url)
630
+ ).json();
631
+ middlewareResult.cookies.set(
632
+ 'csrftoken',
633
+ csrf_token,
634
+ {
635
+ path: '/',
636
+ domain: rootHostname,
637
+ ...getCsrfCookieFlags()
638
+ }
639
+ );
640
+ }
641
+ } catch (error) {
642
+ logger.error('CSRF Error', {
643
+ error,
644
+ ip
645
+ });
646
+ }
635
647
  } catch (error) {
636
- logger.error('CSRF Error', {
648
+ logger.error('withPzDefault Error', {
637
649
  error,
638
650
  ip
639
651
  });
640
652
  }
641
- } catch (error) {
642
- logger.error('withPzDefault Error', {
643
- error,
644
- ip
645
- });
646
- }
647
653
 
648
- return middlewareResult;
649
- })
654
+ return middlewareResult;
655
+ }
656
+ )
650
657
  )
651
658
  )
652
659
  )
@@ -86,7 +86,9 @@ const withPrettyUrl =
86
86
  const matchedLanguagePrefix = url.pathname.match(
87
87
  urlLocaleMatcherRegex
88
88
  )?.[0];
89
- const prettyUrlPathname = url.pathname.replace(matchedLanguagePrefix, '');
89
+ const prettyUrlPathname = matchedLanguagePrefix
90
+ ? url.pathname.replace(matchedLanguagePrefix, '')
91
+ : url.pathname;
90
92
  const isValidPrettyUrlPath = (pathname: string) => {
91
93
  return (
92
94
  new RegExp(/^\/[a-zA-Z0-9/]+(?:-[a-zA-Z0-9/]+)*$/).test(pathname) &&
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.150-beta.0",
4
+ "version": "2.0.150-rc.0",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -36,7 +36,7 @@
36
36
  "set-cookie-parser": "2.6.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@akinon/eslint-plugin-projectzero": "2.0.150-beta.0",
39
+ "@akinon/eslint-plugin-projectzero": "2.0.150-rc.0",
40
40
  "@babel/core": "7.26.10",
41
41
  "@babel/preset-env": "7.26.9",
42
42
  "@babel/preset-typescript": "7.27.0",
package/plugins.d.ts CHANGED
@@ -37,6 +37,16 @@ declare module '@akinon/pz-cybersource-uc/src/redux/middleware' {
37
37
  export default middleware as any;
38
38
  }
39
39
 
40
+ declare module '@akinon/pz-apple-pay' {}
41
+
42
+ declare module '@akinon/pz-similar-products' {
43
+ export const SimilarProductsModal: any;
44
+ export const SimilarProductsFilterSidebar: any;
45
+ export const SimilarProductsResultsGrid: any;
46
+ export const SimilarProductsPlugin: any;
47
+ export const SimilarProductsButtonPlugin: any;
48
+ }
49
+
40
50
  declare module '@akinon/pz-cybersource-uc/src/redux/reducer' {
41
51
  export default reducer as any;
42
52
  }
package/plugins.js CHANGED
@@ -16,6 +16,7 @@ module.exports = [
16
16
  'pz-tabby-extension',
17
17
  'pz-apple-pay',
18
18
  'pz-tamara-extension',
19
+ 'pz-similar-products',
19
20
  'pz-cybersource-uc',
20
21
  'pz-hepsipay',
21
22
  'pz-flow-payment',