@trieb.work/nextjs-turbo-redis-cache 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/.github/workflows/ci.yml +3 -2
  2. package/.github/workflows/release.yml +1 -0
  3. package/CHANGELOG.md +17 -0
  4. package/README.md +7 -2
  5. package/dist/index.d.mts +5 -1
  6. package/dist/index.d.ts +5 -1
  7. package/dist/index.js +3 -6
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +3 -6
  10. package/dist/index.mjs.map +1 -1
  11. package/package.json +4 -2
  12. package/src/RedisStringsHandler.ts +53 -54
  13. package/src/ZodHandler.ts +45 -0
  14. package/test/integration/{next-app → next-app-15-0-3}/package.json +1 -1
  15. package/test/integration/next-app-15-3-2/README.md +36 -0
  16. package/test/integration/next-app-15-3-2/eslint.config.mjs +16 -0
  17. package/test/integration/next-app-15-3-2/next.config.js +6 -0
  18. package/test/integration/next-app-15-3-2/package-lock.json +5969 -0
  19. package/test/integration/next-app-15-3-2/package.json +33 -0
  20. package/test/integration/next-app-15-3-2/pnpm-lock.yaml +3688 -0
  21. package/test/integration/next-app-15-3-2/postcss.config.mjs +5 -0
  22. package/test/integration/next-app-15-3-2/public/file.svg +1 -0
  23. package/test/integration/next-app-15-3-2/public/globe.svg +1 -0
  24. package/test/integration/next-app-15-3-2/public/next.svg +1 -0
  25. package/test/integration/next-app-15-3-2/public/vercel.svg +1 -0
  26. package/test/integration/next-app-15-3-2/public/window.svg +1 -0
  27. package/test/integration/next-app-15-3-2/src/app/api/cached-static-fetch/route.ts +18 -0
  28. package/test/integration/next-app-15-3-2/src/app/api/nested-fetch-in-api-route/revalidated-fetch/route.ts +27 -0
  29. package/test/integration/next-app-15-3-2/src/app/api/revalidatePath/route.ts +15 -0
  30. package/test/integration/next-app-15-3-2/src/app/api/revalidateTag/route.ts +15 -0
  31. package/test/integration/next-app-15-3-2/src/app/api/revalidated-fetch/route.ts +17 -0
  32. package/test/integration/next-app-15-3-2/src/app/api/uncached-fetch/route.ts +15 -0
  33. package/test/integration/next-app-15-3-2/src/app/globals.css +26 -0
  34. package/test/integration/next-app-15-3-2/src/app/layout.tsx +59 -0
  35. package/test/integration/next-app-15-3-2/src/app/page.tsx +755 -0
  36. package/test/integration/next-app-15-3-2/src/app/pages/cached-static-fetch/default--force-dynamic-page/page.tsx +19 -0
  37. package/test/integration/next-app-15-3-2/src/app/pages/cached-static-fetch/revalidate15--default-page/page.tsx +34 -0
  38. package/test/integration/next-app-15-3-2/src/app/pages/cached-static-fetch/revalidate15--force-dynamic-page/page.tsx +25 -0
  39. package/test/integration/next-app-15-3-2/src/app/pages/no-fetch/default-page/page.tsx +55 -0
  40. package/test/integration/next-app-15-3-2/src/app/pages/revalidated-fetch/default--force-dynamic-page/page.tsx +19 -0
  41. package/test/integration/next-app-15-3-2/src/app/pages/revalidated-fetch/revalidate15--default-page/page.tsx +35 -0
  42. package/test/integration/next-app-15-3-2/src/app/pages/revalidated-fetch/revalidate15--force-dynamic-page/page.tsx +25 -0
  43. package/test/integration/next-app-15-3-2/src/app/pages/uncached-fetch/default--force-dynamic-page/page.tsx +19 -0
  44. package/test/integration/next-app-15-3-2/src/app/pages/uncached-fetch/revalidate15--default-page/page.tsx +32 -0
  45. package/test/integration/next-app-15-3-2/src/app/pages/uncached-fetch/revalidate15--force-dynamic-page/page.tsx +25 -0
  46. package/test/integration/next-app-15-3-2/src/app/revalidation-interface.tsx +267 -0
  47. package/test/integration/next-app-15-3-2/tsconfig.json +27 -0
  48. package/test/integration/nextjs-cache-handler.integration.test.ts +29 -10
  49. /package/test/integration/{next-app → next-app-15-0-3}/README.md +0 -0
  50. /package/test/integration/{next-app → next-app-15-0-3}/eslint.config.mjs +0 -0
  51. /package/test/integration/{next-app → next-app-15-0-3}/next.config.js +0 -0
  52. /package/test/integration/{next-app → next-app-15-0-3}/package-lock.json +0 -0
  53. /package/test/integration/{next-app → next-app-15-0-3}/pnpm-lock.yaml +0 -0
  54. /package/test/integration/{next-app → next-app-15-0-3}/postcss.config.mjs +0 -0
  55. /package/test/integration/{next-app → next-app-15-0-3}/public/file.svg +0 -0
  56. /package/test/integration/{next-app → next-app-15-0-3}/public/globe.svg +0 -0
  57. /package/test/integration/{next-app → next-app-15-0-3}/public/next.svg +0 -0
  58. /package/test/integration/{next-app → next-app-15-0-3}/public/vercel.svg +0 -0
  59. /package/test/integration/{next-app → next-app-15-0-3}/public/window.svg +0 -0
  60. /package/test/integration/{next-app → next-app-15-0-3}/src/app/api/cached-static-fetch/route.ts +0 -0
  61. /package/test/integration/{next-app → next-app-15-0-3}/src/app/api/nested-fetch-in-api-route/revalidated-fetch/route.ts +0 -0
  62. /package/test/integration/{next-app → next-app-15-0-3}/src/app/api/revalidatePath/route.ts +0 -0
  63. /package/test/integration/{next-app → next-app-15-0-3}/src/app/api/revalidateTag/route.ts +0 -0
  64. /package/test/integration/{next-app → next-app-15-0-3}/src/app/api/revalidated-fetch/route.ts +0 -0
  65. /package/test/integration/{next-app → next-app-15-0-3}/src/app/api/uncached-fetch/route.ts +0 -0
  66. /package/test/integration/{next-app → next-app-15-0-3}/src/app/globals.css +0 -0
  67. /package/test/integration/{next-app → next-app-15-0-3}/src/app/layout.tsx +0 -0
  68. /package/test/integration/{next-app → next-app-15-0-3}/src/app/page.tsx +0 -0
  69. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/cached-static-fetch/default--force-dynamic-page/page.tsx +0 -0
  70. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/cached-static-fetch/revalidate15--default-page/page.tsx +0 -0
  71. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/cached-static-fetch/revalidate15--force-dynamic-page/page.tsx +0 -0
  72. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/no-fetch/default-page/page.tsx +0 -0
  73. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/revalidated-fetch/default--force-dynamic-page/page.tsx +0 -0
  74. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/revalidated-fetch/revalidate15--default-page/page.tsx +0 -0
  75. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/revalidated-fetch/revalidate15--force-dynamic-page/page.tsx +0 -0
  76. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/uncached-fetch/default--force-dynamic-page/page.tsx +0 -0
  77. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/uncached-fetch/revalidate15--default-page/page.tsx +0 -0
  78. /package/test/integration/{next-app → next-app-15-0-3}/src/app/pages/uncached-fetch/revalidate15--force-dynamic-page/page.tsx +0 -0
  79. /package/test/integration/{next-app → next-app-15-0-3}/src/app/revalidation-interface.tsx +0 -0
  80. /package/test/integration/{next-app → next-app-15-0-3}/tsconfig.json +0 -0
@@ -4,8 +4,10 @@ import fetch from 'node-fetch';
4
4
  import { createClient } from 'redis';
5
5
  import { join } from 'path';
6
6
  import { CacheEntry } from '../../src/RedisStringsHandler';
7
+ import { revalidate as next1503_revalidatedFetch_route } from './next-app-15-0-3/src/app/api/revalidated-fetch/route';
7
8
 
8
- const NEXT_APP_DIR = join(__dirname, 'next-app');
9
+ // const NEXT_APP_DIR = join(__dirname, 'next-app-15-0-3');
10
+ const NEXT_APP_DIR = join(__dirname, 'next-app-15-3-2');
9
11
  console.log('NEXT_APP_DIR', NEXT_APP_DIR);
10
12
  const NEXT_START_PORT = 3055;
11
13
  const NEXT_START_URL = `http://localhost:${NEXT_START_PORT}`;
@@ -126,6 +128,8 @@ describe('Next.js Turbo Redis Cache Integration', () => {
126
128
  url: `redis://${process.env.REDISHOST}:${process.env.REDISPORT}`,
127
129
  });
128
130
  await redisClient.connect();
131
+
132
+ console.log('redis key prefix is:', process.env.VERCEL_URL);
129
133
  }, 60_000);
130
134
 
131
135
  afterAll(async () => {
@@ -156,6 +160,7 @@ describe('Next.js Turbo Redis Cache Integration', () => {
156
160
  });
157
161
 
158
162
  it('The data in the redis key should match the expected format', async () => {
163
+ await delay(REDIS_BACKGROUND_SYNC_DELAY);
159
164
  const keys = await redisClient.keys(process.env.VERCEL_URL + '*');
160
165
  expect(keys.length).toBeGreaterThan(0);
161
166
 
@@ -226,6 +231,7 @@ describe('Next.js Turbo Redis Cache Integration', () => {
226
231
  });
227
232
 
228
233
  it('After the new request was made the redis key and hashmap should be set again', async () => {
234
+ await delay(REDIS_BACKGROUND_SYNC_DELAY);
229
235
  // check Redis keys
230
236
  const keys = await redisClient.keys(
231
237
  process.env.VERCEL_URL + '/api/cached-static-fetch',
@@ -263,15 +269,17 @@ describe('Next.js Turbo Redis Cache Integration', () => {
263
269
  });
264
270
 
265
271
  if (process.env.SKIP_OPTIONAL_LONG_RUNNER_TESTS !== 'true') {
272
+ const FIRST_DELAY = 6000;
273
+ const SECOND_DELAY = 1000;
266
274
  it('Third request which is send directly after revalidation time will still serve cache but trigger re-evaluation (stale-while-revalidate)', async () => {
267
- await delay(6000);
275
+ await delay(FIRST_DELAY);
268
276
  const res = await fetch(NEXT_START_URL + '/api/revalidated-fetch');
269
277
  const data: any = await res.json();
270
278
  expect(data.counter).toBe(counter1);
271
279
  }, 10_000);
272
280
 
273
281
  it('Third request which is send directly after revalidation time will serve re-evaluated data (stale-while-revalidate)', async () => {
274
- await delay(1000);
282
+ await delay(SECOND_DELAY);
275
283
  const res = await fetch(NEXT_START_URL + '/api/revalidated-fetch');
276
284
  const data: any = await res.json();
277
285
  expect(data.counter).toBe(counter1 + 1);
@@ -281,7 +289,13 @@ describe('Next.js Turbo Redis Cache Integration', () => {
281
289
  const ttl = await redisClient.ttl(
282
290
  process.env.VERCEL_URL + '/api/revalidated-fetch',
283
291
  );
284
- expect(ttl).toBeGreaterThan(3);
292
+ expect(ttl).toBeLessThan(2 * next1503_revalidatedFetch_route);
293
+ expect(ttl).toBeGreaterThan(
294
+ 2 * next1503_revalidatedFetch_route -
295
+ FIRST_DELAY -
296
+ SECOND_DELAY -
297
+ REDIS_BACKGROUND_SYNC_DELAY,
298
+ );
285
299
 
286
300
  await delay(ttl * 1000 + 500);
287
301
 
@@ -429,10 +443,12 @@ describe('Next.js Turbo Redis Cache Integration', () => {
429
443
  );
430
444
  const data: any = await res.json();
431
445
  expect(data.counter).toBe(counter + 4);
432
- expect(data.subFetchData.counter).toBe(subCounter + 2); // <- fails in CI only
446
+ expect(data.subFetchData.counter).toBe(subCounter + 2);
433
447
  });
434
448
 
435
449
  it('After the new request was made the redis key and hashmap should be set again', async () => {
450
+ await delay(REDIS_BACKGROUND_SYNC_DELAY);
451
+
436
452
  // This cache entry key is the key of the sub-fetch-request, it will be generated by nextjs based on the headers/payload etc.
437
453
  // So it should stay the same unless nextjs will change something in there implementation
438
454
  const cacheEntryKey =
@@ -483,7 +499,7 @@ describe('Next.js Turbo Redis Cache Integration', () => {
483
499
  );
484
500
  const data: any = await res.json();
485
501
  expect(data.counter).toBe(counter + 5);
486
- expect(data.subFetchData.counter).toBe(subCounter + 3); // <- fails in CI only
502
+ expect(data.subFetchData.counter).toBe(subCounter + 3);
487
503
  });
488
504
 
489
505
  it('After the new request was made the redis key and hashmap should be set again', async () => {
@@ -643,6 +659,7 @@ describe('Next.js Turbo Redis Cache Integration', () => {
643
659
 
644
660
  it('After the new request was made the redis key and hashmap should be set again', async () => {
645
661
  // check Redis keys
662
+ await delay(REDIS_BACKGROUND_SYNC_DELAY);
646
663
  const keys = await redisClient.keys(
647
664
  process.env.VERCEL_URL + '/pages/no-fetch/default-page',
648
665
  );
@@ -685,6 +702,8 @@ describe('Next.js Turbo Redis Cache Integration', () => {
685
702
  firstTimestamp = timestamp!;
686
703
  firstCounter = counter!;
687
704
 
705
+ await delay(REDIS_BACKGROUND_SYNC_DELAY);
706
+
688
707
  // test cache entry for 3 keys are set
689
708
  const keys1 = await redisClient.keys(
690
709
  process.env.VERCEL_URL +
@@ -783,11 +802,11 @@ describe('Next.js Turbo Redis Cache Integration', () => {
783
802
  // the page should also be in revalidatedTagsMap so that the nested fetch requests knows that the page was invalidated
784
803
  const revalidationTimestamp = await redisClient.hGet(
785
804
  process.env.VERCEL_URL + '__revalidated_tags__',
786
- '/pages/revalidated-fetch/revalidate15--default-page',
805
+ '_N_T_/pages/revalidated-fetch/revalidate15--default-page',
787
806
  );
788
- console.log('revalidationTimestamp', revalidationTimestamp);
789
- expect(revalidationTimestamp).toBeDefined();
790
- expect(Number(revalidationTimestamp)).toBeLessThan(Number(Date.now()));
807
+ const ts = Number(revalidationTimestamp);
808
+ expect(ts).toBeGreaterThan(1);
809
+ expect(ts).toBeLessThan(Number(Date.now()));
791
810
 
792
811
  // API route should still be cached
793
812
  const keys3 = await redisClient.keys(