@akinon/next 2.0.95-beta.1 → 2.0.95-rc.1

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';
@@ -332,98 +336,98 @@ const withPzDefault =
332
336
  req: PzNextRequest,
333
337
  event: NextFetchEvent
334
338
  ) => {
335
- let middlewareResult: NextResponse | void =
336
- NextResponse.next();
337
-
338
- try {
339
- const { locale, prettyUrl, currency } =
340
- req.middlewareParams.rewrites;
341
- const { defaultLocaleValue } =
342
- Settings.localization;
343
- const url = req.nextUrl.clone();
344
- const pathnameWithoutLocale =
345
- url.pathname.replace(
346
- urlLocaleMatcherRegex,
347
- ''
348
- );
339
+ let middlewareResult: NextResponse | void =
340
+ NextResponse.next();
341
+
342
+ try {
343
+ const { locale, prettyUrl, currency } =
344
+ req.middlewareParams.rewrites;
345
+ const { defaultLocaleValue } =
346
+ Settings.localization;
347
+ const url = req.nextUrl.clone();
348
+ const pathnameWithoutLocale =
349
+ url.pathname.replace(
350
+ urlLocaleMatcherRegex,
351
+ ''
352
+ );
349
353
 
350
- middlewareResult = (await middleware(
351
- req,
352
- event
353
- )) as NextResponse | void;
354
-
355
- let customRewriteUrlDiff = '';
356
-
357
- if (
358
- middlewareResult instanceof
359
- NextResponse &&
360
- middlewareResult.headers.get(
361
- 'pz-override-response'
362
- ) &&
363
- middlewareResult.headers.get(
364
- 'x-middleware-rewrite'
365
- )
366
- ) {
367
- const rewriteUrl = new URL(
354
+ middlewareResult = (await middleware(
355
+ req,
356
+ event
357
+ )) as NextResponse | void;
358
+
359
+ let customRewriteUrlDiff = '';
360
+
361
+ if (
362
+ middlewareResult instanceof
363
+ NextResponse &&
364
+ middlewareResult.headers.get(
365
+ 'pz-override-response'
366
+ ) &&
368
367
  middlewareResult.headers.get(
369
368
  'x-middleware-rewrite'
370
369
  )
371
- );
372
- const originalUrl = new URL(req.url);
373
- customRewriteUrlDiff =
374
- rewriteUrl.pathname.replace(
375
- originalUrl.pathname,
376
- ''
370
+ ) {
371
+ const rewriteUrl = new URL(
372
+ middlewareResult.headers.get(
373
+ 'x-middleware-rewrite'
374
+ )
377
375
  );
378
- }
376
+ const originalUrl = new URL(req.url);
377
+ customRewriteUrlDiff =
378
+ rewriteUrl.pathname.replace(
379
+ originalUrl.pathname,
380
+ ''
381
+ );
382
+ }
379
383
 
380
- let ordersPrefix: string;
384
+ let ordersPrefix: string;
381
385
 
382
- if (isLegacyMode(Settings)) {
383
- url.basePath = `/${commerceUrl}`;
384
- url.pathname =
385
- `/${locale.length ? `${locale}/` : ''}${currency}/${customRewriteUrlDiff}${
386
- prettyUrl ?? pathnameWithoutLocale
387
- }`.replace(/\/+/g, '/');
388
- ordersPrefix = `/${currency}/orders`;
389
- } else {
390
- const pzConfig =
391
- getPzSegmentsConfig(Settings);
392
- const fullUrlPath =
393
- `${customRewriteUrlDiff}${
386
+ if (isLegacyMode(Settings)) {
387
+ url.basePath = `/${commerceUrl}`;
388
+ url.pathname = `/${
389
+ locale.length ? `${locale}/` : ''
390
+ }${currency}/${customRewriteUrlDiff}${
394
391
  prettyUrl ?? pathnameWithoutLocale
395
392
  }`.replace(/\/+/g, '/');
396
- const fullUrl = `${req.nextUrl.origin}${fullUrlPath}`;
397
- const resolvedLocale =
398
- locale?.length > 0
399
- ? locale
400
- : Settings.localization
401
- .defaultLocaleValue;
402
- const resolveContext = {
403
- req,
404
- event,
405
- url,
406
- locale: resolvedLocale,
407
- currency,
408
- pathname: pathnameWithoutLocale
409
- };
410
- const customSegments = pzConfig.segments
411
- .filter(
412
- (seg) =>
413
- seg.name !== 'locale' &&
414
- seg.name !== 'currency' &&
415
- seg.name !== 'url'
416
- );
417
- const segmentValues: Record<
418
- string,
419
- string
420
- > = {
421
- locale: resolvedLocale,
422
- currency,
423
- url: encodeURIComponent(fullUrl),
424
- ...Object.fromEntries(
425
- customSegments
426
- .map((seg) => [
393
+ ordersPrefix = `/${currency}/orders`;
394
+ } else {
395
+ const pzConfig =
396
+ getPzSegmentsConfig(Settings);
397
+ const fullUrlPath =
398
+ `${customRewriteUrlDiff}${
399
+ prettyUrl ?? pathnameWithoutLocale
400
+ }`.replace(/\/+/g, '/');
401
+ const fullUrl = `${req.nextUrl.origin}${fullUrlPath}`;
402
+ const resolvedLocale =
403
+ locale?.length > 0
404
+ ? locale
405
+ : Settings.localization
406
+ .defaultLocaleValue;
407
+ const resolveContext = {
408
+ req,
409
+ event,
410
+ url,
411
+ locale: resolvedLocale,
412
+ currency,
413
+ pathname: pathnameWithoutLocale
414
+ };
415
+ const customSegments =
416
+ pzConfig.segments.filter(
417
+ (seg) =>
418
+ seg.name !== 'locale' &&
419
+ seg.name !== 'currency' &&
420
+ seg.name !== 'url'
421
+ );
422
+ const segmentValues: Record<
423
+ string,
424
+ string
425
+ > = {
426
+ locale: resolvedLocale,
427
+ currency,
428
+ url: encodeURIComponent(fullUrl),
429
+ ...Object.fromEntries(
430
+ customSegments.map((seg) => [
427
431
  seg.name,
428
432
  req.middlewareParams.rewrites[
429
433
  seg.name
@@ -432,105 +436,121 @@ const withPzDefault =
432
436
  ? seg.resolve(resolveContext)
433
437
  : '')
434
438
  ])
435
- )
436
- };
437
-
438
- const pzValue = encodePzValue(
439
- segmentValues,
440
- pzConfig
441
- );
439
+ )
440
+ };
442
441
 
443
- url.pathname =
444
- `/${pzValue}/${fullUrlPath}`.replace(
445
- /\/+/g,
446
- '/'
442
+ const pzValue = encodePzValue(
443
+ segmentValues,
444
+ pzConfig
447
445
  );
448
- ordersPrefix = `/${pzValue}/orders`;
449
- }
450
446
 
451
- if (
452
- Settings.usePrettyUrlRoute &&
453
- url.searchParams.toString().length > 0 &&
454
- !Object.entries(ROUTES).find(
455
- ([, value]) =>
456
- new RegExp(`^${value}/?$`).test(
457
- pathnameWithoutLocale
458
- )
459
- )
460
- ) {
461
- url.pathname =
462
- url.pathname +
463
- (/\/$/.test(url.pathname) ? '' : '/') +
464
- `searchparams|${encodeURIComponent(
465
- url.searchParams.toString()
466
- )}`;
467
- }
468
-
469
- Settings.rewrites.forEach((rewrite) => {
470
- url.pathname = url.pathname.replace(
471
- rewrite.source,
472
- rewrite.destination
473
- );
474
- });
447
+ url.pathname =
448
+ `/${pzValue}/${fullUrlPath}`.replace(
449
+ /\/+/g,
450
+ '/'
451
+ );
452
+ ordersPrefix = `/${pzValue}/orders`;
453
+ }
475
454
 
476
- // if middleware.ts has a return value for current url
477
- if (
478
- middlewareResult instanceof NextResponse
479
- ) {
480
- // pz-override-response header is used to prevent 404 page for custom responses.
481
455
  if (
482
- middlewareResult.headers.get(
483
- 'pz-override-response'
484
- ) !== 'true'
456
+ Settings.usePrettyUrlRoute &&
457
+ url.searchParams.toString().length >
458
+ 0 &&
459
+ !Object.entries(ROUTES).find(
460
+ ([, value]) =>
461
+ new RegExp(`^${value}/?$`).test(
462
+ pathnameWithoutLocale
463
+ )
464
+ )
485
465
  ) {
486
- middlewareResult.headers.set(
487
- 'x-middleware-rewrite',
488
- url.href
466
+ url.pathname =
467
+ url.pathname +
468
+ (/\/$/.test(url.pathname)
469
+ ? ''
470
+ : '/') +
471
+ `searchparams|${encodeURIComponent(
472
+ url.searchParams.toString()
473
+ )}`;
474
+ }
475
+
476
+ Settings.rewrites.forEach((rewrite) => {
477
+ url.pathname = url.pathname.replace(
478
+ rewrite.source,
479
+ rewrite.destination
489
480
  );
490
- } else if (
491
- middlewareResult.headers.get(
492
- 'x-middleware-rewrite'
493
- ) &&
494
- middlewareResult.headers.get(
495
- 'pz-override-response'
496
- ) === 'true'
481
+ });
482
+
483
+ // if middleware.ts has a return value for current url
484
+ if (
485
+ middlewareResult instanceof NextResponse
497
486
  ) {
487
+ // pz-override-response header is used to prevent 404 page for custom responses.
488
+ if (
489
+ middlewareResult.headers.get(
490
+ 'pz-override-response'
491
+ ) !== 'true'
492
+ ) {
493
+ middlewareResult.headers.set(
494
+ 'x-middleware-rewrite',
495
+ url.href
496
+ );
497
+ } else if (
498
+ middlewareResult.headers.get(
499
+ 'x-middleware-rewrite'
500
+ ) &&
501
+ middlewareResult.headers.get(
502
+ 'pz-override-response'
503
+ ) === 'true'
504
+ ) {
505
+ middlewareResult =
506
+ NextResponse.rewrite(url);
507
+ }
508
+ } else {
509
+ // if middleware.ts doesn't have a return value.
510
+ // e.g. NextResponse.next() doesn't exist in middleware.ts
511
+
498
512
  middlewareResult =
499
513
  NextResponse.rewrite(url);
500
514
  }
501
- } else {
502
- // if middleware.ts doesn't have a return value.
503
- // e.g. NextResponse.next() doesn't exist in middleware.ts
504
515
 
505
- middlewareResult =
506
- NextResponse.rewrite(url);
507
- }
516
+ const { localeUrlStrategy } =
517
+ Settings.localization;
518
+
519
+ const fallbackHost =
520
+ req.headers.get('x-forwarded-host') ||
521
+ req.headers.get('host');
522
+ const hostname =
523
+ process.env.NEXT_PUBLIC_URL ||
524
+ `https://${fallbackHost}`;
525
+ const rootHostname =
526
+ localeUrlStrategy ===
527
+ LocaleUrlStrategy.Subdomain
528
+ ? getRootHostname(hostname)
529
+ : null;
530
+
531
+ if (
532
+ !url.pathname.startsWith(ordersPrefix)
533
+ ) {
534
+ middlewareResult.cookies.set(
535
+ 'pz-locale',
536
+ locale?.length > 0
537
+ ? locale
538
+ : defaultLocaleValue,
539
+ {
540
+ domain: rootHostname,
541
+ sameSite: 'none',
542
+ secure: true,
543
+ expires: new Date(
544
+ Date.now() +
545
+ 1000 * 60 * 60 * 24 * 7
546
+ ) // 7 days
547
+ }
548
+ );
549
+ }
508
550
 
509
- const { localeUrlStrategy } =
510
- Settings.localization;
511
-
512
- const fallbackHost =
513
- req.headers.get('x-forwarded-host') ||
514
- req.headers.get('host');
515
- const hostname =
516
- process.env.NEXT_PUBLIC_URL ||
517
- `https://${fallbackHost}`;
518
- const rootHostname =
519
- localeUrlStrategy ===
520
- LocaleUrlStrategy.Subdomain
521
- ? getRootHostname(hostname)
522
- : null;
523
-
524
- if (
525
- !url.pathname.startsWith(
526
- ordersPrefix
527
- )
528
- ) {
529
551
  middlewareResult.cookies.set(
530
- 'pz-locale',
531
- locale?.length > 0
532
- ? locale
533
- : defaultLocaleValue,
552
+ 'pz-currency',
553
+ currency,
534
554
  {
535
555
  domain: rootHostname,
536
556
  sameSite: 'none',
@@ -540,102 +560,89 @@ const withPzDefault =
540
560
  ) // 7 days
541
561
  }
542
562
  );
543
- }
544
563
 
545
- middlewareResult.cookies.set(
546
- 'pz-currency',
547
- currency,
548
- {
549
- domain: rootHostname,
550
- sameSite: 'none',
551
- secure: true,
552
- expires: new Date(
553
- Date.now() + 1000 * 60 * 60 * 24 * 7
554
- ) // 7 days
564
+ if (
565
+ req.cookies.get('pz-locale') &&
566
+ req.cookies.get('pz-locale').value !==
567
+ locale
568
+ ) {
569
+ logger.debug('Locale changed', {
570
+ locale,
571
+ oldLocale:
572
+ req.cookies.get('pz-locale')?.value,
573
+ ip
574
+ });
555
575
  }
556
- );
557
-
558
- if (
559
- req.cookies.get('pz-locale') &&
560
- req.cookies.get('pz-locale').value !==
561
- locale
562
- ) {
563
- logger.debug('Locale changed', {
564
- locale,
565
- oldLocale:
566
- req.cookies.get('pz-locale')?.value,
567
- ip
568
- });
569
- }
570
-
571
- middlewareResult.headers.set(
572
- 'pz-url',
573
- req.nextUrl.toString()
574
- );
575
576
 
576
- if (req.cookies.get('pz-set-currency')) {
577
- middlewareResult.cookies.delete(
578
- 'pz-set-currency'
577
+ middlewareResult.headers.set(
578
+ 'pz-url',
579
+ req.nextUrl.toString()
579
580
  );
580
- }
581
581
 
582
- if (
583
- req.cookies.get('pz-post-checkout-flow')
584
- ) {
585
- if (
586
- pathnameWithoutLocale.startsWith(
587
- '/orders/completed/'
588
- ) ||
589
- pathnameWithoutLocale.startsWith(
590
- '/basket'
591
- )
592
- ) {
582
+ if (req.cookies.get('pz-set-currency')) {
593
583
  middlewareResult.cookies.delete(
594
- 'pz-post-checkout-flow'
584
+ 'pz-set-currency'
595
585
  );
596
586
  }
597
- }
598
-
599
- if (process.env.ACC_APP_VERSION) {
600
- middlewareResult.headers.set(
601
- 'acc-app-version',
602
- process.env.ACC_APP_VERSION
603
- );
604
- }
605
587
 
606
- // Set CSRF token if not set
607
- try {
608
- const url = `${Settings.commerceUrl}${user.csrfToken}`;
588
+ if (
589
+ req.cookies.get('pz-post-checkout-flow')
590
+ ) {
591
+ if (
592
+ pathnameWithoutLocale.startsWith(
593
+ '/orders/completed/'
594
+ ) ||
595
+ pathnameWithoutLocale.startsWith(
596
+ '/basket'
597
+ )
598
+ ) {
599
+ middlewareResult.cookies.delete(
600
+ 'pz-post-checkout-flow'
601
+ );
602
+ }
603
+ }
609
604
 
610
- if (!req.cookies.get('csrftoken')) {
611
- const { csrf_token } = await (
612
- await fetch(url)
613
- ).json();
614
- middlewareResult.cookies.set(
615
- 'csrftoken',
616
- csrf_token,
617
- {
618
- path: '/',
619
- domain: rootHostname,
620
- ...getCsrfCookieFlags()
621
- }
605
+ if (process.env.ACC_APP_VERSION) {
606
+ middlewareResult.headers.set(
607
+ 'acc-app-version',
608
+ process.env.ACC_APP_VERSION
622
609
  );
623
610
  }
611
+
612
+ // Set CSRF token if not set
613
+ try {
614
+ const url = `${Settings.commerceUrl}${user.csrfToken}`;
615
+
616
+ if (!req.cookies.get('csrftoken')) {
617
+ const { csrf_token } = await (
618
+ await fetch(url)
619
+ ).json();
620
+ middlewareResult.cookies.set(
621
+ 'csrftoken',
622
+ csrf_token,
623
+ {
624
+ path: '/',
625
+ domain: rootHostname,
626
+ ...getCsrfCookieFlags()
627
+ }
628
+ );
629
+ }
630
+ } catch (error) {
631
+ logger.error('CSRF Error', {
632
+ error,
633
+ ip
634
+ });
635
+ }
624
636
  } catch (error) {
625
- logger.error('CSRF Error', {
637
+ logger.error('withPzDefault Error', {
626
638
  error,
627
639
  ip
628
640
  });
629
641
  }
630
- } catch (error) {
631
- logger.error('withPzDefault Error', {
632
- error,
633
- ip
634
- });
635
- }
636
642
 
637
- return middlewareResult;
638
- })
643
+ return middlewareResult;
644
+ }
645
+ )
639
646
  )
640
647
  )
641
648
  )
@@ -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.95-beta.1",
4
+ "version": "2.0.95-rc.1",
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.95-beta.1",
39
+ "@akinon/eslint-plugin-projectzero": "2.0.95-rc.1",
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',