@akinon/next 1.89.0-snapshot-ZERO-3400-20250516071934 → 1.90.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,15 +1,12 @@
1
1
  # @akinon/next
2
2
 
3
- ## 1.89.0-snapshot-ZERO-3400-20250516071934
3
+ ## 1.90.0
4
4
 
5
5
  ### Minor Changes
6
6
 
7
- - f8e4cac: ZERO-3343: restrict root hostname to only locale subdomains
8
- - 832bee3: ZERO-3343: add domain to cookie for subdomain locale strategy
9
- - 28a59d4: ZERO-3400: refactor cookie domain logic using fallback host
10
- - 8feabe9: ZERO-3343: add custom NextAuth options support
11
- - 068dc39: ZERO-3343: update get-root-hostname logic
12
- - b6d5bda: ZERO-3343: update changeset config
7
+ - e68e120: ZERO-3398: Add redirectUrlMiddleware to handle redirection based on checkout results
8
+
9
+ ## 1.89.0
13
10
 
14
11
  ## 1.88.0
15
12
 
package/api/auth.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { NextApiRequest, NextApiResponse } from 'next';
2
- import NextAuth, { Session, NextAuthOptions } from 'next-auth';
2
+ import NextAuth, { Session } from 'next-auth';
3
3
  import CredentialProvider from 'next-auth/providers/credentials';
4
4
  import { ROUTES } from 'routes';
5
5
  import { URLS, user } from '../data/urls';
@@ -7,8 +7,6 @@ import Settings from 'settings';
7
7
  import { urlLocaleMatcherRegex } from '../utils';
8
8
  import logger from '@akinon/next/utils/log';
9
9
  import { AuthError } from '../types';
10
- import getRootHostname from '../utils/get-root-hostname';
11
- import { LocaleUrlStrategy } from '../localization';
12
10
 
13
11
  async function getCurrentUser(sessionId: string, currency = '') {
14
12
  const headers = {
@@ -42,15 +40,7 @@ async function getCurrentUser(sessionId: string, currency = '') {
42
40
  };
43
41
  }
44
42
 
45
- type CustomNextAuthOptions = (
46
- req: NextApiRequest,
47
- res: NextApiResponse
48
- ) => Partial<NextAuthOptions>;
49
-
50
- const defaultNextAuthOptions = (
51
- req: NextApiRequest,
52
- res: NextApiResponse
53
- ): NextAuthOptions => {
43
+ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
54
44
  return {
55
45
  providers: [
56
46
  CredentialProvider({
@@ -160,19 +150,7 @@ const defaultNextAuthOptions = (
160
150
 
161
151
  if (sessionId) {
162
152
  const maxAge = 30 * 24 * 60 * 60; // 30 days in seconds
163
- const { localeUrlStrategy } = Settings.localization;
164
-
165
- const fallbackHost =
166
- req.headers['x-forwarded-host']?.toString() ||
167
- req.headers.host?.toString();
168
- const hostname =
169
- process.env.NEXT_PUBLIC_URL || `https://${fallbackHost}`;
170
- const rootHostname =
171
- localeUrlStrategy === LocaleUrlStrategy.Subdomain
172
- ? getRootHostname(hostname)
173
- : null;
174
- const domainOption = rootHostname ? `Domain=${rootHostname};` : '';
175
- const cookieOptions = `Path=/; HttpOnly; Secure; Max-Age=${maxAge}; ${domainOption}`;
153
+ const cookieOptions = `Path=/; HttpOnly; Secure; Max-Age=${maxAge}`;
176
154
 
177
155
  res.setHeader('Set-Cookie', [
178
156
  `osessionid=${sessionId}; ${cookieOptions}`,
@@ -275,36 +253,8 @@ const defaultNextAuthOptions = (
275
253
  };
276
254
  };
277
255
 
278
- const Auth = (
279
- req: NextApiRequest,
280
- res: NextApiResponse,
281
- customOptions?: CustomNextAuthOptions
282
- ) => {
283
- const baseOptions = defaultNextAuthOptions(req, res);
284
- const customOptionsResult = customOptions ? customOptions(req, res) : {};
285
-
286
- const mergedOptions = {
287
- ...baseOptions,
288
- ...customOptionsResult,
289
- providers: [
290
- ...baseOptions.providers,
291
- ...(customOptionsResult.providers || [])
292
- ],
293
- callbacks: {
294
- ...baseOptions.callbacks,
295
- ...customOptionsResult.callbacks
296
- },
297
- events: {
298
- ...baseOptions.events,
299
- ...customOptionsResult.events
300
- },
301
- pages: {
302
- ...baseOptions.pages,
303
- ...customOptionsResult.pages
304
- }
305
- };
306
-
307
- return NextAuth(req, res, mergedOptions);
256
+ const Auth = (req, res) => {
257
+ return NextAuth(req, res, nextAuthOptions(req, res));
308
258
  };
309
259
 
310
260
  export default Auth;
package/api/client.ts CHANGED
@@ -5,8 +5,6 @@ import logger from '../utils/log';
5
5
  import formatCookieString from '../utils/format-cookie-string';
6
6
  import cookieParser from 'set-cookie-parser';
7
7
  import { cookies } from 'next/headers';
8
- import getRootHostname from '../utils/get-root-hostname';
9
- import { LocaleUrlStrategy } from '../localization';
10
8
 
11
9
  interface RouteParams {
12
10
  params: {
@@ -192,23 +190,8 @@ async function proxyRequest(...args) {
192
190
  const responseHeaders: any = {};
193
191
 
194
192
  if (filteredCookies.length > 0) {
195
- const { localeUrlStrategy } = settings.localization;
196
-
197
- const fallbackHost =
198
- req.headers.get('x-forwarded-host') || req.headers.get('host');
199
- const hostname = process.env.NEXT_PUBLIC_URL || `https://${fallbackHost}`;
200
- const rootHostname =
201
- localeUrlStrategy === LocaleUrlStrategy.Subdomain
202
- ? getRootHostname(hostname)
203
- : null;
204
-
205
193
  responseHeaders['set-cookie'] = filteredCookies
206
- .map((cookie) => {
207
- if (!cookie.domain && rootHostname) {
208
- cookie.domain = rootHostname;
209
- }
210
- return formatCookieString(cookie);
211
- })
194
+ .map(formatCookieString)
212
195
  .join(', ');
213
196
  }
214
197
 
@@ -55,8 +55,8 @@ export const Price = (props: NumericFormatProps & PriceProps) => {
55
55
  : formattedValue;
56
56
 
57
57
  const currentCurrencyDecimalScale = Settings.localization.currencies.find(
58
- (currency) => currency.code === currencyCode_
59
- ).decimalScale;
58
+ (currency) => currency?.code === currencyCode_
59
+ )?.decimalScale;
60
60
 
61
61
  return (
62
62
  <NumericFormat
@@ -19,8 +19,6 @@ import withLocale from './locale';
19
19
  import logger from '../utils/log';
20
20
  import { user } from '../data/urls';
21
21
  import { getUrlPathWithLocale } from '../utils/localization';
22
- import getRootHostname from '../utils/get-root-hostname';
23
- import { LocaleUrlStrategy } from '../localization';
24
22
 
25
23
  const withPzDefault =
26
24
  (middleware: NextMiddleware) =>
@@ -298,7 +296,7 @@ const withPzDefault =
298
296
  !req.middlewareParams.found &&
299
297
  Settings.customNotFoundEnabled
300
298
  ) {
301
- const pathname = url.pathname
299
+ let pathname = url.pathname
302
300
  .replace(/\/+$/, '')
303
301
  .split('/');
304
302
  url.pathname = url.pathname.replace(
@@ -343,21 +341,6 @@ const withPzDefault =
343
341
  middlewareResult = NextResponse.rewrite(url);
344
342
  }
345
343
 
346
- const { localeUrlStrategy } =
347
- Settings.localization;
348
-
349
- const fallbackHost =
350
- req.headers.get('x-forwarded-host') ||
351
- req.headers.get('host');
352
- const hostname =
353
- process.env.NEXT_PUBLIC_URL ||
354
- `https://${fallbackHost}`;
355
- const rootHostname =
356
- localeUrlStrategy ===
357
- LocaleUrlStrategy.Subdomain
358
- ? getRootHostname(hostname)
359
- : null;
360
-
361
344
  if (
362
345
  !url.pathname.startsWith(`/${currency}/orders`)
363
346
  ) {
@@ -367,7 +350,6 @@ const withPzDefault =
367
350
  ? locale
368
351
  : defaultLocaleValue,
369
352
  {
370
- domain: rootHostname,
371
353
  sameSite: 'none',
372
354
  secure: true,
373
355
  expires: new Date(
@@ -376,12 +358,10 @@ const withPzDefault =
376
358
  }
377
359
  );
378
360
  }
379
-
380
361
  middlewareResult.cookies.set(
381
362
  'pz-currency',
382
363
  currency,
383
364
  {
384
- domain: rootHostname,
385
365
  sameSite: 'none',
386
366
  secure: true,
387
367
  expires: new Date(
@@ -430,10 +410,7 @@ const withPzDefault =
430
410
  ).json();
431
411
  middlewareResult.cookies.set(
432
412
  'csrftoken',
433
- csrf_token,
434
- {
435
- domain: rootHostname
436
- }
413
+ csrf_token
437
414
  );
438
415
  }
439
416
  } catch (error) {
@@ -13,8 +13,7 @@ const getMatchedLocale = (pathname: string, req: PzNextRequest) => {
13
13
  const { localeUrlStrategy, defaultLocaleValue } = settings.localization;
14
14
 
15
15
  if (localeUrlStrategy === LocaleUrlStrategy.Subdomain) {
16
- const host =
17
- req.headers.get('x-forwarded-host') || req.headers.get('host') || '';
16
+ const host = req.headers.get('x-forwarded-host');
18
17
 
19
18
  if (host) {
20
19
  const subDomain = host.split('.')[0] || '';
@@ -45,9 +44,7 @@ const withLocale =
45
44
  try {
46
45
  const url = req.nextUrl.clone();
47
46
  const matchedLocale = getMatchedLocale(url.pathname, req);
48
- let { localeUrlStrategy } = settings.localization;
49
-
50
- const { defaultLocaleValue, redirectToDefaultLocale } =
47
+ let { localeUrlStrategy, defaultLocaleValue, redirectToDefaultLocale } =
51
48
  settings.localization;
52
49
 
53
50
  localeUrlStrategy =
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.89.0-snapshot-ZERO-3400-20250516071934",
4
+ "version": "1.90.0",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -31,7 +31,7 @@
31
31
  "set-cookie-parser": "2.6.0"
32
32
  },
33
33
  "devDependencies": {
34
- "@akinon/eslint-plugin-projectzero": "1.89.0-snapshot-ZERO-3400-20250516071934",
34
+ "@akinon/eslint-plugin-projectzero": "1.90.0",
35
35
  "@types/react-redux": "7.1.30",
36
36
  "@types/set-cookie-parser": "2.4.7",
37
37
  "@typescript-eslint/eslint-plugin": "6.7.4",
@@ -36,6 +36,7 @@ interface CheckoutResult {
36
36
  errors?: Record<string, string[]>;
37
37
  pre_order?: PreOrder;
38
38
  context_list?: CheckoutContext[];
39
+ redirect_url?: string;
39
40
  };
40
41
  }
41
42
 
@@ -57,6 +58,33 @@ export const errorMiddleware: Middleware = ({ dispatch }: MiddlewareParams) => {
57
58
  };
58
59
  };
59
60
 
61
+ export const redirectUrlMiddleware: Middleware = () => {
62
+ return (next) => (action) => {
63
+ const result: CheckoutResult = next(action);
64
+ const redirectUrl = result?.payload?.redirect_url;
65
+
66
+ if (redirectUrl) {
67
+ const currentLocale = getCookie('pz-locale');
68
+
69
+ let url = redirectUrl;
70
+
71
+ if (currentLocale && !redirectUrl.includes('/orders/redirection')) {
72
+ const { defaultLocaleValue, localeUrlStrategy } = settings.localization;
73
+
74
+ url =
75
+ currentLocale === defaultLocaleValue &&
76
+ localeUrlStrategy !== LocaleUrlStrategy.ShowAllLocales
77
+ ? redirectUrl
78
+ : `/${currentLocale}${redirectUrl}`;
79
+ }
80
+
81
+ window.location.href = url;
82
+ }
83
+
84
+ return result;
85
+ };
86
+ };
87
+
60
88
  export const contextListMiddleware: Middleware = ({
61
89
  dispatch,
62
90
  getState
@@ -5,6 +5,7 @@ import { ROUTES } from 'routes';
5
5
  import type { Middleware } from '@reduxjs/toolkit';
6
6
  import {
7
7
  errorMiddleware,
8
+ redirectUrlMiddleware,
8
9
  contextListMiddleware,
9
10
  hepsiPayMiddleware,
10
11
  walletPaymentMiddleware
@@ -50,6 +51,7 @@ const middlewares = [
50
51
  rtkQueryResponseHandler,
51
52
  rtkQueryErrorHandler,
52
53
  errorMiddleware,
54
+ redirectUrlMiddleware,
53
55
  ...preOrderMiddlewares,
54
56
  contextListMiddleware,
55
57
  hepsiPayMiddleware,
@@ -1,28 +0,0 @@
1
- import Settings from 'settings';
2
-
3
- export default function getRootHostname(
4
- url: string | undefined
5
- ): string | null {
6
- if (!url) return null;
7
-
8
- try {
9
- const urlObj = new URL(url);
10
- const hostname = urlObj.hostname;
11
- const parts = hostname.split('.');
12
-
13
- const firstPart = parts[0];
14
-
15
- const isLocale = Settings.localization.locales.some(
16
- (locale) => locale.value === firstPart
17
- );
18
-
19
- if (isLocale) {
20
- const hostnameAfterLocale = parts.slice(1).join('.');
21
- return `.${hostnameAfterLocale}`;
22
- }
23
-
24
- return `.${hostname}`;
25
- } catch {
26
- return null;
27
- }
28
- }