@akinon/next 1.24.1 → 1.25.0-rc.1
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 +40 -1
- package/api/auth.ts +13 -2
- package/bin/pz-check-dependencies.js +16 -1
- package/bin/pz-install-extensions.js +27 -0
- package/bin/pz-predev.js +2 -0
- package/components/index.ts +2 -1
- package/components/link.tsx +7 -18
- package/components/live-commerce.tsx +42 -0
- package/data/client/user.ts +12 -0
- package/data/urls.ts +1 -0
- package/package.json +4 -1
- package/sentry/index.ts +20 -14
- package/types/commerce/address.ts +1 -0
- package/types/commerce/category.ts +1 -0
- package/types/commerce/product.ts +4 -0
- package/types/index.ts +6 -0
- package/utils/log.ts +30 -47
- package/utils/redirect.ts +30 -0
- package/with-pz-config.js +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,49 @@
|
|
|
1
1
|
# @akinon/next
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
3
|
+
## 1.25.0-rc.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6d4aadb: ZERO-2476: Auto install recommendenent extension
|
|
8
|
+
- e20b27f: ZERO-2454:add otp login
|
|
9
|
+
- e0a945e: ZERO-2494:Add LiveCommerce for managing basket and product actions
|
|
10
|
+
- a4674c6: ZERO-2461: add optional chaining for referrer header and add locale value for redirect url
|
|
11
|
+
- 1ec9775: ZERO-2462:add custom span to logs
|
|
12
|
+
- ab5a493: ZERO-2475:add types [key: string]: any; for unknown attributes
|
|
13
|
+
- 3690d3b: ZERO-2485: Check ESLint peerDependency version
|
|
14
|
+
- 92094d4: ZERO-2477: Update Sentry version and add hideSourceMaps option
|
|
15
|
+
- b4452e9: ZERO-2463: Refactor Sentry initialization and add Sentry DSN option to settings
|
|
16
|
+
- b2da5e4: Revert ZERO-2435
|
|
17
|
+
- d3edd3a: ZERO-2499:add style prop in link component
|
|
18
|
+
- f76f079: ZERO-2493: Add redirect util function
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
6
21
|
|
|
22
|
+
- da1e501: ZERO-2296: Fix ROUTES import
|
|
7
23
|
- 95510c7: ZERO-2508: Enable rc branch pipeline and add check-publish-version step
|
|
24
|
+
- 2e44646: ZERO-2434: Fix category URL in getCategoryDataHandler function
|
|
25
|
+
- 8c7f5bc: ZERO-2440: Pipeline test
|
|
26
|
+
- Updated dependencies [95510c7]
|
|
27
|
+
- @akinon/eslint-plugin-projectzero@1.25.0-rc.1
|
|
28
|
+
|
|
29
|
+
## 1.25.0-rc.0
|
|
30
|
+
|
|
31
|
+
### Minor Changes
|
|
32
|
+
|
|
33
|
+
- 6d4aadb: ZERO-2476: Auto install recommendenent extension
|
|
34
|
+
- e20b27f: ZERO-2454:add otp login
|
|
35
|
+
- a4674c6: ZERO-2461: add optional chaining for referrer header and add locale value for redirect url
|
|
36
|
+
- 1ec9775: ZERO-2462:add custom span to logs
|
|
37
|
+
- 3690d3b: ZERO-2485: Check ESLint peerDependency version
|
|
38
|
+
- b4452e9: ZERO-2463: Refactor Sentry initialization and add Sentry DSN option to settings
|
|
39
|
+
- b2da5e4: Revert ZERO-2435
|
|
40
|
+
|
|
41
|
+
### Patch Changes
|
|
42
|
+
|
|
43
|
+
- da1e501: ZERO-2296: Fix ROUTES import
|
|
44
|
+
- 2e44646: ZERO-2434: Fix category URL in getCategoryDataHandler function
|
|
45
|
+
- 8c7f5bc: ZERO-2440: Pipeline test
|
|
46
|
+
- @akinon/eslint-plugin-projectzero@1.25.0-rc.0
|
|
8
47
|
|
|
9
48
|
## 1.24.0
|
|
10
49
|
|
package/api/auth.ts
CHANGED
|
@@ -199,8 +199,8 @@ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
|
|
|
199
199
|
);
|
|
200
200
|
|
|
201
201
|
const localeResults = req.headers.referer
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
?.replace(baseUrl, '')
|
|
203
|
+
?.match(urlLocaleMatcherRegex);
|
|
204
204
|
|
|
205
205
|
return `${baseUrl}${localeResults?.[0] || ''}${pathnameWithoutLocale}`;
|
|
206
206
|
}
|
|
@@ -220,6 +220,17 @@ const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
|
|
|
220
220
|
pages: {
|
|
221
221
|
signIn: ROUTES.AUTH,
|
|
222
222
|
error: ROUTES.AUTH
|
|
223
|
+
},
|
|
224
|
+
cookies: {
|
|
225
|
+
sessionToken: {
|
|
226
|
+
name: `__Secure-next-auth.session-token`,
|
|
227
|
+
options: {
|
|
228
|
+
httpOnly: true,
|
|
229
|
+
sameSite: 'none',
|
|
230
|
+
path: '/',
|
|
231
|
+
secure: true
|
|
232
|
+
}
|
|
233
|
+
}
|
|
223
234
|
}
|
|
224
235
|
};
|
|
225
236
|
};
|
|
@@ -23,6 +23,21 @@ 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
|
+
|
|
26
41
|
try {
|
|
27
42
|
const akinonNextPackagePath = fs.existsSync(
|
|
28
43
|
path.join(BASE_DIR, 'packages/akinon-next/package.json')
|
|
@@ -34,7 +49,7 @@ try {
|
|
|
34
49
|
fs.readFileSync(akinonNextPackagePath, 'utf8')
|
|
35
50
|
);
|
|
36
51
|
|
|
37
|
-
const projectZeroNextPackagePath =
|
|
52
|
+
const projectZeroNextPackagePath = getProjectZeroNextPackagePath();
|
|
38
53
|
|
|
39
54
|
const projectZeroNextPackage = JSON.parse(
|
|
40
55
|
fs.readFileSync(projectZeroNextPackagePath, 'utf8')
|
|
@@ -0,0 +1,27 @@
|
|
|
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/bin/pz-predev.js
CHANGED
package/components/index.ts
CHANGED
package/components/link.tsx
CHANGED
|
@@ -6,19 +6,13 @@ import { urlLocaleMatcherRegex } from '@akinon/next/utils';
|
|
|
6
6
|
import NextLink, { LinkProps as NextLinkProps } from 'next/link';
|
|
7
7
|
import { useEffect, useState } from 'react';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
type LinkProps = Omit<
|
|
10
|
+
React.AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
11
|
+
keyof NextLinkProps
|
|
12
|
+
> &
|
|
13
|
+
NextLinkProps;
|
|
14
14
|
|
|
15
|
-
export const Link = ({
|
|
16
|
-
children,
|
|
17
|
-
target,
|
|
18
|
-
className,
|
|
19
|
-
href,
|
|
20
|
-
...rest
|
|
21
|
-
}: LinkProps) => {
|
|
15
|
+
export const Link = ({ children, href, ...rest }: LinkProps) => {
|
|
22
16
|
const { locale, defaultLocaleValue, localeUrlStrategy } = useLocalization();
|
|
23
17
|
const [formattedHref, setFormattedHref] = useState(href ?? '#');
|
|
24
18
|
|
|
@@ -40,12 +34,7 @@ export const Link = ({
|
|
|
40
34
|
}, [href, defaultLocaleValue, locale, localeUrlStrategy]);
|
|
41
35
|
|
|
42
36
|
return (
|
|
43
|
-
<NextLink
|
|
44
|
-
href={formattedHref}
|
|
45
|
-
target={target}
|
|
46
|
-
className={className}
|
|
47
|
-
{...rest}
|
|
48
|
-
>
|
|
37
|
+
<NextLink href={formattedHref} {...rest}>
|
|
49
38
|
{children}
|
|
50
39
|
</NextLink>
|
|
51
40
|
);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { memo, useEffect } from 'react';
|
|
4
|
+
import { useAppDispatch } from '@akinon/next/redux/hooks';
|
|
5
|
+
import { useAddProductMutation } from '../data/client/product';
|
|
6
|
+
import { basketApi } from '@akinon/next/data/client/basket';
|
|
7
|
+
import { useGetBasketQuery } from '@akinon/next/data/client/basket';
|
|
8
|
+
|
|
9
|
+
export const LiveCommerce = memo(function Callback() {
|
|
10
|
+
const dispatch = useAppDispatch();
|
|
11
|
+
const { refetch: refetchBasketData } = useGetBasketQuery();
|
|
12
|
+
const [addProduct] = useAddProductMutation();
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
document.addEventListener('refresh-basket', () => refetchBasketData());
|
|
16
|
+
|
|
17
|
+
document.addEventListener('add-to-cart', async (e: CustomEvent) => {
|
|
18
|
+
const productData = e.detail.data;
|
|
19
|
+
|
|
20
|
+
await addProduct({
|
|
21
|
+
product: productData.product,
|
|
22
|
+
quantity: productData.quantity,
|
|
23
|
+
attributes: productData.attributes
|
|
24
|
+
})
|
|
25
|
+
.unwrap()
|
|
26
|
+
.then((data) =>
|
|
27
|
+
dispatch(
|
|
28
|
+
basketApi.util.updateQueryData(
|
|
29
|
+
'getBasket',
|
|
30
|
+
undefined,
|
|
31
|
+
(draftBasket) => {
|
|
32
|
+
Object.assign(draftBasket, data.basket);
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
return null;
|
|
42
|
+
});
|
package/data/client/user.ts
CHANGED
|
@@ -71,6 +71,17 @@ const userApi = api.injectEndpoints({
|
|
|
71
71
|
body
|
|
72
72
|
})
|
|
73
73
|
}),
|
|
74
|
+
otpLogin: build.mutation<void, { phone: string }>({
|
|
75
|
+
query: ({ phone }) => ({
|
|
76
|
+
url: buildClientRequestUrl(user.otpLogin, {
|
|
77
|
+
contentType: 'application/json'
|
|
78
|
+
}),
|
|
79
|
+
method: 'POST',
|
|
80
|
+
body: {
|
|
81
|
+
phone
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
}),
|
|
74
85
|
changeEmailVerification: build.query<void, string>({
|
|
75
86
|
query: (token) => ({
|
|
76
87
|
url: buildClientRequestUrl(user.changeEmailVerification(token), {
|
|
@@ -110,6 +121,7 @@ export const {
|
|
|
110
121
|
useConfirmEmailVerificationQuery,
|
|
111
122
|
useValidateCaptchaMutation,
|
|
112
123
|
useLogoutMutation,
|
|
124
|
+
useOtpLoginMutation,
|
|
113
125
|
useForgotPasswordMutation,
|
|
114
126
|
useGetAnonymousTrackingMutation
|
|
115
127
|
} = userApi;
|
package/data/urls.ts
CHANGED
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.
|
|
4
|
+
"version": "1.25.0-rc.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -34,5 +34,8 @@
|
|
|
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"
|
|
37
40
|
}
|
|
38
41
|
}
|
package/sentry/index.ts
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
import * as Sentry from '@sentry/nextjs';
|
|
2
|
+
import settings from 'settings';
|
|
2
3
|
|
|
3
4
|
const SENTRY_DSN: string =
|
|
4
|
-
|
|
5
|
+
settings.sentryDsn ||
|
|
6
|
+
process.env.SENTRY_DSN ||
|
|
7
|
+
process.env.NEXT_PUBLIC_SENTRY_DSN;
|
|
5
8
|
|
|
6
9
|
export const initSentry = (
|
|
7
10
|
type: 'Server' | 'Client' | 'Edge',
|
|
8
|
-
options: Sentry.BrowserOptions | Sentry.NodeOptions | Sentry.EdgeOptions = {
|
|
11
|
+
options: Sentry.BrowserOptions | Sentry.NodeOptions | Sentry.EdgeOptions = {
|
|
12
|
+
dsn: SENTRY_DSN,
|
|
13
|
+
integrations: [],
|
|
14
|
+
tracesSampleRate: 1.0
|
|
15
|
+
}
|
|
9
16
|
) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// TODO: Remove Zero Project DSN
|
|
13
|
-
|
|
14
|
-
Sentry.init({
|
|
15
|
-
dsn:
|
|
16
|
-
SENTRY_DSN ||
|
|
17
|
-
'https://d8558ef8997543deacf376c7d8d7cf4b@o64293.ingest.sentry.io/4504338423742464',
|
|
17
|
+
const initOptions = {
|
|
18
|
+
...options,
|
|
18
19
|
initialScope: {
|
|
19
20
|
tags: {
|
|
21
|
+
...((
|
|
22
|
+
options.initialScope as {
|
|
23
|
+
tags?: Record<string, string>;
|
|
24
|
+
}
|
|
25
|
+
)?.tags ?? {}),
|
|
20
26
|
APP_TYPE: 'ProjectZeroNext',
|
|
21
27
|
TYPE: type
|
|
22
28
|
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
Sentry.init(initOptions);
|
|
27
33
|
};
|
package/types/index.ts
CHANGED
|
@@ -71,6 +71,12 @@ 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;
|
|
74
80
|
redis: {
|
|
75
81
|
defaultExpirationTime: number;
|
|
76
82
|
};
|
package/utils/log.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { trace } from '@opentelemetry/api';
|
|
2
|
+
|
|
1
3
|
enum LogLevel {
|
|
2
4
|
TRACE = 'trace',
|
|
3
5
|
DEBUG = 'debug',
|
|
@@ -78,61 +80,42 @@ const writeMsg = ({ level, message, payload }: Message) => {
|
|
|
78
80
|
}
|
|
79
81
|
};
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
message,
|
|
85
|
-
payload
|
|
86
|
-
});
|
|
87
|
-
};
|
|
83
|
+
function createCustomSpan({ level, message, payload }: Message) {
|
|
84
|
+
const tracer = trace.getTracer('pz-next-app');
|
|
85
|
+
const span = tracer.startSpan('custom-operation-log');
|
|
88
86
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
payload
|
|
94
|
-
});
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const warn: LoggerFn = (message, payload) => {
|
|
98
|
-
writeMsg({
|
|
99
|
-
level: LogLevel.WARN,
|
|
100
|
-
message,
|
|
101
|
-
payload
|
|
87
|
+
span.setAttributes({
|
|
88
|
+
level: level,
|
|
89
|
+
message: message,
|
|
90
|
+
payload: payload
|
|
102
91
|
});
|
|
103
|
-
};
|
|
104
92
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
level: LogLevel.DEBUG,
|
|
108
|
-
message,
|
|
109
|
-
payload
|
|
110
|
-
});
|
|
111
|
-
};
|
|
93
|
+
span.end();
|
|
94
|
+
}
|
|
112
95
|
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
level
|
|
96
|
+
const createLogAndSpan = (level: LogLevel, message: string, payload?: any) => {
|
|
97
|
+
const content = {
|
|
98
|
+
level,
|
|
116
99
|
message,
|
|
117
|
-
payload
|
|
118
|
-
}
|
|
119
|
-
};
|
|
100
|
+
payload: JSON.stringify(payload)
|
|
101
|
+
};
|
|
120
102
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
level: LogLevel.FATAL,
|
|
124
|
-
message,
|
|
125
|
-
payload
|
|
126
|
-
});
|
|
103
|
+
writeMsg(content);
|
|
104
|
+
createCustomSpan(content);
|
|
127
105
|
};
|
|
128
106
|
|
|
129
|
-
const logger = {
|
|
130
|
-
trace,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
107
|
+
const logger: Record<LogLevel, LoggerFn> = {
|
|
108
|
+
trace: (message, payload) =>
|
|
109
|
+
createLogAndSpan(LogLevel.TRACE, message, payload),
|
|
110
|
+
debug: (message, payload) =>
|
|
111
|
+
createLogAndSpan(LogLevel.DEBUG, message, payload),
|
|
112
|
+
info: (message, payload) => createLogAndSpan(LogLevel.INFO, message, payload),
|
|
113
|
+
warn: (message, payload) => createLogAndSpan(LogLevel.WARN, message, payload),
|
|
114
|
+
error: (message, payload) =>
|
|
115
|
+
createLogAndSpan(LogLevel.ERROR, message, payload),
|
|
116
|
+
fatal: (message, payload) =>
|
|
117
|
+
createLogAndSpan(LogLevel.FATAL, message, payload),
|
|
118
|
+
silent: () => {}
|
|
136
119
|
};
|
|
137
120
|
|
|
138
121
|
export default logger;
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
};
|