@akinon/next 2.0.34-rc.0 → 2.0.35-beta.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 +8 -24
- package/api/virtual-try-on.ts +264 -242
- package/bin/pz-generate-routes.js +1 -4
- package/components/plugin-module.tsx +1 -0
- package/data/client/checkout.ts +1 -0
- package/data/server/category.ts +1 -13
- package/data/server/list.ts +0 -12
- package/data/server/product.ts +0 -10
- package/data/server/special-page.ts +0 -13
- package/data/server/widget.ts +1 -14
- package/data/urls.ts +4 -9
- package/hooks/use-captcha.tsx +1 -1
- package/middlewares/default.ts +205 -252
- package/package.json +2 -2
- package/plugins.d.ts +0 -10
- package/plugins.js +0 -1
- package/redux/middlewares/checkout.ts +3 -45
- package/redux/middlewares/pre-order/installment-option.ts +1 -9
- package/types/index.ts +9 -20
- package/utils/csrf.ts +1 -1
- package/with-pz-config.js +2 -3
- package/utils/payload-optimizer.ts +0 -481
package/CHANGELOG.md
CHANGED
|
@@ -1,32 +1,16 @@
|
|
|
1
1
|
# @akinon/next
|
|
2
2
|
|
|
3
|
-
## 2.0.
|
|
3
|
+
## 2.0.35-beta.0
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
- 7889b08f: ZERO-4276: Enhance route generation by adding .env loading and custom skip segments support
|
|
15
|
-
- 9f8cd3bc5: ZERO-3449: AI Search Active Filters & Crop Style changes have been implemented
|
|
16
|
-
- bfafa3f49: ZERO-4160: Refactor oauth-login middleware to use fetchCommerce for API calls and improve cookie handling
|
|
17
|
-
- 57d7eb30: ZERO-4276: Refactor route generation logic by removing environment loading and simplifying skip segments handling
|
|
18
|
-
- d99a6a7d: ZERO-3457_1: Fixed the settings prop and made sure everything is customizable.
|
|
19
|
-
- 9db81a71: ZERO-4365: Remove brand `@theme/*` alias imports from library packages
|
|
20
|
-
- 591e345e: ZERO-3855: Enhance credit card payment handling in checkout middlewares
|
|
21
|
-
- 4de5303c5: ZERO-2504: add cookie filter to api client request
|
|
22
|
-
- 95b139dc: ZERO-3795: Remove duplicate entry for SavedCard in PluginComponents map
|
|
23
|
-
- 1d00f2d0: BRDG-16664: Set secure flag for CSRF token cookies in useCaptcha and default middleware
|
|
24
|
-
- 4ac7b2a1e: ZERO-4219: fix masterpass-rest callback route format and double-encoded error cookie
|
|
25
|
-
- 4998a9631: ZERO-4168: Add server-side payload optimization
|
|
26
|
-
- 804d2bd6: ZERO-4536: Add akinon.net domain to CSP frame-ancestors directive
|
|
27
|
-
- 3909d3224: Edit the duplicate Plugin.SimilarProducts in the plugin-module.
|
|
28
|
-
- 6a3d8a63: ZERO-4541: Fix URL query string formatting in getOrders and getOldOrders functions
|
|
29
|
-
- e18836b20: ZERO-4160: Restore scope in Sentry addon configuration in akinon.json
|
|
7
|
+
- cbbbfd75: ZERO-4376: Bootstrap beta cycle (next-main pre-release motor)
|
|
8
|
+
|
|
9
|
+
## 2.0.34
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 4e2ea16b: ZERO-4582: enhance virtual try-on functionality with single and async mutations
|
|
30
14
|
|
|
31
15
|
## 2.0.33
|
|
32
16
|
|
package/api/virtual-try-on.ts
CHANGED
|
@@ -48,20 +48,100 @@ function getLocaleFromRequest(request: NextRequest): string | null {
|
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
export
|
|
52
|
-
|
|
51
|
+
export const createVirtualTryOnHandlers = (opts?: {
|
|
52
|
+
auth?: () => Promise<any>;
|
|
53
|
+
}) => {
|
|
54
|
+
const getIdentityHeaders = async (
|
|
55
|
+
request: NextRequest
|
|
56
|
+
): Promise<Record<string, string>> => {
|
|
57
|
+
const sessionId = request.cookies.get('osessionid')?.value;
|
|
58
|
+
|
|
59
|
+
let userId: string | undefined;
|
|
60
|
+
if (opts?.auth) {
|
|
61
|
+
try {
|
|
62
|
+
const session = await opts.auth();
|
|
63
|
+
if (session?.user?.pk !== undefined && session?.user?.pk !== null) {
|
|
64
|
+
userId = String(session.user.pk);
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
userId = undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
...(sessionId && { 'X-Session-Id': sessionId }),
|
|
73
|
+
...(userId && { 'X-User-Id': userId })
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const GET = async (request: NextRequest) => {
|
|
53
78
|
const { searchParams } = new URL(request.url);
|
|
54
79
|
const endpoint = searchParams.get('endpoint');
|
|
55
80
|
|
|
56
|
-
|
|
57
|
-
|
|
81
|
+
try {
|
|
82
|
+
if (endpoint === 'limited-categories') {
|
|
83
|
+
const now = Date.now();
|
|
84
|
+
|
|
85
|
+
if (
|
|
86
|
+
limitedCategoriesCache &&
|
|
87
|
+
now - limitedCategoriesCache.timestamp < CACHE_TTL
|
|
88
|
+
) {
|
|
89
|
+
return NextResponse.json(limitedCategoriesCache.data, {
|
|
90
|
+
status: 200,
|
|
91
|
+
headers: {
|
|
92
|
+
'Access-Control-Allow-Origin': '*',
|
|
93
|
+
'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
|
|
94
|
+
'Access-Control-Allow-Headers':
|
|
95
|
+
'Content-Type, Accept, Authorization',
|
|
96
|
+
'Cache-Control':
|
|
97
|
+
'public, s-maxage=3600, stale-while-revalidate=7200',
|
|
98
|
+
'X-Virtual-Try-On-Cache-Status': 'HIT'
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/limited-categories`;
|
|
104
|
+
const clientIP = getClientIP(request);
|
|
105
|
+
const locale = getLocaleFromRequest(request);
|
|
106
|
+
const identityHeaders = await getIdentityHeaders(request);
|
|
107
|
+
|
|
108
|
+
const headersToSend = {
|
|
109
|
+
Accept: 'application/json',
|
|
110
|
+
...(locale && { 'Accept-Language': locale }),
|
|
111
|
+
...(request.headers.get('authorization') && {
|
|
112
|
+
Authorization: request.headers.get('authorization')!
|
|
113
|
+
}),
|
|
114
|
+
...(clientIP && {
|
|
115
|
+
'X-Forwarded-For': clientIP
|
|
116
|
+
}),
|
|
117
|
+
...identityHeaders
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const response = await fetch(externalUrl, {
|
|
121
|
+
method: 'GET',
|
|
122
|
+
headers: headersToSend
|
|
123
|
+
});
|
|
58
124
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
125
|
+
let responseData: any;
|
|
126
|
+
const responseText = await response.text();
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
responseData = responseText ? JSON.parse(responseText) : {};
|
|
130
|
+
} catch (parseError) {
|
|
131
|
+
responseData = { category_ids: [] };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!response.ok) {
|
|
135
|
+
responseData = { category_ids: [] };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
limitedCategoriesCache = {
|
|
139
|
+
data: responseData,
|
|
140
|
+
timestamp: Date.now()
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
return NextResponse.json(responseData, {
|
|
144
|
+
status: response.ok ? response.status : 200,
|
|
65
145
|
headers: {
|
|
66
146
|
'Access-Control-Allow-Origin': '*',
|
|
67
147
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
|
|
@@ -69,100 +149,222 @@ export async function GET(request: NextRequest) {
|
|
|
69
149
|
'Content-Type, Accept, Authorization',
|
|
70
150
|
'Cache-Control':
|
|
71
151
|
'public, s-maxage=3600, stale-while-revalidate=7200',
|
|
72
|
-
'X-Virtual-Try-On-Cache-Status': '
|
|
152
|
+
'X-Virtual-Try-On-Cache-Status': 'MISS'
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
} else if (endpoint === 'job-status') {
|
|
156
|
+
const processId = searchParams.get('process_id');
|
|
157
|
+
if (!processId) {
|
|
158
|
+
return NextResponse.json(
|
|
159
|
+
{ error: 'process_id is required' },
|
|
160
|
+
{ status: 400 }
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/process/${encodeURIComponent(
|
|
165
|
+
processId
|
|
166
|
+
)}`;
|
|
167
|
+
const clientIP = getClientIP(request);
|
|
168
|
+
const locale = getLocaleFromRequest(request);
|
|
169
|
+
const identityHeaders = await getIdentityHeaders(request);
|
|
170
|
+
|
|
171
|
+
const headersToSend = {
|
|
172
|
+
Accept: 'application/json',
|
|
173
|
+
...(locale && { 'Accept-Language': locale }),
|
|
174
|
+
...(request.headers.get('authorization') && {
|
|
175
|
+
Authorization: request.headers.get('authorization')!
|
|
176
|
+
}),
|
|
177
|
+
...(clientIP && {
|
|
178
|
+
'X-Forwarded-For': clientIP
|
|
179
|
+
}),
|
|
180
|
+
...identityHeaders
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const response = await fetch(externalUrl, {
|
|
184
|
+
method: 'GET',
|
|
185
|
+
headers: headersToSend
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
let responseData: any;
|
|
189
|
+
const responseText = await response.text();
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
responseData = responseText ? JSON.parse(responseText) : {};
|
|
193
|
+
} catch (parseError) {
|
|
194
|
+
return NextResponse.json(
|
|
195
|
+
{ error: 'Invalid JSON response from job status API' },
|
|
196
|
+
{ status: 500 }
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return NextResponse.json(responseData, {
|
|
201
|
+
status: response.status,
|
|
202
|
+
headers: {
|
|
203
|
+
'Access-Control-Allow-Origin': '*',
|
|
204
|
+
'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
|
|
205
|
+
'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
|
|
73
206
|
}
|
|
74
207
|
});
|
|
75
208
|
}
|
|
76
209
|
|
|
77
|
-
|
|
210
|
+
return NextResponse.json(
|
|
211
|
+
{ error: 'Invalid endpoint for GET method' },
|
|
212
|
+
{ status: 400 }
|
|
213
|
+
);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
if (endpoint === 'limited-categories') {
|
|
216
|
+
return NextResponse.json({ category_ids: [] }, { status: 200 });
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return NextResponse.json(
|
|
220
|
+
{
|
|
221
|
+
status: 'error',
|
|
222
|
+
message: 'Internal server error occurred during virtual try-on request'
|
|
223
|
+
},
|
|
224
|
+
{ status: 500 }
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const POST = async (request: NextRequest) => {
|
|
230
|
+
try {
|
|
231
|
+
const { searchParams } = new URL(request.url);
|
|
232
|
+
const endpoint = searchParams.get('endpoint');
|
|
233
|
+
|
|
234
|
+
const body = await request.json();
|
|
235
|
+
|
|
236
|
+
let externalUrl: string;
|
|
237
|
+
let httpMethod = 'POST';
|
|
238
|
+
|
|
239
|
+
if (endpoint === 'feedback') {
|
|
240
|
+
if (!body.url || typeof body.url !== 'string' || !body.url.trim()) {
|
|
241
|
+
return NextResponse.json(
|
|
242
|
+
{ status: 'error', message: 'URL is required for feedback' },
|
|
243
|
+
{ status: 400 }
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (typeof body.feedback !== 'boolean') {
|
|
247
|
+
return NextResponse.json(
|
|
248
|
+
{ status: 'error', message: 'Feedback must be a boolean value' },
|
|
249
|
+
{ status: 400 }
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/feedback`;
|
|
253
|
+
httpMethod = 'PUT';
|
|
254
|
+
} else if (endpoint === 'single-try-on') {
|
|
255
|
+
externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/virtual-try-on`;
|
|
256
|
+
} else if (endpoint === 'multiple-try-on') {
|
|
257
|
+
externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/multiple-virtual-try-on`;
|
|
258
|
+
} else if (endpoint === 'usage') {
|
|
259
|
+
externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/try-on-usage`;
|
|
260
|
+
} else if (endpoint === 'event') {
|
|
261
|
+
externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/try-on-event`;
|
|
262
|
+
} else {
|
|
263
|
+
return NextResponse.json(
|
|
264
|
+
{ error: 'Invalid endpoint specified' },
|
|
265
|
+
{ status: 400 }
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
78
269
|
const clientIP = getClientIP(request);
|
|
79
270
|
const locale = getLocaleFromRequest(request);
|
|
271
|
+
const identityHeaders = await getIdentityHeaders(request);
|
|
80
272
|
|
|
81
273
|
const headersToSend = {
|
|
82
|
-
|
|
274
|
+
'Content-Type': 'application/json',
|
|
83
275
|
...(locale && { 'Accept-Language': locale }),
|
|
276
|
+
...(httpMethod === 'POST' && { Accept: 'application/json' }),
|
|
84
277
|
...(request.headers.get('authorization') && {
|
|
85
278
|
Authorization: request.headers.get('authorization')!
|
|
86
279
|
}),
|
|
87
280
|
...(clientIP && {
|
|
88
281
|
'X-Forwarded-For': clientIP
|
|
89
|
-
})
|
|
282
|
+
}),
|
|
283
|
+
...identityHeaders
|
|
90
284
|
};
|
|
91
285
|
|
|
92
286
|
const response = await fetch(externalUrl, {
|
|
93
|
-
method:
|
|
94
|
-
headers: headersToSend
|
|
287
|
+
method: httpMethod,
|
|
288
|
+
headers: headersToSend,
|
|
289
|
+
body: JSON.stringify(body)
|
|
95
290
|
});
|
|
96
291
|
|
|
97
|
-
let responseData: any
|
|
292
|
+
let responseData: Record<string, any>;
|
|
98
293
|
const responseText = await response.text();
|
|
99
294
|
|
|
100
295
|
try {
|
|
101
296
|
responseData = responseText ? JSON.parse(responseText) : {};
|
|
102
297
|
} catch (parseError) {
|
|
103
|
-
responseData =
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
responseData = { category_ids: [] };
|
|
298
|
+
responseData =
|
|
299
|
+
endpoint === 'feedback'
|
|
300
|
+
? { error: 'Invalid JSON response from feedback API' }
|
|
301
|
+
: { error: 'Invalid JSON response' };
|
|
108
302
|
}
|
|
109
303
|
|
|
110
|
-
limitedCategoriesCache = {
|
|
111
|
-
data: responseData,
|
|
112
|
-
timestamp: Date.now()
|
|
113
|
-
};
|
|
114
|
-
|
|
115
304
|
return NextResponse.json(responseData, {
|
|
116
|
-
status: response.
|
|
305
|
+
status: response.status,
|
|
117
306
|
headers: {
|
|
118
307
|
'Access-Control-Allow-Origin': '*',
|
|
119
|
-
'Access-Control-Allow-Methods': '
|
|
120
|
-
'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
|
|
121
|
-
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
|
122
|
-
'X-Virtual-Try-On-Cache-Status': 'MISS'
|
|
308
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
309
|
+
'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
|
|
123
310
|
}
|
|
124
311
|
});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
312
|
+
} catch (error) {
|
|
313
|
+
return NextResponse.json(
|
|
314
|
+
{
|
|
315
|
+
status: 'error',
|
|
316
|
+
message:
|
|
317
|
+
'Internal server error occurred during virtual try-on processing'
|
|
318
|
+
},
|
|
319
|
+
{ status: 500 }
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
const PUT = async (request: NextRequest) => {
|
|
325
|
+
try {
|
|
326
|
+
const { searchParams } = new URL(request.url);
|
|
327
|
+
const endpoint = searchParams.get('endpoint');
|
|
328
|
+
|
|
329
|
+
if (endpoint !== 'feedback') {
|
|
128
330
|
return NextResponse.json(
|
|
129
|
-
{ error: '
|
|
331
|
+
{ error: 'PUT method only supports feedback endpoint' },
|
|
130
332
|
{ status: 400 }
|
|
131
333
|
);
|
|
132
334
|
}
|
|
133
335
|
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
336
|
+
const body = await request.json();
|
|
337
|
+
|
|
338
|
+
const externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/feedback`;
|
|
137
339
|
const clientIP = getClientIP(request);
|
|
138
340
|
const locale = getLocaleFromRequest(request);
|
|
341
|
+
const identityHeaders = await getIdentityHeaders(request);
|
|
139
342
|
|
|
140
343
|
const headersToSend = {
|
|
141
|
-
|
|
344
|
+
'Content-Type': 'application/json',
|
|
142
345
|
...(locale && { 'Accept-Language': locale }),
|
|
143
346
|
...(request.headers.get('authorization') && {
|
|
144
347
|
Authorization: request.headers.get('authorization')!
|
|
145
348
|
}),
|
|
146
349
|
...(clientIP && {
|
|
147
350
|
'X-Forwarded-For': clientIP
|
|
148
|
-
})
|
|
351
|
+
}),
|
|
352
|
+
...identityHeaders
|
|
149
353
|
};
|
|
150
354
|
|
|
151
355
|
const response = await fetch(externalUrl, {
|
|
152
|
-
method: '
|
|
153
|
-
headers: headersToSend
|
|
356
|
+
method: 'PUT',
|
|
357
|
+
headers: headersToSend,
|
|
358
|
+
body: JSON.stringify(body)
|
|
154
359
|
});
|
|
155
360
|
|
|
156
|
-
let responseData: any
|
|
361
|
+
let responseData: Record<string, any>;
|
|
157
362
|
const responseText = await response.text();
|
|
158
363
|
|
|
159
364
|
try {
|
|
160
365
|
responseData = responseText ? JSON.parse(responseText) : {};
|
|
161
366
|
} catch (parseError) {
|
|
162
|
-
|
|
163
|
-
{ error: 'Invalid JSON response from job status API' },
|
|
164
|
-
{ status: 500 }
|
|
165
|
-
);
|
|
367
|
+
responseData = { error: 'Invalid JSON response from feedback API' };
|
|
166
368
|
}
|
|
167
369
|
|
|
168
370
|
return NextResponse.json(responseData, {
|
|
@@ -173,210 +375,30 @@ export async function GET(request: NextRequest) {
|
|
|
173
375
|
'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
|
|
174
376
|
}
|
|
175
377
|
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return NextResponse.json(
|
|
179
|
-
{ error: 'Invalid endpoint for GET method' },
|
|
180
|
-
{ status: 400 }
|
|
181
|
-
);
|
|
182
|
-
} catch (error) {
|
|
183
|
-
return NextResponse.json({ category_ids: [] }, { status: 200 });
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export async function POST(request: NextRequest) {
|
|
188
|
-
try {
|
|
189
|
-
const { searchParams } = new URL(request.url);
|
|
190
|
-
const endpoint = searchParams.get('endpoint');
|
|
191
|
-
|
|
192
|
-
const body = await request.json();
|
|
193
|
-
|
|
194
|
-
let externalUrl: string;
|
|
195
|
-
let httpMethod = 'POST';
|
|
196
|
-
|
|
197
|
-
if (endpoint === 'feedback') {
|
|
198
|
-
if (!body.url || typeof body.url !== 'string' || !body.url.trim()) {
|
|
199
|
-
return NextResponse.json(
|
|
200
|
-
{ status: 'error', message: 'URL is required for feedback' },
|
|
201
|
-
{ status: 400 }
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
if (typeof body.feedback !== 'boolean') {
|
|
205
|
-
return NextResponse.json(
|
|
206
|
-
{ status: 'error', message: 'Feedback must be a boolean value' },
|
|
207
|
-
{ status: 400 }
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/feedback`;
|
|
211
|
-
httpMethod = 'PUT';
|
|
212
|
-
} else if (endpoint === 'async-multiple-try-on') {
|
|
213
|
-
externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/async/v1/multiple-virtual-try-on`;
|
|
214
|
-
} else {
|
|
215
|
-
return NextResponse.json(
|
|
216
|
-
{ error: 'Invalid endpoint specified' },
|
|
217
|
-
{ status: 400 }
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const clientIP = getClientIP(request);
|
|
222
|
-
const locale = getLocaleFromRequest(request);
|
|
223
|
-
|
|
224
|
-
const headersToSend = {
|
|
225
|
-
'Content-Type': 'application/json',
|
|
226
|
-
...(locale && { 'Accept-Language': locale }),
|
|
227
|
-
...(httpMethod === 'POST' && { Accept: 'application/json' }),
|
|
228
|
-
...(request.headers.get('authorization') && {
|
|
229
|
-
Authorization: request.headers.get('authorization')!
|
|
230
|
-
}),
|
|
231
|
-
...(clientIP && {
|
|
232
|
-
'X-Forwarded-For': clientIP
|
|
233
|
-
})
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
const fetchOptions: RequestInit = {
|
|
237
|
-
method: httpMethod,
|
|
238
|
-
headers: headersToSend
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
if (httpMethod !== 'GET') {
|
|
242
|
-
fetchOptions.body = JSON.stringify(body);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const response = await fetch(externalUrl, fetchOptions);
|
|
246
|
-
|
|
247
|
-
let responseData: Record<string, any>;
|
|
248
|
-
const responseText = await response.text();
|
|
249
|
-
|
|
250
|
-
if (endpoint === 'feedback') {
|
|
251
|
-
try {
|
|
252
|
-
responseData = responseText ? JSON.parse(responseText) : {};
|
|
253
|
-
} catch (parseError) {
|
|
254
|
-
responseData = { error: 'Invalid JSON response from feedback API' };
|
|
255
|
-
}
|
|
256
|
-
} else {
|
|
257
|
-
try {
|
|
258
|
-
responseData = responseText ? JSON.parse(responseText) : {};
|
|
259
|
-
} catch (parseError) {
|
|
260
|
-
responseData = { error: 'Invalid JSON response' };
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (!response.ok && responseData.error) {
|
|
265
|
-
let userFriendlyMessage = responseData.error;
|
|
266
|
-
|
|
267
|
-
if (
|
|
268
|
-
typeof responseData.error === 'string' &&
|
|
269
|
-
(responseData.error.includes('duplicate key value') ||
|
|
270
|
-
responseData.error.includes('image_pk'))
|
|
271
|
-
) {
|
|
272
|
-
userFriendlyMessage =
|
|
273
|
-
'This image has already been processed. Please try with a different image.';
|
|
274
|
-
} else if (responseData.error.includes('bulk insert images')) {
|
|
275
|
-
userFriendlyMessage =
|
|
276
|
-
'There was an issue processing your image. Please try again with a different image.';
|
|
277
|
-
}
|
|
278
|
-
|
|
378
|
+
} catch (error) {
|
|
279
379
|
return NextResponse.json(
|
|
280
380
|
{
|
|
281
|
-
|
|
282
|
-
message:
|
|
381
|
+
status: 'error',
|
|
382
|
+
message: 'Internal server error occurred during feedback submission',
|
|
383
|
+
error: (error as Error).message
|
|
283
384
|
},
|
|
284
|
-
{
|
|
285
|
-
status: response.status,
|
|
286
|
-
headers: {
|
|
287
|
-
'Access-Control-Allow-Origin': '*',
|
|
288
|
-
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
289
|
-
'Access-Control-Allow-Headers':
|
|
290
|
-
'Content-Type, Accept, Authorization'
|
|
291
|
-
}
|
|
292
|
-
}
|
|
385
|
+
{ status: 500 }
|
|
293
386
|
);
|
|
294
387
|
}
|
|
388
|
+
};
|
|
295
389
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
'Access-Control-Allow-Origin': '*',
|
|
300
|
-
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
301
|
-
'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
} catch (error) {
|
|
305
|
-
return NextResponse.json(
|
|
306
|
-
{
|
|
307
|
-
status: 'error',
|
|
308
|
-
message:
|
|
309
|
-
'Internal server error occurred during virtual try-on processing'
|
|
310
|
-
},
|
|
311
|
-
{ status: 500 }
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
export async function PUT(request: NextRequest) {
|
|
317
|
-
try {
|
|
318
|
-
const { searchParams } = new URL(request.url);
|
|
319
|
-
const endpoint = searchParams.get('endpoint');
|
|
320
|
-
|
|
321
|
-
if (endpoint !== 'feedback') {
|
|
322
|
-
return NextResponse.json(
|
|
323
|
-
{ error: 'PUT method only supports feedback endpoint' },
|
|
324
|
-
{ status: 400 }
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const body = await request.json();
|
|
329
|
-
|
|
330
|
-
const externalUrl = `${VIRTUAL_TRY_ON_API_URL}/api/v1/feedback`;
|
|
331
|
-
const clientIP = getClientIP(request);
|
|
332
|
-
const locale = getLocaleFromRequest(request);
|
|
333
|
-
|
|
334
|
-
const headersToSend = {
|
|
335
|
-
'Content-Type': 'application/json',
|
|
336
|
-
...(locale && { 'Accept-Language': locale }),
|
|
337
|
-
...(request.headers.get('authorization') && {
|
|
338
|
-
Authorization: request.headers.get('authorization')!
|
|
339
|
-
}),
|
|
340
|
-
...(clientIP && {
|
|
341
|
-
'X-Forwarded-For': clientIP
|
|
342
|
-
})
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
const response = await fetch(externalUrl, {
|
|
346
|
-
method: 'PUT',
|
|
347
|
-
headers: headersToSend,
|
|
348
|
-
body: JSON.stringify(body)
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
const responseData = response?.json() || {};
|
|
352
|
-
|
|
353
|
-
return NextResponse.json(responseData, {
|
|
354
|
-
status: response.status,
|
|
390
|
+
const OPTIONS = async () => {
|
|
391
|
+
return new NextResponse(null, {
|
|
392
|
+
status: 200,
|
|
355
393
|
headers: {
|
|
356
394
|
'Access-Control-Allow-Origin': '*',
|
|
357
395
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
|
|
358
396
|
'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
|
|
359
397
|
}
|
|
360
398
|
});
|
|
361
|
-
}
|
|
362
|
-
return NextResponse.json(
|
|
363
|
-
{
|
|
364
|
-
status: 'error',
|
|
365
|
-
message: 'Internal server error occurred during feedback submission',
|
|
366
|
-
error: (error as Error).message
|
|
367
|
-
},
|
|
368
|
-
{ status: 500 }
|
|
369
|
-
);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
399
|
+
};
|
|
372
400
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
'Access-Control-Allow-Origin': '*',
|
|
378
|
-
'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS',
|
|
379
|
-
'Access-Control-Allow-Headers': 'Content-Type, Accept, Authorization'
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
}
|
|
401
|
+
return { GET, POST, PUT, OPTIONS };
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
export const { GET, POST, PUT, OPTIONS } = createVirtualTryOnHandlers();
|
|
@@ -6,7 +6,6 @@ const findBaseDir = require('../utils/find-base-dir');
|
|
|
6
6
|
|
|
7
7
|
const generateRoutes = () => {
|
|
8
8
|
const baseDir = findBaseDir();
|
|
9
|
-
|
|
10
9
|
const srcDir = path.join(baseDir, 'src');
|
|
11
10
|
const appDir = path.join(srcDir, 'app');
|
|
12
11
|
|
|
@@ -35,10 +34,8 @@ const generateRoutes = () => {
|
|
|
35
34
|
'[segment]',
|
|
36
35
|
'[url]',
|
|
37
36
|
'[theme]',
|
|
38
|
-
'[member_type]'
|
|
39
|
-
'[clienttype]'
|
|
37
|
+
'[member_type]'
|
|
40
38
|
];
|
|
41
|
-
|
|
42
39
|
const skipCatchAllRoutes = ['[...prettyurl]', '[...not_found]'];
|
|
43
40
|
|
|
44
41
|
const walkDirectory = (dir, basePath = '') => {
|
package/data/client/checkout.ts
CHANGED
|
@@ -738,6 +738,7 @@ export const checkoutApi = api.injectEndpoints({
|
|
|
738
738
|
},
|
|
739
739
|
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
|
740
740
|
dispatch(setPaymentStepBusy(true));
|
|
741
|
+
dispatch(setCardType(arg));
|
|
741
742
|
await queryFulfilled;
|
|
742
743
|
dispatch(setPaymentStepBusy(false));
|
|
743
744
|
}
|