@akinon/next 1.114.0-snapshot-ZERO-3890-20251209002835 → 1.115.0-rc.22

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.
package/CHANGELOG.md CHANGED
@@ -1,11 +1,26 @@
1
1
  # @akinon/next
2
2
 
3
- ## 1.114.0-snapshot-ZERO-3890-20251209002835
3
+ ## 1.115.0-rc.22
4
4
 
5
5
  ### Minor Changes
6
6
 
7
- - b59bed4: ZERO-3878: Reintegrated similar products and removed localStorage checks and implemented props based showing of buttons
8
- - cbcfdf4: ZERO-3859: Haso payment gateway implmeneted
7
+ - d2c0e759: ZERO-3684: Handle cross-origin iframe access in iframeURLChange function
8
+ - b55acb76: ZERO-2577: Fix pagination bug and update usePagination hook and ensure pagination controls rendering correctly
9
+ - 143be2b9: ZERO-3457: Crop styles are customizable and logic improved for rendering similar products modal
10
+ - 9f8cd3bc: ZERO-3449: AI Search Active Filters & Crop Style changes have been implemented
11
+ - d99a6a7d: ZERO-3457_1: Fixed the settings prop and made sure everything is customizable.
12
+ - 7056203a: ZERO-3875: removed shared_tags through stripTags function for unused keys
13
+ - 4de5303c: ZERO-2504: add cookie filter to api client request
14
+ - 95b139dc: ZERO-3795: Remove duplicate entry for SavedCard in PluginComponents map
15
+
16
+ ## 1.114.0
17
+
18
+ ### Minor Changes
19
+
20
+ - 65d3b862: ZERO-3054: Update headers in appFetch
21
+ - 43c182ee: ZERO-3054: Update Redis variable checks to conditionally include CACHE_SECRET
22
+ - eeb20bea: Revert "ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing"
23
+ - fdd255ee: ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing
9
24
 
10
25
  ## 1.113.0
11
26
 
@@ -24,9 +24,7 @@ enum Plugin {
24
24
  FlowPayment = 'pz-flow-payment',
25
25
  VirtualTryOn = 'pz-virtual-try-on',
26
26
  Hepsipay = 'pz-hepsipay',
27
- MasterpassRest = 'pz-masterpass-rest',
28
- SimilarProducts = 'pz-similar-products',
29
- Haso = 'pz-haso'
27
+ MasterpassRest = 'pz-masterpass-rest'
30
28
  }
31
29
 
32
30
  export enum Component {
@@ -57,15 +55,7 @@ export enum Component {
57
55
  IyzicoSavedCard = 'IyzicoSavedCardOption',
58
56
  Hepsipay = 'Hepsipay',
59
57
  FlowPayment = 'FlowPayment',
60
- MasterpassRest = 'MasterpassRestOption',
61
- SimilarProductsModal = 'SimilarProductsModal',
62
- SimilarProductsFilterSidebar = 'SimilarProductsFilterSidebar',
63
- SimilarProductsResultsGrid = 'SimilarProductsResultsGrid',
64
- SimilarProductsPlugin = 'SimilarProductsPlugin',
65
- ProductImageSearchFeature = 'ProductImageSearchFeature',
66
- ImageSearchButton = 'ImageSearchButton',
67
- HeaderImageSearchFeature = 'HeaderImageSearchFeature',
68
- HasoPaymentGateway = 'HasoPaymentGateway'
58
+ MasterpassRest = 'MasterpassRestOption'
69
59
  }
70
60
 
71
61
  const PluginComponents = new Map([
@@ -111,7 +101,6 @@ const PluginComponents = new Map([
111
101
  ]
112
102
  ],
113
103
  [Plugin.SavedCard, [Component.SavedCard, Component.IyzicoSavedCard]],
114
- [Plugin.SavedCard, [Component.SavedCard]],
115
104
  [Plugin.FlowPayment, [Component.FlowPayment]],
116
105
  [
117
106
  Plugin.VirtualTryOn,
@@ -119,8 +108,7 @@ const PluginComponents = new Map([
119
108
  ],
120
109
  [Plugin.Hepsipay, [Component.Hepsipay]],
121
110
  [Plugin.Hepsipay, [Component.Hepsipay]],
122
- [Plugin.MasterpassRest, [Component.MasterpassRest]],
123
- [Plugin.Haso, [Component.HasoPaymentGateway]]
111
+ [Plugin.MasterpassRest, [Component.MasterpassRest]]
124
112
  ]);
125
113
 
126
114
  const getPlugin = (component: Component) => {
@@ -185,6 +173,8 @@ export default function PluginModule({
185
173
  promise = import(`${'@akinon/pz-multi-basket'}`);
186
174
  } else if (plugin === Plugin.SavedCard) {
187
175
  promise = import(`${'@akinon/pz-saved-card'}`);
176
+ } else if (plugin === Plugin.SimilarProducts) {
177
+ promise = import(`${'@akinon/pz-similar-products'}`);
188
178
  } else if (plugin === Plugin.Hepsipay) {
189
179
  promise = import(`${'@akinon/pz-hepsipay'}`);
190
180
  } else if (plugin === Plugin.FlowPayment) {
@@ -193,10 +183,6 @@ export default function PluginModule({
193
183
  promise = import(`${'@akinon/pz-virtual-try-on'}`);
194
184
  } else if (plugin === Plugin.MasterpassRest) {
195
185
  promise = import(`${'@akinon/pz-masterpass-rest'}`);
196
- } else if (plugin === Plugin.SimilarProducts) {
197
- promise = import(`${'@akinon/pz-similar-products'}`);
198
- } else if (plugin === Plugin.Haso) {
199
- promise = import(`${'@akinon/pz-haso'}`);
200
186
  }
201
187
  } catch (error) {
202
188
  logger.error(error);
package/data/urls.ts CHANGED
@@ -183,7 +183,11 @@ export const product = {
183
183
  breadcrumbUrl: (menuitemmodel: string) =>
184
184
  `/menus/generate_breadcrumb/?item=${menuitemmodel}&generator_name=menu_item`,
185
185
  bundleProduct: (productPk: string, queryString: string) =>
186
- `/bundle-product/${productPk}/?${queryString}`
186
+ `/bundle-product/${productPk}/?${queryString}`,
187
+ similarProducts: (params?: string) =>
188
+ `/similar-products${params ? `?${params}` : ''}`,
189
+ similarProductsList: (params?: string) =>
190
+ `/similar-product-list${params ? `?${params}` : ''}`
187
191
  };
188
192
 
189
193
  export const wishlist = {
@@ -72,10 +72,13 @@ const addRootLayoutProps = async (componentProps: RootLayoutProps) => {
72
72
  const checkRedisVariables = () => {
73
73
  const requiredVariableValues = [
74
74
  process.env.CACHE_HOST,
75
- process.env.CACHE_PORT,
76
- process.env.CACHE_SECRET
75
+ process.env.CACHE_PORT
77
76
  ];
78
77
 
78
+ if (!settings.usePrettyUrlRoute) {
79
+ requiredVariableValues.push(process.env.CACHE_SECRET);
80
+ }
81
+
79
82
  if (
80
83
  !requiredVariableValues.every((v) => v) &&
81
84
  process.env.NODE_ENV === 'production'
@@ -518,8 +518,8 @@ CacheHandler.onCreation(async () => {
518
518
  localSetResult = { status: 'fulfilled' };
519
519
  } catch (error) {
520
520
  localSetResult = { status: 'rejected', reason: error };
521
+ return localSetResult;
521
522
  }
522
- return localSetResult;
523
523
  },
524
524
  delete: async (key, context) => {
525
525
  const vKey = versionKey(key);
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.114.0-snapshot-ZERO-3890-20251209002835",
4
+ "version": "1.115.0-rc.22",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -35,7 +35,7 @@
35
35
  "set-cookie-parser": "2.6.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@akinon/eslint-plugin-projectzero": "1.114.0-snapshot-ZERO-3890-20251209002835",
38
+ "@akinon/eslint-plugin-projectzero": "1.115.0-rc.22",
39
39
  "@babel/core": "7.26.10",
40
40
  "@babel/preset-env": "7.26.9",
41
41
  "@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,11 +16,10 @@ 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',
22
23
  'pz-virtual-try-on',
23
- 'pz-masterpass-rest',
24
- 'pz-similar-products',
25
- 'pz-haso'
24
+ 'pz-masterpass-rest'
26
25
  ];
package/types/index.ts CHANGED
@@ -83,6 +83,12 @@ export interface Settings {
83
83
  };
84
84
  usePrettyUrlRoute?: boolean;
85
85
  commerceUrl: string;
86
+ /**
87
+ * This option allows you to track Sentry events on the client side, in addition to server and edge environments.
88
+ *
89
+ * It overrides process.env.NEXT_PUBLIC_SENTRY_DSN and process.env.SENTRY_DSN.
90
+ */
91
+ sentryDsn?: string;
86
92
  redis: {
87
93
  defaultExpirationTime: number;
88
94
  };
@@ -43,12 +43,12 @@ const appFetch = async <T>({
43
43
  const requestURL = `${decodeURIComponent(commerceUrl)}${url}`;
44
44
 
45
45
  init.headers = {
46
+ cookie: nextCookies.toString(),
46
47
  ...(init.headers ?? {}),
47
48
  ...(ServerVariables.globalHeaders ?? {}),
48
49
  'Accept-Language': currentLocale.apiValue,
49
50
  'x-currency': currency,
50
- 'x-forwarded-for': ip,
51
- cookie: nextCookies.toString()
51
+ 'x-forwarded-for': ip
52
52
  };
53
53
 
54
54
  init.next = {
@@ -1,8 +1,14 @@
1
1
  const iframeURLChange = (iframe, callback) => {
2
2
  iframe.addEventListener('load', () => {
3
3
  setTimeout(() => {
4
- if (iframe?.contentWindow?.location) {
5
- callback(iframe.contentWindow.location);
4
+ try {
5
+ if (iframe?.contentWindow?.location) {
6
+ const iframeLocation = iframe.contentWindow.location;
7
+
8
+ callback(iframeLocation);
9
+ }
10
+ } catch (error) {
11
+ // Expected: browser blocks cross-origin iframe access for security
6
12
  }
7
13
  }, 0);
8
14
  });
@@ -1,8 +1,14 @@
1
1
  const iframeURLChange = (iframe, callback) => {
2
2
  iframe.addEventListener('load', () => {
3
3
  setTimeout(() => {
4
- if (iframe?.contentWindow?.location) {
5
- callback(iframe.contentWindow.location);
4
+ try {
5
+ if (iframe?.contentWindow?.location) {
6
+ const iframeLocation = iframe.contentWindow.location;
7
+
8
+ callback(iframeLocation);
9
+ }
10
+ } catch (error) {
11
+ // Expected: browser blocks cross-origin iframe access for security
6
12
  }
7
13
  }, 0);
8
14
  });
@@ -1,53 +0,0 @@
1
- import { NextRequest, NextResponse } from 'next/server';
2
- import { getProductData } from '@akinon/next/data/server';
3
-
4
- export async function GET(request: NextRequest) {
5
- try {
6
- const { searchParams } = new URL(request.url);
7
- const pksParam = searchParams.get('pks');
8
-
9
- if (!pksParam) {
10
- return NextResponse.json(
11
- { error: 'pks parameter required' },
12
- { status: 400 }
13
- );
14
- }
15
-
16
- const pks = pksParam.split(',').map(Number).filter(Boolean);
17
-
18
- if (pks.length === 0) {
19
- return NextResponse.json({ error: 'Invalid pks' }, { status: 400 });
20
- }
21
-
22
- const results = await Promise.all(
23
- pks.map(async (pk) => {
24
- try {
25
- const { breadcrumbData } = await getProductData({ pk });
26
-
27
- const categoryIds =
28
- breadcrumbData
29
- ?.map((item: any) => item.extra_context?.attributes?.category_id)
30
- .filter(Boolean) || [];
31
-
32
- return { pk, categoryIds };
33
- } catch (error) {
34
- console.error(`Error fetching product ${pk}:`, error);
35
- return { pk, categoryIds: [] };
36
- }
37
- })
38
- );
39
-
40
- const mapping: Record<string, number[]> = {};
41
- results.forEach(({ pk, categoryIds }) => {
42
- mapping[String(pk)] = categoryIds;
43
- });
44
-
45
- return NextResponse.json(mapping);
46
- } catch (error) {
47
- console.error('Error in product-categories API:', error);
48
- return NextResponse.json(
49
- { error: 'Internal server error' },
50
- { status: 500 }
51
- );
52
- }
53
- }