@akinon/next 1.115.0-rc.22 → 1.115.0-snapshot-ZERO-3895-20251210115756

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,17 +1,6 @@
1
1
  # @akinon/next
2
2
 
3
- ## 1.115.0-rc.22
4
-
5
- ### Minor Changes
6
-
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
3
+ ## 1.115.0-snapshot-ZERO-3895-20251210115756
15
4
 
16
5
  ## 1.114.0
17
6
 
@@ -88,19 +88,8 @@ const PluginComponents = new Map([
88
88
  [Component.AkifastQuickLoginButton, Component.AkifastCheckoutButton]
89
89
  ],
90
90
  [Plugin.MultiBasket, [Component.MultiBasket]],
91
- [
92
- Plugin.SimilarProducts,
93
- [
94
- Component.SimilarProductsModal,
95
- Component.SimilarProductsFilterSidebar,
96
- Component.SimilarProductsResultsGrid,
97
- Component.SimilarProductsPlugin,
98
- Component.ProductImageSearchFeature,
99
- Component.ImageSearchButton,
100
- Component.HeaderImageSearchFeature
101
- ]
102
- ],
103
91
  [Plugin.SavedCard, [Component.SavedCard, Component.IyzicoSavedCard]],
92
+ [Plugin.SavedCard, [Component.SavedCard]],
104
93
  [Plugin.FlowPayment, [Component.FlowPayment]],
105
94
  [
106
95
  Plugin.VirtualTryOn,
@@ -173,8 +162,6 @@ export default function PluginModule({
173
162
  promise = import(`${'@akinon/pz-multi-basket'}`);
174
163
  } else if (plugin === Plugin.SavedCard) {
175
164
  promise = import(`${'@akinon/pz-saved-card'}`);
176
- } else if (plugin === Plugin.SimilarProducts) {
177
- promise = import(`${'@akinon/pz-similar-products'}`);
178
165
  } else if (plugin === Plugin.Hepsipay) {
179
166
  promise = import(`${'@akinon/pz-hepsipay'}`);
180
167
  } else if (plugin === Plugin.FlowPayment) {
package/data/urls.ts CHANGED
@@ -183,11 +183,7 @@ 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}`,
187
- similarProducts: (params?: string) =>
188
- `/similar-products${params ? `?${params}` : ''}`,
189
- similarProductsList: (params?: string) =>
190
- `/similar-product-list${params ? `?${params}` : ''}`
186
+ `/bundle-product/${productPk}/?${queryString}`
191
187
  };
192
188
 
193
189
  export const wishlist = {
@@ -463,14 +463,6 @@ CacheHandler.onCreation(async () => {
463
463
  set: async (key, value, context) => {
464
464
  const vKey = versionKey(key);
465
465
 
466
- const stripTags = (val) => {
467
- if (val && typeof val === 'object') {
468
- const { tags, ...rest } = val;
469
- return { ...rest, tags: [] };
470
- }
471
- return val;
472
- };
473
-
474
466
  let compressedValue;
475
467
  let shouldUseCompressed = false;
476
468
 
@@ -490,12 +482,12 @@ CacheHandler.onCreation(async () => {
490
482
 
491
483
  if (shouldUseCompressed) {
492
484
  try {
493
- await redisHandler.set(vKey, stripTags(compressedValue), context);
485
+ await redisHandler.set(vKey, compressedValue, context);
494
486
 
495
487
  redisSetResult = { status: 'fulfilled' };
496
488
  } catch (compressionError) {
497
489
  try {
498
- await redisHandler.set(vKey, stripTags(value), context);
490
+ await redisHandler.set(vKey, value, context);
499
491
 
500
492
  redisSetResult = { status: 'fulfilled' };
501
493
  } catch (fallbackError) {
@@ -504,7 +496,7 @@ CacheHandler.onCreation(async () => {
504
496
  }
505
497
  } else {
506
498
  try {
507
- await redisHandler.set(vKey, stripTags(value), context);
499
+ await redisHandler.set(vKey, value, context);
508
500
  redisSetResult = { status: 'fulfilled' };
509
501
  } catch (error) {
510
502
  redisSetResult = { status: 'rejected', reason: error };
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.115.0-rc.22",
4
+ "version": "1.115.0-snapshot-ZERO-3895-20251210115756",
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.115.0-rc.22",
38
+ "@akinon/eslint-plugin-projectzero": "1.115.0-snapshot-ZERO-3895-20251210115756",
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,16 +37,6 @@ 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
-
50
40
  declare module '@akinon/pz-cybersource-uc/src/redux/reducer' {
51
41
  export default reducer as any;
52
42
  }
package/plugins.js CHANGED
@@ -16,7 +16,6 @@ module.exports = [
16
16
  'pz-tabby-extension',
17
17
  'pz-apple-pay',
18
18
  'pz-tamara-extension',
19
- 'pz-similar-products',
20
19
  'pz-cybersource-uc',
21
20
  'pz-hepsipay',
22
21
  'pz-flow-payment',
package/types/index.ts CHANGED
@@ -83,12 +83,6 @@ 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;
92
86
  redis: {
93
87
  defaultExpirationTime: number;
94
88
  };
@@ -1,14 +1,8 @@
1
1
  const iframeURLChange = (iframe, callback) => {
2
2
  iframe.addEventListener('load', () => {
3
3
  setTimeout(() => {
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
4
+ if (iframe?.contentWindow?.location) {
5
+ callback(iframe.contentWindow.location);
12
6
  }
13
7
  }, 0);
14
8
  });
@@ -1,14 +1,8 @@
1
1
  const iframeURLChange = (iframe, callback) => {
2
2
  iframe.addEventListener('load', () => {
3
3
  setTimeout(() => {
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
4
+ if (iframe?.contentWindow?.location) {
5
+ callback(iframe.contentWindow.location);
12
6
  }
13
7
  }, 0);
14
8
  });
@@ -1,75 +0,0 @@
1
- import { NextRequest, NextResponse } from 'next/server';
2
-
3
- async function proxyImage(imageUrl: string) {
4
- if (!imageUrl) {
5
- return NextResponse.json(
6
- { success: false, error: 'Missing url parameter' },
7
- { status: 400 }
8
- );
9
- }
10
-
11
- const imageResponse = await fetch(imageUrl);
12
-
13
- if (!imageResponse.ok) {
14
- return NextResponse.json(
15
- { success: false, error: 'Failed to fetch image from URL' },
16
- { status: 400 }
17
- );
18
- }
19
-
20
- const imageBuffer = await imageResponse.arrayBuffer();
21
- const base64Image = Buffer.from(imageBuffer).toString('base64');
22
- const contentType = imageResponse.headers.get('content-type') || 'image/jpeg';
23
-
24
- return { base64Image, contentType, imageBuffer };
25
- }
26
-
27
- export async function GET(request: NextRequest) {
28
- try {
29
- const { searchParams } = new URL(request.url);
30
- const imageUrl = searchParams.get('url');
31
-
32
- const result = await proxyImage(imageUrl!);
33
- if (result instanceof NextResponse) {
34
- return result;
35
- }
36
-
37
- return new NextResponse(result.imageBuffer, {
38
- status: 200,
39
- headers: {
40
- 'Content-Type': result.contentType,
41
- 'Access-Control-Allow-Origin': '*',
42
- 'Cache-Control': 'public, max-age=3600'
43
- }
44
- });
45
- } catch (error) {
46
- console.error('Image proxy error:', error);
47
- return NextResponse.json(
48
- { success: false, error: 'Internal server error' },
49
- { status: 500 }
50
- );
51
- }
52
- }
53
-
54
- export async function POST(request: NextRequest) {
55
- try {
56
- const body = await request.json();
57
- const imageUrl = body.imageUrl;
58
-
59
- const result = await proxyImage(imageUrl);
60
- if (result instanceof NextResponse) {
61
- return result;
62
- }
63
-
64
- return NextResponse.json({
65
- success: true,
66
- base64Image: `data:${result.contentType};base64,${result.base64Image}`
67
- });
68
- } catch (error) {
69
- console.error('Image proxy POST error:', error);
70
- return NextResponse.json(
71
- { success: false, error: 'Internal server error' },
72
- { status: 500 }
73
- );
74
- }
75
- }
@@ -1,63 +0,0 @@
1
- import { NextRequest, NextResponse } from 'next/server';
2
- import Settings from 'settings';
3
-
4
- export async function GET(request: NextRequest) {
5
- try {
6
- const { searchParams } = new URL(request.url);
7
- const dynamicFilter = request.headers.get('x-search-dynamic-filter');
8
- const dynamicExclude = request.headers.get('x-search-dynamic-exclude');
9
-
10
- if (!dynamicFilter && !dynamicExclude) {
11
- return NextResponse.json(
12
- {
13
- error:
14
- 'Missing x-search-dynamic-filter or x-search-dynamic-exclude header'
15
- },
16
- { status: 400 }
17
- );
18
- }
19
-
20
- if (Settings.commerceUrl === 'default') {
21
- return NextResponse.json(
22
- { error: 'Commerce URL is not configured' },
23
- { status: 500 }
24
- );
25
- }
26
-
27
- const queryString = searchParams.toString();
28
- const apiUrl = `${Settings.commerceUrl}/list${
29
- queryString ? `?${queryString}` : ''
30
- }`;
31
-
32
- const headers: Record<string, string> = {
33
- Accept: 'application/json',
34
- 'Content-Type': 'application/json'
35
- };
36
-
37
- if (dynamicFilter) {
38
- headers['x-search-dynamic-filter'] = dynamicFilter;
39
- } else if (dynamicExclude) {
40
- headers['x-search-dynamic-exclude'] = dynamicExclude;
41
- }
42
-
43
- const response = await fetch(apiUrl, {
44
- method: 'GET',
45
- headers
46
- });
47
-
48
- if (!response.ok) {
49
- return NextResponse.json(
50
- { error: `API request failed with status: ${response.status}` },
51
- { status: response.status }
52
- );
53
- }
54
-
55
- const data = await response.json();
56
- return NextResponse.json(data);
57
- } catch (error) {
58
- return NextResponse.json(
59
- { error: (error as Error).message },
60
- { status: 500 }
61
- );
62
- }
63
- }
@@ -1,111 +0,0 @@
1
- import { NextResponse } from 'next/server';
2
- import Settings from 'settings';
3
-
4
- const IMAGE_SEARCH_API_URL = Settings.commerceUrl + '/image-search/';
5
-
6
- const errorResponse = (message: string, status: number) => {
7
- return NextResponse.json({ error: message }, { status });
8
- };
9
-
10
- export async function GET(request: Request) {
11
- const { searchParams } = new URL(request.url);
12
- const limit = searchParams.get('limit') || '20';
13
- const url = searchParams.get('url');
14
- const excludedProductIds = searchParams.get('excluded_product_ids');
15
-
16
- if (!url) {
17
- return errorResponse('URL parameter is required', 400);
18
- }
19
-
20
- if (Settings.commerceUrl === 'default') {
21
- return errorResponse('Commerce URL is not configured', 500);
22
- }
23
-
24
- const apiParams = new URLSearchParams();
25
- apiParams.append('limit', limit);
26
- apiParams.append('url', url);
27
-
28
- if (excludedProductIds) {
29
- apiParams.append('excluded_product_ids', excludedProductIds);
30
- }
31
-
32
- const apiUrl = `${IMAGE_SEARCH_API_URL}?${apiParams.toString()}`;
33
-
34
- try {
35
- const response = await fetch(apiUrl, {
36
- method: 'GET',
37
- headers: {
38
- Accept: 'application/json'
39
- }
40
- });
41
-
42
- if (!response.ok) {
43
- const errorText = await response.text();
44
- return errorResponse(
45
- errorText || `API request failed with status: ${response.status}`,
46
- response.status
47
- );
48
- }
49
-
50
- const responseText = await response.text();
51
-
52
- return NextResponse.json(JSON.parse(responseText));
53
- } catch (error) {
54
- return errorResponse((error as Error).message, 500);
55
- }
56
- }
57
-
58
- export async function POST(request: Request) {
59
- const { searchParams } = new URL(request.url);
60
- const limit = searchParams.get('limit') || '20';
61
-
62
- if (Settings.commerceUrl === 'default') {
63
- return errorResponse('Commerce URL is not configured', 500);
64
- }
65
-
66
- let requestBody;
67
- try {
68
- requestBody = await request.json();
69
- } catch (error) {
70
- return errorResponse('Invalid JSON in request body', 400);
71
- }
72
-
73
- if (!requestBody.image) {
74
- return errorResponse('Image data is required in request body', 400);
75
- }
76
-
77
- const apiParams = new URLSearchParams();
78
- apiParams.append('limit', limit);
79
-
80
- const apiUrl = `${IMAGE_SEARCH_API_URL}?${apiParams.toString()}`;
81
-
82
- const bodyData: any = { image: requestBody.image };
83
-
84
- if (requestBody.excluded_product_ids) {
85
- bodyData.excluded_product_ids = requestBody.excluded_product_ids;
86
- }
87
-
88
- try {
89
- const response = await fetch(apiUrl, {
90
- method: 'POST',
91
- headers: {
92
- 'Content-Type': 'application/json',
93
- Accept: 'application/json'
94
- },
95
- body: JSON.stringify(bodyData)
96
- });
97
-
98
- if (!response.ok) {
99
- const errorText = await response.text();
100
- return errorResponse(
101
- errorText || `API request failed with status: ${response.status}`,
102
- response.status
103
- );
104
- }
105
-
106
- const responseData = await response.json();
107
- return NextResponse.json(responseData);
108
- } catch (error) {
109
- return errorResponse((error as Error).message, 500);
110
- }
111
- }