@akinon/next 1.103.0-snapshot-ZERO-3648-20251002184136 → 1.103.0

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,10 +1,6 @@
1
1
  # @akinon/next
2
2
 
3
- ## 1.103.0-snapshot-ZERO-3648-20251002184136
4
-
5
- ### Minor Changes
6
-
7
- - fcbbea7: ZERO-3648: Add virtual try-on feature with localization support
3
+ ## 1.103.0
8
4
 
9
5
  ## 1.102.0
10
6
 
@@ -21,8 +21,7 @@ enum Plugin {
21
21
  Akifast = 'pz-akifast',
22
22
  MultiBasket = 'pz-multi-basket',
23
23
  SavedCard = 'pz-saved-card',
24
- FlowPayment = 'pz-flow-payment',
25
- VirtualTryOn = 'pz-virtual-try-on'
24
+ FlowPayment = 'pz-flow-payment'
26
25
  }
27
26
 
28
27
  export enum Component {
@@ -48,8 +47,7 @@ export enum Component {
48
47
  AkifastCheckoutButton = 'CheckoutButton',
49
48
  MultiBasket = 'MultiBasket',
50
49
  SavedCard = 'SavedCardOption',
51
- FlowPayment = 'FlowPayment',
52
- VirtualTryOnPlugin = 'VirtualTryOnPlugin'
50
+ FlowPayment = 'FlowPayment'
53
51
  }
54
52
 
55
53
  const PluginComponents = new Map([
@@ -83,8 +81,7 @@ const PluginComponents = new Map([
83
81
  ],
84
82
  [Plugin.MultiBasket, [Component.MultiBasket]],
85
83
  [Plugin.SavedCard, [Component.SavedCard]],
86
- [Plugin.FlowPayment, [Component.FlowPayment]],
87
- [Plugin.VirtualTryOn, [Component.VirtualTryOnPlugin]]
84
+ [Plugin.FlowPayment, [Component.FlowPayment]]
88
85
  ]);
89
86
 
90
87
  const getPlugin = (component: Component) => {
@@ -151,8 +148,6 @@ export default function PluginModule({
151
148
  promise = import(`${'@akinon/pz-saved-card'}`);
152
149
  } else if (plugin === Plugin.FlowPayment) {
153
150
  promise = import(`${'@akinon/pz-flow-payment'}`);
154
- } else if (plugin === Plugin.VirtualTryOn) {
155
- promise = import(`${'@akinon/pz-virtual-try-on'}`);
156
151
  }
157
152
  } catch (error) {
158
153
  logger.error(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.103.0-snapshot-ZERO-3648-20251002184136",
4
+ "version": "1.103.0",
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.103.0-snapshot-ZERO-3648-20251002184136",
38
+ "@akinon/eslint-plugin-projectzero": "1.103.0",
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.js CHANGED
@@ -16,6 +16,5 @@ module.exports = [
16
16
  'pz-tabby-extension',
17
17
  'pz-apple-pay',
18
18
  'pz-tamara-extension',
19
- 'pz-flow-payment',
20
- 'pz-virtual-try-on'
19
+ 'pz-flow-payment'
21
20
  ];
@@ -1,309 +0,0 @@
1
- import { NextRequest, NextResponse } from 'next/server';
2
- import Settings from 'settings';
3
-
4
- const VIRTUAL_TRY_ON_API_URL = process.env.NEXT_PUBLIC_VIRTUAL_TRY_ON_API_URL;
5
-
6
- let limitedCategoriesCache: {
7
- data: any;
8
- timestamp: number;
9
- } | null = null;
10
-
11
- const CACHE_TTL = 3600000;
12
-
13
- function getClientIP(request: NextRequest): string | null {
14
- const forwardedFor = request.headers.get('x-forwarded-for');
15
- if (forwardedFor) {
16
- const ip = forwardedFor.split(',')[0].trim();
17
- if (ip === '::1' || ip === '::ffff:127.0.0.1') {
18
- return '127.0.0.1';
19
- }
20
- return ip;
21
- }
22
-
23
- const realIP = request.headers.get('x-real-ip');
24
- if (realIP) {
25
- if (realIP === '::1' || realIP === '::ffff:127.0.0.1') {
26
- return '127.0.0.1';
27
- }
28
- return realIP;
29
- }
30
-
31
- if (process.env.NODE_ENV === 'development') {
32
- return '127.0.0.1';
33
- }
34
-
35
- return null;
36
- }
37
-
38
- function getLocaleFromRequest(request: NextRequest): string | null {
39
- const referer = request.headers.get('referer') || '';
40
- const localeMatch = referer.match(/\/(\w{2})[-/]/);
41
-
42
- if (!localeMatch) {
43
- return null;
44
- }
45
-
46
- const localeValue = localeMatch[1];
47
- const currentLocale = Settings.localization.locales.find(
48
- (l) => l.value === localeValue
49
- );
50
-
51
- return currentLocale?.apiValue || null;
52
- }
53
-
54
- export async function GET(request: NextRequest) {
55
- try {
56
- const { searchParams } = new URL(request.url);
57
- const endpoint = searchParams.get('endpoint');
58
-
59
- if (endpoint === 'limited-categories') {
60
- const now = Date.now();
61
-
62
- if (
63
- limitedCategoriesCache &&
64
- now - limitedCategoriesCache.timestamp < CACHE_TTL
65
- ) {
66
- return NextResponse.json(limitedCategoriesCache.data, {
67
- status: 200,
68
- headers: {
69
- 'Access-Control-Allow-Origin': '*',
70
- 'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
71
- 'Access-Control-Allow-Headers':
72
- 'Content-Type, Accept, Authorization',
73
- 'Cache-Control':
74
- 'public, s-maxage=3600, stale-while-revalidate=7200',
75
- 'X-Virtual-Try-On-Cache-Status': 'HIT'
76
- }
77
- });
78
- }
79
-
80
- const externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/limited-categories`;
81
- const clientIP = getClientIP(request);
82
- const locale = getLocaleFromRequest(request);
83
-
84
- const headersToSend = {
85
- Accept: 'application/json',
86
- ...(locale && { 'Accept-Language': locale }),
87
- ...(request.headers.get('authorization') && {
88
- Authorization: request.headers.get('authorization')!
89
- }),
90
- ...(clientIP && {
91
- 'X-Forwarded-For': clientIP
92
- })
93
- };
94
-
95
- const response = await fetch(externalUrl, {
96
- method: 'GET',
97
- headers: headersToSend
98
- });
99
-
100
- let responseData: any;
101
- const responseText = await response.text();
102
-
103
- try {
104
- responseData = responseText ? JSON.parse(responseText) : {};
105
- } catch (parseError) {
106
- responseData = { category_ids: [] };
107
- }
108
-
109
- if (!response.ok) {
110
- responseData = { category_ids: [] };
111
- }
112
-
113
- limitedCategoriesCache = {
114
- data: responseData,
115
- timestamp: Date.now()
116
- };
117
-
118
- return NextResponse.json(responseData, {
119
- status: response.ok ? response.status : 200,
120
- headers: {
121
- 'Access-Control-Allow-Origin': '*',
122
- 'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
123
- 'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization',
124
- 'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
125
- 'X-Virtual-Try-On-Cache-Status': 'MISS'
126
- }
127
- });
128
- }
129
-
130
- return NextResponse.json(
131
- { error: 'Invalid endpoint for GET method' },
132
- { status: 400 }
133
- );
134
- } catch (error) {
135
- return NextResponse.json({ category_ids: [] }, { status: 200 });
136
- }
137
- }
138
-
139
- export async function POST(request: NextRequest) {
140
- try {
141
- const { searchParams } = new URL(request.url);
142
- const endpoint = searchParams.get('endpoint');
143
-
144
- const body = await request.json();
145
-
146
- let externalUrl: string;
147
- if (endpoint === 'feedback') {
148
- externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/feedback`;
149
- } else {
150
- externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/virtual-try-on`;
151
- }
152
-
153
- const httpMethod = endpoint === 'feedback' ? 'PUT' : 'POST';
154
- const clientIP = getClientIP(request);
155
- const locale = getLocaleFromRequest(request);
156
-
157
- const headersToSend = {
158
- 'Content-Type': 'application/json',
159
- ...(locale && { 'Accept-Language': locale }),
160
- ...(httpMethod === 'POST' && { Accept: 'application/json' }),
161
- ...(request.headers.get('authorization') && {
162
- Authorization: request.headers.get('authorization')!
163
- }),
164
- ...(clientIP && {
165
- 'X-Forwarded-For': clientIP
166
- })
167
- };
168
-
169
- const response = await fetch(externalUrl, {
170
- method: httpMethod,
171
- headers: headersToSend,
172
- body: JSON.stringify(body)
173
- });
174
-
175
- let responseData: any;
176
- const responseText = await response.text();
177
-
178
- if (endpoint === 'feedback') {
179
- try {
180
- responseData = responseText ? JSON.parse(responseText) : {};
181
- } catch (parseError) {
182
- responseData = { error: 'Invalid JSON response from feedback API' };
183
- }
184
- } else {
185
- try {
186
- responseData = responseText ? JSON.parse(responseText) : {};
187
- } catch (parseError) {
188
- responseData = { error: 'Invalid JSON response' };
189
- }
190
- }
191
-
192
- if (!response.ok && responseData.error) {
193
- let userFriendlyMessage = responseData.error;
194
-
195
- if (
196
- typeof responseData.error === 'string' &&
197
- (responseData.error.includes('duplicate key value') ||
198
- responseData.error.includes('image_pk'))
199
- ) {
200
- userFriendlyMessage =
201
- 'This image has already been processed. Please try with a different image.';
202
- } else if (responseData.error.includes('bulk insert images')) {
203
- userFriendlyMessage =
204
- 'There was an issue processing your image. Please try again with a different image.';
205
- }
206
-
207
- return NextResponse.json(
208
- {
209
- ...responseData,
210
- message: userFriendlyMessage
211
- },
212
- {
213
- status: response.status,
214
- headers: {
215
- 'Access-Control-Allow-Origin': '*',
216
- 'Access-Control-Allow-Methods': 'POST, OPTIONS',
217
- 'Access-Control-Allow-Headers':
218
- 'Content-Type, Accept, Authorization'
219
- }
220
- }
221
- );
222
- }
223
-
224
- return NextResponse.json(responseData, {
225
- status: response.status,
226
- headers: {
227
- 'Access-Control-Allow-Origin': '*',
228
- 'Access-Control-Allow-Methods': 'POST, OPTIONS',
229
- 'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
230
- }
231
- });
232
- } catch (error) {
233
- return NextResponse.json(
234
- {
235
- status: 'error',
236
- message:
237
- 'Internal server error occurred during virtual try-on processing'
238
- },
239
- { status: 500 }
240
- );
241
- }
242
- }
243
-
244
- export async function PUT(request: NextRequest) {
245
- try {
246
- const { searchParams } = new URL(request.url);
247
- const endpoint = searchParams.get('endpoint');
248
-
249
- if (endpoint !== 'feedback') {
250
- return NextResponse.json(
251
- { error: 'PUT method only supports feedback endpoint' },
252
- { status: 400 }
253
- );
254
- }
255
-
256
- const body = await request.json();
257
-
258
- const externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/feedback`;
259
- const clientIP = getClientIP(request);
260
- const locale = getLocaleFromRequest(request);
261
-
262
- const headersToSend = {
263
- 'Content-Type': 'application/json',
264
- ...(locale && { 'Accept-Language': locale }),
265
- ...(request.headers.get('authorization') && {
266
- Authorization: request.headers.get('authorization')!
267
- }),
268
- ...(clientIP && {
269
- 'X-Forwarded-For': clientIP
270
- })
271
- };
272
-
273
- const response = await fetch(externalUrl, {
274
- method: 'PUT',
275
- headers: headersToSend,
276
- body: JSON.stringify(body)
277
- });
278
-
279
- const responseData = await response.json();
280
-
281
- return NextResponse.json(responseData, {
282
- status: response.status,
283
- headers: {
284
- 'Access-Control-Allow-Origin': '*',
285
- 'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
286
- 'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
287
- }
288
- });
289
- } catch (error) {
290
- return NextResponse.json(
291
- {
292
- status: 'error',
293
- message: 'Internal server error occurred during feedback submission'
294
- },
295
- { status: 500 }
296
- );
297
- }
298
- }
299
-
300
- export async function OPTIONS() {
301
- return new NextResponse(null, {
302
- status: 200,
303
- headers: {
304
- 'Access-Control-Allow-Origin': '*',
305
- 'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
306
- 'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
307
- }
308
- });
309
- }