@akinon/next 1.96.0-rc.57 → 1.96.0-snapshot-ZERO-35861-20250908151109

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 (49) hide show
  1. package/CHANGELOG.md +41 -1246
  2. package/__tests__/next-config.test.ts +10 -1
  3. package/api/cache.ts +39 -5
  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 -30
  10. package/data/client/checkout.ts +4 -5
  11. package/data/server/category.ts +32 -50
  12. package/data/server/flatpage.ts +16 -17
  13. package/data/server/form.ts +4 -1
  14. package/data/server/landingpage.ts +12 -16
  15. package/data/server/list.ts +15 -24
  16. package/data/server/menu.ts +5 -2
  17. package/data/server/product.ts +41 -67
  18. package/data/server/special-page.ts +12 -16
  19. package/data/server/widget.ts +4 -1
  20. package/data/urls.ts +1 -5
  21. package/hocs/server/with-segment-defaults.tsx +2 -5
  22. package/hooks/use-localization.ts +3 -2
  23. package/jest.config.js +1 -7
  24. package/lib/cache-handler.mjs +365 -87
  25. package/lib/cache.ts +252 -25
  26. package/middlewares/complete-gpay.ts +1 -2
  27. package/middlewares/complete-masterpass.ts +1 -2
  28. package/middlewares/default.ts +13 -50
  29. package/middlewares/locale.ts +1 -9
  30. package/middlewares/pretty-url.ts +2 -1
  31. package/middlewares/redirection-payment.ts +1 -2
  32. package/middlewares/saved-card-redirection.ts +1 -2
  33. package/middlewares/three-d-redirection.ts +1 -2
  34. package/middlewares/url-redirection.ts +14 -8
  35. package/package.json +4 -3
  36. package/plugins.d.ts +0 -8
  37. package/plugins.js +1 -3
  38. package/redux/middlewares/checkout.ts +1 -5
  39. package/types/commerce/order.ts +0 -1
  40. package/types/index.ts +2 -34
  41. package/utils/app-fetch.ts +2 -7
  42. package/utils/redirect.ts +6 -31
  43. package/with-pz-config.js +5 -1
  44. package/__tests__/redirect.test.ts +0 -319
  45. package/api/image-proxy.ts +0 -75
  46. package/api/similar-product-list.ts +0 -84
  47. package/api/similar-products.ts +0 -120
  48. package/data/server/basket.ts +0 -72
  49. package/utils/redirect-ignore.ts +0 -35
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) {
@@ -60,8 +119,32 @@ export const CacheKey = {
60
119
  export class Cache {
61
120
  static PROXY_URL = `${process.env.NEXT_PUBLIC_URL}/api/cache`;
62
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
+
63
144
  static formatKey(key: string, locale: string) {
64
- return encodeURIComponent(`${Settings.commerceUrl}_${locale}_${key}`);
145
+ return encodeURIComponent(
146
+ `${CACHE_VERSION}_${Settings.commerceUrl}_${locale}_${key}`
147
+ );
65
148
  }
66
149
 
67
150
  static clientPool: Pool<RedisClientType> = createPool(
@@ -98,9 +181,9 @@ export class Cache {
98
181
  return await Cache.clientPool.acquire();
99
182
  }
100
183
 
101
- static async get(key: string) {
102
- let value;
103
- let client;
184
+ static async get(key: string): Promise<any> {
185
+ let value: any;
186
+ let client: RedisClientType | undefined;
104
187
 
105
188
  try {
106
189
  client = await Cache.getClient();
@@ -110,9 +193,7 @@ export class Cache {
110
193
  } else {
111
194
  value = null;
112
195
  }
113
- logger.debug('Redis get success', { key, value });
114
196
  } catch (error) {
115
- logger.error('Redis get error', { key, error });
116
197
  value = null;
117
198
  } finally {
118
199
  if (client) {
@@ -123,14 +204,13 @@ export class Cache {
123
204
  return value;
124
205
  }
125
206
 
126
- static async set(key: string, value: any, expire?: number) {
207
+ static async set(key: string, value: any, expire?: number): Promise<boolean> {
127
208
  let success = false;
128
- let client;
209
+ let client: RedisClientType | undefined;
129
210
 
130
211
  try {
131
212
  client = await Cache.getClient();
132
- const serializedValue =
133
- typeof value === 'object' ? JSON.stringify(value) : value;
213
+ const serializedValue = Cache.serializeValue(value);
134
214
 
135
215
  if (expire) {
136
216
  await client.set(key, serializedValue, { EX: expire });
@@ -139,9 +219,7 @@ export class Cache {
139
219
  }
140
220
 
141
221
  success = true;
142
- logger.debug('Redis set success', { key, value });
143
222
  } catch (error) {
144
- logger.error('Redis set error', { key, error });
145
223
  success = false;
146
224
  } finally {
147
225
  if (client) {
@@ -170,7 +248,8 @@ export class Cache {
170
248
 
171
249
  const defaultOptions: CacheOptions = {
172
250
  cache: true,
173
- expire: Settings.redis.defaultExpirationTime
251
+ expire: Settings.redis.defaultExpirationTime,
252
+ compressed: process.env.CACHE_COMPRESSION_ENABLED !== 'false'
174
253
  };
175
254
 
176
255
  const _options = Object.assign(defaultOptions, options);
@@ -180,21 +259,22 @@ export class Cache {
180
259
  _options.expire = 120;
181
260
  }
182
261
 
183
- logger.debug('Cache wrap', { key, formattedKey, _options });
184
-
185
262
  if (_options.cache) {
186
- let cachedValue;
263
+ let cachedValue: any;
187
264
 
188
265
  if (_options.useProxy) {
189
266
  const body = new URLSearchParams();
190
267
 
191
268
  body.append('key', formattedKey);
269
+ if (_options.compressed) {
270
+ body.append('compressed', 'true');
271
+ }
192
272
 
193
273
  cachedValue = await Cache.proxyRequest('POST', body);
194
- logger.debug('Cache proxy request success', { key });
195
- logger.trace('Cache proxy request', { key, cachedValue });
196
274
  } else {
197
- cachedValue = await Cache.get(formattedKey);
275
+ cachedValue = _options.compressed
276
+ ? await Cache.getCompressed(formattedKey)
277
+ : await Cache.get(formattedKey);
198
278
  }
199
279
 
200
280
  if (cachedValue) {
@@ -202,8 +282,6 @@ export class Cache {
202
282
  }
203
283
  }
204
284
 
205
- logger.debug('Redis cache miss. Setting new value...', { key });
206
-
207
285
  const data = await handler();
208
286
 
209
287
  if (data && _options.cache) {
@@ -217,14 +295,19 @@ export class Cache {
217
295
  'expire',
218
296
  String(_options?.expire ?? Settings.redis.defaultExpirationTime)
219
297
  );
298
+ if (_options.compressed) {
299
+ body.append('compressed', 'true');
300
+ }
220
301
  await Cache.proxyRequest('PUT', body);
221
-
222
- logger.debug('Cache proxy request', { key, body: body.toString() });
223
302
  } catch (error) {
224
303
  logger.error('Cache proxy error', error);
225
304
  }
226
305
  } else {
227
- 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
+ }
228
311
  }
229
312
  }
230
313
 
@@ -236,7 +319,7 @@ export class Cache {
236
319
  await fetch(Cache.PROXY_URL, {
237
320
  method,
238
321
  headers: {
239
- authorization: process.env.CACHE_SECRET
322
+ authorization: process.env.CACHE_SECRET || ''
240
323
  },
241
324
  body
242
325
  })
@@ -244,4 +327,148 @@ export class Cache {
244
327
 
245
328
  return response;
246
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
+ }
247
474
  }
@@ -148,8 +148,7 @@ const withCompleteGpay =
148
148
  logger.info('Redirecting to order success page', {
149
149
  middleware: 'complete-gpay',
150
150
  redirectUrlWithLocale,
151
- ip,
152
- setCookie: request.headers.get('set-cookie')
151
+ ip
153
152
  });
154
153
 
155
154
  // Using POST method while redirecting causes an error,
@@ -149,8 +149,7 @@ const withCompleteMasterpass =
149
149
  logger.info('Redirecting to order success page', {
150
150
  middleware: 'complete-masterpass',
151
151
  redirectUrlWithLocale,
152
- ip,
153
- setCookie: request.headers.get('set-cookie')
152
+ ip
154
153
  });
155
154
 
156
155
  // Using POST method while redirecting causes an error,
@@ -302,6 +302,19 @@ 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
+
305
318
  Settings.rewrites.forEach((rewrite) => {
306
319
  url.pathname = url.pathname.replace(
307
320
  rewrite.source,
@@ -339,24 +352,6 @@ const withPzDefault =
339
352
  middlewareResult = NextResponse.rewrite(url);
340
353
  }
341
354
 
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
-
360
355
  const { localeUrlStrategy } =
361
356
  Settings.localization;
362
357
 
@@ -406,38 +401,6 @@ const withPzDefault =
406
401
  }
407
402
  );
408
403
 
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
-
441
404
  if (
442
405
  req.cookies.get('pz-locale') &&
443
406
  req.cookies.get('pz-locale').value !== locale
@@ -23,15 +23,7 @@ const getMatchedLocale = (pathname: string, req: PzNextRequest) => {
23
23
  );
24
24
 
25
25
  if (subDomainLocaleMatched && subDomainLocaleMatched[0]) {
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
- }
26
+ matchedLocale = subDomainLocaleMatched[0].slice(1);
35
27
  }
36
28
  }
37
29
  }
@@ -53,7 +53,8 @@ const resolvePrettyUrl = async (
53
53
  locale,
54
54
  resolvePrettyUrlHandler(pathname, ip),
55
55
  {
56
- useProxy: true
56
+ useProxy: true,
57
+ compressed: true
57
58
  }
58
59
  );
59
60
  };
@@ -149,8 +149,7 @@ const withRedirectionPayment =
149
149
  logger.info('Redirecting to order success page', {
150
150
  middleware: 'redirection-payment',
151
151
  redirectUrlWithLocale,
152
- ip,
153
- setCookie: request.headers.get('set-cookie')
152
+ ip
154
153
  });
155
154
 
156
155
  // Using POST method while redirecting causes an error,
@@ -149,8 +149,7 @@ const withSavedCardRedirection =
149
149
  logger.info('Redirecting to order success page', {
150
150
  middleware: 'saved-card-redirection',
151
151
  redirectUrlWithLocale,
152
- ip,
153
- setCookie: request.headers.get('set-cookie')
152
+ ip
154
153
  });
155
154
 
156
155
  // Using POST method while redirecting causes an error,
@@ -149,8 +149,7 @@ const withThreeDRedirection =
149
149
  logger.info('Redirecting to order success page', {
150
150
  middleware: 'three-d-redirection',
151
151
  redirectUrlWithLocale,
152
- ip,
153
- setCookie: request.headers.get('set-cookie')
152
+ ip
154
153
  });
155
154
 
156
155
  // 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.96.0-rc.57",
4
+ "version": "1.96.0-snapshot-ZERO-35861-20250908151109",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -17,13 +17,14 @@
17
17
  "test": "jest"
18
18
  },
19
19
  "dependencies": {
20
+ "@mongodb-js/zstd": "^2.0.1",
21
+ "@neshca/cache-handler": "1.9.0",
20
22
  "@opentelemetry/exporter-trace-otlp-http": "0.46.0",
21
23
  "@opentelemetry/resources": "1.19.0",
22
24
  "@opentelemetry/sdk-node": "0.46.0",
23
25
  "@opentelemetry/sdk-trace-node": "1.19.0",
24
26
  "@opentelemetry/semantic-conventions": "1.19.0",
25
27
  "@reduxjs/toolkit": "1.9.7",
26
- "@neshca/cache-handler": "1.9.0",
27
28
  "@sentry/nextjs": "9.5.0",
28
29
  "cross-spawn": "7.0.3",
29
30
  "generic-pool": "3.9.0",
@@ -34,7 +35,7 @@
34
35
  "set-cookie-parser": "2.6.0"
35
36
  },
36
37
  "devDependencies": {
37
- "@akinon/eslint-plugin-projectzero": "1.96.0-rc.57",
38
+ "@akinon/eslint-plugin-projectzero": "1.96.0-snapshot-ZERO-35861-20250908151109",
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
@@ -38,11 +38,3 @@ declare module '@akinon/pz-iyzico-saved-card' {
38
38
  declare module '@akinon/pz-apple-pay' {}
39
39
 
40
40
  declare module '@akinon/pz-flow-payment' {}
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
- }
package/plugins.js CHANGED
@@ -16,7 +16,5 @@ module.exports = [
16
16
  'pz-tabby-extension',
17
17
  'pz-apple-pay',
18
18
  'pz-tamara-extension',
19
- 'pz-hepsipay',
20
- 'pz-flow-payment',
21
- 'pz-similar-products'
19
+ 'pz-flow-payment'
22
20
  ];
@@ -51,11 +51,7 @@ export const errorMiddleware: Middleware = ({ dispatch }: MiddlewareParams) => {
51
51
  const result: CheckoutResult = next(action);
52
52
  const errors = result?.payload?.errors;
53
53
 
54
- if (
55
- !!errors &&
56
- ((typeof errors === 'object' && Object.keys(errors).length > 0) ||
57
- (Array.isArray(errors) && errors.length > 0))
58
- ) {
54
+ if (errors) {
59
55
  dispatch(setErrors(errors));
60
56
  }
61
57
 
@@ -114,7 +114,6 @@ export interface Order {
114
114
  pk: number;
115
115
  name: string;
116
116
  slug: string;
117
- logo: string;
118
117
  [key: string]: any;
119
118
  };
120
119
  }