@akinon/next 1.95.0-snapshot-ZERO-3586-20250903094652 → 1.96.0-rc.55

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,6 @@
1
1
  # @akinon/next
2
2
 
3
- ## 1.95.0-snapshot-ZERO-3586-20250903094652
4
-
5
- ### Minor Changes
6
-
7
- - 5dfeea04: ZERO-2801: Revert ZERO-2801
8
- - 823d82f9: ZERO-3393: Enhance error handling in checkout middleware to ensure errors are checked for existence before processing
9
- - 412f0e2: ZERO-3586: Enhance caching functionality by adding support for compressed data storage and retrieval, along with a new method for setting multiple key-value pairs.
10
- - 28c7ea79: ZERO-3427: Refactor redirect utility to handle undefined URL and improve locale handling
11
- - e1aa030d: ZERO-3473: Refactor locale handling to prioritize cookie value for matched locale
12
- - 63774a6a: ZERO-3351: Add commerce redirection ignore list functionality and related utility
13
- - 2d9b2b2c: ZERO-2816: Add segment to headers
14
- - 5e1feca6: Revert "ZERO-3286: Add notFound handling for chunk URLs starting with \_next"
15
- - 40a46853: ZERO-3182: Optimize basket update mutation with optimistic update
16
- - 5f7edd6: ZERO-3571: Enhance Jest configuration by adding base directory resolution and module name mapping
17
- - 68bbcb27: ZERO-3393: Fix error handling in checkout middleware to check for errors array length
18
- - d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
19
- - b55acb76: ZERO-2577: Fix pagination bug and update usePagination hook and ensure pagination controls rendering correctly
20
- - f49bb74f: ZERO-3097: Add setCookie to logging in payment redirection middlewares
21
- - 0ad91bbd: ZERO-3489: Improve error handling in data fetching across multiple pages and server functions
22
- - 143be2b9: ZERO-3457: Crop styles are customizable and logic improved for rendering similar products modal
23
- - e9541a13: ZERO-2816: Add headers to url
24
- - 9b7d0de6: ZERO-3393: Improve error handling in checkout middleware to support both object and array error formats
25
- - 72fd4d67: ZERO-3084: Fix URL search parameters encoding in default middleware
26
- - c53ef7b95: 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.
27
- - a8539c8c: ZERO-3439: Enhance locale handling in middleware and redirect utility
28
- - 16aff543: ZERO-3431: Add test script for redirect utility in package.json
29
- - 64699d3f: ZERO-2761: Fix invalid import for plugin module
30
- - 9f8cd3bc: ZERO-3449: AI Search Active Filters & Crop Style changes have been implemented
31
- - e974d8e8: ZERO-3406: Fix rc build
32
- - 89ce46fc: ZERO-3493: return 404 status code for pz-not-found pages
33
- - 8645d90: ZERO-3574:Refactor redirect tests: streamline mock setup, enhance locale handling, and improve URL path resolution logic
34
- - 7eb51ca9: ZERO-3424 :Update package versions
35
- - 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
36
- - 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
37
- - d552629f: ZERO-3182: Refactor basketApi to use invalidatesTags and comment out onQueryStarted logic
38
- - 17f87524: ZERO-2816: Make the incoming currency lowercase
39
- - 65d3b862: ZERO-3054: Update headers in appFetch
40
- - c39c7000: ZERO-3420: Refactor Modal component
41
- - bbe18b9ff: ZERO-2575: Fix build error
42
- - 35dfb8f8: ZERO-3363: Refactor URL handling in checkout and redirection middlewares to use url.origin instead of process.env.NEXT_PUBLIC_URL
43
- - 4920742c: Disable getCachedTranslations
44
- - b6e5b624: ZERO-3257: Enhance locale middleware to redirect using existing or default locale and support 303 status for POST requests
45
- - 0de55738: ZERO-3418: Update remotePatterns hostname to allow all subdomains
46
- - 7e56d6b6: ZERO-2841: Update api tagTypes
47
- - d99a6a7d: ZERO-3457: Fixed the settings prop and made sure everything is customizable.
48
- - 9dc7298a: ZERO-3416: Refactor Accordion component to enhance props and improve styling flexibility
49
- - 33377cfd: ZERO-3267: Refactor import statement for ROUTES in error-page component
50
- - 43c182ee: ZERO-3054: Update Redis variable checks to conditionally include CACHE_SECRET
51
- - c480272: ZERO-3531: Refactor checkoutApi: Remove unnecessary invalidatesTags property from POST request from sample products
52
- - b00a90b1: ZERO-3436: Preserve query params on redirect
53
- - facf1ada: ZERO-3445: Add SameSite and Secure attributes
54
- - 26b2d0b: ZERO-3571: Remove test script execution from prebuild and simplify Jest module name mapping
55
- - eeb20bea: Revert "ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing"
56
- - 99b6e7b9: ZERO-3421: Enhance Sentry error handling by adding network error detection logic and refining initialization options
57
- - 3bf63c8a: ZERO-3286: Add notFound handling for chunk URLs starting with \_next
58
- - 9be2c081: ZERO-3243: Improve basket update query handling with optimistic updates
59
- - f7fd459b: ZERO-3445: Refactor setCookie function to include domain handling and improve cookie string construction
60
- - 4de5303c: ZERO-2504: add cookie filter to api client request
61
- - dc678c3: ZERO-3523: Enhance redirect tests with dynamic locale handling and settings integration
62
- - f2c92d5c: ZERO-2816: Update cookie name
63
- - a420947d: ZERO-3517: Fix optional chaining for rawData in error logging for category data handlers
64
- - 7bd3d992: ZERO-2801: Refactor locale middleware to handle single locale configuration
65
- - acd2afdf: ZERO-3431: Fix import statement for findBaseDir in next-config test
66
- - 2d3f1788: ZERO-3417: Enhance FileInput component with additional props for customization
67
- - fdd255ee: ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing
68
- - 49eeebfa: ZERO-2909: Add deleteCollectionItem query to wishlistApi
69
- - 3f9b8d7e: ZERO-2761: Update plugins.js for akinon-next
70
- - cbdb5c14: ZERO-3448: fix set cookie domain handling for subdomain locale strategy
71
- - 0e823010: ZERO-3531: Add saveSampleProducts endpoint
72
-
73
- ## 1.95.0-rc.54
3
+ ## 1.96.0-rc.55
74
4
 
75
5
  ### Minor Changes
76
6
 
@@ -98,7 +28,7 @@
98
28
  - 64699d3ff: ZERO-2761: Fix invalid import for plugin module
99
29
  - 9f8cd3bc: ZERO-3449: AI Search Active Filters & Crop Style changes have been implemented
100
30
  - e974d8e8: ZERO-3406: Fix rc build
101
- - 89ce46f: ZERO-3493: return 404 status code for pz-not-found pages
31
+ - 89ce46fc: ZERO-3493: return 404 status code for pz-not-found pages
102
32
  - 8645d90: ZERO-3574:Refactor redirect tests: streamline mock setup, enhance locale handling, and improve URL path resolution logic
103
33
  - 7eb51ca9: ZERO-3424 :Update package versions
104
34
  - 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
@@ -108,7 +38,6 @@
108
38
  - 65d3b862: ZERO-3054: Update headers in appFetch
109
39
  - c39c7000: ZERO-3420: Refactor Modal component
110
40
  - bbe18b9ff: ZERO-2575: Fix build error
111
- - 35dfb8f8: ZERO-3363: Refactor URL handling in checkout and redirection middlewares to use url.origin instead of process.env.NEXT_PUBLIC_URL
112
41
  - 4920742c2: Disable getCachedTranslations
113
42
  - b6e5b624: ZERO-3257: Enhance locale middleware to redirect using existing or default locale and support 303 status for POST requests
114
43
  - 0de55738: ZERO-3418: Update remotePatterns hostname to allow all subdomains
@@ -122,7 +51,6 @@
122
51
  - facf1ada: ZERO-3445: Add SameSite and Secure attributes
123
52
  - 26b2d0b: ZERO-3571: Remove test script execution from prebuild and simplify Jest module name mapping
124
53
  - eeb20bea: Revert "ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing"
125
- - 99b6e7b9: ZERO-3421: Enhance Sentry error handling by adding network error detection logic and refining initialization options
126
54
  - 3bf63c8a: ZERO-3286: Add notFound handling for chunk URLs starting with \_next
127
55
  - 9be2c081: ZERO-3243: Improve basket update query handling with optimistic updates
128
56
  - f7fd459b: ZERO-3445: Refactor setCookie function to include domain handling and improve cookie string construction
@@ -131,14 +59,21 @@
131
59
  - f2c92d5c7: ZERO-2816: Update cookie name
132
60
  - a420947d: ZERO-3517: Fix optional chaining for rawData in error logging for category data handlers
133
61
  - 7bd3d9928: ZERO-2801: Refactor locale middleware to handle single locale configuration
134
- - acd2afd: ZERO-3431: Fix import statement for findBaseDir in next-config test
62
+ - acd2afdf: ZERO-3431: Fix import statement for findBaseDir in next-config test
135
63
  - 2d3f1788: ZERO-3417: Enhance FileInput component with additional props for customization
136
64
  - fdd255ee: ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing
137
65
  - 49eeebfa: ZERO-2909: Add deleteCollectionItem query to wishlistApi
138
66
  - 3f9b8d7e7: ZERO-2761: Update plugins.js for akinon-next
139
- - cbdb5c14: ZERO-3448: fix set cookie domain handling for subdomain locale strategy
140
67
  - 0e82301: ZERO-3531: Add saveSampleProducts endpoint
141
68
 
69
+ ## 1.95.0
70
+
71
+ ### Minor Changes
72
+
73
+ - 35dfb8f: ZERO-3363: Refactor URL handling in checkout and redirection middlewares to use url.origin instead of process.env.NEXT_PUBLIC_URL
74
+ - 99b6e7b: ZERO-3421: Enhance Sentry error handling by adding network error detection logic and refining initialization options
75
+ - cbdb5c1: ZERO-3448: fix set cookie domain handling for subdomain locale strategy
76
+
142
77
  ## 1.94.0
143
78
 
144
79
  ### Minor Changes
package/api/cache.ts CHANGED
@@ -21,54 +21,20 @@ async function handleRequest(...args) {
21
21
  }
22
22
 
23
23
  const formData = await req.formData();
24
- const body = {} as {
25
- key: string;
26
- value?: string;
27
- expire?: number;
28
- keyValuePairs?: string;
29
- compressed?: string;
30
- };
24
+ const body = {} as { key: string; value?: string; expire?: number };
31
25
 
32
26
  formData.forEach((value, key) => {
33
27
  body[key] = value;
34
28
  });
35
29
 
36
- const { key, value, expire, keyValuePairs, compressed } = body;
37
- let response: any;
30
+ const { key, value, expire } = body;
31
+ let response: string | boolean;
38
32
 
39
33
  try {
40
34
  if (req.method === 'POST') {
41
- if (compressed === 'true') {
42
- response = await Cache.getCompressed(key);
43
- } else {
44
- response = await Cache.get(key);
45
- }
35
+ response = await Cache.get(key);
46
36
  } else if (req.method === 'PUT') {
47
- if (keyValuePairs) {
48
- try {
49
- const parsedKeyValuePairs = JSON.parse(keyValuePairs);
50
- if (
51
- typeof parsedKeyValuePairs !== 'object' ||
52
- parsedKeyValuePairs === null ||
53
- Array.isArray(parsedKeyValuePairs)
54
- ) {
55
- throw new Error('Invalid keyValuePairs format - must be an object');
56
- }
57
- response = await Cache.mset(parsedKeyValuePairs, expire);
58
- } catch (error) {
59
- logger.error('Invalid keyValuePairs in mset request', { error });
60
- return NextResponse.json(
61
- { error: 'Invalid keyValuePairs format' },
62
- { status: 400 }
63
- );
64
- }
65
- } else {
66
- if (compressed === 'true') {
67
- response = await Cache.setCompressed(key, value, expire);
68
- } else {
69
- response = await Cache.set(key, value, expire);
70
- }
71
- }
37
+ response = await Cache.set(key, value, expire);
72
38
  }
73
39
  } catch (error) {
74
40
  logger.error(error);
@@ -118,8 +118,7 @@ export const getCategoryData = ({
118
118
  locale,
119
119
  getCategoryDataHandler(pk, locale, currency, searchParams, headers),
120
120
  {
121
- expire: 300,
122
- compressed: true
121
+ expire: 300
123
122
  }
124
123
  );
125
124
  };
@@ -179,8 +178,7 @@ export const getCategoryBySlugData = async ({
179
178
  locale,
180
179
  getCategoryBySlugDataHandler(slug, locale, currency),
181
180
  {
182
- expire: 300,
183
- compressed: true
181
+ expire: 300
184
182
  }
185
183
  );
186
184
  };
@@ -46,9 +46,6 @@ export const getFlatPageData = ({
46
46
  return Cache.wrap(
47
47
  CacheKey.FlatPage(pk),
48
48
  locale,
49
- getFlatPageDataHandler(pk, locale, currency, headers),
50
- {
51
- compressed: true
52
- }
49
+ getFlatPageDataHandler(pk, locale, currency, headers)
53
50
  );
54
51
  };
@@ -43,9 +43,6 @@ export const getFormData = ({
43
43
  return Cache.wrap(
44
44
  CacheKey.Form(pk),
45
45
  locale,
46
- getFormDataHandler(pk, locale, currency, headers),
47
- {
48
- compressed: true
49
- }
46
+ getFormDataHandler(pk, locale, currency, headers)
50
47
  );
51
48
  };
@@ -46,9 +46,6 @@ export const getLandingPageData = ({
46
46
  return Cache.wrap(
47
47
  CacheKey.LandingPage(pk),
48
48
  locale,
49
- getLandingPageHandler(pk, locale, currency, headers),
50
- {
51
- compressed: true
52
- }
49
+ getLandingPageHandler(pk, locale, currency, headers)
53
50
  );
54
51
  };
@@ -81,8 +81,7 @@ export const getListData = async ({
81
81
  locale,
82
82
  getListDataHandler(locale, currency, searchParams, headers),
83
83
  {
84
- expire: 300,
85
- compressed: true
84
+ expire: 300
86
85
  }
87
86
  );
88
87
  };
@@ -48,9 +48,6 @@ export const getMenu = async (params?: MenuHandlerParams) => {
48
48
  return Cache.wrap(
49
49
  CacheKey.Menu(params?.depth ?? DEFAULT_DEPTH, params?.parent),
50
50
  params?.locale ?? ServerVariables.locale,
51
- getMenuHandler(params),
52
- {
53
- compressed: true
54
- }
51
+ getMenuHandler(params)
55
52
  );
56
53
  };
@@ -143,8 +143,7 @@ export const getProductData = async ({
143
143
  headers
144
144
  }),
145
145
  {
146
- expire: 300,
147
- compressed: true
146
+ expire: 300
148
147
  }
149
148
  );
150
149
  };
@@ -43,9 +43,6 @@ export const getSeoData = async (
43
43
  return Cache.wrap(
44
44
  CacheKey.Seo(url),
45
45
  locale,
46
- getSeoDataHandler({ url, locale, currency, headers }),
47
- {
48
- compressed: true
49
- }
46
+ getSeoDataHandler({ url, locale, currency, headers })
50
47
  );
51
48
  };
@@ -54,8 +54,7 @@ export const getSpecialPageData = async ({
54
54
  locale,
55
55
  getSpecialPageDataHandler(pk, locale, currency, searchParams, headers),
56
56
  {
57
- expire: 300,
58
- compressed: true
57
+ expire: 300
59
58
  }
60
59
  );
61
60
  };
@@ -44,9 +44,6 @@ export const getWidgetData = async <T>({
44
44
  CacheKey.Widget(slug),
45
45
  locale,
46
46
  getWidgetDataHandler(slug, locale, currency, headers),
47
- {
48
- compressed: true,
49
- ...cacheOptions
50
- }
47
+ cacheOptions
51
48
  );
52
49
  };
@@ -3,261 +3,7 @@ import createLruHandler from '@neshca/cache-handler/local-lru';
3
3
  import createRedisHandler from '@neshca/cache-handler/redis-strings';
4
4
  import { createClient } from 'redis';
5
5
 
6
- let zstd;
7
-
8
- (async () => {
9
- try {
10
- const { compress, decompress } = await import('@mongodb-js/zstd');
11
- zstd = { compress, decompress, type: 'native' };
12
- } catch (_) {
13
- zstd = false;
14
- }
15
- })();
16
-
17
- const getZstd = () => {
18
- return zstd;
19
- };
20
-
21
- const compressValue = async (value) => {
22
- try {
23
- if (value && typeof value === 'object' && value.value !== undefined) {
24
- const nestedValue = value.value;
25
- const serializedNestedValue =
26
- typeof nestedValue === 'string'
27
- ? nestedValue
28
- : JSON.stringify(nestedValue);
29
- const originalSize = Buffer.byteLength(serializedNestedValue, 'utf8');
30
-
31
- if (originalSize < 1024) {
32
- const result = {
33
- ...value,
34
- tags: Array.isArray(value.tags) ? value.tags : []
35
- };
36
- return result;
37
- }
38
-
39
- const zstdLib = getZstd();
40
- let compressed;
41
-
42
- if (zstdLib && zstdLib !== false) {
43
- const inputBuffer = Buffer.from(serializedNestedValue, 'utf8');
44
-
45
- if (
46
- typeof zstdLib.compress === 'function' &&
47
- zstdLib.compress.constructor.name === 'AsyncFunction'
48
- ) {
49
- compressed = await zstdLib.compress(inputBuffer, 3);
50
- } else {
51
- compressed = zstdLib.compress(inputBuffer, 3);
52
- }
53
- } else {
54
- return {
55
- ...value,
56
- tags: Array.isArray(value.tags) ? value.tags : []
57
- };
58
- }
59
-
60
- const compressedBase64 = Buffer.from(compressed).toString('base64');
61
-
62
- const result = {
63
- ...value,
64
- tags: Array.isArray(value.tags) ? value.tags : [],
65
- lifespan: {
66
- ...value.lifespan,
67
- expireAge: value.lifespan?.revalidate || value.lifespan?.expireAge,
68
- expireAt:
69
- value.lifespan?.lastModifiedAt && value.lifespan?.revalidate
70
- ? value.lifespan.lastModifiedAt + value.lifespan.revalidate
71
- : value.lifespan?.expireAt
72
- },
73
- value: {
74
- __compressed: true,
75
- __method: 'zstd',
76
- __originalSize: originalSize,
77
- __compressedSize: compressed.length,
78
- __data: compressedBase64
79
- }
80
- };
81
-
82
- return result;
83
- }
84
-
85
- const serializedValue =
86
- typeof value === 'string' ? value : JSON.stringify(value);
87
- const originalSize = Buffer.byteLength(serializedValue, 'utf8');
88
-
89
- if (originalSize < 1024) {
90
- if (
91
- value &&
92
- typeof value === 'object' &&
93
- value.lastModified === undefined &&
94
- value.lifespan === undefined &&
95
- value.value === undefined
96
- ) {
97
- return {
98
- ...value,
99
- tags: value.tags || [],
100
- lastModified: Date.now(),
101
- lifespan: {
102
- expireAt: Math.floor(Date.now() / 1000) + 3600
103
- }
104
- };
105
- }
106
- if (
107
- value &&
108
- typeof value === 'object' &&
109
- value.lifespan &&
110
- value.lifespan.revalidate
111
- ) {
112
- return {
113
- ...value,
114
- lifespan: {
115
- ...value.lifespan,
116
- expireAge: value.lifespan.revalidate,
117
- expireAt:
118
- value.lifespan.lastModifiedAt && value.lifespan.revalidate
119
- ? value.lifespan.lastModifiedAt + value.lifespan.revalidate
120
- : value.lifespan.expireAt
121
- }
122
- };
123
- }
124
- return value;
125
- }
126
-
127
- const zstdLib = getZstd();
128
- let compressed;
129
-
130
- if (zstdLib && zstdLib !== false) {
131
- const inputBuffer = Buffer.from(serializedValue, 'utf8');
132
-
133
- if (
134
- typeof zstdLib.compress === 'function' &&
135
- zstdLib.compress.constructor.name === 'AsyncFunction'
136
- ) {
137
- compressed = await zstdLib.compress(inputBuffer, 3);
138
- } else {
139
- compressed = zstdLib.compress(inputBuffer, 3);
140
- }
141
- } else {
142
- if (
143
- value &&
144
- typeof value === 'object' &&
145
- value.lastModified === undefined &&
146
- value.lifespan === undefined &&
147
- value.value === undefined
148
- ) {
149
- return {
150
- ...value,
151
- tags: value.tags || [],
152
- lastModified: Date.now(),
153
- lifespan: {
154
- expireAt: Math.floor(Date.now() / 1000) + 3600
155
- }
156
- };
157
- }
158
- return value;
159
- }
160
-
161
- const compressedBase64 = Buffer.from(compressed).toString('base64');
162
-
163
- const compressedResult = {
164
- __compressed: true,
165
- __method: 'zstd',
166
- __originalSize: originalSize,
167
- __compressedSize: compressed.length,
168
- __data: compressedBase64,
169
- tags: [],
170
- lastModified: Date.now(),
171
- lifespan: { expireAt: Math.floor(Date.now() / 1000) + 3600 }
172
- };
173
-
174
- return compressedResult;
175
- } catch (_) {
176
- return value;
177
- }
178
- };
179
-
180
- const decompressValue = async (compressedData) => {
181
- try {
182
- if (
183
- compressedData &&
184
- typeof compressedData === 'object' &&
185
- compressedData.value &&
186
- typeof compressedData.value === 'object' &&
187
- compressedData.value.__compressed
188
- ) {
189
- const compressedNestedValue = compressedData.value;
190
- const compressedBuffer = Buffer.from(
191
- compressedNestedValue.__data,
192
- 'base64'
193
- );
194
- let decompressed;
195
-
196
- if (compressedNestedValue.__method === 'zstd') {
197
- const zstdLib = getZstd();
198
- if (zstdLib && zstdLib !== false) {
199
- if (
200
- typeof zstdLib.decompress === 'function' &&
201
- zstdLib.decompress.constructor.name === 'AsyncFunction'
202
- ) {
203
- const decompressedBuffer = await zstdLib.decompress(
204
- compressedBuffer
205
- );
206
- decompressed = decompressedBuffer.toString('utf8');
207
- } else {
208
- decompressed = zstdLib
209
- .decompress(compressedBuffer)
210
- .toString('utf8');
211
- }
212
- } else {
213
- throw new Error('zstd not available for decompression');
214
- }
215
- }
216
-
217
- return {
218
- ...compressedData,
219
- value: JSON.parse(decompressed)
220
- };
221
- }
222
-
223
- if (
224
- compressedData &&
225
- typeof compressedData === 'object' &&
226
- compressedData.__compressed
227
- ) {
228
- const compressedBuffer = Buffer.from(compressedData.__data, 'base64');
229
- let decompressed;
230
-
231
- if (compressedData.__method === 'zstd') {
232
- const zstdLib = getZstd();
233
- if (zstdLib && zstdLib !== false) {
234
- if (
235
- typeof zstdLib.decompress === 'function' &&
236
- zstdLib.decompress.constructor.name === 'AsyncFunction'
237
- ) {
238
- const decompressedBuffer = await zstdLib.decompress(
239
- compressedBuffer
240
- );
241
- decompressed = decompressedBuffer.toString('utf8');
242
- } else {
243
- decompressed = zstdLib
244
- .decompress(compressedBuffer)
245
- .toString('utf8');
246
- }
247
- } else {
248
- throw new Error('zstd not available for decompression');
249
- }
250
- }
251
-
252
- return JSON.parse(decompressed);
253
- }
254
-
255
- return compressedData;
256
- } catch (error) {
257
- return compressedData;
258
- }
259
- };
260
-
6
+ // Cache configuration
261
7
  const CACHE_CONFIG = {
262
8
  lru: {
263
9
  maxItemCount: 2000
@@ -276,6 +22,7 @@ const CACHE_CONFIG = {
276
22
  version: process.env.ACC_APP_VERSION || ''
277
23
  };
278
24
 
25
+ // Use global to persist across module reloads in development
279
26
  const globalForRedis = global;
280
27
  if (!globalForRedis.redisClient) {
281
28
  globalForRedis.redisClient = null;
@@ -284,22 +31,42 @@ if (!globalForRedis.redisClient) {
284
31
  globalForRedis.connectionAttempts = 0;
285
32
  }
286
33
 
34
+ // Logging configuration
35
+ const debugValue = process.env.NEXT_PRIVATE_DEBUG_CACHE;
36
+ const debug = debugValue === 'true' || debugValue === '1';
37
+
38
+ let console_log;
39
+ if (debug) {
40
+ // eslint-disable-next-line no-console
41
+ console_log = (...args) => console.log('[Cache Handler]', ...args);
42
+ } else {
43
+ console_log = () => {};
44
+ }
45
+
287
46
  async function getRedisClient() {
47
+ // If client exists and is ready, return it
288
48
  if (globalForRedis.redisClient?.isReady) {
49
+ console_log('Reusing existing Redis connection');
289
50
  return globalForRedis.redisClient;
290
51
  }
291
52
 
53
+ // If we're already connecting, wait a bit and retry
292
54
  if (globalForRedis.isConnecting) {
293
55
  await new Promise((resolve) => setTimeout(resolve, 100));
294
56
  return getRedisClient();
295
57
  }
296
58
 
59
+ // Start new connection
297
60
  globalForRedis.isConnecting = true;
298
61
  globalForRedis.connectionAttempts++;
299
62
 
300
63
  try {
301
64
  const redisUrl = `redis://${CACHE_CONFIG.host}:${CACHE_CONFIG.port}/${CACHE_CONFIG.bucket}`;
302
65
 
66
+ if (globalForRedis.connectionAttempts === 1) {
67
+ console_log('Creating Redis connection:', redisUrl);
68
+ }
69
+
303
70
  const redisClient = createClient({
304
71
  url: redisUrl,
305
72
  socket: {
@@ -320,6 +87,7 @@ async function getRedisClient() {
320
87
  });
321
88
 
322
89
  redisClient.on('error', (error) => {
90
+ // Only log the first connection error to avoid spam
323
91
  if (!globalForRedis.hasLoggedConnectionError) {
324
92
  if (error.code === 'ECONNREFUSED') {
325
93
  console.warn(
@@ -333,10 +101,12 @@ async function getRedisClient() {
333
101
  });
334
102
 
335
103
  redisClient.on('connect', () => {
104
+ console_log('Redis connected');
336
105
  globalForRedis.hasLoggedConnectionError = false;
337
106
  });
338
107
 
339
108
  redisClient.on('ready', () => {
109
+ console_log('Redis ready');
340
110
  globalForRedis.hasLoggedConnectionError = false;
341
111
  });
342
112
 
@@ -345,6 +115,16 @@ async function getRedisClient() {
345
115
  return redisClient;
346
116
  } catch (error) {
347
117
  if (!globalForRedis.hasLoggedConnectionError) {
118
+ if (error.code === 'ECONNREFUSED') {
119
+ console.warn(
120
+ '[Cache Handler] Could not connect to Redis - using local cache only'
121
+ );
122
+ } else {
123
+ console.error(
124
+ '[Cache Handler] Failed to connect to Redis:',
125
+ error.message
126
+ );
127
+ }
348
128
  globalForRedis.hasLoggedConnectionError = true;
349
129
  }
350
130
  globalForRedis.redisClient = null;
@@ -355,10 +135,13 @@ async function getRedisClient() {
355
135
  }
356
136
 
357
137
  CacheHandler.onCreation(async () => {
138
+ console_log('Initializing cache handlers...');
139
+
358
140
  let client;
359
141
  try {
360
142
  client = await getRedisClient();
361
143
  } catch (error) {
144
+ // Error already logged in getRedisClient, just return local handler
362
145
  return {
363
146
  handlers: [createLruHandler(CACHE_CONFIG.lru)]
364
147
  };
@@ -367,161 +150,98 @@ CacheHandler.onCreation(async () => {
367
150
  const redisHandler = createRedisHandler({
368
151
  client,
369
152
  timeoutMs: CACHE_CONFIG.redis.timeoutMs,
370
- keyExpirationStrategy: 'EXPIREAT'
153
+ keyExpirationStrategy: 'EXAT'
371
154
  });
372
155
 
373
156
  const localHandler = createLruHandler(CACHE_CONFIG.lru);
374
157
 
375
- const CACHE_VERSION = 'v2';
376
- const versionPrefix = `${CACHE_VERSION}_`;
158
+ // Pre-compute version prefix if exists
159
+ const versionPrefix = CACHE_CONFIG.version ? `${CACHE_CONFIG.version}:` : '';
377
160
 
378
- const versionKeyString = (key) => `${versionPrefix}${key}`;
379
- const versionKeyObject = (key) => ({
380
- ...key,
381
- key: `${versionPrefix}${key.key}`
382
- });
161
+ // Create optimized functions for each scenario
162
+ const versionKeyString = versionPrefix
163
+ ? (key) => `${versionPrefix}${key}`
164
+ : (key) => key;
383
165
 
166
+ const versionKeyObject = versionPrefix
167
+ ? (key) => ({ ...key, key: `${versionPrefix}${key.key}` })
168
+ : (key) => key;
169
+
170
+ // Main version key function that routes to optimized paths
384
171
  const versionKey = (key) => {
385
172
  return typeof key === 'string'
386
173
  ? versionKeyString(key)
387
174
  : versionKeyObject(key);
388
175
  };
389
176
 
177
+ // Create a custom handler that checks local first, then Redis
390
178
  const customHandler = {
391
179
  name: 'custom-local-then-redis',
392
180
  get: async (key, context) => {
393
181
  const vKey = versionKey(key);
182
+ console_log(
183
+ 'GET called for key:',
184
+ typeof vKey === 'string' ? vKey : vKey?.key
185
+ );
394
186
 
187
+ // Check local cache first
188
+ console_log('Checking local cache...');
395
189
  const localResult = await localHandler.get(vKey, context);
396
190
 
397
191
  if (localResult) {
398
- if (
399
- localResult &&
400
- typeof localResult === 'object' &&
401
- (localResult.__compressed ||
402
- (localResult.value && localResult.value.__compressed) ||
403
- localResult.compressed !== undefined)
404
- ) {
405
- try {
406
- const decompressed = await decompressValue(localResult);
407
- return typeof decompressed === 'string'
408
- ? JSON.parse(decompressed)
409
- : decompressed;
410
- } catch (_) {
411
- return localResult;
412
- }
413
- }
414
-
192
+ console_log('Found in local cache');
415
193
  return localResult;
416
194
  }
417
195
 
196
+ console_log('Not found in local, checking Redis...');
418
197
  try {
419
198
  const redisResult = await redisHandler.get(vKey, context);
420
199
 
421
200
  if (redisResult) {
422
- let finalResult = redisResult;
423
-
424
- if (typeof redisResult === 'string') {
425
- try {
426
- finalResult = JSON.parse(redisResult);
427
- } catch (parseError) {
428
- finalResult = redisResult;
429
- }
430
- }
431
-
432
- if (
433
- finalResult &&
434
- typeof finalResult === 'object' &&
435
- (finalResult.__compressed ||
436
- (finalResult.value && finalResult.value.__compressed) ||
437
- finalResult.compressed !== undefined)
438
- ) {
439
- try {
440
- const decompressed = await decompressValue(finalResult);
441
- finalResult =
442
- typeof decompressed === 'string'
443
- ? JSON.parse(decompressed)
444
- : decompressed;
445
- } catch (_) {
446
- return finalResult;
447
- }
448
- }
449
-
201
+ console_log('Found in Redis');
202
+ // Sync back to local cache for faster future access
450
203
  try {
451
- await localHandler.set(vKey, finalResult, context);
452
- } catch (_) {
453
- return finalResult;
204
+ await localHandler.set(vKey, redisResult, context);
205
+ console_log('Synced to local cache');
206
+ } catch (error) {
207
+ console_log('Failed to sync to local:', error.message);
454
208
  }
455
- return finalResult;
209
+ return redisResult;
456
210
  }
457
- } catch (_) {
458
- return undefined;
211
+ } catch (error) {
212
+ console_log('Redis error:', error.message);
459
213
  }
460
214
 
215
+ console_log('Not found in any cache');
461
216
  return undefined;
462
217
  },
463
218
  set: async (key, value, context) => {
464
219
  const vKey = versionKey(key);
465
-
466
- let compressedValue;
467
- let shouldUseCompressed = false;
468
-
469
- try {
470
- compressedValue = await compressValue(value);
471
-
472
- shouldUseCompressed =
473
- compressedValue !== value &&
474
- (compressedValue?.__compressed ||
475
- compressedValue?.value?.__compressed);
476
- } catch (error) {
477
- compressedValue = value;
478
- shouldUseCompressed = false;
479
- }
480
-
481
- let redisSetResult;
482
-
483
- if (shouldUseCompressed) {
484
- try {
485
- await redisHandler.set(vKey, compressedValue, context);
486
-
487
- redisSetResult = { status: 'fulfilled' };
488
- } catch (compressionError) {
489
- try {
490
- await redisHandler.set(vKey, value, context);
491
-
492
- redisSetResult = { status: 'fulfilled' };
493
- } catch (fallbackError) {
494
- redisSetResult = { status: 'rejected', reason: fallbackError };
495
- }
496
- }
497
- } else {
498
- try {
499
- await redisHandler.set(vKey, value, context);
500
- redisSetResult = { status: 'fulfilled' };
501
- } catch (error) {
502
- redisSetResult = { status: 'rejected', reason: error };
503
- return redisSetResult;
504
- }
505
- }
506
-
507
- let localSetResult;
508
- try {
509
- await localHandler.set(vKey, value, context);
510
- localSetResult = { status: 'fulfilled' };
511
- } catch (error) {
512
- localSetResult = { status: 'rejected', reason: error };
513
- return localSetResult;
514
- }
220
+ console_log(
221
+ 'SET called for key:',
222
+ typeof vKey === 'string' ? vKey : vKey?.key
223
+ );
224
+ // Set to both caches
225
+ await Promise.allSettled([
226
+ localHandler.set(vKey, value, context),
227
+ redisHandler
228
+ .set(vKey, value, context)
229
+ .catch((error) => console_log('Redis SET error:', error.message))
230
+ ]);
515
231
  },
516
232
  delete: async (key, context) => {
517
233
  const vKey = versionKey(key);
518
-
234
+ console_log(
235
+ 'DELETE called for key:',
236
+ typeof vKey === 'string' ? vKey : vKey?.key
237
+ );
519
238
  await Promise.allSettled([
520
239
  localHandler.delete?.(vKey, context),
521
240
  redisHandler.delete?.(vKey, context)
522
241
  ]);
523
242
  },
524
243
  revalidateTag: async (tags, context) => {
244
+ console_log('REVALIDATE_TAG called for tags:', tags);
525
245
  await Promise.allSettled([
526
246
  localHandler.revalidateTag?.(tags, context),
527
247
  redisHandler.revalidateTag?.(tags, context)
@@ -529,6 +249,8 @@ CacheHandler.onCreation(async () => {
529
249
  }
530
250
  };
531
251
 
252
+ console_log('[Cache Handler] Handlers initialized successfully');
253
+
532
254
  return {
533
255
  handlers: [customHandler]
534
256
  };
package/lib/cache.ts CHANGED
@@ -3,65 +3,6 @@ import { RedisClientType } from 'redis';
3
3
  import Settings from 'settings';
4
4
  import { CacheOptions } from '../types';
5
5
  import logger from '../utils/log';
6
- const CACHE_VERSION = 'v2';
7
-
8
- const compressData = async (data: string): Promise<Uint8Array> => {
9
- const stream = new CompressionStream('gzip');
10
- const writer = stream.writable.getWriter();
11
- const reader = stream.readable.getReader();
12
-
13
- writer.write(new TextEncoder().encode(data));
14
- writer.close();
15
-
16
- const chunks: Uint8Array[] = [];
17
- let done = false;
18
-
19
- while (!done) {
20
- const { value, done: readerDone } = await reader.read();
21
- done = readerDone;
22
- if (value) chunks.push(value);
23
- }
24
-
25
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
26
- const result = new Uint8Array(totalLength);
27
- let offset = 0;
28
-
29
- for (const chunk of chunks) {
30
- result.set(chunk, offset);
31
- offset += chunk.length;
32
- }
33
-
34
- return result;
35
- };
36
-
37
- const decompressData = async (compressed: Uint8Array): Promise<string> => {
38
- const stream = new DecompressionStream('gzip');
39
- const writer = stream.writable.getWriter();
40
- const reader = stream.readable.getReader();
41
-
42
- writer.write(compressed);
43
- writer.close();
44
-
45
- const chunks: Uint8Array[] = [];
46
- let done = false;
47
-
48
- while (!done) {
49
- const { value, done: readerDone } = await reader.read();
50
- done = readerDone;
51
- if (value) chunks.push(value);
52
- }
53
-
54
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
55
- const result = new Uint8Array(totalLength);
56
- let offset = 0;
57
-
58
- for (const chunk of chunks) {
59
- result.set(chunk, offset);
60
- offset += chunk.length;
61
- }
62
-
63
- return new TextDecoder().decode(result);
64
- };
65
6
 
66
7
  const hashCacheKey = (object?: Record<string, string>) => {
67
8
  if (!object) {
@@ -119,32 +60,8 @@ export const CacheKey = {
119
60
  export class Cache {
120
61
  static PROXY_URL = `${process.env.NEXT_PUBLIC_URL}/api/cache`;
121
62
 
122
- private static serializeValue(value: any): string {
123
- return typeof value === 'object' ? JSON.stringify(value) : String(value);
124
- }
125
-
126
- private static validateKey(key: string): boolean {
127
- return !(!key || key.trim() === '');
128
- }
129
-
130
- private static validateKeyValuePairs(keyValuePairs: Record<string, any>): {
131
- isValid: boolean;
132
- invalidKeys: string[];
133
- } {
134
- if (!keyValuePairs || Object.keys(keyValuePairs).length === 0) {
135
- return { isValid: false, invalidKeys: [] };
136
- }
137
-
138
- const invalidKeys = Object.keys(keyValuePairs).filter(
139
- (key) => !this.validateKey(key)
140
- );
141
- return { isValid: invalidKeys.length === 0, invalidKeys };
142
- }
143
-
144
63
  static formatKey(key: string, locale: string) {
145
- return encodeURIComponent(
146
- `${CACHE_VERSION}_${Settings.commerceUrl}_${locale}_${key}`
147
- );
64
+ return encodeURIComponent(`${Settings.commerceUrl}_${locale}_${key}`);
148
65
  }
149
66
 
150
67
  static clientPool: Pool<RedisClientType> = createPool(
@@ -181,9 +98,9 @@ export class Cache {
181
98
  return await Cache.clientPool.acquire();
182
99
  }
183
100
 
184
- static async get(key: string): Promise<any> {
185
- let value: any;
186
- let client: RedisClientType | undefined;
101
+ static async get(key: string) {
102
+ let value;
103
+ let client;
187
104
 
188
105
  try {
189
106
  client = await Cache.getClient();
@@ -193,7 +110,9 @@ export class Cache {
193
110
  } else {
194
111
  value = null;
195
112
  }
113
+ logger.debug('Redis get success', { key, value });
196
114
  } catch (error) {
115
+ logger.error('Redis get error', { key, error });
197
116
  value = null;
198
117
  } finally {
199
118
  if (client) {
@@ -204,13 +123,14 @@ export class Cache {
204
123
  return value;
205
124
  }
206
125
 
207
- static async set(key: string, value: any, expire?: number): Promise<boolean> {
126
+ static async set(key: string, value: any, expire?: number) {
208
127
  let success = false;
209
- let client: RedisClientType | undefined;
128
+ let client;
210
129
 
211
130
  try {
212
131
  client = await Cache.getClient();
213
- const serializedValue = Cache.serializeValue(value);
132
+ const serializedValue =
133
+ typeof value === 'object' ? JSON.stringify(value) : value;
214
134
 
215
135
  if (expire) {
216
136
  await client.set(key, serializedValue, { EX: expire });
@@ -219,7 +139,9 @@ export class Cache {
219
139
  }
220
140
 
221
141
  success = true;
142
+ logger.debug('Redis set success', { key, value });
222
143
  } catch (error) {
144
+ logger.error('Redis set error', { key, error });
223
145
  success = false;
224
146
  } finally {
225
147
  if (client) {
@@ -248,8 +170,7 @@ export class Cache {
248
170
 
249
171
  const defaultOptions: CacheOptions = {
250
172
  cache: true,
251
- expire: Settings.redis.defaultExpirationTime,
252
- compressed: process.env.CACHE_COMPRESSION_ENABLED !== 'false'
173
+ expire: Settings.redis.defaultExpirationTime
253
174
  };
254
175
 
255
176
  const _options = Object.assign(defaultOptions, options);
@@ -259,22 +180,21 @@ export class Cache {
259
180
  _options.expire = 120;
260
181
  }
261
182
 
183
+ logger.debug('Cache wrap', { key, formattedKey, _options });
184
+
262
185
  if (_options.cache) {
263
- let cachedValue: any;
186
+ let cachedValue;
264
187
 
265
188
  if (_options.useProxy) {
266
189
  const body = new URLSearchParams();
267
190
 
268
191
  body.append('key', formattedKey);
269
- if (_options.compressed) {
270
- body.append('compressed', 'true');
271
- }
272
192
 
273
193
  cachedValue = await Cache.proxyRequest('POST', body);
194
+ logger.debug('Cache proxy request success', { key });
195
+ logger.trace('Cache proxy request', { key, cachedValue });
274
196
  } else {
275
- cachedValue = _options.compressed
276
- ? await Cache.getCompressed(formattedKey)
277
- : await Cache.get(formattedKey);
197
+ cachedValue = await Cache.get(formattedKey);
278
198
  }
279
199
 
280
200
  if (cachedValue) {
@@ -282,6 +202,8 @@ export class Cache {
282
202
  }
283
203
  }
284
204
 
205
+ logger.debug('Redis cache miss. Setting new value...', { key });
206
+
285
207
  const data = await handler();
286
208
 
287
209
  if (data && _options.cache) {
@@ -295,19 +217,14 @@ export class Cache {
295
217
  'expire',
296
218
  String(_options?.expire ?? Settings.redis.defaultExpirationTime)
297
219
  );
298
- if (_options.compressed) {
299
- body.append('compressed', 'true');
300
- }
301
220
  await Cache.proxyRequest('PUT', body);
221
+
222
+ logger.debug('Cache proxy request', { key, body: body.toString() });
302
223
  } catch (error) {
303
224
  logger.error('Cache proxy error', error);
304
225
  }
305
226
  } else {
306
- if (_options.compressed) {
307
- await Cache.setCompressed(formattedKey, data, _options?.expire);
308
- } else {
309
- await Cache.set(formattedKey, JSON.stringify(data), _options?.expire);
310
- }
227
+ await Cache.set(formattedKey, JSON.stringify(data), _options?.expire);
311
228
  }
312
229
  }
313
230
 
@@ -319,7 +236,7 @@ export class Cache {
319
236
  await fetch(Cache.PROXY_URL, {
320
237
  method,
321
238
  headers: {
322
- authorization: process.env.CACHE_SECRET || ''
239
+ authorization: process.env.CACHE_SECRET
323
240
  },
324
241
  body
325
242
  })
@@ -327,148 +244,4 @@ export class Cache {
327
244
 
328
245
  return response;
329
246
  }
330
-
331
- static async mset(
332
- keyValuePairs: Record<string, any>,
333
- expire?: number
334
- ): Promise<boolean> {
335
- const validation = Cache.validateKeyValuePairs(keyValuePairs);
336
- if (!validation.isValid) {
337
- if (validation.invalidKeys.length > 0) {
338
- logger.error('Invalid keys in mset', {
339
- invalidKeys: validation.invalidKeys
340
- });
341
- } else {
342
- logger.warn('mset called with empty keyValuePairs');
343
- }
344
- return false;
345
- }
346
-
347
- let success = false;
348
- let client: RedisClientType | undefined;
349
-
350
- try {
351
- client = await Cache.getClient();
352
- const pipeline = client.multi();
353
-
354
- Object.entries(keyValuePairs).forEach(([key, value]) => {
355
- const serializedValue = Cache.serializeValue(value);
356
- if (expire) {
357
- pipeline.set(key, serializedValue, { EX: expire });
358
- } else {
359
- pipeline.set(key, serializedValue);
360
- }
361
- });
362
-
363
- const results = await pipeline.exec();
364
-
365
- const failures =
366
- results?.filter((result) => result instanceof Error) || [];
367
-
368
- if (failures.length > 0) {
369
- success = false;
370
- } else {
371
- success = true;
372
- }
373
- } catch (error) {
374
- success = false;
375
- } finally {
376
- if (client) {
377
- await Cache.clientPool.release(client);
378
- }
379
- }
380
-
381
- return success;
382
- }
383
-
384
- static async setCompressed(
385
- key: string,
386
- value: any,
387
- expire?: number
388
- ): Promise<boolean> {
389
- if (!Cache.validateKey(key)) {
390
- return false;
391
- }
392
-
393
- let success = false;
394
- let client: RedisClientType | undefined;
395
-
396
- try {
397
- client = await Cache.getClient();
398
- const serializedValue = Cache.serializeValue(value);
399
-
400
- try {
401
- const compressed = await compressData(serializedValue);
402
- const compressedBase64 = Buffer.from(compressed).toString('base64');
403
-
404
- if (expire) {
405
- await client.set(key, compressedBase64, { EX: expire });
406
- } else {
407
- await client.set(key, compressedBase64);
408
- }
409
-
410
- success = true;
411
- } catch (compressionError) {
412
- if (expire) {
413
- await client.set(key, serializedValue, { EX: expire });
414
- } else {
415
- await client.set(key, serializedValue);
416
- }
417
-
418
- success = true;
419
- }
420
- } catch (error) {
421
- success = false;
422
- } finally {
423
- if (client) {
424
- await Cache.clientPool.release(client);
425
- }
426
- }
427
-
428
- return success;
429
- }
430
-
431
- static async getCompressed(key: string): Promise<unknown> {
432
- if (!Cache.validateKey(key)) {
433
- return null;
434
- }
435
-
436
- let value: unknown;
437
- let client: RedisClientType | undefined;
438
-
439
- try {
440
- client = await Cache.getClient();
441
- const compressed = await client.get(key);
442
-
443
- if (compressed) {
444
- const compressedBuffer = Buffer.from(compressed, 'base64');
445
-
446
- try {
447
- const decompressedString = await decompressData(
448
- new Uint8Array(compressedBuffer)
449
- );
450
- value = JSON.parse(decompressedString);
451
- return value;
452
- } catch (decompressionError) {
453
- try {
454
- const rawString = compressed;
455
- const parsedData = JSON.parse(rawString);
456
- return parsedData;
457
- } catch (jsonError) {
458
- return null;
459
- }
460
- }
461
- } else {
462
- value = null;
463
- }
464
- } catch (error) {
465
- value = null;
466
- } finally {
467
- if (client) {
468
- await Cache.clientPool.release(client);
469
- }
470
- }
471
-
472
- return value;
473
- }
474
247
  }
@@ -53,8 +53,7 @@ const resolvePrettyUrl = async (
53
53
  locale,
54
54
  resolvePrettyUrlHandler(pathname, ip),
55
55
  {
56
- useProxy: true,
57
- compressed: true
56
+ useProxy: true
58
57
  }
59
58
  );
60
59
  };
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.95.0-snapshot-ZERO-3586-20250903094652",
4
+ "version": "1.96.0-rc.55",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -17,14 +17,13 @@
17
17
  "test": "jest"
18
18
  },
19
19
  "dependencies": {
20
- "@mongodb-js/zstd": "^2.0.1",
21
- "@neshca/cache-handler": "1.9.0",
22
20
  "@opentelemetry/exporter-trace-otlp-http": "0.46.0",
23
21
  "@opentelemetry/resources": "1.19.0",
24
22
  "@opentelemetry/sdk-node": "0.46.0",
25
23
  "@opentelemetry/sdk-trace-node": "1.19.0",
26
24
  "@opentelemetry/semantic-conventions": "1.19.0",
27
25
  "@reduxjs/toolkit": "1.9.7",
26
+ "@neshca/cache-handler": "1.9.0",
28
27
  "@sentry/nextjs": "9.5.0",
29
28
  "cross-spawn": "7.0.3",
30
29
  "generic-pool": "3.9.0",
@@ -35,7 +34,7 @@
35
34
  "set-cookie-parser": "2.6.0"
36
35
  },
37
36
  "devDependencies": {
38
- "@akinon/eslint-plugin-projectzero": "1.95.0-snapshot-ZERO-3586-20250903094652",
37
+ "@akinon/eslint-plugin-projectzero": "1.96.0-rc.55",
39
38
  "@babel/core": "7.26.10",
40
39
  "@babel/preset-env": "7.26.9",
41
40
  "@babel/preset-typescript": "7.27.0",
package/types/index.ts CHANGED
@@ -222,7 +222,6 @@ export interface CacheOptions {
222
222
  cache?: boolean;
223
223
  expire?: number;
224
224
  useProxy?: boolean;
225
- compressed?: boolean;
226
225
  }
227
226
 
228
227
  export interface SetCookieOptions {
package/with-pz-config.js CHANGED
@@ -17,7 +17,7 @@ const defaultConfig = {
17
17
  {
18
18
  protocol: 'https',
19
19
  hostname: '**'
20
- }
20
+ },
21
21
  ]
22
22
  },
23
23
  modularizeImports: {
@@ -57,7 +57,6 @@ const defaultConfig = {
57
57
  }, {}),
58
58
  translations: false
59
59
  };
60
-
61
60
  return config;
62
61
  },
63
62
  sentry: {