@akinon/next 1.102.0-rc.79 → 1.103.0-rc.80

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,18 +1,6 @@
1
1
  # @akinon/next
2
2
 
3
- ## 1.102.0-rc.79
4
-
5
- ### Minor Changes
6
-
7
- - 9a3885b: ZERO-3660: skip catch-all not_found route in generate route script
8
-
9
- ## 1.102.0-rc.78
10
-
11
- ### Minor Changes
12
-
13
- - d512ea2: ZERO-3656: update setLoyaltyData mutation to accept string type
14
-
15
- ## 1.102.0-rc.77
3
+ ## 1.103.0-rc.80
16
4
 
17
5
  ### Minor Changes
18
6
 
@@ -60,6 +48,7 @@
60
48
  - 9dc7298a: ZERO-3416: Refactor Accordion component to enhance props and improve styling flexibility
61
49
  - 33377cfd: ZERO-3267: Refactor import statement for ROUTES in error-page component
62
50
  - 43c182eef: ZERO-3054: Update Redis variable checks to conditionally include CACHE_SECRET
51
+ - d512ea2: ZERO-3656: update setLoyaltyData mutation to accept string type
63
52
  - c480272c: ZERO-3531: Refactor checkoutApi: Remove unnecessary invalidatesTags property from POST request from sample products
64
53
  - facf1ada: ZERO-3445: Add SameSite and Secure attributes
65
54
  - 3b255fe: ZERO-3629 :edit warnings in build
@@ -79,6 +68,13 @@
79
68
  - 3f9b8d7e7: ZERO-2761: Update plugins.js for akinon-next
80
69
  - 0e823010: ZERO-3531: Add saveSampleProducts endpoint
81
70
 
71
+ ## 1.102.0
72
+
73
+ ### Minor Changes
74
+
75
+ - 6b949cb: ZERO-3615: Refactor product data handling and improve 404 error handling
76
+ - 9a3885b: ZERO-3660: skip catch-all not_found route in generate route script
77
+
82
78
  ## 1.101.0
83
79
 
84
80
  ### Minor Changes
@@ -6,7 +6,7 @@ import { ServerVariables } from '../../utils/server-variables';
6
6
  import logger from '../../utils/log';
7
7
 
8
8
  type GetProduct = {
9
- pk: number;
9
+ pk: number | string;
10
10
  locale?: string;
11
11
  currency?: string;
12
12
  searchParams?: URLSearchParams;
@@ -23,9 +23,21 @@ const getProductDataHandler = ({
23
23
  headers
24
24
  }: GetProduct) => {
25
25
  return async function () {
26
+ // Convert pk to number if it's a string and validate
27
+ const numericPk = typeof pk === 'string' ? parseInt(pk, 10) : pk;
28
+
29
+ if (isNaN(numericPk)) {
30
+ logger.warn('Invalid product pk provided', {
31
+ handler: 'getProductDataHandler',
32
+ pk,
33
+ numericPk
34
+ });
35
+ return null;
36
+ }
37
+
26
38
  let url = groupProduct
27
- ? product.getGroupProductByPk(pk)
28
- : product.getProductByPk(pk);
39
+ ? product.getGroupProductByPk(numericPk)
40
+ : product.getProductByPk(numericPk);
29
41
 
30
42
  if (searchParams) {
31
43
  url +=
@@ -35,10 +47,8 @@ const getProductDataHandler = ({
35
47
  .join('&');
36
48
  }
37
49
 
38
- let data: ProductResult;
39
-
40
50
  try {
41
- data = await appFetch<ProductResult>({
51
+ const data = await appFetch<ProductResult>({
42
52
  url,
43
53
  locale,
44
54
  currency,
@@ -50,23 +60,21 @@ const getProductDataHandler = ({
50
60
  }
51
61
  }
52
62
  });
53
- } catch (error) {
54
- logger.error('Failed to fetch product data', {
55
- handler: 'getProductDataHandler',
56
- pk,
57
- error: error.message,
58
- url
59
- });
60
- return null;
61
- }
62
63
 
63
- const categoryUrl = product.categoryUrl(data.product.pk);
64
+ // If product data is not found, return null to trigger 404
65
+ if (!data?.product?.pk) {
66
+ logger.warn('Product not found', {
67
+ handler: 'getProductDataHandler',
68
+ pk: numericPk,
69
+ hasData: !!data,
70
+ hasProduct: !!data?.product
71
+ });
72
+ return null;
73
+ }
64
74
 
65
- let productCategoryData: ProductCategoryResult;
66
- let breadcrumbData: { menu?: unknown } = {};
75
+ const categoryUrl = product.categoryUrl(data.product.pk);
67
76
 
68
- try {
69
- productCategoryData = await appFetch<ProductCategoryResult>({
77
+ const productCategoryData = await appFetch<ProductCategoryResult>({
70
78
  url: categoryUrl,
71
79
  locale,
72
80
  currency,
@@ -81,19 +89,16 @@ const getProductDataHandler = ({
81
89
  const menuItemModel = productCategoryData?.results[0]?.menuitemmodel;
82
90
 
83
91
  if (!menuItemModel) {
84
- logger.warn(
85
- 'menuItemModel is undefined, skipping breadcrumbData fetch',
86
- {
87
- handler: 'getProductDataHandler',
88
- pk
89
- }
90
- );
92
+ logger.warn('menuItemModel is undefined, skipping breadcrumbData fetch', {
93
+ handler: 'getProductDataHandler',
94
+ pk: numericPk
95
+ });
91
96
  return { data, breadcrumbData: undefined };
92
97
  }
93
98
 
94
99
  const breadcrumbUrl = product.breadcrumbUrl(menuItemModel);
95
100
 
96
- breadcrumbData = await appFetch<{ menu?: unknown }>({
101
+ const breadcrumbData = await appFetch<any>({
97
102
  url: breadcrumbUrl,
98
103
  locale,
99
104
  currency,
@@ -104,19 +109,19 @@ const getProductDataHandler = ({
104
109
  }
105
110
  }
106
111
  });
112
+
113
+ return {
114
+ data,
115
+ breadcrumbData: breadcrumbData?.menu
116
+ };
107
117
  } catch (error) {
108
- logger.warn('Failed to fetch breadcrumb data', {
118
+ logger.error('Error in getProductDataHandler', {
109
119
  handler: 'getProductDataHandler',
110
- pk,
120
+ pk: numericPk,
111
121
  error: error.message
112
122
  });
113
- // Continue without breadcrumb data
123
+ return null;
114
124
  }
115
-
116
- return {
117
- data,
118
- breadcrumbData: breadcrumbData?.menu
119
- };
120
125
  };
121
126
  };
122
127
 
@@ -128,9 +133,12 @@ export const getProductData = async ({
128
133
  groupProduct,
129
134
  headers
130
135
  }: GetProduct) => {
131
- return Cache.wrap(
136
+ // Convert pk to number for cache key if it's a string
137
+ const numericPkForCache = typeof pk === 'string' ? parseInt(pk, 10) : pk;
138
+
139
+ const result = await Cache.wrap(
132
140
  CacheKey[groupProduct ? 'GroupProduct' : 'Product'](
133
- pk,
141
+ numericPkForCache,
134
142
  searchParams ?? new URLSearchParams()
135
143
  ),
136
144
  locale,
@@ -147,4 +155,13 @@ export const getProductData = async ({
147
155
  compressed: true
148
156
  }
149
157
  );
158
+
159
+ // If product data is not found, throw 404 error
160
+ if (!result) {
161
+ const error = new Error('Product not found') as Error & { status: number };
162
+ error.status = 404;
163
+ throw error;
164
+ }
165
+
166
+ return result;
150
167
  };
@@ -214,7 +214,6 @@ const withPzDefault =
214
214
 
215
215
  req.middlewareParams = {
216
216
  commerceUrl,
217
- found: true,
218
217
  rewrites: {}
219
218
  };
220
219
 
@@ -30,7 +30,6 @@ export {
30
30
  export interface PzNextRequest extends NextRequest {
31
31
  middlewareParams: {
32
32
  commerceUrl: string;
33
- found: boolean;
34
33
  rewrites: {
35
34
  locale?: string;
36
35
  prettyUrl?: string;
@@ -123,8 +123,6 @@ const withPrettyUrl =
123
123
  return middleware(req, event);
124
124
  }
125
125
 
126
- req.middlewareParams.found = false;
127
-
128
126
  return middleware(req, event);
129
127
  };
130
128
 
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.102.0-rc.79",
4
+ "version": "1.103.0-rc.80",
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": "1.102.0-rc.79",
38
+ "@akinon/eslint-plugin-projectzero": "1.103.0-rc.80",
39
39
  "@babel/core": "7.26.10",
40
40
  "@babel/preset-env": "7.26.9",
41
41
  "@babel/preset-typescript": "7.27.0",