@akinon/next 1.89.0-rc.2 → 1.89.0-rc.20
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 +158 -0
- package/__tests__/next-config.test.ts +83 -0
- package/__tests__/tsconfig.json +23 -0
- package/babel.config.js +6 -0
- package/bin/pz-prebuild.js +1 -0
- package/bin/pz-run-tests.js +99 -0
- package/components/price.tsx +2 -2
- package/hooks/use-loyalty-availability.ts +21 -0
- package/jest.config.js +19 -0
- package/middlewares/url-redirection.ts +8 -14
- package/package.json +14 -3
- package/redux/middlewares/checkout.ts +43 -2
- package/redux/middlewares/index.ts +2 -0
- package/redux/reducers/checkout.ts +7 -1
- package/utils/redirect-ignore.ts +35 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,163 @@
|
|
|
1
1
|
# @akinon/next
|
|
2
2
|
|
|
3
|
+
## 1.89.0-rc.20
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e68e120: ZERO-3398: Add redirectUrlMiddleware to handle redirection based on checkout results
|
|
8
|
+
|
|
9
|
+
## 1.89.0-rc.19
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 823d82f: ZERO-3393: Enhance error handling in checkout middleware to ensure errors are checked for existence before processing
|
|
14
|
+
|
|
15
|
+
## 1.89.0-rc.18
|
|
16
|
+
|
|
17
|
+
## 1.89.0-rc.17
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- 9b7d0de: ZERO-3393: Improve error handling in checkout middleware to support both object and array error formats
|
|
22
|
+
|
|
23
|
+
## 1.89.0-rc.16
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- 68bbcb2: ZERO-3393: Fix error handling in checkout middleware to check for errors array length
|
|
28
|
+
|
|
29
|
+
## 1.89.0-rc.15
|
|
30
|
+
|
|
31
|
+
## 1.89.0-rc.14
|
|
32
|
+
|
|
33
|
+
## 1.89.0-rc.13
|
|
34
|
+
|
|
35
|
+
## 1.89.0-rc.12
|
|
36
|
+
|
|
37
|
+
## 1.89.0-rc.11
|
|
38
|
+
|
|
39
|
+
## 1.89.0-rc.10
|
|
40
|
+
|
|
41
|
+
### Minor Changes
|
|
42
|
+
|
|
43
|
+
- 5dfeea04: ZERO-2801: Revert ZERO-2801
|
|
44
|
+
- 63774a6: ZERO-3351: Add commerce redirection ignore list functionality and related utility
|
|
45
|
+
- 2d9b2b2c: ZERO-2816: Add segment to headers
|
|
46
|
+
- 5e1feca6: Revert "ZERO-3286: Add notFound handling for chunk URLs starting with \_next"
|
|
47
|
+
- d8fad39: ZERO-3370: include plugins test to build stage
|
|
48
|
+
- 40a46853: ZERO-3182: Optimize basket update mutation with optimistic update
|
|
49
|
+
- f49bb74f: ZERO-3097: Add setCookie to logging in payment redirection middlewares
|
|
50
|
+
- e9541a13: ZERO-2816: Add headers to url
|
|
51
|
+
- 72fd4d67: ZERO-3084: Fix URL search parameters encoding in default middleware
|
|
52
|
+
- c53ef7b9: ZERO-2668: The Link component has been updated to improve the logic for handling href values. Previously, if the href was not a string or started with 'http', it would return the href as is. Now, if the href is not provided, it will default to '#' to prevent any potential errors. Additionally, if the href is a string and does not start with 'http', it will be formatted with the locale and pathname, based on the localeUrlStrategy and defaultLocaleValue. This ensures that the correct href is generated based on the localization settings.
|
|
53
|
+
- 64699d3f: ZERO-2761: Fix invalid import for plugin module
|
|
54
|
+
- bf354de: ZERO-3321: add babel compiler for akinon/next test
|
|
55
|
+
- 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
|
|
56
|
+
- d552629f: ZERO-3182: Refactor basketApi to use invalidatesTags and comment out onQueryStarted logic
|
|
57
|
+
- 448adef: ZERO-3321: move csp test to akinon-next
|
|
58
|
+
- 17f87524: ZERO-2816: Make the incoming currency lowercase
|
|
59
|
+
- 65d3b862: ZERO-3054: Update headers in appFetch
|
|
60
|
+
- bbe18b9f: ZERO-2575: Fix build error
|
|
61
|
+
- 17bfadc4: ZERO-3275: Disable OpenTelemetry monitoring in production environment
|
|
62
|
+
- 4920742c: Disable getCachedTranslations
|
|
63
|
+
- b6e5b624: ZERO-3257: Enhance locale middleware to redirect using existing or default locale and support 303 status for POST requests
|
|
64
|
+
- 6c3629c: ZERO-3321: fix jest tests in akinon-next for standalone projects
|
|
65
|
+
- 7e56d6b6: ZERO-2841: Update api tagTypes
|
|
66
|
+
- dfaceff: ZERO-3356: Add useLoyaltyAvailability hook and update checkout state management
|
|
67
|
+
- 33377cfd: ZERO-3267: Refactor import statement for ROUTES in error-page component
|
|
68
|
+
- 43c182ee: ZERO-3054: Update Redis variable checks to conditionally include CACHE_SECRET
|
|
69
|
+
- 943a239: ZERO-3370: add allowJs in akinon-next test tsconfig
|
|
70
|
+
- eeb20bea: Revert "ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing"
|
|
71
|
+
- 3bf63c8a: ZERO-3286: Add notFound handling for chunk URLs starting with \_next
|
|
72
|
+
- 9be2c081: ZERO-3243: Improve basket update query handling with optimistic updates
|
|
73
|
+
- f2c92d5c: ZERO-2816: Update cookie name
|
|
74
|
+
- 7bd3d992: ZERO-2801: Refactor locale middleware to handle single locale configuration
|
|
75
|
+
- fdd255ee: ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing
|
|
76
|
+
- acf0320: ZERO-3321: remove babel config
|
|
77
|
+
- 387356b: ZERO-3323: Refactor locale filtering logic in URL matcher regex
|
|
78
|
+
- 49eeebfa: ZERO-2909: Add deleteCollectionItem query to wishlistApi
|
|
79
|
+
- 3f9b8d7e: ZERO-2761: Update plugins.js for akinon-next
|
|
80
|
+
- b2ee69b: ZERO-3321: delete unnecessary files
|
|
81
|
+
- 0cabbda: ZERO-3370: replace inline monorepo check with reusable utility
|
|
82
|
+
|
|
83
|
+
## 1.89.0-rc.9
|
|
84
|
+
|
|
85
|
+
### Minor Changes
|
|
86
|
+
|
|
87
|
+
- 5dfeea04: ZERO-2801: Revert ZERO-2801
|
|
88
|
+
- 63774a6: ZERO-3351: Add commerce redirection ignore list functionality and related utility
|
|
89
|
+
- 2d9b2b2c: ZERO-2816: Add segment to headers
|
|
90
|
+
- 5e1feca6: Revert "ZERO-3286: Add notFound handling for chunk URLs starting with \_next"
|
|
91
|
+
- d8fad39: ZERO-3370: include plugins test to build stage
|
|
92
|
+
- 40a46853: ZERO-3182: Optimize basket update mutation with optimistic update
|
|
93
|
+
- f49bb74f: ZERO-3097: Add setCookie to logging in payment redirection middlewares
|
|
94
|
+
- e9541a13: ZERO-2816: Add headers to url
|
|
95
|
+
- 72fd4d67: ZERO-3084: Fix URL search parameters encoding in default middleware
|
|
96
|
+
- c53ef7b9: ZERO-2668: The Link component has been updated to improve the logic for handling href values. Previously, if the href was not a string or started with 'http', it would return the href as is. Now, if the href is not provided, it will default to '#' to prevent any potential errors. Additionally, if the href is a string and does not start with 'http', it will be formatted with the locale and pathname, based on the localeUrlStrategy and defaultLocaleValue. This ensures that the correct href is generated based on the localization settings.
|
|
97
|
+
- 64699d3f: ZERO-2761: Fix invalid import for plugin module
|
|
98
|
+
- bf354de: ZERO-3321: add babel compiler for akinon/next test
|
|
99
|
+
- 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
|
|
100
|
+
- d552629f: ZERO-3182: Refactor basketApi to use invalidatesTags and comment out onQueryStarted logic
|
|
101
|
+
- 448adef: ZERO-3321: move csp test to akinon-next
|
|
102
|
+
- 17f87524: ZERO-2816: Make the incoming currency lowercase
|
|
103
|
+
- 65d3b862: ZERO-3054: Update headers in appFetch
|
|
104
|
+
- bbe18b9f: ZERO-2575: Fix build error
|
|
105
|
+
- 17bfadc4: ZERO-3275: Disable OpenTelemetry monitoring in production environment
|
|
106
|
+
- 4920742c: Disable getCachedTranslations
|
|
107
|
+
- b6e5b624: ZERO-3257: Enhance locale middleware to redirect using existing or default locale and support 303 status for POST requests
|
|
108
|
+
- 6c3629c: ZERO-3321: fix jest tests in akinon-next for standalone projects
|
|
109
|
+
- 7e56d6b6: ZERO-2841: Update api tagTypes
|
|
110
|
+
- dfaceff: ZERO-3356: Add useLoyaltyAvailability hook and update checkout state management
|
|
111
|
+
- 33377cfd: ZERO-3267: Refactor import statement for ROUTES in error-page component
|
|
112
|
+
- 43c182ee: ZERO-3054: Update Redis variable checks to conditionally include CACHE_SECRET
|
|
113
|
+
- 943a239: ZERO-3370: add allowJs in akinon-next test tsconfig
|
|
114
|
+
- eeb20bea: Revert "ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing"
|
|
115
|
+
- 3bf63c8a: ZERO-3286: Add notFound handling for chunk URLs starting with \_next
|
|
116
|
+
- 9be2c081: ZERO-3243: Improve basket update query handling with optimistic updates
|
|
117
|
+
- f2c92d5c: ZERO-2816: Update cookie name
|
|
118
|
+
- 7bd3d992: ZERO-2801: Refactor locale middleware to handle single locale configuration
|
|
119
|
+
- fdd255ee: ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing
|
|
120
|
+
- acf0320: ZERO-3321: remove babel config
|
|
121
|
+
- 387356b: ZERO-3323: Refactor locale filtering logic in URL matcher regex
|
|
122
|
+
- 49eeebfa: ZERO-2909: Add deleteCollectionItem query to wishlistApi
|
|
123
|
+
- 3f9b8d7e: ZERO-2761: Update plugins.js for akinon-next
|
|
124
|
+
- b2ee69b: ZERO-3321: delete unnecessary files
|
|
125
|
+
- 0cabbda: ZERO-3370: replace inline monorepo check with reusable utility
|
|
126
|
+
|
|
127
|
+
## 1.89.0-rc.8
|
|
128
|
+
|
|
129
|
+
### Minor Changes
|
|
130
|
+
|
|
131
|
+
- d8fad39: ZERO-3370: include plugins test to build stage
|
|
132
|
+
- 943a239: ZERO-3370: add allowJs in akinon-next test tsconfig
|
|
133
|
+
- 0cabbda: ZERO-3370: replace inline monorepo check with reusable utility
|
|
134
|
+
|
|
135
|
+
## 1.89.0-rc.7
|
|
136
|
+
|
|
137
|
+
### Minor Changes
|
|
138
|
+
|
|
139
|
+
- dfaceff: ZERO-3356: Add useLoyaltyAvailability hook and update checkout state management
|
|
140
|
+
|
|
141
|
+
## 1.89.0-rc.6
|
|
142
|
+
|
|
143
|
+
## 1.89.0-rc.5
|
|
144
|
+
|
|
145
|
+
## 1.89.0-rc.4
|
|
146
|
+
|
|
147
|
+
### Minor Changes
|
|
148
|
+
|
|
149
|
+
- bf354de: ZERO-3321: add babel compiler for akinon/next test
|
|
150
|
+
- 448adef: ZERO-3321: move csp test to akinon-next
|
|
151
|
+
- 6c3629c: ZERO-3321: fix jest tests in akinon-next for standalone projects
|
|
152
|
+
- acf0320: ZERO-3321: remove babel config
|
|
153
|
+
- b2ee69b: ZERO-3321: delete unnecessary files
|
|
154
|
+
|
|
155
|
+
## 1.89.0-rc.3
|
|
156
|
+
|
|
157
|
+
### Minor Changes
|
|
158
|
+
|
|
159
|
+
- 63774a6: ZERO-3351: Add commerce redirection ignore list functionality and related utility
|
|
160
|
+
|
|
3
161
|
## 1.89.0-rc.2
|
|
4
162
|
|
|
5
163
|
## 1.89.0-rc.1
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import type { NextConfig } from 'next';
|
|
3
|
+
|
|
4
|
+
function findBaseDir() {
|
|
5
|
+
const insideNodeModules = __dirname.includes('node_modules');
|
|
6
|
+
|
|
7
|
+
if (insideNodeModules) {
|
|
8
|
+
return resolve(__dirname, '../../../../');
|
|
9
|
+
} else {
|
|
10
|
+
return resolve(__dirname, '../../../apps/projectzeronext');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const baseDir = findBaseDir();
|
|
15
|
+
|
|
16
|
+
jest.mock('next-pwa', () => {
|
|
17
|
+
return () => (config: NextConfig) => config;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
jest.mock('@sentry/nextjs', () => ({
|
|
21
|
+
withSentryConfig: (config: NextConfig) => config
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
jest.mock('../with-pz-config.js', () => {
|
|
25
|
+
return (config: NextConfig) => {
|
|
26
|
+
const originalHeaders = config.headers;
|
|
27
|
+
|
|
28
|
+
config.headers = async () => {
|
|
29
|
+
const originalHeadersResult = (await originalHeaders?.()) ?? [];
|
|
30
|
+
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
source: '/(.*)',
|
|
34
|
+
headers: [
|
|
35
|
+
{
|
|
36
|
+
key: 'Content-Security-Policy',
|
|
37
|
+
value: 'https://*.akifast.com akifast.com'
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
...originalHeadersResult
|
|
42
|
+
];
|
|
43
|
+
};
|
|
44
|
+
return config;
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
interface Header {
|
|
49
|
+
key: string;
|
|
50
|
+
value: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface HeaderGroup {
|
|
54
|
+
source: string;
|
|
55
|
+
headers: Header[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const nextConfigPath = resolve(baseDir, 'next.config.mjs');
|
|
59
|
+
let nextConfig: any;
|
|
60
|
+
|
|
61
|
+
beforeAll(async () => {
|
|
62
|
+
nextConfig = await import(nextConfigPath);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('Next.js Configuration', () => {
|
|
66
|
+
it('should contain Content-Security-Policy header with akifast domain values', async () => {
|
|
67
|
+
const headers = nextConfig.default.headers;
|
|
68
|
+
expect(headers).toBeDefined();
|
|
69
|
+
|
|
70
|
+
const headersResult = await headers();
|
|
71
|
+
|
|
72
|
+
const cspHeaders = headersResult
|
|
73
|
+
.flatMap((headerGroup: HeaderGroup) => headerGroup.headers)
|
|
74
|
+
.filter((header: Header) => header.key === 'Content-Security-Policy');
|
|
75
|
+
|
|
76
|
+
expect(cspHeaders.length).toBeGreaterThan(0);
|
|
77
|
+
|
|
78
|
+
const lastCspHeader = cspHeaders[cspHeaders.length - 1];
|
|
79
|
+
|
|
80
|
+
expect(lastCspHeader.value).toContain('akifast.com');
|
|
81
|
+
expect(lastCspHeader.value).toContain('https://*.akifast.com');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"display": "Default",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"composite": false,
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationMap": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"inlineSources": false,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"moduleResolution": "node",
|
|
13
|
+
"noUnusedLocals": false,
|
|
14
|
+
"noUnusedParameters": false,
|
|
15
|
+
"preserveWatchOutput": true,
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
"strict": true,
|
|
18
|
+
"jsx": "react-jsx",
|
|
19
|
+
"allowJs": true
|
|
20
|
+
},
|
|
21
|
+
"exclude": ["node_modules"],
|
|
22
|
+
"include": [".", "../."]
|
|
23
|
+
}
|
package/babel.config.js
ADDED
package/bin/pz-prebuild.js
CHANGED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const glob = require('glob');
|
|
7
|
+
const findBaseDir = require('../utils/find-base-dir');
|
|
8
|
+
const checkMonorepo = require('../utils/check-monorepo');
|
|
9
|
+
|
|
10
|
+
const IS_MONOREPO = checkMonorepo() !== null;
|
|
11
|
+
const BASE_DIR = findBaseDir();
|
|
12
|
+
const PLUGINS = require(path.join(BASE_DIR, 'src', 'plugins.js'));
|
|
13
|
+
|
|
14
|
+
function findPluginTestFiles(akinonNextPackagePath) {
|
|
15
|
+
const pluginsRootPath = path.join(
|
|
16
|
+
akinonNextPackagePath,
|
|
17
|
+
'..',
|
|
18
|
+
'..',
|
|
19
|
+
IS_MONOREPO ? 'packages' : '@akinon'
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
if (!fs.existsSync(pluginsRootPath)) {
|
|
23
|
+
console.log('Plugins directory not found:', pluginsRootPath);
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return PLUGINS.reduce((testFiles, pluginName) => {
|
|
28
|
+
const pluginDirectoryPath = path.join(pluginsRootPath, pluginName);
|
|
29
|
+
if (fs.existsSync(pluginDirectoryPath)) {
|
|
30
|
+
const pluginTestFiles = glob.sync('**/*.test.ts', {
|
|
31
|
+
cwd: pluginDirectoryPath,
|
|
32
|
+
absolute: true
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return testFiles.concat(pluginTestFiles);
|
|
36
|
+
} else {
|
|
37
|
+
console.log(`Plugin directory not found: ${pluginName}`);
|
|
38
|
+
}
|
|
39
|
+
return testFiles;
|
|
40
|
+
}, []);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isJestInstalled() {
|
|
44
|
+
try {
|
|
45
|
+
const jestExecutablePath = path.join(
|
|
46
|
+
BASE_DIR,
|
|
47
|
+
'node_modules',
|
|
48
|
+
'.bin',
|
|
49
|
+
'jest'
|
|
50
|
+
);
|
|
51
|
+
return fs.existsSync(jestExecutablePath);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getAkinonNextPackagePath() {
|
|
58
|
+
if (!IS_MONOREPO) {
|
|
59
|
+
return path.resolve(__dirname, '..');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return path.resolve(__dirname, '../../../packages/akinon-next');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!isJestInstalled()) {
|
|
66
|
+
console.error('\x1b[31mError: Jest is not installed in the project!\x1b[0m');
|
|
67
|
+
console.error(
|
|
68
|
+
'Please install all dependencies by running one of the following commands:'
|
|
69
|
+
);
|
|
70
|
+
console.error(' npm install');
|
|
71
|
+
console.error(' yarn install');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const jestExecutablePath = path.join(BASE_DIR, 'node_modules', '.bin', 'jest');
|
|
76
|
+
const akinonNextPackagePath = getAkinonNextPackagePath();
|
|
77
|
+
|
|
78
|
+
const testFiles = [
|
|
79
|
+
...glob.sync('__tests__/**/*.test.ts', {
|
|
80
|
+
cwd: akinonNextPackagePath,
|
|
81
|
+
absolute: true
|
|
82
|
+
}),
|
|
83
|
+
...findPluginTestFiles(akinonNextPackagePath)
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
console.log(`Found ${testFiles.length} test files to run`);
|
|
87
|
+
|
|
88
|
+
const jestArguments = [
|
|
89
|
+
...testFiles,
|
|
90
|
+
`--config ${path.join(akinonNextPackagePath, 'jest.config.js')}`,
|
|
91
|
+
'--runTestsByPath',
|
|
92
|
+
'--passWithNoTests'
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
spawn(jestExecutablePath, jestArguments, {
|
|
96
|
+
cwd: akinonNextPackagePath,
|
|
97
|
+
stdio: 'inherit',
|
|
98
|
+
shell: true
|
|
99
|
+
});
|
package/components/price.tsx
CHANGED
|
@@ -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
|
|
59
|
-
)
|
|
58
|
+
(currency) => currency?.code === currencyCode_
|
|
59
|
+
)?.decimalScale;
|
|
60
60
|
|
|
61
61
|
return (
|
|
62
62
|
<NumericFormat
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useAppSelector } from '../redux/hooks';
|
|
2
|
+
|
|
3
|
+
export const useLoyaltyAvailability = () => {
|
|
4
|
+
const { paymentOptions, unavailablePaymentOptions } = useAppSelector(
|
|
5
|
+
(state) => state.checkout
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
const hasLoyaltyInAvailable = paymentOptions.some(
|
|
9
|
+
(option) =>
|
|
10
|
+
option.payment_type === 'loyalty_money' ||
|
|
11
|
+
option.payment_type === 'loyalty'
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const hasLoyaltyInUnavailable = unavailablePaymentOptions.some(
|
|
15
|
+
(option) =>
|
|
16
|
+
option.payment_type === 'loyalty_money' ||
|
|
17
|
+
option.payment_type === 'loyalty'
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return hasLoyaltyInAvailable || hasLoyaltyInUnavailable;
|
|
21
|
+
};
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
preset: 'ts-jest',
|
|
5
|
+
testEnvironment: 'node',
|
|
6
|
+
rootDir: path.resolve(__dirname),
|
|
7
|
+
roots: [],
|
|
8
|
+
testMatch: ['**/*.test.ts'],
|
|
9
|
+
testPathIgnorePatterns: [],
|
|
10
|
+
transformIgnorePatterns: [],
|
|
11
|
+
transform: {
|
|
12
|
+
'^.+\\.(tsx?|jsx?|mjs?)$': [
|
|
13
|
+
'ts-jest',
|
|
14
|
+
{
|
|
15
|
+
tsconfig: path.resolve(__dirname, '__tests__/tsconfig.json')
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
};
|
|
@@ -4,6 +4,7 @@ import { PzNextRequest } from '.';
|
|
|
4
4
|
import logger from '../utils/log';
|
|
5
5
|
import { urlLocaleMatcherRegex } from '../utils';
|
|
6
6
|
import { getUrlPathWithLocale } from '../utils/localization';
|
|
7
|
+
import { shouldIgnoreRedirect } from '../utils/redirect-ignore';
|
|
7
8
|
import { ROUTES } from 'routes';
|
|
8
9
|
|
|
9
10
|
// This middleware is used to handle url redirections set in Omnitron
|
|
@@ -60,20 +61,13 @@ const withUrlRedirection =
|
|
|
60
61
|
|
|
61
62
|
const setCookies = request.headers.getSetCookie();
|
|
62
63
|
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
)
|
|
71
|
-
)
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
if (shouldIgnoreRedirect) {
|
|
75
|
-
return middleware(req, event);
|
|
76
|
-
}
|
|
64
|
+
if (
|
|
65
|
+
shouldIgnoreRedirect(
|
|
66
|
+
url.pathname,
|
|
67
|
+
req.middlewareParams.rewrites.locale
|
|
68
|
+
)
|
|
69
|
+
) {
|
|
70
|
+
return middleware(req, event);
|
|
77
71
|
}
|
|
78
72
|
|
|
79
73
|
const response = NextResponse.redirect(redirectUrl.toString(), {
|
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-rc.
|
|
4
|
+
"version": "1.89.0-rc.20",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"pz-predev": "bin/pz-predev.js",
|
|
14
14
|
"pz-postdev": "bin/pz-postdev.js"
|
|
15
15
|
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "jest"
|
|
18
|
+
},
|
|
16
19
|
"dependencies": {
|
|
17
20
|
"@opentelemetry/exporter-trace-otlp-http": "0.46.0",
|
|
18
21
|
"@opentelemetry/resources": "1.19.0",
|
|
@@ -31,13 +34,21 @@
|
|
|
31
34
|
"set-cookie-parser": "2.6.0"
|
|
32
35
|
},
|
|
33
36
|
"devDependencies": {
|
|
34
|
-
"@akinon/eslint-plugin-projectzero": "1.89.0-rc.
|
|
37
|
+
"@akinon/eslint-plugin-projectzero": "1.89.0-rc.20",
|
|
38
|
+
"@babel/core": "7.26.10",
|
|
39
|
+
"@babel/preset-env": "7.26.9",
|
|
40
|
+
"@babel/preset-typescript": "7.27.0",
|
|
41
|
+
"@types/jest": "29.5.14",
|
|
35
42
|
"@types/react-redux": "7.1.30",
|
|
36
43
|
"@types/set-cookie-parser": "2.4.7",
|
|
37
44
|
"@typescript-eslint/eslint-plugin": "6.7.4",
|
|
38
45
|
"@typescript-eslint/parser": "6.7.4",
|
|
46
|
+
"babel-jest": "29.7.0",
|
|
39
47
|
"eslint": "8.56.0",
|
|
40
48
|
"eslint-config-next": "14.2.3",
|
|
41
|
-
"eslint-config-prettier": "8.5.0"
|
|
49
|
+
"eslint-config-prettier": "8.5.0",
|
|
50
|
+
"jest": "29.7.0",
|
|
51
|
+
"ts-jest": "29.3.2",
|
|
52
|
+
"typescript": "5.2.2"
|
|
42
53
|
}
|
|
43
54
|
}
|
|
@@ -20,7 +20,8 @@ import {
|
|
|
20
20
|
setShippingOptions,
|
|
21
21
|
setHepsipayAvailability,
|
|
22
22
|
setWalletPaymentData,
|
|
23
|
-
setPayOnDeliveryOtpModalActive
|
|
23
|
+
setPayOnDeliveryOtpModalActive,
|
|
24
|
+
setUnavailablePaymentOptions
|
|
24
25
|
} from '../../redux/reducers/checkout';
|
|
25
26
|
import { RootState, TypedDispatch } from 'redux/store';
|
|
26
27
|
import { checkoutApi } from '../../data/client/checkout';
|
|
@@ -36,6 +37,7 @@ interface CheckoutResult {
|
|
|
36
37
|
errors?: Record<string, string[]>;
|
|
37
38
|
pre_order?: PreOrder;
|
|
38
39
|
context_list?: CheckoutContext[];
|
|
40
|
+
redirect_url?: string;
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
43
|
|
|
@@ -49,7 +51,11 @@ export const errorMiddleware: Middleware = ({ dispatch }: MiddlewareParams) => {
|
|
|
49
51
|
const result: CheckoutResult = next(action);
|
|
50
52
|
const errors = result?.payload?.errors;
|
|
51
53
|
|
|
52
|
-
if (
|
|
54
|
+
if (
|
|
55
|
+
!!errors &&
|
|
56
|
+
((typeof errors === 'object' && Object.keys(errors).length > 0) ||
|
|
57
|
+
(Array.isArray(errors) && errors.length > 0))
|
|
58
|
+
) {
|
|
53
59
|
dispatch(setErrors(errors));
|
|
54
60
|
}
|
|
55
61
|
|
|
@@ -57,6 +63,33 @@ export const errorMiddleware: Middleware = ({ dispatch }: MiddlewareParams) => {
|
|
|
57
63
|
};
|
|
58
64
|
};
|
|
59
65
|
|
|
66
|
+
export const redirectUrlMiddleware: Middleware = () => {
|
|
67
|
+
return (next) => (action) => {
|
|
68
|
+
const result: CheckoutResult = next(action);
|
|
69
|
+
const redirectUrl = result?.payload?.redirect_url;
|
|
70
|
+
|
|
71
|
+
if (redirectUrl) {
|
|
72
|
+
const currentLocale = getCookie('pz-locale');
|
|
73
|
+
|
|
74
|
+
let url = redirectUrl;
|
|
75
|
+
|
|
76
|
+
if (currentLocale && !redirectUrl.includes('/orders/redirection')) {
|
|
77
|
+
const { defaultLocaleValue, localeUrlStrategy } = settings.localization;
|
|
78
|
+
|
|
79
|
+
url =
|
|
80
|
+
currentLocale === defaultLocaleValue &&
|
|
81
|
+
localeUrlStrategy !== LocaleUrlStrategy.ShowAllLocales
|
|
82
|
+
? redirectUrl
|
|
83
|
+
: `/${currentLocale}${redirectUrl}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
window.location.href = url;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return result;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
60
93
|
export const contextListMiddleware: Middleware = ({
|
|
61
94
|
dispatch,
|
|
62
95
|
getState
|
|
@@ -148,6 +181,14 @@ export const contextListMiddleware: Middleware = ({
|
|
|
148
181
|
dispatch(setPaymentOptions(context.page_context.payment_options));
|
|
149
182
|
}
|
|
150
183
|
|
|
184
|
+
if (context.page_context.unavailable_options) {
|
|
185
|
+
dispatch(
|
|
186
|
+
setUnavailablePaymentOptions(
|
|
187
|
+
context.page_context.unavailable_options
|
|
188
|
+
)
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
151
192
|
if (context.page_context.credit_payment_options) {
|
|
152
193
|
dispatch(
|
|
153
194
|
setCreditPaymentOptions(context.page_context.credit_payment_options)
|
|
@@ -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,
|
|
@@ -40,6 +40,7 @@ export interface CheckoutState {
|
|
|
40
40
|
shippingOptions: ShippingOption[];
|
|
41
41
|
dataSourceShippingOptions: DataSource[];
|
|
42
42
|
paymentOptions: PaymentOption[];
|
|
43
|
+
unavailablePaymentOptions: PaymentOption[];
|
|
43
44
|
creditPaymentOptions: CheckoutCreditPaymentOption[];
|
|
44
45
|
selectedCreditPaymentPk: number;
|
|
45
46
|
paymentChoices: PaymentChoice[];
|
|
@@ -94,6 +95,7 @@ const initialState: CheckoutState = {
|
|
|
94
95
|
shippingOptions: [],
|
|
95
96
|
dataSourceShippingOptions: [],
|
|
96
97
|
paymentOptions: [],
|
|
98
|
+
unavailablePaymentOptions: [],
|
|
97
99
|
creditPaymentOptions: [],
|
|
98
100
|
selectedCreditPaymentPk: null,
|
|
99
101
|
paymentChoices: [],
|
|
@@ -157,6 +159,9 @@ const checkoutSlice = createSlice({
|
|
|
157
159
|
setPaymentOptions(state, { payload }) {
|
|
158
160
|
state.paymentOptions = payload;
|
|
159
161
|
},
|
|
162
|
+
setUnavailablePaymentOptions(state, { payload }) {
|
|
163
|
+
state.unavailablePaymentOptions = payload;
|
|
164
|
+
},
|
|
160
165
|
setPaymentChoices(state, { payload }) {
|
|
161
166
|
state.paymentChoices = payload;
|
|
162
167
|
},
|
|
@@ -218,9 +223,10 @@ export const {
|
|
|
218
223
|
setShippingOptions,
|
|
219
224
|
setDataSourceShippingOptions,
|
|
220
225
|
setPaymentOptions,
|
|
226
|
+
setUnavailablePaymentOptions,
|
|
227
|
+
setPaymentChoices,
|
|
221
228
|
setCreditPaymentOptions,
|
|
222
229
|
setSelectedCreditPaymentPk,
|
|
223
|
-
setPaymentChoices,
|
|
224
230
|
setCardType,
|
|
225
231
|
setInstallmentOptions,
|
|
226
232
|
setBankAccounts,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import settings from 'settings';
|
|
2
|
+
import { getUrlPathWithLocale } from './localization';
|
|
3
|
+
|
|
4
|
+
type IgnorePath = string | RegExp;
|
|
5
|
+
|
|
6
|
+
const defaultIgnoreList: string[] = [];
|
|
7
|
+
|
|
8
|
+
const extraIgnores: IgnorePath[] = Array.isArray(
|
|
9
|
+
settings.commerceRedirectionIgnoreList
|
|
10
|
+
)
|
|
11
|
+
? settings.commerceRedirectionIgnoreList.map((path) => {
|
|
12
|
+
if (path === '/users/reset') {
|
|
13
|
+
return /^\/users\/reset\/[^/]+\/[^/]+\/$/;
|
|
14
|
+
}
|
|
15
|
+
return path;
|
|
16
|
+
})
|
|
17
|
+
: [];
|
|
18
|
+
|
|
19
|
+
export function shouldIgnoreRedirect(
|
|
20
|
+
pathname: string,
|
|
21
|
+
locale: string
|
|
22
|
+
): boolean {
|
|
23
|
+
if (!pathname) return false;
|
|
24
|
+
|
|
25
|
+
const rawIgnoreList: IgnorePath[] = [...defaultIgnoreList, ...extraIgnores];
|
|
26
|
+
|
|
27
|
+
return rawIgnoreList.some((ignorePath) => {
|
|
28
|
+
if (ignorePath instanceof RegExp) {
|
|
29
|
+
return ignorePath.test(pathname);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const localized = getUrlPathWithLocale(ignorePath, locale);
|
|
33
|
+
return localized === pathname;
|
|
34
|
+
});
|
|
35
|
+
}
|