@akinon/next 1.92.0-rc.9 → 1.92.0-snapshot-ZERO-3449-20250618101111

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +33 -1180
  2. package/api/similar-product-list.ts +63 -0
  3. package/api/similar-products.ts +109 -0
  4. package/components/accordion.tsx +5 -20
  5. package/components/file-input.tsx +3 -65
  6. package/components/input.tsx +0 -2
  7. package/components/link.tsx +12 -16
  8. package/components/modal.tsx +16 -32
  9. package/components/plugin-module.tsx +3 -13
  10. package/components/selected-payment-option-view.tsx +0 -11
  11. package/data/client/similar-products.ts +122 -0
  12. package/data/urls.ts +5 -1
  13. package/hocs/server/with-segment-defaults.tsx +2 -5
  14. package/hooks/index.ts +2 -0
  15. package/hooks/use-image-cropper.ts +160 -0
  16. package/hooks/use-similar-products.ts +720 -0
  17. package/instrumentation/node.ts +13 -15
  18. package/lib/cache.ts +0 -2
  19. package/middlewares/complete-gpay.ts +1 -2
  20. package/middlewares/complete-masterpass.ts +1 -2
  21. package/middlewares/default.ts +184 -196
  22. package/middlewares/index.ts +1 -3
  23. package/middlewares/redirection-payment.ts +1 -2
  24. package/middlewares/saved-card-redirection.ts +1 -2
  25. package/middlewares/three-d-redirection.ts +1 -2
  26. package/middlewares/url-redirection.ts +14 -8
  27. package/package.json +3 -3
  28. package/plugins.d.ts +0 -2
  29. package/plugins.js +1 -3
  30. package/redux/middlewares/checkout.ts +2 -15
  31. package/redux/reducers/checkout.ts +1 -9
  32. package/sentry/index.ts +17 -54
  33. package/types/commerce/order.ts +0 -1
  34. package/types/index.ts +73 -26
  35. package/utils/app-fetch.ts +2 -2
  36. package/utils/image-validation.ts +303 -0
  37. package/utils/redirect.ts +3 -5
  38. package/with-pz-config.js +5 -1
  39. package/data/server/basket.ts +0 -72
  40. package/hooks/use-loyalty-availability.ts +0 -21
  41. package/middlewares/wallet-complete-redirection.ts +0 -179
  42. package/utils/redirect-ignore.ts +0 -35
@@ -4,19 +4,17 @@ import { Resource } from '@opentelemetry/resources';
4
4
  import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
5
5
  import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
6
6
 
7
- if (process.env.NODE_ENV === 'development') {
8
- const sdk = new NodeSDK({
9
- resource: new Resource({
10
- [SemanticResourceAttributes.SERVICE_NAME]: 'pz-next-app'
11
- }),
12
- spanProcessor: new SimpleSpanProcessor(
13
- new OTLPTraceExporter({
14
- url: `${
15
- process.env.PZ_DASHBOARD_URL ?? 'http://localhost:3005'
16
- }/api/traces`
17
- })
18
- )
19
- });
7
+ const sdk = new NodeSDK({
8
+ resource: new Resource({
9
+ [SemanticResourceAttributes.SERVICE_NAME]: 'pz-next-app'
10
+ }),
11
+ spanProcessor: new SimpleSpanProcessor(
12
+ new OTLPTraceExporter({
13
+ url: `${
14
+ process.env.PZ_DASHBOARD_URL ?? 'http://localhost:3005'
15
+ }/api/traces`
16
+ })
17
+ )
18
+ });
20
19
 
21
- sdk.start();
22
- }
20
+ sdk.start();
package/lib/cache.ts CHANGED
@@ -31,8 +31,6 @@ export const CacheKey = {
31
31
  `category_${pk}_${encodeURIComponent(
32
32
  JSON.stringify(searchParams)
33
33
  )}${hashCacheKey(headers)}`,
34
- Basket: (namespace?: string) => `basket${namespace ? `_${namespace}` : ''}`,
35
- AllBaskets: () => 'all_baskets',
36
34
  CategorySlug: (slug: string) => `category_${slug}`,
37
35
  SpecialPage: (
38
36
  pk: number,
@@ -145,8 +145,7 @@ const withCompleteGpay =
145
145
  logger.info('Redirecting to order success page', {
146
146
  middleware: 'complete-gpay',
147
147
  redirectUrlWithLocale,
148
- ip,
149
- setCookie: request.headers.get('set-cookie')
148
+ ip
150
149
  });
151
150
 
152
151
  // Using POST method while redirecting causes an error,
@@ -145,8 +145,7 @@ const withCompleteMasterpass =
145
145
  logger.info('Redirecting to order success page', {
146
146
  middleware: 'complete-masterpass',
147
147
  redirectUrlWithLocale,
148
- ip,
149
- setCookie: request.headers.get('set-cookie')
148
+ ip
150
149
  });
151
150
 
152
151
  // Using POST method while redirecting causes an error,
@@ -11,8 +11,7 @@ import {
11
11
  withRedirectionPayment,
12
12
  withSavedCardRedirection,
13
13
  withThreeDRedirection,
14
- withUrlRedirection,
15
- withWalletCompleteRedirection
14
+ withUrlRedirection
16
15
  } from '.';
17
16
  import { urlLocaleMatcherRegex } from '../utils';
18
17
  import withCurrency from './currency';
@@ -229,168 +228,144 @@ const withPzDefault =
229
228
  withCompleteGpay(
230
229
  withCompleteMasterpass(
231
230
  withSavedCardRedirection(
232
- withWalletCompleteRedirection(
233
- async (
234
- req: PzNextRequest,
235
- event: NextFetchEvent
236
- ) => {
237
- let middlewareResult: NextResponse | void =
238
- NextResponse.next();
239
-
240
- try {
241
- const { locale, prettyUrl, currency } =
242
- req.middlewareParams.rewrites;
243
- const { defaultLocaleValue } =
244
- Settings.localization;
245
- const url = req.nextUrl.clone();
246
- const pathnameWithoutLocale =
247
- url.pathname.replace(
248
- urlLocaleMatcherRegex,
231
+ async (req: PzNextRequest, event: NextFetchEvent) => {
232
+ let middlewareResult: NextResponse | void =
233
+ NextResponse.next();
234
+
235
+ try {
236
+ const { locale, prettyUrl, currency } =
237
+ req.middlewareParams.rewrites;
238
+ const { defaultLocaleValue } =
239
+ Settings.localization;
240
+ const url = req.nextUrl.clone();
241
+ const pathnameWithoutLocale =
242
+ url.pathname.replace(urlLocaleMatcherRegex, '');
243
+
244
+ middlewareResult = (await middleware(
245
+ req,
246
+ event
247
+ )) as NextResponse | void;
248
+
249
+ let customRewriteUrlDiff = '';
250
+
251
+ if (
252
+ middlewareResult instanceof NextResponse &&
253
+ middlewareResult.headers.get(
254
+ 'pz-override-response'
255
+ ) &&
256
+ middlewareResult.headers.get(
257
+ 'x-middleware-rewrite'
258
+ )
259
+ ) {
260
+ const rewriteUrl = new URL(
261
+ middlewareResult.headers.get(
262
+ 'x-middleware-rewrite'
263
+ )
264
+ );
265
+ const originalUrl = new URL(req.url);
266
+ customRewriteUrlDiff =
267
+ rewriteUrl.pathname.replace(
268
+ originalUrl.pathname,
249
269
  ''
250
270
  );
271
+ }
251
272
 
252
- middlewareResult = (await middleware(
253
- req,
254
- event
255
- )) as NextResponse | void;
273
+ url.basePath = `/${commerceUrl}`;
274
+ url.pathname = `/${
275
+ locale.length ? `${locale}/` : ''
276
+ }${currency}/${customRewriteUrlDiff}${
277
+ prettyUrl ?? pathnameWithoutLocale
278
+ }`.replace(/\/+/g, '/');
279
+
280
+ if (
281
+ Settings.usePrettyUrlRoute &&
282
+ url.searchParams.toString().length > 0 &&
283
+ !Object.entries(ROUTES).find(([, value]) =>
284
+ new RegExp(`^${value}/?$`).test(
285
+ pathnameWithoutLocale
286
+ )
287
+ )
288
+ ) {
289
+ url.pathname =
290
+ url.pathname +
291
+ (/\/$/.test(url.pathname) ? '' : '/') +
292
+ `searchparams|${encodeURIComponent(
293
+ url.searchParams.toString()
294
+ )}`;
295
+ }
256
296
 
257
- let customRewriteUrlDiff = '';
297
+ if (
298
+ !req.middlewareParams.found &&
299
+ Settings.customNotFoundEnabled
300
+ ) {
301
+ const pathname = url.pathname
302
+ .replace(/\/+$/, '')
303
+ .split('/');
304
+ url.pathname = url.pathname.replace(
305
+ pathname.pop(),
306
+ 'pz-not-found'
307
+ );
308
+ }
309
+
310
+ Settings.rewrites.forEach((rewrite) => {
311
+ url.pathname = url.pathname.replace(
312
+ rewrite.source,
313
+ rewrite.destination
314
+ );
315
+ });
258
316
 
317
+ // if middleware.ts has a return value for current url
318
+ if (middlewareResult instanceof NextResponse) {
319
+ // pz-override-response header is used to prevent 404 page for custom responses.
259
320
  if (
260
- middlewareResult instanceof NextResponse &&
261
321
  middlewareResult.headers.get(
262
322
  'pz-override-response'
263
- ) &&
264
- middlewareResult.headers.get(
265
- 'x-middleware-rewrite'
266
- )
323
+ ) !== 'true'
267
324
  ) {
268
- const rewriteUrl = new URL(
269
- middlewareResult.headers.get(
270
- 'x-middleware-rewrite'
271
- )
325
+ middlewareResult.headers.set(
326
+ 'x-middleware-rewrite',
327
+ url.href
272
328
  );
273
- const originalUrl = new URL(req.url);
274
- customRewriteUrlDiff =
275
- rewriteUrl.pathname.replace(
276
- originalUrl.pathname,
277
- ''
278
- );
279
- }
280
-
281
- url.basePath = `/${commerceUrl}`;
282
- url.pathname = `/${
283
- locale.length ? `${locale}/` : ''
284
- }${currency}/${customRewriteUrlDiff}${
285
- prettyUrl ?? pathnameWithoutLocale
286
- }`.replace(/\/+/g, '/');
287
-
288
- if (
289
- Settings.usePrettyUrlRoute &&
290
- url.searchParams.toString().length > 0 &&
291
- !Object.entries(ROUTES).find(([, value]) =>
292
- new RegExp(`^${value}/?$`).test(
293
- pathnameWithoutLocale
294
- )
295
- )
296
- ) {
297
- url.pathname =
298
- url.pathname +
299
- (/\/$/.test(url.pathname) ? '' : '/') +
300
- `searchparams|${encodeURIComponent(
301
- url.searchParams.toString()
302
- )}`;
303
- }
304
-
305
- if (
306
- !req.middlewareParams.found &&
307
- Settings.customNotFoundEnabled
329
+ } else if (
330
+ middlewareResult.headers.get(
331
+ 'x-middleware-rewrite'
332
+ ) &&
333
+ middlewareResult.headers.get(
334
+ 'pz-override-response'
335
+ ) === 'true'
308
336
  ) {
309
- const pathname = url.pathname
310
- .replace(/\/+$/, '')
311
- .split('/');
312
- url.pathname = url.pathname.replace(
313
- pathname.pop(),
314
- 'pz-not-found'
315
- );
316
- }
317
-
318
- Settings.rewrites.forEach((rewrite) => {
319
- url.pathname = url.pathname.replace(
320
- rewrite.source,
321
- rewrite.destination
322
- );
323
- });
324
-
325
- // if middleware.ts has a return value for current url
326
- if (middlewareResult instanceof NextResponse) {
327
- // pz-override-response header is used to prevent 404 page for custom responses.
328
- if (
329
- middlewareResult.headers.get(
330
- 'pz-override-response'
331
- ) !== 'true'
332
- ) {
333
- middlewareResult.headers.set(
334
- 'x-middleware-rewrite',
335
- url.href
336
- );
337
- } else if (
338
- middlewareResult.headers.get(
339
- 'x-middleware-rewrite'
340
- ) &&
341
- middlewareResult.headers.get(
342
- 'pz-override-response'
343
- ) === 'true'
344
- ) {
345
- middlewareResult =
346
- NextResponse.rewrite(url);
347
- }
348
- } else {
349
- // if middleware.ts doesn't have a return value.
350
- // e.g. NextResponse.next() doesn't exist in middleware.ts
351
-
352
337
  middlewareResult = NextResponse.rewrite(url);
353
338
  }
339
+ } else {
340
+ // if middleware.ts doesn't have a return value.
341
+ // e.g. NextResponse.next() doesn't exist in middleware.ts
354
342
 
355
- const { localeUrlStrategy } =
356
- Settings.localization;
357
-
358
- const fallbackHost =
359
- req.headers.get('x-forwarded-host') ||
360
- req.headers.get('host');
361
- const hostname =
362
- process.env.NEXT_PUBLIC_URL ||
363
- `https://${fallbackHost}`;
364
- const rootHostname =
365
- localeUrlStrategy ===
366
- LocaleUrlStrategy.Subdomain
367
- ? getRootHostname(hostname)
368
- : null;
369
-
370
- if (
371
- !url.pathname.startsWith(
372
- `/${currency}/orders`
373
- )
374
- ) {
375
- middlewareResult.cookies.set(
376
- 'pz-locale',
377
- locale?.length > 0
378
- ? locale
379
- : defaultLocaleValue,
380
- {
381
- domain: rootHostname,
382
- sameSite: 'none',
383
- secure: true,
384
- expires: new Date(
385
- Date.now() + 1000 * 60 * 60 * 24 * 7
386
- ) // 7 days
387
- }
388
- );
389
- }
343
+ middlewareResult = NextResponse.rewrite(url);
344
+ }
390
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
+
361
+ if (
362
+ !url.pathname.startsWith(`/${currency}/orders`)
363
+ ) {
391
364
  middlewareResult.cookies.set(
392
- 'pz-currency',
393
- currency,
365
+ 'pz-locale',
366
+ locale?.length > 0
367
+ ? locale
368
+ : defaultLocaleValue,
394
369
  {
395
370
  domain: rootHostname,
396
371
  sameSite: 'none',
@@ -400,69 +375,82 @@ const withPzDefault =
400
375
  ) // 7 days
401
376
  }
402
377
  );
378
+ }
403
379
 
404
- if (
405
- req.cookies.get('pz-locale') &&
406
- req.cookies.get('pz-locale').value !== locale
407
- ) {
408
- logger.debug('Locale changed', {
409
- locale,
410
- oldLocale:
411
- req.cookies.get('pz-locale')?.value,
412
- ip
413
- });
380
+ middlewareResult.cookies.set(
381
+ 'pz-currency',
382
+ currency,
383
+ {
384
+ domain: rootHostname,
385
+ sameSite: 'none',
386
+ secure: true,
387
+ expires: new Date(
388
+ Date.now() + 1000 * 60 * 60 * 24 * 7
389
+ ) // 7 days
414
390
  }
391
+ );
392
+
393
+ if (
394
+ req.cookies.get('pz-locale') &&
395
+ req.cookies.get('pz-locale').value !== locale
396
+ ) {
397
+ logger.debug('Locale changed', {
398
+ locale,
399
+ oldLocale:
400
+ req.cookies.get('pz-locale')?.value,
401
+ ip
402
+ });
403
+ }
404
+
405
+ middlewareResult.headers.set(
406
+ 'pz-url',
407
+ req.nextUrl.toString()
408
+ );
409
+
410
+ if (req.cookies.get('pz-set-currency')) {
411
+ middlewareResult.cookies.delete(
412
+ 'pz-set-currency'
413
+ );
414
+ }
415
415
 
416
+ if (process.env.ACC_APP_VERSION) {
416
417
  middlewareResult.headers.set(
417
- 'pz-url',
418
- req.nextUrl.toString()
418
+ 'acc-app-version',
419
+ process.env.ACC_APP_VERSION
419
420
  );
421
+ }
420
422
 
421
- if (req.cookies.get('pz-set-currency')) {
422
- middlewareResult.cookies.delete(
423
- 'pz-set-currency'
424
- );
425
- }
423
+ // Set CSRF token if not set
424
+ try {
425
+ const url = `${Settings.commerceUrl}${user.csrfToken}`;
426
426
 
427
- if (process.env.ACC_APP_VERSION) {
428
- middlewareResult.headers.set(
429
- 'acc-app-version',
430
- process.env.ACC_APP_VERSION
427
+ if (!req.cookies.get('csrftoken')) {
428
+ const { csrf_token } = await (
429
+ await fetch(url)
430
+ ).json();
431
+ middlewareResult.cookies.set(
432
+ 'csrftoken',
433
+ csrf_token,
434
+ {
435
+ domain: rootHostname
436
+ }
431
437
  );
432
438
  }
433
-
434
- // Set CSRF token if not set
435
- try {
436
- const url = `${Settings.commerceUrl}${user.csrfToken}`;
437
-
438
- if (!req.cookies.get('csrftoken')) {
439
- const { csrf_token } = await (
440
- await fetch(url)
441
- ).json();
442
- middlewareResult.cookies.set(
443
- 'csrftoken',
444
- csrf_token,
445
- {
446
- domain: rootHostname
447
- }
448
- );
449
- }
450
- } catch (error) {
451
- logger.error('CSRF Error', {
452
- error,
453
- ip
454
- });
455
- }
456
439
  } catch (error) {
457
- logger.error('withPzDefault Error', {
440
+ logger.error('CSRF Error', {
458
441
  error,
459
442
  ip
460
443
  });
461
444
  }
462
-
463
- return middlewareResult;
445
+ } catch (error) {
446
+ logger.error('withPzDefault Error', {
447
+ error,
448
+ ip
449
+ });
464
450
  }
465
- )
451
+
452
+ return middlewareResult;
453
+ }
466
454
  )
467
455
  )
468
456
  )
@@ -9,7 +9,6 @@ import withCompleteGpay from './complete-gpay';
9
9
  import withCompleteMasterpass from './complete-masterpass';
10
10
  import withCheckoutProvider from './checkout-provider';
11
11
  import withSavedCardRedirection from './saved-card-redirection';
12
- import withWalletCompleteRedirection from './wallet-complete-redirection';
13
12
  import { NextRequest } from 'next/server';
14
13
 
15
14
  export {
@@ -23,8 +22,7 @@ export {
23
22
  withCompleteGpay,
24
23
  withCompleteMasterpass,
25
24
  withCheckoutProvider,
26
- withSavedCardRedirection,
27
- withWalletCompleteRedirection
25
+ withSavedCardRedirection
28
26
  };
29
27
 
30
28
  export interface PzNextRequest extends NextRequest {
@@ -146,8 +146,7 @@ const withRedirectionPayment =
146
146
  logger.info('Redirecting to order success page', {
147
147
  middleware: 'redirection-payment',
148
148
  redirectUrlWithLocale,
149
- ip,
150
- setCookie: request.headers.get('set-cookie')
149
+ ip
151
150
  });
152
151
 
153
152
  // Using POST method while redirecting causes an error,
@@ -145,8 +145,7 @@ const withSavedCardRedirection =
145
145
  logger.info('Redirecting to order success page', {
146
146
  middleware: 'saved-card-redirection',
147
147
  redirectUrlWithLocale,
148
- ip,
149
- setCookie: request.headers.get('set-cookie')
148
+ ip
150
149
  });
151
150
 
152
151
  // Using POST method while redirecting causes an error,
@@ -145,8 +145,7 @@ const withThreeDRedirection =
145
145
  logger.info('Redirecting to order success page', {
146
146
  middleware: 'three-d-redirection',
147
147
  redirectUrlWithLocale,
148
- ip,
149
- setCookie: request.headers.get('set-cookie')
148
+ ip
150
149
  });
151
150
 
152
151
  // Using POST method while redirecting causes an error,
@@ -4,7 +4,6 @@ import { PzNextRequest } from '.';
4
4
  import logger from '../utils/log';
5
5
  import { urlLocaleMatcherRegex } from '../utils';
6
6
  import { getUrlPathWithLocale } from '../utils/localization';
7
- import { shouldIgnoreRedirect } from '../utils/redirect-ignore';
8
7
  import { ROUTES } from 'routes';
9
8
 
10
9
  // This middleware is used to handle url redirections set in Omnitron
@@ -61,13 +60,20 @@ const withUrlRedirection =
61
60
 
62
61
  const setCookies = request.headers.getSetCookie();
63
62
 
64
- if (
65
- shouldIgnoreRedirect(
66
- url.pathname,
67
- req.middlewareParams.rewrites.locale
68
- )
69
- ) {
70
- return middleware(req, event);
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
+ }
71
77
  }
72
78
 
73
79
  const response = NextResponse.redirect(redirectUrl.toString(), {
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.92.0-rc.9",
4
+ "version": "1.92.0-snapshot-ZERO-3449-20250618101111",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -17,13 +17,13 @@
17
17
  "test": "jest"
18
18
  },
19
19
  "dependencies": {
20
+ "@neshca/cache-handler": "1.5.1",
20
21
  "@opentelemetry/exporter-trace-otlp-http": "0.46.0",
21
22
  "@opentelemetry/resources": "1.19.0",
22
23
  "@opentelemetry/sdk-node": "0.46.0",
23
24
  "@opentelemetry/sdk-trace-node": "1.19.0",
24
25
  "@opentelemetry/semantic-conventions": "1.19.0",
25
26
  "@reduxjs/toolkit": "1.9.7",
26
- "@neshca/cache-handler": "1.9.0",
27
27
  "@sentry/nextjs": "9.5.0",
28
28
  "cross-spawn": "7.0.3",
29
29
  "generic-pool": "3.9.0",
@@ -34,7 +34,7 @@
34
34
  "set-cookie-parser": "2.6.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@akinon/eslint-plugin-projectzero": "1.92.0-rc.9",
37
+ "@akinon/eslint-plugin-projectzero": "1.92.0-snapshot-ZERO-3449-20250618101111",
38
38
  "@babel/core": "7.26.10",
39
39
  "@babel/preset-env": "7.26.9",
40
40
  "@babel/preset-typescript": "7.27.0",
package/plugins.d.ts CHANGED
@@ -36,5 +36,3 @@ declare module '@akinon/pz-iyzico-saved-card' {
36
36
  }
37
37
 
38
38
  declare module '@akinon/pz-apple-pay' {}
39
-
40
- declare module '@akinon/pz-flow-payment' {}
package/plugins.js CHANGED
@@ -15,7 +15,5 @@ module.exports = [
15
15
  'pz-saved-card',
16
16
  'pz-tabby-extension',
17
17
  'pz-apple-pay',
18
- 'pz-tamara-extension',
19
- 'pz-hepsipay',
20
- 'pz-flow-payment'
18
+ 'pz-tamara-extension'
21
19
  ];