@akinon/next 2.0.0-beta.13 → 2.0.0-beta.15
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 +16 -0
- package/data/client/account.ts +12 -1
- package/lib/cache-handler.mjs +8 -2
- package/lib/cache.ts +8 -3
- package/middlewares/complete-gpay.ts +3 -4
- package/middlewares/complete-masterpass.ts +3 -4
- package/middlewares/complete-wallet.ts +3 -4
- package/middlewares/default.ts +6 -1
- package/middlewares/masterpass-rest-callback.ts +17 -7
- package/middlewares/redirection-payment.ts +3 -4
- package/middlewares/saved-card-redirection.ts +3 -4
- package/middlewares/three-d-redirection.ts +3 -4
- package/middlewares/wallet-complete-redirection.ts +3 -4
- package/package.json +2 -2
- package/utils/index.ts +24 -1
- package/with-pz-config.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @akinon/next
|
|
2
2
|
|
|
3
|
+
## 2.0.0-beta.15
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 49c82e1a: ZERO-4047: Remove Sentry configuration from default Next.js config
|
|
8
|
+
- d7e5178b: ZERO-3985: Add query string handling for orders redirection in middleware
|
|
9
|
+
- b59fdd1c: ZERO-4009: Add password reset token validation
|
|
10
|
+
|
|
11
|
+
## 2.0.0-beta.14
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- aef81c5d: ZERO-4034: Refactor checkout API to use dynamic store imports for improved performance
|
|
16
|
+
- 0754c835: ZERO-4063: Add support for optional Redis password in cache handlers
|
|
17
|
+
- c6c5c1cd: ZERO-4128: Use cookies API for pz-pos-error to ensure delivery on 303 redirects
|
|
18
|
+
|
|
3
19
|
## 2.0.0-beta.13
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/data/client/account.ts
CHANGED
|
@@ -77,6 +77,10 @@ interface LoyaltyTransactions {
|
|
|
77
77
|
}[];
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
interface PasswordResetValidateResponse {
|
|
81
|
+
validlink: boolean;
|
|
82
|
+
}
|
|
83
|
+
|
|
80
84
|
const accountApi = api.injectEndpoints({
|
|
81
85
|
endpoints: (builder) => ({
|
|
82
86
|
updatePassword: builder.mutation<void, AccountChangePasswordFormType>({
|
|
@@ -221,6 +225,12 @@ const accountApi = api.injectEndpoints({
|
|
|
221
225
|
}),
|
|
222
226
|
getLoyaltyTransactions: builder.query<LoyaltyTransactions, void>({
|
|
223
227
|
query: () => buildClientRequestUrl(account.loyaltyTransactions)
|
|
228
|
+
}),
|
|
229
|
+
getValidatePasswordResetToken: builder.query<
|
|
230
|
+
PasswordResetValidateResponse,
|
|
231
|
+
string
|
|
232
|
+
>({
|
|
233
|
+
query: (slug) => buildClientRequestUrl(account.passwordReset(slug))
|
|
224
234
|
})
|
|
225
235
|
}),
|
|
226
236
|
overrideExisting: true
|
|
@@ -247,5 +257,6 @@ export const {
|
|
|
247
257
|
usePasswordResetMutation,
|
|
248
258
|
useAnonymizeMutation,
|
|
249
259
|
useGetLoyaltyBalanceQuery,
|
|
250
|
-
useGetLoyaltyTransactionsQuery
|
|
260
|
+
useGetLoyaltyTransactionsQuery,
|
|
261
|
+
useGetValidatePasswordResetTokenQuery
|
|
251
262
|
} = accountApi;
|
package/lib/cache-handler.mjs
CHANGED
|
@@ -364,11 +364,17 @@ CacheHandler.onCreation(async () => {
|
|
|
364
364
|
};
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
const
|
|
367
|
+
const redisOptions = {
|
|
368
368
|
client,
|
|
369
369
|
timeoutMs: CACHE_CONFIG.redis.timeoutMs,
|
|
370
370
|
keyExpirationStrategy: 'EXPIREAT'
|
|
371
|
-
}
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
if (process.env.CACHE_PASSWORD) {
|
|
374
|
+
redisOptions.password = process.env.CACHE_PASSWORD;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const redisHandler = createRedisHandler(redisOptions);
|
|
372
378
|
|
|
373
379
|
const localHandler = createLruHandler(CACHE_CONFIG.lru);
|
|
374
380
|
|
package/lib/cache.ts
CHANGED
|
@@ -155,9 +155,14 @@ export class Cache {
|
|
|
155
155
|
process.env.CACHE_PORT
|
|
156
156
|
}/${process.env.CACHE_BUCKET ?? '0'}`;
|
|
157
157
|
|
|
158
|
-
const
|
|
159
|
-
url: redisUrl
|
|
160
|
-
|
|
158
|
+
const options = {
|
|
159
|
+
url: redisUrl,
|
|
160
|
+
...(process.env.CACHE_PASSWORD && {
|
|
161
|
+
password: process.env.CACHE_PASSWORD
|
|
162
|
+
})
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const client: RedisClientType = createClient(options);
|
|
161
166
|
|
|
162
167
|
client.on('error', (error) => {
|
|
163
168
|
logger.error('Redis client error', { redisUrl, error });
|
|
@@ -110,10 +110,9 @@ const withCompleteGpay =
|
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
// Add error cookie
|
|
113
|
-
errorResponse.
|
|
114
|
-
'
|
|
115
|
-
|
|
116
|
-
);
|
|
113
|
+
errorResponse.cookies.set('pz-pos-error', JSON.stringify(errors), {
|
|
114
|
+
path: '/'
|
|
115
|
+
});
|
|
117
116
|
|
|
118
117
|
return errorResponse;
|
|
119
118
|
}
|
|
@@ -111,10 +111,9 @@ const withCompleteMasterpass =
|
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
// Add error cookie
|
|
114
|
-
errorResponse.
|
|
115
|
-
'
|
|
116
|
-
|
|
117
|
-
);
|
|
114
|
+
errorResponse.cookies.set('pz-pos-error', JSON.stringify(errors), {
|
|
115
|
+
path: '/'
|
|
116
|
+
});
|
|
118
117
|
|
|
119
118
|
return errorResponse;
|
|
120
119
|
}
|
|
@@ -107,10 +107,9 @@ const withCompleteWallet =
|
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
// Add error cookie
|
|
110
|
-
errorResponse.
|
|
111
|
-
'
|
|
112
|
-
|
|
113
|
-
);
|
|
110
|
+
errorResponse.cookies.set('pz-pos-error', JSON.stringify(errors), {
|
|
111
|
+
path: '/'
|
|
112
|
+
});
|
|
114
113
|
|
|
115
114
|
return errorResponse;
|
|
116
115
|
}
|
package/middlewares/default.ts
CHANGED
|
@@ -132,8 +132,13 @@ const withPzDefault =
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
if (req.nextUrl.pathname.startsWith('/orders/redirection/')) {
|
|
135
|
+
const queryString = searchParams.toString();
|
|
135
136
|
return NextResponse.rewrite(
|
|
136
|
-
new URL(
|
|
137
|
+
new URL(
|
|
138
|
+
`${encodeURI(Settings.commerceUrl)}/orders/redirection/${
|
|
139
|
+
queryString ? `?${queryString}` : ''
|
|
140
|
+
}`
|
|
141
|
+
)
|
|
137
142
|
);
|
|
138
143
|
}
|
|
139
144
|
|
|
@@ -137,7 +137,7 @@ const withMasterpassRestCallback =
|
|
|
137
137
|
ip
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
const errorResponse = NextResponse.redirect(
|
|
141
141
|
`${url.origin}${getUrlPathWithLocale(
|
|
142
142
|
'/orders/checkout/',
|
|
143
143
|
req.cookies.get('pz-locale')?.value
|
|
@@ -145,10 +145,17 @@ const withMasterpassRestCallback =
|
|
|
145
145
|
{
|
|
146
146
|
status: 303,
|
|
147
147
|
headers: {
|
|
148
|
-
'Set-Cookie': `pz-pos-error=${JSON.stringify(errors)}; path=/;`
|
|
148
|
+
'Set-Cookie': `pz-pos-error=${encodeURIComponent(JSON.stringify(errors))}; path=/;`
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
);
|
|
152
|
+
|
|
153
|
+
// Add error cookie
|
|
154
|
+
errorResponse.cookies.set('pz-pos-error', JSON.stringify(errors), {
|
|
155
|
+
path: '/'
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return errorResponse;
|
|
152
159
|
}
|
|
153
160
|
|
|
154
161
|
logger.info('Masterpass REST callback response', {
|
|
@@ -184,16 +191,19 @@ const withMasterpassRestCallback =
|
|
|
184
191
|
|
|
185
192
|
logger.info('Redirecting after masterpass REST callback', {
|
|
186
193
|
middleware: 'masterpass-rest-callback',
|
|
187
|
-
redirectUrlWithLocale,
|
|
194
|
+
redirectUrl: redirectUrlWithLocale,
|
|
188
195
|
ip
|
|
189
196
|
});
|
|
190
197
|
|
|
191
198
|
const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
192
199
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
// Forward set-cookie headers from the upstream response
|
|
201
|
+
const setCookieHeader = request.headers.get('set-cookie');
|
|
202
|
+
if (setCookieHeader) {
|
|
203
|
+
setCookieHeader.split(',').forEach((cookie) => {
|
|
204
|
+
nextResponse.headers.append('Set-Cookie', cookie.trim());
|
|
205
|
+
});
|
|
206
|
+
}
|
|
197
207
|
|
|
198
208
|
return nextResponse;
|
|
199
209
|
} catch (error) {
|
|
@@ -111,10 +111,9 @@ const withRedirectionPayment =
|
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
// Add error cookie
|
|
114
|
-
errorResponse.
|
|
115
|
-
'
|
|
116
|
-
|
|
117
|
-
);
|
|
114
|
+
errorResponse.cookies.set('pz-pos-error', JSON.stringify(errors), {
|
|
115
|
+
path: '/'
|
|
116
|
+
});
|
|
118
117
|
|
|
119
118
|
return errorResponse;
|
|
120
119
|
}
|
|
@@ -111,10 +111,9 @@ const withSavedCardRedirection =
|
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
// Add error cookie
|
|
114
|
-
errorResponse.
|
|
115
|
-
'
|
|
116
|
-
|
|
117
|
-
);
|
|
114
|
+
errorResponse.cookies.set('pz-pos-error', JSON.stringify(errors), {
|
|
115
|
+
path: '/'
|
|
116
|
+
});
|
|
118
117
|
|
|
119
118
|
return errorResponse;
|
|
120
119
|
}
|
|
@@ -110,10 +110,9 @@ const withThreeDRedirection =
|
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
// Add error cookie
|
|
113
|
-
errorResponse.
|
|
114
|
-
'
|
|
115
|
-
|
|
116
|
-
);
|
|
113
|
+
errorResponse.cookies.set('pz-pos-error', JSON.stringify(errors), {
|
|
114
|
+
path: '/'
|
|
115
|
+
});
|
|
117
116
|
|
|
118
117
|
return errorResponse;
|
|
119
118
|
}
|
|
@@ -131,10 +131,9 @@ const withWalletCompleteRedirection =
|
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
// Add error cookie
|
|
134
|
-
errorResponse.
|
|
135
|
-
'
|
|
136
|
-
|
|
137
|
-
);
|
|
134
|
+
errorResponse.cookies.set('pz-pos-error', JSON.stringify(errors), {
|
|
135
|
+
path: '/'
|
|
136
|
+
});
|
|
138
137
|
|
|
139
138
|
return errorResponse;
|
|
140
139
|
}
|
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": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.15",
|
|
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": "2.0.0-beta.
|
|
38
|
+
"@akinon/eslint-plugin-projectzero": "2.0.0-beta.15",
|
|
39
39
|
"@babel/core": "7.26.10",
|
|
40
40
|
"@babel/preset-env": "7.26.9",
|
|
41
41
|
"@babel/preset-typescript": "7.27.0",
|
package/utils/index.ts
CHANGED
|
@@ -196,7 +196,13 @@ export const urlLocaleMatcherRegex = new RegExp(
|
|
|
196
196
|
|
|
197
197
|
export const getPosError = () => {
|
|
198
198
|
const cookieValue = getCookie('pz-pos-error');
|
|
199
|
-
|
|
199
|
+
let decoded: string;
|
|
200
|
+
try {
|
|
201
|
+
decoded = cookieValue ? decodeURIComponent(cookieValue) : '{}';
|
|
202
|
+
} catch {
|
|
203
|
+
decoded = cookieValue ?? '{}';
|
|
204
|
+
}
|
|
205
|
+
const error = JSON.parse(decoded);
|
|
200
206
|
|
|
201
207
|
// delete 'pz-pos-error' cookie when refreshing or closing page
|
|
202
208
|
window.addEventListener('beforeunload', () => {
|
|
@@ -206,6 +212,23 @@ export const getPosError = () => {
|
|
|
206
212
|
return error;
|
|
207
213
|
};
|
|
208
214
|
|
|
215
|
+
export const checkPaymentWillRedirect = (response: {
|
|
216
|
+
context_list?: Array<{
|
|
217
|
+
page_name: string;
|
|
218
|
+
page_context?: { context_data?: { redirect_url?: string } };
|
|
219
|
+
}>;
|
|
220
|
+
redirect_url?: string;
|
|
221
|
+
errors?: unknown;
|
|
222
|
+
}): boolean => {
|
|
223
|
+
if (!response) return false;
|
|
224
|
+
|
|
225
|
+
const hasThankYouPage = response.context_list?.some(
|
|
226
|
+
(c) => c.page_name === 'ThankYouPage'
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
return Boolean(hasThankYouPage || response.redirect_url);
|
|
230
|
+
};
|
|
231
|
+
|
|
209
232
|
export const urlSchemes = [
|
|
210
233
|
'http',
|
|
211
234
|
'tel:',
|