@akinon/next 1.99.0-snapshot-ZERO-3640-20250919140935 → 1.100.0-rc.71

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 (54) hide show
  1. package/CHANGELOG.md +1337 -51
  2. package/__tests__/next-config.test.ts +1 -10
  3. package/__tests__/redirect.test.ts +319 -0
  4. package/api/cache.ts +41 -5
  5. package/api/form.ts +84 -0
  6. package/api/image-proxy.ts +75 -0
  7. package/api/similar-product-list.ts +84 -0
  8. package/api/similar-products.ts +120 -0
  9. package/bin/pz-generate-routes.js +105 -0
  10. package/bin/pz-prebuild.js +1 -0
  11. package/bin/pz-predev.js +1 -0
  12. package/components/accordion.tsx +20 -5
  13. package/components/file-input.tsx +65 -3
  14. package/components/input.tsx +2 -0
  15. package/components/link.tsx +16 -12
  16. package/components/modal.tsx +32 -16
  17. package/components/plugin-module.tsx +32 -4
  18. package/data/client/checkout.ts +4 -2
  19. package/data/server/basket.ts +72 -0
  20. package/data/server/category.ts +48 -26
  21. package/data/server/flatpage.ts +20 -13
  22. package/data/server/form.ts +4 -1
  23. package/data/server/landingpage.ts +20 -13
  24. package/data/server/list.ts +25 -14
  25. package/data/server/menu.ts +4 -1
  26. package/data/server/product.ts +68 -40
  27. package/data/server/seo.ts +4 -1
  28. package/data/server/special-page.ts +18 -13
  29. package/data/server/widget.ts +4 -1
  30. package/data/urls.ts +6 -2
  31. package/hocs/server/with-segment-defaults.tsx +5 -2
  32. package/hooks/use-localization.ts +2 -3
  33. package/jest.config.js +7 -1
  34. package/lib/cache-handler.mjs +365 -87
  35. package/lib/cache.ts +254 -25
  36. package/middlewares/complete-gpay.ts +2 -1
  37. package/middlewares/complete-masterpass.ts +2 -1
  38. package/middlewares/default.ts +50 -13
  39. package/middlewares/locale.ts +9 -1
  40. package/middlewares/pretty-url.ts +21 -6
  41. package/middlewares/redirection-payment.ts +2 -1
  42. package/middlewares/saved-card-redirection.ts +2 -1
  43. package/middlewares/three-d-redirection.ts +2 -2
  44. package/middlewares/url-redirection.ts +8 -14
  45. package/package.json +4 -3
  46. package/plugins.d.ts +8 -5
  47. package/plugins.js +3 -1
  48. package/redux/middlewares/checkout.ts +5 -1
  49. package/types/commerce/order.ts +1 -0
  50. package/types/index.ts +35 -1
  51. package/utils/app-fetch.ts +7 -2
  52. package/utils/redirect-ignore.ts +35 -0
  53. package/utils/redirect.ts +31 -6
  54. package/with-pz-config.js +1 -5
package/lib/cache.ts CHANGED
@@ -3,6 +3,65 @@ import { RedisClientType } from 'redis';
3
3
  import Settings from 'settings';
4
4
  import { CacheOptions } from '../types';
5
5
  import logger from '../utils/log';
6
+ const CACHE_VERSION = 'v2';
7
+
8
+ const compressData = async (data: string): Promise<Uint8Array> => {
9
+ const stream = new CompressionStream('gzip');
10
+ const writer = stream.writable.getWriter();
11
+ const reader = stream.readable.getReader();
12
+
13
+ writer.write(new TextEncoder().encode(data));
14
+ writer.close();
15
+
16
+ const chunks: Uint8Array[] = [];
17
+ let done = false;
18
+
19
+ while (!done) {
20
+ const { value, done: readerDone } = await reader.read();
21
+ done = readerDone;
22
+ if (value) chunks.push(value);
23
+ }
24
+
25
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
26
+ const result = new Uint8Array(totalLength);
27
+ let offset = 0;
28
+
29
+ for (const chunk of chunks) {
30
+ result.set(chunk, offset);
31
+ offset += chunk.length;
32
+ }
33
+
34
+ return result;
35
+ };
36
+
37
+ const decompressData = async (compressed: Uint8Array): Promise<string> => {
38
+ const stream = new DecompressionStream('gzip');
39
+ const writer = stream.writable.getWriter();
40
+ const reader = stream.readable.getReader();
41
+
42
+ writer.write(compressed);
43
+ writer.close();
44
+
45
+ const chunks: Uint8Array[] = [];
46
+ let done = false;
47
+
48
+ while (!done) {
49
+ const { value, done: readerDone } = await reader.read();
50
+ done = readerDone;
51
+ if (value) chunks.push(value);
52
+ }
53
+
54
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
55
+ const result = new Uint8Array(totalLength);
56
+ let offset = 0;
57
+
58
+ for (const chunk of chunks) {
59
+ result.set(chunk, offset);
60
+ offset += chunk.length;
61
+ }
62
+
63
+ return new TextDecoder().decode(result);
64
+ };
6
65
 
7
66
  const hashCacheKey = (object?: Record<string, string>) => {
8
67
  if (!object) {
@@ -31,6 +90,8 @@ export const CacheKey = {
31
90
  `category_${pk}_${encodeURIComponent(
32
91
  JSON.stringify(searchParams)
33
92
  )}${hashCacheKey(headers)}`,
93
+ Basket: (namespace?: string) => `basket${namespace ? `_${namespace}` : ''}`,
94
+ AllBaskets: () => 'all_baskets',
34
95
  CategorySlug: (slug: string) => `category_${slug}`,
35
96
  SpecialPage: (
36
97
  pk: number,
@@ -58,8 +119,32 @@ export const CacheKey = {
58
119
  export class Cache {
59
120
  static PROXY_URL = `${process.env.NEXT_PUBLIC_URL}/api/cache`;
60
121
 
122
+ private static serializeValue(value: any): string {
123
+ return typeof value === 'object' ? JSON.stringify(value) : String(value);
124
+ }
125
+
126
+ private static validateKey(key: string): boolean {
127
+ return !(!key || key.trim() === '');
128
+ }
129
+
130
+ private static validateKeyValuePairs(keyValuePairs: Record<string, any>): {
131
+ isValid: boolean;
132
+ invalidKeys: string[];
133
+ } {
134
+ if (!keyValuePairs || Object.keys(keyValuePairs).length === 0) {
135
+ return { isValid: false, invalidKeys: [] };
136
+ }
137
+
138
+ const invalidKeys = Object.keys(keyValuePairs).filter(
139
+ (key) => !this.validateKey(key)
140
+ );
141
+ return { isValid: invalidKeys.length === 0, invalidKeys };
142
+ }
143
+
61
144
  static formatKey(key: string, locale: string) {
62
- return encodeURIComponent(`${Settings.commerceUrl}_${locale}_${key}`);
145
+ return encodeURIComponent(
146
+ `${CACHE_VERSION}_${Settings.commerceUrl}_${locale}_${key}`
147
+ );
63
148
  }
64
149
 
65
150
  static clientPool: Pool<RedisClientType> = createPool(
@@ -96,9 +181,9 @@ export class Cache {
96
181
  return await Cache.clientPool.acquire();
97
182
  }
98
183
 
99
- static async get(key: string) {
100
- let value;
101
- let client;
184
+ static async get(key: string): Promise<any> {
185
+ let value: any;
186
+ let client: RedisClientType | undefined;
102
187
 
103
188
  try {
104
189
  client = await Cache.getClient();
@@ -108,9 +193,7 @@ export class Cache {
108
193
  } else {
109
194
  value = null;
110
195
  }
111
- logger.debug('Redis get success', { key, value });
112
196
  } catch (error) {
113
- logger.error('Redis get error', { key, error });
114
197
  value = null;
115
198
  } finally {
116
199
  if (client) {
@@ -121,14 +204,13 @@ export class Cache {
121
204
  return value;
122
205
  }
123
206
 
124
- static async set(key: string, value: any, expire?: number) {
207
+ static async set(key: string, value: any, expire?: number): Promise<boolean> {
125
208
  let success = false;
126
- let client;
209
+ let client: RedisClientType | undefined;
127
210
 
128
211
  try {
129
212
  client = await Cache.getClient();
130
- const serializedValue =
131
- typeof value === 'object' ? JSON.stringify(value) : value;
213
+ const serializedValue = Cache.serializeValue(value);
132
214
 
133
215
  if (expire) {
134
216
  await client.set(key, serializedValue, { EX: expire });
@@ -137,9 +219,7 @@ export class Cache {
137
219
  }
138
220
 
139
221
  success = true;
140
- logger.debug('Redis set success', { key, value });
141
222
  } catch (error) {
142
- logger.error('Redis set error', { key, error });
143
223
  success = false;
144
224
  } finally {
145
225
  if (client) {
@@ -168,7 +248,8 @@ export class Cache {
168
248
 
169
249
  const defaultOptions: CacheOptions = {
170
250
  cache: true,
171
- expire: Settings.redis.defaultExpirationTime
251
+ expire: Settings.redis.defaultExpirationTime,
252
+ compressed: process.env.CACHE_COMPRESSION_ENABLED !== 'false'
172
253
  };
173
254
 
174
255
  const _options = Object.assign(defaultOptions, options);
@@ -178,21 +259,22 @@ export class Cache {
178
259
  _options.expire = 120;
179
260
  }
180
261
 
181
- logger.debug('Cache wrap', { key, formattedKey, _options });
182
-
183
262
  if (_options.cache) {
184
- let cachedValue;
263
+ let cachedValue: any;
185
264
 
186
265
  if (_options.useProxy) {
187
266
  const body = new URLSearchParams();
188
267
 
189
268
  body.append('key', formattedKey);
269
+ if (_options.compressed) {
270
+ body.append('compressed', 'true');
271
+ }
190
272
 
191
273
  cachedValue = await Cache.proxyRequest('POST', body);
192
- logger.debug('Cache proxy request success', { key });
193
- logger.trace('Cache proxy request', { key, cachedValue });
194
274
  } else {
195
- cachedValue = await Cache.get(formattedKey);
275
+ cachedValue = _options.compressed
276
+ ? await Cache.getCompressed(formattedKey)
277
+ : await Cache.get(formattedKey);
196
278
  }
197
279
 
198
280
  if (cachedValue) {
@@ -200,8 +282,6 @@ export class Cache {
200
282
  }
201
283
  }
202
284
 
203
- logger.debug('Redis cache miss. Setting new value...', { key });
204
-
205
285
  const data = await handler();
206
286
 
207
287
  if (data && _options.cache) {
@@ -215,14 +295,19 @@ export class Cache {
215
295
  'expire',
216
296
  String(_options?.expire ?? Settings.redis.defaultExpirationTime)
217
297
  );
298
+ if (_options.compressed) {
299
+ body.append('compressed', 'true');
300
+ }
218
301
  await Cache.proxyRequest('PUT', body);
219
-
220
- logger.debug('Cache proxy request', { key, body: body.toString() });
221
302
  } catch (error) {
222
303
  logger.error('Cache proxy error', error);
223
304
  }
224
305
  } else {
225
- await Cache.set(formattedKey, JSON.stringify(data), _options?.expire);
306
+ if (_options.compressed) {
307
+ await Cache.setCompressed(formattedKey, data, _options?.expire);
308
+ } else {
309
+ await Cache.set(formattedKey, JSON.stringify(data), _options?.expire);
310
+ }
226
311
  }
227
312
  }
228
313
 
@@ -234,7 +319,7 @@ export class Cache {
234
319
  await fetch(Cache.PROXY_URL, {
235
320
  method,
236
321
  headers: {
237
- authorization: process.env.CACHE_SECRET
322
+ authorization: process.env.CACHE_SECRET || ''
238
323
  },
239
324
  body
240
325
  })
@@ -242,4 +327,148 @@ export class Cache {
242
327
 
243
328
  return response;
244
329
  }
330
+
331
+ static async mset(
332
+ keyValuePairs: Record<string, any>,
333
+ expire?: number
334
+ ): Promise<boolean> {
335
+ const validation = Cache.validateKeyValuePairs(keyValuePairs);
336
+ if (!validation.isValid) {
337
+ if (validation.invalidKeys.length > 0) {
338
+ logger.error('Invalid keys in mset', {
339
+ invalidKeys: validation.invalidKeys
340
+ });
341
+ } else {
342
+ logger.warn('mset called with empty keyValuePairs');
343
+ }
344
+ return false;
345
+ }
346
+
347
+ let success = false;
348
+ let client: RedisClientType | undefined;
349
+
350
+ try {
351
+ client = await Cache.getClient();
352
+ const pipeline = client.multi();
353
+
354
+ Object.entries(keyValuePairs).forEach(([key, value]) => {
355
+ const serializedValue = Cache.serializeValue(value);
356
+ if (expire) {
357
+ pipeline.set(key, serializedValue, { EX: expire });
358
+ } else {
359
+ pipeline.set(key, serializedValue);
360
+ }
361
+ });
362
+
363
+ const results = await pipeline.exec();
364
+
365
+ const failures =
366
+ results?.filter((result) => result instanceof Error) || [];
367
+
368
+ if (failures.length > 0) {
369
+ success = false;
370
+ } else {
371
+ success = true;
372
+ }
373
+ } catch (error) {
374
+ success = false;
375
+ } finally {
376
+ if (client) {
377
+ await Cache.clientPool.release(client);
378
+ }
379
+ }
380
+
381
+ return success;
382
+ }
383
+
384
+ static async setCompressed(
385
+ key: string,
386
+ value: any,
387
+ expire?: number
388
+ ): Promise<boolean> {
389
+ if (!Cache.validateKey(key)) {
390
+ return false;
391
+ }
392
+
393
+ let success = false;
394
+ let client: RedisClientType | undefined;
395
+
396
+ try {
397
+ client = await Cache.getClient();
398
+ const serializedValue = Cache.serializeValue(value);
399
+
400
+ try {
401
+ const compressed = await compressData(serializedValue);
402
+ const compressedBase64 = Buffer.from(compressed).toString('base64');
403
+
404
+ if (expire) {
405
+ await client.set(key, compressedBase64, { EX: expire });
406
+ } else {
407
+ await client.set(key, compressedBase64);
408
+ }
409
+
410
+ success = true;
411
+ } catch (compressionError) {
412
+ if (expire) {
413
+ await client.set(key, serializedValue, { EX: expire });
414
+ } else {
415
+ await client.set(key, serializedValue);
416
+ }
417
+
418
+ success = true;
419
+ }
420
+ } catch (error) {
421
+ success = false;
422
+ } finally {
423
+ if (client) {
424
+ await Cache.clientPool.release(client);
425
+ }
426
+ }
427
+
428
+ return success;
429
+ }
430
+
431
+ static async getCompressed(key: string): Promise<unknown> {
432
+ if (!Cache.validateKey(key)) {
433
+ return null;
434
+ }
435
+
436
+ let value: unknown;
437
+ let client: RedisClientType | undefined;
438
+
439
+ try {
440
+ client = await Cache.getClient();
441
+ const compressed = await client.get(key);
442
+
443
+ if (compressed) {
444
+ const compressedBuffer = Buffer.from(compressed, 'base64');
445
+
446
+ try {
447
+ const decompressedString = await decompressData(
448
+ new Uint8Array(compressedBuffer)
449
+ );
450
+ value = JSON.parse(decompressedString);
451
+ return value;
452
+ } catch (decompressionError) {
453
+ try {
454
+ const rawString = compressed;
455
+ const parsedData = JSON.parse(rawString);
456
+ return parsedData;
457
+ } catch (jsonError) {
458
+ return null;
459
+ }
460
+ }
461
+ } else {
462
+ value = null;
463
+ }
464
+ } catch (error) {
465
+ value = null;
466
+ } finally {
467
+ if (client) {
468
+ await Cache.clientPool.release(client);
469
+ }
470
+ }
471
+
472
+ return value;
473
+ }
245
474
  }
@@ -148,7 +148,8 @@ const withCompleteGpay =
148
148
  logger.info('Redirecting to order success page', {
149
149
  middleware: 'complete-gpay',
150
150
  redirectUrlWithLocale,
151
- ip
151
+ ip,
152
+ setCookie: request.headers.get('set-cookie')
152
153
  });
153
154
 
154
155
  // Using POST method while redirecting causes an error,
@@ -149,7 +149,8 @@ const withCompleteMasterpass =
149
149
  logger.info('Redirecting to order success page', {
150
150
  middleware: 'complete-masterpass',
151
151
  redirectUrlWithLocale,
152
- ip
152
+ ip,
153
+ setCookie: request.headers.get('set-cookie')
153
154
  });
154
155
 
155
156
  // Using POST method while redirecting causes an error,
@@ -302,19 +302,6 @@ const withPzDefault =
302
302
  )}`;
303
303
  }
304
304
 
305
- if (
306
- !req.middlewareParams.found &&
307
- Settings.customNotFoundEnabled
308
- ) {
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
305
  Settings.rewrites.forEach((rewrite) => {
319
306
  url.pathname = url.pathname.replace(
320
307
  rewrite.source,
@@ -352,6 +339,24 @@ const withPzDefault =
352
339
  middlewareResult = NextResponse.rewrite(url);
353
340
  }
354
341
 
342
+ if (
343
+ !req.middlewareParams.found &&
344
+ Settings.customNotFoundEnabled
345
+ ) {
346
+ const pathSegments = url.pathname
347
+ .replace(/\/+$/, '')
348
+ .split('/');
349
+ if (pathSegments.length >= 3) {
350
+ url.pathname = `/${pathSegments[1]}/${pathSegments[2]}/pz-not-found`;
351
+ } else {
352
+ url.pathname = '/pz-not-found';
353
+ }
354
+
355
+ middlewareResult = NextResponse.rewrite(url, {
356
+ status: 404
357
+ });
358
+ }
359
+
355
360
  const { localeUrlStrategy } =
356
361
  Settings.localization;
357
362
 
@@ -401,6 +406,38 @@ const withPzDefault =
401
406
  }
402
407
  );
403
408
 
409
+ if (
410
+ !url.pathname.startsWith(
411
+ `/${currency}/orders`
412
+ )
413
+ ) {
414
+ const currentCookieLocale =
415
+ req.cookies.get('pz-locale')?.value;
416
+
417
+ const urlHasExplicitLocale =
418
+ url.pathname.match(urlLocaleMatcherRegex);
419
+ const shouldUpdateCookie =
420
+ !currentCookieLocale ||
421
+ urlHasExplicitLocale;
422
+
423
+ if (shouldUpdateCookie) {
424
+ middlewareResult.cookies.set(
425
+ 'pz-locale',
426
+ locale?.length > 0
427
+ ? locale
428
+ : defaultLocaleValue,
429
+ {
430
+ domain: rootHostname,
431
+ sameSite: 'none',
432
+ secure: true,
433
+ expires: new Date(
434
+ Date.now() + 1000 * 60 * 60 * 24 * 7
435
+ ) // 7 days
436
+ }
437
+ );
438
+ }
439
+ }
440
+
404
441
  if (
405
442
  req.cookies.get('pz-locale') &&
406
443
  req.cookies.get('pz-locale').value !== locale
@@ -23,7 +23,15 @@ const getMatchedLocale = (pathname: string, req: PzNextRequest) => {
23
23
  );
24
24
 
25
25
  if (subDomainLocaleMatched && subDomainLocaleMatched[0]) {
26
- matchedLocale = subDomainLocaleMatched[0].slice(1);
26
+ const subdomainLocale = subDomainLocaleMatched[0].slice(1);
27
+
28
+ const isValidSubdomainLocale = settings.localization.locales.find(
29
+ (l) => l.value === subdomainLocale
30
+ );
31
+
32
+ if (isValidSubdomainLocale) {
33
+ matchedLocale = subdomainLocale;
34
+ }
27
35
  }
28
36
  }
29
37
  }
@@ -1,17 +1,33 @@
1
1
  import { Cache, CacheKey } from '../lib/cache';
2
- import { NextFetchEvent, NextMiddleware, NextRequest } from 'next/server';
3
- import { ROUTES } from 'routes';
2
+ import { NextFetchEvent, NextMiddleware } from 'next/server';
4
3
  import { URLS } from '../data/urls';
5
4
  import Settings from 'settings';
6
5
  import { urlLocaleMatcherRegex } from '../utils';
7
6
  import { PzNextRequest } from '.';
8
7
  import logger from '../utils/log';
8
+ import { ROUTES } from 'routes';
9
9
 
10
10
  type PrettyUrlResult = {
11
11
  matched: boolean;
12
12
  path?: string;
13
13
  };
14
14
 
15
+ let APP_ROUTES: string[] = [];
16
+
17
+ const legacyRoutes = Object.values(ROUTES);
18
+
19
+ try {
20
+ const generatedRoutes = require('routes/generated-routes');
21
+ const allRoutes = [...legacyRoutes, ...(generatedRoutes || [])];
22
+ APP_ROUTES = Array.from(new Set(allRoutes));
23
+ logger.debug('Loaded merged routes (legacy + generated)', {
24
+ count: APP_ROUTES.length
25
+ });
26
+ } catch (error) {
27
+ APP_ROUTES = legacyRoutes;
28
+ logger.debug('Loaded only legacy routes', { count: APP_ROUTES.length });
29
+ }
30
+
15
31
  const resolvePrettyUrlHandler =
16
32
  (pathname: string, ip: string | null) => async () => {
17
33
  let results = <{ old_path: string }[]>[];
@@ -53,7 +69,8 @@ const resolvePrettyUrl = async (
53
69
  locale,
54
70
  resolvePrettyUrlHandler(pathname, ip),
55
71
  {
56
- useProxy: true
72
+ useProxy: true,
73
+ compressed: true
57
74
  }
58
75
  );
59
76
  };
@@ -73,9 +90,7 @@ const withPrettyUrl =
73
90
  const isValidPrettyUrlPath = (pathname: string) => {
74
91
  return (
75
92
  new RegExp(/^\/[a-zA-Z0-9/]+(?:-[a-zA-Z0-9/]+)*$/).test(pathname) &&
76
- !Object.entries(ROUTES).find(([, value]) =>
77
- new RegExp(`^${value}$`).test(pathname)
78
- )
93
+ !APP_ROUTES.some((route) => new RegExp(`^${route}$`).test(pathname))
79
94
  );
80
95
  };
81
96
  const ip = req.headers.get('x-forwarded-for') ?? '';
@@ -149,7 +149,8 @@ const withRedirectionPayment =
149
149
  logger.info('Redirecting to order success page', {
150
150
  middleware: 'redirection-payment',
151
151
  redirectUrlWithLocale,
152
- ip
152
+ ip,
153
+ setCookie: request.headers.get('set-cookie')
153
154
  });
154
155
 
155
156
  // Using POST method while redirecting causes an error,
@@ -149,7 +149,8 @@ const withSavedCardRedirection =
149
149
  logger.info('Redirecting to order success page', {
150
150
  middleware: 'saved-card-redirection',
151
151
  redirectUrlWithLocale,
152
- ip
152
+ ip,
153
+ setCookie: request.headers.get('set-cookie')
153
154
  });
154
155
 
155
156
  // Using POST method while redirecting causes an error,
@@ -4,7 +4,6 @@ import { Buffer } from 'buffer';
4
4
  import logger from '../utils/log';
5
5
  import { getUrlPathWithLocale } from '../utils/localization';
6
6
  import { PzNextRequest } from '.';
7
- import { ServerVariables } from '../utils/server-variables';
8
7
 
9
8
  const streamToString = async (stream: ReadableStream<Uint8Array> | null) => {
10
9
  if (stream) {
@@ -149,7 +148,8 @@ const withThreeDRedirection =
149
148
  logger.info('Redirecting to order success page', {
150
149
  middleware: 'three-d-redirection',
151
150
  redirectUrlWithLocale,
152
- ip
151
+ ip,
152
+ setCookie: request.headers.get('set-cookie')
153
153
  });
154
154
 
155
155
  // Using POST method while redirecting causes an error,
@@ -4,6 +4,7 @@ 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';
7
8
  import { ROUTES } from 'routes';
8
9
 
9
10
  // This middleware is used to handle url redirections set in Omnitron
@@ -60,20 +61,13 @@ const withUrlRedirection =
60
61
 
61
62
  const setCookies = request.headers.getSetCookie();
62
63
 
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
- }
64
+ if (
65
+ shouldIgnoreRedirect(
66
+ url.pathname,
67
+ req.middlewareParams.rewrites.locale
68
+ )
69
+ ) {
70
+ return middleware(req, event);
77
71
  }
78
72
 
79
73
  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.99.0-snapshot-ZERO-3640-20250919140935",
4
+ "version": "1.100.0-rc.71",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -17,7 +17,8 @@
17
17
  "test": "jest"
18
18
  },
19
19
  "dependencies": {
20
- "@neshca/cache-handler": "1.5.1",
20
+ "@mongodb-js/zstd": "^2.0.1",
21
+ "@neshca/cache-handler": "1.9.0",
21
22
  "@opentelemetry/exporter-trace-otlp-http": "0.46.0",
22
23
  "@opentelemetry/resources": "1.19.0",
23
24
  "@opentelemetry/sdk-node": "0.46.0",
@@ -34,7 +35,7 @@
34
35
  "set-cookie-parser": "2.6.0"
35
36
  },
36
37
  "devDependencies": {
37
- "@akinon/eslint-plugin-projectzero": "1.99.0-snapshot-ZERO-3640-20250919140935",
38
+ "@akinon/eslint-plugin-projectzero": "1.100.0-rc.71",
38
39
  "@babel/core": "7.26.10",
39
40
  "@babel/preset-env": "7.26.9",
40
41
  "@babel/preset-typescript": "7.27.0",
package/plugins.d.ts CHANGED
@@ -30,11 +30,14 @@ declare module '@akinon/pz-saved-card' {
30
30
  export const SavedCardOption: any;
31
31
  }
32
32
 
33
- declare module '@akinon/pz-iyzico-saved-card' {
34
- export const iyzicoSavedCardReducer: any;
35
- export const iyzicoSavedCardMiddleware: any;
36
- }
37
-
38
33
  declare module '@akinon/pz-apple-pay' {}
39
34
 
40
35
  declare module '@akinon/pz-flow-payment' {}
36
+
37
+ declare module '@akinon/pz-similar-products' {
38
+ export const SimilarProductsModal: any;
39
+ export const SimilarProductsFilterSidebar: any;
40
+ export const SimilarProductsResultsGrid: any;
41
+ export const SimilarProductsPlugin: any;
42
+ export const SimilarProductsButtonPlugin: any;
43
+ }