@akinon/next 1.25.0-rc.4 → 1.25.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,76 +1,23 @@
1
1
  # @akinon/next
2
2
 
3
- ## 1.25.0-rc.4
4
-
5
- ### Patch Changes
6
-
7
- - 183674f: BRDG-9158: Handle locale prefix
8
- - @akinon/eslint-plugin-projectzero@1.25.0-rc.4
9
-
10
- ## 1.25.0-rc.3
3
+ ## 1.25.0
11
4
 
12
5
  ### Minor Changes
13
6
 
14
- - 1289982: ZERO-2521: Add x-forwarded-for header to requests
15
-
16
- ### Patch Changes
17
-
18
- - @akinon/eslint-plugin-projectzero@1.25.0-rc.3
19
-
20
- ## 1.25.0-rc.2
21
-
22
- ### Minor Changes
23
-
24
- - 7e41bdc: BRDG-9158: Remove redirect-three-d page endpoint
25
-
26
- ### Patch Changes
27
-
28
- - @akinon/eslint-plugin-projectzero@1.25.0-rc.2
29
-
30
- ## 1.25.0-rc.1
31
-
32
- ### Minor Changes
33
-
34
- - 6d4aadb: ZERO-2476: Auto install recommendenent extension
7
+ - eae7644: ZERO-2479: optimize Link component with useMemo for href formatting
35
8
  - e20b27f: ZERO-2454:add otp login
36
9
  - e0a945e: ZERO-2494:Add LiveCommerce for managing basket and product actions
37
10
  - a4674c6: ZERO-2461: add optional chaining for referrer header and add locale value for redirect url
38
11
  - 1ec9775: ZERO-2462:add custom span to logs
39
12
  - ab5a493: ZERO-2475:add types [key: string]: any; for unknown attributes
40
- - 3690d3b: ZERO-2485: Check ESLint peerDependency version
41
13
  - 92094d4: ZERO-2477: Update Sentry version and add hideSourceMaps option
42
- - b4452e9: ZERO-2463: Refactor Sentry initialization and add Sentry DSN option to settings
43
- - b2da5e4: Revert ZERO-2435
44
14
  - d3edd3a: ZERO-2499:add style prop in link component
45
- - f76f079: ZERO-2493: Add redirect util function
46
-
47
- ### Patch Changes
48
-
49
- - da1e501: ZERO-2296: Fix ROUTES import
50
- - 95510c7: ZERO-2508: Enable rc branch pipeline and add check-publish-version step
51
- - 2e44646: ZERO-2434: Fix category URL in getCategoryDataHandler function
52
- - 8c7f5bc: ZERO-2440: Pipeline test
53
- - Updated dependencies [95510c7]
54
- - @akinon/eslint-plugin-projectzero@1.25.0-rc.1
55
15
 
56
- ## 1.25.0-rc.0
57
-
58
- ### Minor Changes
59
-
60
- - 6d4aadb: ZERO-2476: Auto install recommendenent extension
61
- - e20b27f: ZERO-2454:add otp login
62
- - a4674c6: ZERO-2461: add optional chaining for referrer header and add locale value for redirect url
63
- - 1ec9775: ZERO-2462:add custom span to logs
64
- - 3690d3b: ZERO-2485: Check ESLint peerDependency version
65
- - b4452e9: ZERO-2463: Refactor Sentry initialization and add Sentry DSN option to settings
66
- - b2da5e4: Revert ZERO-2435
16
+ ## 1.24.1
67
17
 
68
18
  ### Patch Changes
69
19
 
70
- - da1e501: ZERO-2296: Fix ROUTES import
71
- - 2e44646: ZERO-2434: Fix category URL in getCategoryDataHandler function
72
- - 8c7f5bc: ZERO-2440: Pipeline test
73
- - @akinon/eslint-plugin-projectzero@1.25.0-rc.0
20
+ - 95510c7: ZERO-2508: Enable rc branch pipeline and add check-publish-version step
74
21
 
75
22
  ## 1.24.0
76
23
 
package/api/auth.ts CHANGED
@@ -80,21 +80,14 @@ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
80
80
  const language = Settings.localization.locales.find(
81
81
  (item) => item.value === credentials.locale
82
82
  ).apiValue;
83
- const userIp = req.headers['x-forwarded-for']?.toString() ?? '';
84
83
 
85
84
  headers.set('Content-Type', 'application/json');
86
85
  headers.set('cookie', `${req.headers.cookie}`);
87
86
  headers.set('Accept-Language', `${language}`);
88
87
  headers.set('x-currency', req.cookies['pz-currency'] ?? '');
89
- headers.set('x-forwarded-for', userIp);
90
- headers.set(
91
- 'x-app-device',
92
- req.headers['x-app-device']?.toString() ?? ''
93
- );
94
88
 
95
89
  logger.debug('Trying to login/register', {
96
- formType: credentials.formType,
97
- userIp
90
+ formType: credentials.formType
98
91
  });
99
92
 
100
93
  const apiRequest = await fetch(
@@ -106,9 +99,7 @@ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
106
99
  }
107
100
  );
108
101
 
109
- logger.info(`Login/Register request result: ${apiRequest.status}`, {
110
- userIp
111
- });
102
+ logger.info(`Login/Register request result: ${apiRequest.status}`);
112
103
 
113
104
  const response = (await apiRequest.json()) as {
114
105
  key: string;
@@ -229,17 +220,6 @@ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
229
220
  pages: {
230
221
  signIn: ROUTES.AUTH,
231
222
  error: ROUTES.AUTH
232
- },
233
- cookies: {
234
- sessionToken: {
235
- name: `__Secure-next-auth.session-token`,
236
- options: {
237
- httpOnly: true,
238
- sameSite: 'none',
239
- path: '/',
240
- secure: true
241
- }
242
- }
243
223
  }
244
224
  };
245
225
  };
package/api/client.ts CHANGED
@@ -51,6 +51,7 @@ async function proxyRequest(...args) {
51
51
 
52
52
  [
53
53
  'x-forwarded-host',
54
+ 'x-forwarded-for',
54
55
  'x-forwarded-proto',
55
56
  'x-forwarded-port',
56
57
  'x-requested-with',
@@ -23,21 +23,6 @@ function checkDir() {
23
23
 
24
24
  const BASE_DIR = checkDir();
25
25
 
26
- function getProjectZeroNextPackagePath() {
27
- const possiblePaths = [
28
- path.join(BASE_DIR, 'apps/projectzeronext/package.json'),
29
- path.join(BASE_DIR, 'package.json')
30
- ];
31
-
32
- for (const packagePath of possiblePaths) {
33
- if (fs.existsSync(packagePath)) {
34
- return packagePath;
35
- }
36
- }
37
-
38
- throw new Error('Unable to find package.json in expected locations.');
39
- }
40
-
41
26
  try {
42
27
  const akinonNextPackagePath = fs.existsSync(
43
28
  path.join(BASE_DIR, 'packages/akinon-next/package.json')
@@ -49,7 +34,7 @@ try {
49
34
  fs.readFileSync(akinonNextPackagePath, 'utf8')
50
35
  );
51
36
 
52
- const projectZeroNextPackagePath = getProjectZeroNextPackagePath();
37
+ const projectZeroNextPackagePath = path.join(BASE_DIR, 'package.json');
53
38
 
54
39
  const projectZeroNextPackage = JSON.parse(
55
40
  fs.readFileSync(projectZeroNextPackagePath, 'utf8')
package/bin/pz-predev.js CHANGED
@@ -1,6 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const runScript = require('./run-script');
4
-
5
- runScript('pz-install-extensions.js');
6
4
  runScript('pz-install-theme.js');
@@ -4,7 +4,7 @@ import { useLocalization } from '@akinon/next/hooks';
4
4
  import { LocaleUrlStrategy } from '@akinon/next/localization';
5
5
  import { urlLocaleMatcherRegex } from '@akinon/next/utils';
6
6
  import NextLink, { LinkProps as NextLinkProps } from 'next/link';
7
- import { useEffect, useState } from 'react';
7
+ import { useMemo } from 'react';
8
8
 
9
9
  type LinkProps = Omit<
10
10
  React.AnchorHTMLAttributes<HTMLAnchorElement>,
@@ -14,23 +14,24 @@ type LinkProps = Omit<
14
14
 
15
15
  export const Link = ({ children, href, ...rest }: LinkProps) => {
16
16
  const { locale, defaultLocaleValue, localeUrlStrategy } = useLocalization();
17
- const [formattedHref, setFormattedHref] = useState(href ?? '#');
18
-
19
- useEffect(() => {
20
- if (typeof href !== 'string') return;
21
- if (href.startsWith('http')) return;
17
+ const formattedHref = useMemo(() => {
18
+ if (typeof href !== 'string' || href.startsWith('http')) {
19
+ return href;
20
+ }
22
21
 
23
22
  const pathnameWithoutLocale = href.replace(urlLocaleMatcherRegex, '');
24
23
  const hrefWithLocale = `/${locale}${pathnameWithoutLocale}`;
25
24
 
26
25
  if (localeUrlStrategy === LocaleUrlStrategy.ShowAllLocales) {
27
- setFormattedHref(hrefWithLocale);
26
+ return hrefWithLocale;
28
27
  } else if (
29
28
  localeUrlStrategy === LocaleUrlStrategy.HideDefaultLocale &&
30
29
  locale !== defaultLocaleValue
31
30
  ) {
32
- setFormattedHref(hrefWithLocale);
31
+ return hrefWithLocale;
33
32
  }
33
+
34
+ return href || '#';
34
35
  }, [href, defaultLocaleValue, locale, localeUrlStrategy]);
35
36
 
36
37
  return (
@@ -0,0 +1,74 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from 'react';
4
+ import { ROUTES } from 'routes';
5
+ import { useGet3dRedirectFormQuery } from '@akinon/next/data/client/checkout';
6
+ import { LoaderSpinner } from 'components';
7
+ import { useLocalization } from '../../../hooks/use-localization';
8
+ import { getUrlPathWithLocale } from '../../../utils/localization';
9
+ import { useSearchParams } from 'next/navigation';
10
+
11
+ interface RedirectThreeDContentProps {
12
+ sessionId: string;
13
+ }
14
+
15
+ export default function RedirectThreeDContent({
16
+ sessionId
17
+ }: RedirectThreeDContentProps) {
18
+ const searchParams = useSearchParams();
19
+ const { data } = useGet3dRedirectFormQuery();
20
+ const [error, setError] = useState(null);
21
+ const { locale } = useLocalization();
22
+
23
+ useEffect(() => {
24
+ if (data) {
25
+ const fragment = document.createElement('fragment');
26
+ fragment.innerHTML = data.result;
27
+
28
+ const form = fragment.querySelector('form');
29
+
30
+ // a way to determine if response includes a redirection form or not
31
+ if (fragment.querySelector('link[rel="canonical"]') || !form) {
32
+ setError('Redirecting to checkout page. Please wait...');
33
+
34
+ setTimeout(() => {
35
+ let checkoutUrl = `${ROUTES.CHECKOUT}`;
36
+
37
+ // iframe param is used to prevent header and footer rendering
38
+ if (searchParams.get('iframe') === 'true') {
39
+ checkoutUrl = `${checkoutUrl}?iframe=true`;
40
+ }
41
+
42
+ // Use `window.location.href` instead of `router.push`
43
+ // to capture the url change event in iframe
44
+ location.href = getUrlPathWithLocale(checkoutUrl, locale);
45
+ }, 3000);
46
+ return;
47
+ }
48
+
49
+ const pzParamsInput = document.createElement('input');
50
+ pzParamsInput.setAttribute('type', 'hidden');
51
+ pzParamsInput.setAttribute('name', 'pzparams');
52
+ pzParamsInput.setAttribute(
53
+ 'value',
54
+ encodeURIComponent(
55
+ JSON.stringify({
56
+ session: sessionId,
57
+ locale
58
+ })
59
+ )
60
+ );
61
+ form.appendChild(pzParamsInput);
62
+
63
+ form.style.display = 'none';
64
+ document.body.appendChild(form);
65
+ form.submit();
66
+ }
67
+ }, [data]);
68
+
69
+ return (
70
+ <div className="flex items-center justify-center py-20">
71
+ {error ?? <LoaderSpinner />}
72
+ </div>
73
+ );
74
+ }
@@ -0,0 +1,17 @@
1
+ import { cookies } from 'next/headers';
2
+ import { redirect } from 'next/navigation';
3
+ import RedirectThreeDContent from './content';
4
+ import { ROUTES } from 'routes';
5
+
6
+ const RedirectThreeD = async () => {
7
+ const nextCookies = cookies();
8
+ const sessionId = await nextCookies.get('osessionid')?.value;
9
+
10
+ if (!sessionId) {
11
+ return redirect(ROUTES.CHECKOUT);
12
+ }
13
+
14
+ return <RedirectThreeDContent sessionId={sessionId} />;
15
+ };
16
+
17
+ export default RedirectThreeD;
@@ -43,8 +43,7 @@ const withCompleteGpay =
43
43
  'X-Requested-With': 'XMLHttpRequest',
44
44
  'Content-Type': 'application/x-www-form-urlencoded',
45
45
  Cookie: `osessionid=${req.cookies.get('osessionid')?.value ?? ''}`,
46
- 'x-currency': req.cookies.get('pz-currency')?.value ?? '',
47
- 'x-forwarded-for': ip
46
+ 'x-currency': req.cookies.get('pz-currency')?.value ?? ''
48
47
  };
49
48
 
50
49
  try {
@@ -43,8 +43,7 @@ const withCompleteMasterpass =
43
43
  'X-Requested-With': 'XMLHttpRequest',
44
44
  'Content-Type': 'application/x-www-form-urlencoded',
45
45
  Cookie: `osessionid=${req.cookies.get('osessionid')?.value ?? ''}`,
46
- 'x-currency': req.cookies.get('pz-currency')?.value ?? '',
47
- 'x-forwarded-for': ip
46
+ 'x-currency': req.cookies.get('pz-currency')?.value ?? ''
48
47
  };
49
48
 
50
49
  try {
@@ -97,12 +97,6 @@ const withPzDefault =
97
97
  );
98
98
  }
99
99
 
100
- if (req.nextUrl.pathname.includes('/orders/redirect-three-d')) {
101
- return NextResponse.rewrite(
102
- new URL(`${encodeURI(Settings.commerceUrl)}/orders/redirect-three-d/`)
103
- );
104
- }
105
-
106
100
  // If commerce redirects to /orders/checkout/ without locale
107
101
  if (
108
102
  req.nextUrl.pathname.match(new RegExp('^/orders/checkout/$')) &&
@@ -139,8 +133,7 @@ const withPzDefault =
139
133
  Cookie: req.headers.get('cookie') || '',
140
134
  Accept: 'application/json',
141
135
  'Content-Type': 'application/json',
142
- 'X-Requested-With': 'XMLHttpRequest',
143
- 'x-forwarded-for': ip
136
+ 'X-Requested-With': 'XMLHttpRequest'
144
137
  }
145
138
  }
146
139
  );
@@ -15,13 +15,11 @@ const withOauthLogin =
15
15
  const loginCallbackUrlMatcherRegex = new RegExp(
16
16
  /^\/(\w+)\/login\/callback\/?$/
17
17
  );
18
- const ip = req.headers.get('x-forwarded-for') ?? '';
19
18
 
20
19
  const headers = {
21
20
  'x-forwarded-host':
22
21
  req.headers.get('x-forwarded-host') || req.headers.get('host') || '',
23
- 'x-currency': req.cookies.get('pz-currency')?.value ?? '',
24
- 'x-forwarded-for': ip
22
+ 'x-currency': req.cookies.get('pz-currency')?.value ?? ''
25
23
  };
26
24
 
27
25
  if (loginUrlMatcherRegex.test(url.pathname)) {
@@ -44,9 +44,7 @@ const withRedirectionPayment =
44
44
  'X-Requested-With': 'XMLHttpRequest',
45
45
  'Content-Type': 'application/x-www-form-urlencoded',
46
46
  Cookie: req.headers.get('cookie') ?? '',
47
- 'x-currency': req.cookies.get('pz-currency')?.value ?? '',
48
- 'x-forwarded-for': ip
49
-
47
+ 'x-currency': req.cookies.get('pz-currency')?.value ?? ''
50
48
  };
51
49
 
52
50
  try {
@@ -43,8 +43,7 @@ const withThreeDRedirection =
43
43
  'X-Requested-With': 'XMLHttpRequest',
44
44
  'Content-Type': 'application/x-www-form-urlencoded',
45
45
  Cookie: `osessionid=${req.cookies.get('osessionid')?.value ?? ''}`,
46
- 'x-currency': req.cookies.get('pz-currency')?.value ?? '',
47
- 'x-forwarded-for': ip
46
+ 'x-currency': req.cookies.get('pz-currency')?.value ?? ''
48
47
  };
49
48
 
50
49
  try {
@@ -31,9 +31,6 @@ const withUrlRedirection =
31
31
  const request = await fetch(
32
32
  `${settings.commerceUrl}${pathnameWithoutLocale}${url.search}`,
33
33
  {
34
- headers: {
35
- 'x-forwarded-for': ip
36
- },
37
34
  redirect: 'manual',
38
35
  next: {
39
36
  revalidate: 0
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.25.0-rc.4",
4
+ "version": "1.25.0",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -34,8 +34,5 @@
34
34
  "eslint": "^8.14.0",
35
35
  "@akinon/eslint-plugin-projectzero": "1.24.0",
36
36
  "eslint-config-prettier": "8.5.0"
37
- },
38
- "peerDependencies": {
39
- "@akinon/eslint-plugin-projectzero": "1.24.0"
40
37
  }
41
38
  }
package/sentry/index.ts CHANGED
@@ -1,33 +1,27 @@
1
1
  import * as Sentry from '@sentry/nextjs';
2
- import settings from 'settings';
3
2
 
4
3
  const SENTRY_DSN: string =
5
- settings.sentryDsn ||
6
- process.env.SENTRY_DSN ||
7
- process.env.NEXT_PUBLIC_SENTRY_DSN;
4
+ process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
8
5
 
9
6
  export const initSentry = (
10
7
  type: 'Server' | 'Client' | 'Edge',
11
- options: Sentry.BrowserOptions | Sentry.NodeOptions | Sentry.EdgeOptions = {
12
- dsn: SENTRY_DSN,
13
- integrations: [],
14
- tracesSampleRate: 1.0
15
- }
8
+ options: Sentry.BrowserOptions | Sentry.NodeOptions | Sentry.EdgeOptions = {}
16
9
  ) => {
17
- const initOptions = {
18
- ...options,
10
+ // TODO: Handle options with ESLint rules
11
+
12
+ // TODO: Remove Zero Project DSN
13
+
14
+ Sentry.init({
15
+ dsn:
16
+ SENTRY_DSN ||
17
+ 'https://d8558ef8997543deacf376c7d8d7cf4b@o64293.ingest.sentry.io/4504338423742464',
19
18
  initialScope: {
20
19
  tags: {
21
- ...((
22
- options.initialScope as {
23
- tags?: Record<string, string>;
24
- }
25
- )?.tags ?? {}),
26
20
  APP_TYPE: 'ProjectZeroNext',
27
21
  TYPE: type
28
22
  }
29
- }
30
- };
31
-
32
- Sentry.init(initOptions);
23
+ },
24
+ tracesSampleRate: 1.0,
25
+ integrations: []
26
+ });
33
27
  };
package/types/index.ts CHANGED
@@ -71,12 +71,6 @@ export interface Currency {
71
71
 
72
72
  export interface Settings {
73
73
  commerceUrl: string;
74
- /**
75
- * This option allows you to track Sentry events on the client side, in addition to server and edge environments.
76
- *
77
- * It overrides process.env.NEXT_PUBLIC_SENTRY_DSN and process.env.SENTRY_DSN.
78
- */
79
- sentryDsn?: string;
80
74
  redis: {
81
75
  defaultExpirationTime: number;
82
76
  };
@@ -36,8 +36,7 @@ const appFetch = async <T>(
36
36
  init.headers = {
37
37
  ...(init.headers ?? {}),
38
38
  'Accept-Language': currentLocale.apiValue,
39
- 'x-currency': ServerVariables.currency,
40
- 'x-forwarded-for': ip
39
+ 'x-currency': ServerVariables.currency
41
40
  };
42
41
 
43
42
  init.next = {
@@ -1,27 +0,0 @@
1
- const { execSync } = require('child_process');
2
- const fs = require('fs');
3
- const path = require('path');
4
-
5
- function findBaseDir() {
6
- let currentDir = __dirname;
7
- while (currentDir !== path.resolve(currentDir, '..')) {
8
- if (fs.existsSync(path.join(currentDir, 'turbo.json'))) {
9
- return currentDir;
10
- }
11
- currentDir = path.resolve(currentDir, '..');
12
- }
13
- return null;
14
- }
15
-
16
- const BASE_DIR = findBaseDir();
17
-
18
- if (BASE_DIR) {
19
- const extensions = ['bilal-akinon.pznext'];
20
- extensions.forEach((extension) => {
21
- try {
22
- execSync(`code --install-extension ${extension}`, { stdio: 'inherit' });
23
- } catch (error) {
24
- console.error(`Error installing ${extension}:`);
25
- }
26
- });
27
- }
package/utils/redirect.ts DELETED
@@ -1,30 +0,0 @@
1
- import { redirect as nextRedirect, RedirectType } from 'next/navigation';
2
- import Settings from 'settings';
3
- import { headers } from 'next/headers';
4
- import { ServerVariables } from '@akinon/next/utils/server-variables';
5
- import { getUrlPathWithLocale } from '@akinon/next/utils/localization';
6
-
7
- export const redirect = (path: string, type?: RedirectType) => {
8
- const nextHeaders = headers();
9
- const pageUrl = new URL(
10
- nextHeaders.get('pz-url') ?? process.env.NEXT_PUBLIC_URL
11
- );
12
-
13
- const currentLocale = Settings.localization.locales.find(
14
- (locale) => locale.value === ServerVariables.locale
15
- );
16
-
17
- const callbackUrl = pageUrl.pathname;
18
- const redirectUrlWithLocale = getUrlPathWithLocale(
19
- path,
20
- currentLocale.localePath ?? currentLocale.value
21
- );
22
-
23
- const redirectUrl = `${redirectUrlWithLocale}?callbackUrl=${callbackUrl}`;
24
-
25
- if (type) {
26
- return nextRedirect(redirectUrl, type);
27
- } else {
28
- return nextRedirect(redirectUrl);
29
- }
30
- };