@trieb.work/nextjs-turbo-redis-cache 1.18.0 → 1.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +27 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +27 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -1
- package/.cursor/skills/testing/SKILL.md +0 -121
- package/.github/workflows/ci.yml +0 -309
- package/.github/workflows/pages.yml +0 -38
- package/.github/workflows/release.yml +0 -58
- package/.prettierrc.json +0 -6
- package/.vscode/settings.json +0 -10
- package/ARCHITECTURE.md +0 -470
- package/commitlint.config.cjs +0 -4
- package/docker/redis.conf +0 -1
- package/docs/index.html +0 -140
- package/docs/robots.txt +0 -4
- package/docs/sitemap.xml +0 -8
- package/docs/styles.css +0 -141
- package/eslint.config.mjs +0 -26
- package/hooks/commit-msg +0 -10
- package/hooks/pre-commit +0 -11
- package/playwright.config.ts +0 -18
- package/release.config.cjs +0 -12
- package/scripts/prepare.sh +0 -7
- package/scripts/setup-git.sh +0 -8
- package/scripts/setup-repo-name.sh +0 -17
- package/scripts/vitest-run-staged.cjs +0 -44
- package/src/CacheComponentsHandler.ts +0 -597
- package/src/CachedHandler.ts +0 -53
- package/src/DeduplicatedRequestHandler.ts +0 -110
- package/src/RedisStringsHandler.ts +0 -949
- package/src/SyncedMap.ts +0 -496
- package/src/ZodHandler.ts +0 -45
- package/src/index.ts +0 -23
- package/src/serializer.ts +0 -59
- package/src/utils/cacheTtl.ts +0 -71
- package/src/utils/compareAndUnlink.ts +0 -29
- package/src/utils/debug.ts +0 -30
- package/src/utils/json.ts +0 -49
- package/src/utils/prefix.ts +0 -44
- package/src/utils/redisConnection.ts +0 -17
- package/src/utils/tagRevalidation.ts +0 -162
- package/test/README.md +0 -194
- package/test/nextjs-test-projects/next-app-15-4-11/README.md +0 -36
- package/test/nextjs-test-projects/next-app-15-4-11/eslint.config.mjs +0 -16
- package/test/nextjs-test-projects/next-app-15-4-11/next.config.js +0 -9
- package/test/nextjs-test-projects/next-app-15-4-11/package-lock.json +0 -5969
- package/test/nextjs-test-projects/next-app-15-4-11/package.json +0 -29
- package/test/nextjs-test-projects/next-app-15-4-11/pnpm-lock.yaml +0 -3726
- package/test/nextjs-test-projects/next-app-15-4-11/postcss.config.mjs +0 -5
- package/test/nextjs-test-projects/next-app-15-4-11/public/file.svg +0 -1
- package/test/nextjs-test-projects/next-app-15-4-11/public/globe.svg +0 -1
- package/test/nextjs-test-projects/next-app-15-4-11/public/next.svg +0 -1
- package/test/nextjs-test-projects/next-app-15-4-11/public/vercel.svg +0 -1
- package/test/nextjs-test-projects/next-app-15-4-11/public/window.svg +0 -1
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/api/cached-static-fetch/route.ts +0 -18
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/api/nested-fetch-in-api-route/revalidated-fetch/route.ts +0 -27
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/api/revalidatePath/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/api/revalidateTag/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/api/revalidated-fetch/route.ts +0 -17
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/api/uncached-fetch/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/globals.css +0 -26
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/layout.tsx +0 -59
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/page.tsx +0 -755
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/cached-static-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/cached-static-fetch/revalidate15--default-page/page.tsx +0 -34
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/cached-static-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/no-fetch/default-page/page.tsx +0 -55
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/revalidated-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/revalidated-fetch/revalidate15--default-page/page.tsx +0 -35
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/revalidated-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/uncached-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/uncached-fetch/revalidate15--default-page/page.tsx +0 -32
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/pages/uncached-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-15-4-11/src/app/revalidation-interface.tsx +0 -267
- package/test/nextjs-test-projects/next-app-15-4-11/tsconfig.json +0 -27
- package/test/nextjs-test-projects/next-app-16-0-11/README.md +0 -36
- package/test/nextjs-test-projects/next-app-16-0-11/eslint.config.mjs +0 -18
- package/test/nextjs-test-projects/next-app-16-0-11/next.config.ts +0 -10
- package/test/nextjs-test-projects/next-app-16-0-11/package.json +0 -28
- package/test/nextjs-test-projects/next-app-16-0-11/pnpm-lock.yaml +0 -4163
- package/test/nextjs-test-projects/next-app-16-0-11/postcss.config.mjs +0 -7
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/api/cached-static-fetch/route.ts +0 -18
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/api/nested-fetch-in-api-route/revalidated-fetch/route.ts +0 -27
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/api/revalidatePath/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/api/revalidateTag/route.ts +0 -20
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/api/revalidated-fetch/route.ts +0 -17
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/api/uncached-fetch/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/favicon.ico +0 -0
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/globals.css +0 -26
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/layout.tsx +0 -59
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/page.tsx +0 -755
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/cached-static-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/cached-static-fetch/revalidate15--default-page/page.tsx +0 -34
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/cached-static-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/no-fetch/default-page/page.tsx +0 -55
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/revalidated-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/revalidated-fetch/revalidate15--default-page/page.tsx +0 -35
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/revalidated-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/uncached-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/uncached-fetch/revalidate15--default-page/page.tsx +0 -32
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/pages/uncached-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/revalidation-interface.tsx +0 -267
- package/test/nextjs-test-projects/next-app-16-0-11/src/app/update-tag-test/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-0-11/tsconfig.json +0 -34
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/README.md +0 -36
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/cache-handler.js +0 -3
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/eslint.config.mjs +0 -18
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/next.config.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/package.json +0 -28
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/pnpm-lock.yaml +0 -4206
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/postcss.config.mjs +0 -7
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/public/file.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/public/globe.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/public/next.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/public/vercel.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/public/window.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/api/cached-static-fetch/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/api/cached-with-cachelife/route.ts +0 -24
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/api/cached-with-tag/route.ts +0 -21
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/api/expire-matrix/revalidate/route.ts +0 -34
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/api/expire-matrix/route.ts +0 -23
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/api/revalidate-tag/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/api/revalidated-fetch/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/cache-lab/cachelife-short/page.tsx +0 -110
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/cache-lab/page.tsx +0 -112
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/cache-lab/revalidate-durations/page.tsx +0 -106
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/cache-lab/runtime-data-suspense/page.tsx +0 -127
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/cache-lab/stale-while-revalidate/page.tsx +0 -130
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/cache-lab/tag-invalidation/page.tsx +0 -127
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/cache-lab/use-cache-nondeterministic/page.tsx +0 -110
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/cache-lab/use-cache-remote/page.tsx +0 -85
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/favicon.ico +0 -0
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/globals.css +0 -26
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/layout.tsx +0 -57
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/page.tsx +0 -755
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/revalidation-interface.tsx +0 -267
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/src/app/update-tag-test/page.tsx +0 -22
- package/test/nextjs-test-projects/next-app-16-0-11-cache-components/tsconfig.json +0 -34
- package/test/nextjs-test-projects/next-app-16-2-6/README.md +0 -36
- package/test/nextjs-test-projects/next-app-16-2-6/eslint.config.mjs +0 -18
- package/test/nextjs-test-projects/next-app-16-2-6/next.config.ts +0 -7
- package/test/nextjs-test-projects/next-app-16-2-6/package.json +0 -28
- package/test/nextjs-test-projects/next-app-16-2-6/pnpm-lock.yaml +0 -4165
- package/test/nextjs-test-projects/next-app-16-2-6/postcss.config.mjs +0 -7
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/api/cached-static-fetch/route.ts +0 -18
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/api/nested-fetch-in-api-route/revalidated-fetch/route.ts +0 -27
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/api/revalidatePath/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/api/revalidateTag/route.ts +0 -20
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/api/revalidated-fetch/route.ts +0 -17
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/api/uncached-fetch/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/favicon.ico +0 -0
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/globals.css +0 -26
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/layout.tsx +0 -59
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/page.tsx +0 -755
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/cached-static-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/cached-static-fetch/revalidate15--default-page/page.tsx +0 -34
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/cached-static-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/no-fetch/default-page/page.tsx +0 -55
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/revalidated-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/revalidated-fetch/revalidate15--default-page/page.tsx +0 -35
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/revalidated-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/uncached-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/uncached-fetch/revalidate15--default-page/page.tsx +0 -32
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/pages/uncached-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/revalidation-interface.tsx +0 -267
- package/test/nextjs-test-projects/next-app-16-2-6/src/app/update-tag-test/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-2-6/tsconfig.json +0 -34
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/README.md +0 -36
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/cache-handler.js +0 -3
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/eslint.config.mjs +0 -18
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/next.config.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/package.json +0 -28
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/pnpm-lock.yaml +0 -4165
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/postcss.config.mjs +0 -7
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/public/file.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/public/globe.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/public/next.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/public/vercel.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/public/window.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/api/cached-static-fetch/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/api/cached-with-cachelife/route.ts +0 -24
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/api/cached-with-tag/route.ts +0 -21
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/api/expire-matrix/revalidate/route.ts +0 -34
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/api/expire-matrix/route.ts +0 -23
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/api/revalidate-tag/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/api/revalidated-fetch/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/cache-lab/cachelife-short/page.tsx +0 -110
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/cache-lab/page.tsx +0 -112
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/cache-lab/revalidate-durations/page.tsx +0 -106
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/cache-lab/runtime-data-suspense/page.tsx +0 -127
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/cache-lab/stale-while-revalidate/page.tsx +0 -130
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/cache-lab/tag-invalidation/page.tsx +0 -127
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/cache-lab/use-cache-nondeterministic/page.tsx +0 -110
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/cache-lab/use-cache-remote/page.tsx +0 -85
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/favicon.ico +0 -0
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/globals.css +0 -26
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/layout.tsx +0 -57
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/page.tsx +0 -755
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/revalidation-interface.tsx +0 -267
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/src/app/update-tag-test/page.tsx +0 -22
- package/test/nextjs-test-projects/next-app-16-2-6-cache-components/tsconfig.json +0 -34
- package/test/nextjs-test-projects/next-app-16-3-0/README.md +0 -36
- package/test/nextjs-test-projects/next-app-16-3-0/eslint.config.mjs +0 -18
- package/test/nextjs-test-projects/next-app-16-3-0/next.config.ts +0 -7
- package/test/nextjs-test-projects/next-app-16-3-0/package.json +0 -28
- package/test/nextjs-test-projects/next-app-16-3-0/pnpm-lock.yaml +0 -4284
- package/test/nextjs-test-projects/next-app-16-3-0/postcss.config.mjs +0 -7
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/api/cached-static-fetch/route.ts +0 -18
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/api/nested-fetch-in-api-route/revalidated-fetch/route.ts +0 -27
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/api/revalidatePath/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/api/revalidateTag/route.ts +0 -20
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/api/revalidated-fetch/route.ts +0 -17
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/api/uncached-fetch/route.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/favicon.ico +0 -0
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/globals.css +0 -26
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/layout.tsx +0 -59
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/page.tsx +0 -755
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/cached-static-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/cached-static-fetch/revalidate15--default-page/page.tsx +0 -34
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/cached-static-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/no-fetch/default-page/page.tsx +0 -55
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/revalidated-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/revalidated-fetch/revalidate15--default-page/page.tsx +0 -35
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/revalidated-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/uncached-fetch/default--force-dynamic-page/page.tsx +0 -19
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/uncached-fetch/revalidate15--default-page/page.tsx +0 -32
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/pages/uncached-fetch/revalidate15--force-dynamic-page/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/revalidation-interface.tsx +0 -267
- package/test/nextjs-test-projects/next-app-16-3-0/src/app/update-tag-test/page.tsx +0 -25
- package/test/nextjs-test-projects/next-app-16-3-0/tsconfig.json +0 -34
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/README.md +0 -36
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/cache-handler.js +0 -3
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/eslint.config.mjs +0 -18
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/next.config.ts +0 -15
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/package.json +0 -28
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/pnpm-lock.yaml +0 -4284
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/postcss.config.mjs +0 -7
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/public/file.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/public/globe.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/public/next.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/public/vercel.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/public/window.svg +0 -1
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/api/cached-static-fetch/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/api/cached-with-cachelife/route.ts +0 -24
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/api/cached-with-tag/route.ts +0 -21
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/api/expire-matrix/revalidate/route.ts +0 -34
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/api/expire-matrix/route.ts +0 -23
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/api/revalidate-tag/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/api/revalidated-fetch/route.ts +0 -19
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/cache-lab/cachelife-short/page.tsx +0 -110
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/cache-lab/page.tsx +0 -112
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/cache-lab/revalidate-durations/page.tsx +0 -106
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/cache-lab/runtime-data-suspense/page.tsx +0 -127
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/cache-lab/stale-while-revalidate/page.tsx +0 -130
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/cache-lab/tag-invalidation/page.tsx +0 -127
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/cache-lab/use-cache-nondeterministic/page.tsx +0 -110
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/cache-lab/use-cache-remote/page.tsx +0 -85
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/favicon.ico +0 -0
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/globals.css +0 -26
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/layout.tsx +0 -57
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/page.tsx +0 -755
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/revalidation-interface.tsx +0 -267
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/src/app/update-tag-test/page.tsx +0 -22
- package/test/nextjs-test-projects/next-app-16-3-0-cache-components/tsconfig.json +0 -34
- package/test/nextjs-test-projects/next-app-customized/README.md +0 -36
- package/test/nextjs-test-projects/next-app-customized/customized-cache-handler.js +0 -34
- package/test/nextjs-test-projects/next-app-customized/eslint.config.mjs +0 -16
- package/test/nextjs-test-projects/next-app-customized/next.config.js +0 -6
- package/test/nextjs-test-projects/next-pages-16-2-6/README.md +0 -16
- package/test/nextjs-test-projects/next-pages-16-2-6/eslint.config.mjs +0 -18
- package/test/nextjs-test-projects/next-pages-16-2-6/next.config.ts +0 -7
- package/test/nextjs-test-projects/next-pages-16-2-6/package.json +0 -26
- package/test/nextjs-test-projects/next-pages-16-2-6/pnpm-lock.yaml +0 -3896
- package/test/nextjs-test-projects/next-pages-16-2-6/src/pages/api/revalidate.ts +0 -24
- package/test/nextjs-test-projects/next-pages-16-2-6/src/pages/index.tsx +0 -11
- package/test/nextjs-test-projects/next-pages-16-2-6/src/pages/isr/[slug].tsx +0 -49
- package/test/nextjs-test-projects/next-pages-16-2-6/src/pages/static-forever.tsx +0 -20
- package/test/nextjs-test-projects/next-pages-16-2-6/tsconfig.json +0 -34
- package/test/nextjs-test-projects/next-pages-16-3-0/README.md +0 -16
- package/test/nextjs-test-projects/next-pages-16-3-0/eslint.config.mjs +0 -18
- package/test/nextjs-test-projects/next-pages-16-3-0/next.config.ts +0 -7
- package/test/nextjs-test-projects/next-pages-16-3-0/package.json +0 -26
- package/test/nextjs-test-projects/next-pages-16-3-0/pnpm-lock.yaml +0 -3939
- package/test/nextjs-test-projects/next-pages-16-3-0/src/pages/api/revalidate.ts +0 -24
- package/test/nextjs-test-projects/next-pages-16-3-0/src/pages/index.tsx +0 -11
- package/test/nextjs-test-projects/next-pages-16-3-0/src/pages/isr/[slug].tsx +0 -49
- package/test/nextjs-test-projects/next-pages-16-3-0/src/pages/static-forever.tsx +0 -20
- package/test/nextjs-test-projects/next-pages-16-3-0/tsconfig.json +0 -34
- package/test/playwright/cache-lab.spec.ts +0 -232
- package/test/playwright/update-tag.spec.ts +0 -33
- package/test/vitest/integration/build-id-prefix.integration.test.ts +0 -102
- package/test/vitest/integration/cache-components/cache-components.integration.test.ts +0 -389
- package/test/vitest/integration/cache-components/redis-kill-reconnect.test.ts +0 -65
- package/test/vitest/integration/cache-components/redis-quit-vs-disconnect.test.ts +0 -59
- package/test/vitest/integration/cache-components/redis-subscriber-outage.test.ts +0 -100
- package/test/vitest/integration/cache-components/scripts/redis-kill-reconnect.ts +0 -243
- package/test/vitest/integration/cache-components/scripts/redis-quit-vs-disconnect.ts +0 -113
- package/test/vitest/integration/cache-components/scripts/redis-subscriber-outage.ts +0 -379
- package/test/vitest/integration/cache-components/scripts/redis-test-helpers.ts +0 -155
- package/test/vitest/integration/nextjs-cache-handler.integration.test.ts +0 -959
- package/test/vitest/integration/pages-router.integration.test.ts +0 -430
- package/test/vitest/unit/SyncedMap-orphan-cleanup.test.ts +0 -111
- package/test/vitest/unit/SyncedMap-reconnect-repro.test.ts +0 -154
- package/test/vitest/unit/cache-components-update-tags.test.ts +0 -350
- package/test/vitest/unit/cache-ttl.test.ts +0 -67
- package/test/vitest/unit/compare-and-unlink.test.ts +0 -22
- package/test/vitest/unit/index.test.ts +0 -190
- package/test/vitest/unit/pages-router-kinds.test.ts +0 -303
- package/test/vitest/unit/reconnect-socket-already-opened.test.ts +0 -117
- package/test/vitest/unit/redis-connection.test.ts +0 -39
- package/test/vitest/unit/serializer.test.ts +0 -182
- package/test/vitest/unit/tag-revalidation.test.ts +0 -178
- package/test/vitest/unit/utils/prefix.test.ts +0 -115
- package/tsconfig.json +0 -18
- package/tsup.config.ts +0 -14
- package/vite.config.ts +0 -34
- package/vitest.cache-components.config.ts +0 -16
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
2
|
-
|
|
3
|
-
// On-demand revalidation endpoint: res.revalidate(path) re-renders the page
|
|
4
|
-
// and writes the fresh entry through the cache handler, so all instances
|
|
5
|
-
// sharing the same Redis pick it up.
|
|
6
|
-
export default async function handler(
|
|
7
|
-
req: NextApiRequest,
|
|
8
|
-
res: NextApiResponse,
|
|
9
|
-
) {
|
|
10
|
-
const path = req.query.path;
|
|
11
|
-
if (typeof path !== 'string') {
|
|
12
|
-
return res
|
|
13
|
-
.status(400)
|
|
14
|
-
.json({ revalidated: false, error: 'Missing ?path= query parameter' });
|
|
15
|
-
}
|
|
16
|
-
try {
|
|
17
|
-
await res.revalidate(path);
|
|
18
|
-
return res.json({ revalidated: true, path });
|
|
19
|
-
} catch (err) {
|
|
20
|
-
return res
|
|
21
|
-
.status(500)
|
|
22
|
-
.json({ revalidated: false, path, error: String(err) });
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { GetStaticPaths, GetStaticProps } from 'next';
|
|
2
|
-
|
|
3
|
-
type Props = { slug: string; timestamp: number; counter: number };
|
|
4
|
-
|
|
5
|
-
// Per-process regeneration counter. Two server instances of the same build
|
|
6
|
-
// have independent counters, while the timestamp proves cross-instance
|
|
7
|
-
// freshness after on-demand revalidation.
|
|
8
|
-
let regenerationCounter = 0;
|
|
9
|
-
|
|
10
|
-
export default function IsrPage({ slug, timestamp, counter }: Props) {
|
|
11
|
-
return (
|
|
12
|
-
<main>
|
|
13
|
-
<h1>ISR page</h1>
|
|
14
|
-
<p>Slug: {slug}</p>
|
|
15
|
-
<p>Timestamp: {timestamp}</p>
|
|
16
|
-
<p>Counter: {counter}</p>
|
|
17
|
-
</main>
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const getStaticPaths: GetStaticPaths = async () => {
|
|
22
|
-
return {
|
|
23
|
-
paths: [{ params: { slug: 'prebuilt' } }],
|
|
24
|
-
fallback: 'blocking',
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// revalidate is set high (300s) so that natural ISR regeneration does not
|
|
29
|
-
// interfere with the on-demand revalidation (res.revalidate) tests.
|
|
30
|
-
export const getStaticProps: GetStaticProps<Props> = async (context) => {
|
|
31
|
-
const slug = context.params?.slug as string;
|
|
32
|
-
|
|
33
|
-
if (slug === 'not-found') {
|
|
34
|
-
return { notFound: true, revalidate: 300 };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (slug === 'redirect') {
|
|
38
|
-
return {
|
|
39
|
-
redirect: { destination: '/static-forever', permanent: false },
|
|
40
|
-
revalidate: 300,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
regenerationCounter += 1;
|
|
45
|
-
return {
|
|
46
|
-
props: { slug, timestamp: Date.now(), counter: regenerationCounter },
|
|
47
|
-
revalidate: 300,
|
|
48
|
-
};
|
|
49
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { GetStaticProps } from 'next';
|
|
2
|
-
|
|
3
|
-
type Props = { timestamp: number };
|
|
4
|
-
|
|
5
|
-
export default function StaticForever({ timestamp }: Props) {
|
|
6
|
-
return (
|
|
7
|
-
<main>
|
|
8
|
-
<h1>Static forever</h1>
|
|
9
|
-
<p>Timestamp: {timestamp}</p>
|
|
10
|
-
</main>
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// revalidate is intentionally omitted (revalidate: false): the cache entry
|
|
15
|
-
// must fall through to the defaultStaleAge based TTL in the cache handler.
|
|
16
|
-
export const getStaticProps: GetStaticProps<Props> = async () => {
|
|
17
|
-
return {
|
|
18
|
-
props: { timestamp: Date.now() },
|
|
19
|
-
};
|
|
20
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2017",
|
|
4
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
-
"allowJs": true,
|
|
6
|
-
"skipLibCheck": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"noEmit": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"module": "esnext",
|
|
11
|
-
"moduleResolution": "bundler",
|
|
12
|
-
"resolveJsonModule": true,
|
|
13
|
-
"isolatedModules": true,
|
|
14
|
-
"jsx": "react-jsx",
|
|
15
|
-
"incremental": true,
|
|
16
|
-
"plugins": [
|
|
17
|
-
{
|
|
18
|
-
"name": "next"
|
|
19
|
-
}
|
|
20
|
-
],
|
|
21
|
-
"paths": {
|
|
22
|
-
"@/*": ["./src/*"]
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
"include": [
|
|
26
|
-
"next-env.d.ts",
|
|
27
|
-
"**/*.ts",
|
|
28
|
-
"**/*.tsx",
|
|
29
|
-
".next/types/**/*.ts",
|
|
30
|
-
".next/dev/types/**/*.ts",
|
|
31
|
-
"**/*.mts"
|
|
32
|
-
],
|
|
33
|
-
"exclude": ["node_modules"]
|
|
34
|
-
}
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
// These tests assume the Cache Components Next.js app is already running on the same origin as baseURL.
|
|
4
|
-
// Recommended:
|
|
5
|
-
// PLAYWRIGHT_BASE_URL=http://localhost:3001 pnpm test:e2e
|
|
6
|
-
|
|
7
|
-
test.describe('Cache Lab (Cache Components)', () => {
|
|
8
|
-
test('use cache non-deterministic values are stable until updateTag', async ({
|
|
9
|
-
page,
|
|
10
|
-
}) => {
|
|
11
|
-
await page.goto('/cache-lab/use-cache-nondeterministic');
|
|
12
|
-
|
|
13
|
-
const random1 = page.getByTestId('random1');
|
|
14
|
-
const now = page.getByTestId('now');
|
|
15
|
-
|
|
16
|
-
await expect(random1).toBeVisible();
|
|
17
|
-
|
|
18
|
-
const beforeRandom = await random1.textContent();
|
|
19
|
-
const beforeNow = await now.textContent();
|
|
20
|
-
|
|
21
|
-
await page.reload();
|
|
22
|
-
await expect(random1).toBeVisible();
|
|
23
|
-
|
|
24
|
-
const afterReloadRandom = await random1.textContent();
|
|
25
|
-
const afterReloadNow = await now.textContent();
|
|
26
|
-
|
|
27
|
-
expect(afterReloadRandom).toBe(beforeRandom);
|
|
28
|
-
expect(afterReloadNow).toBe(beforeNow);
|
|
29
|
-
|
|
30
|
-
await page
|
|
31
|
-
.getByRole('button', { name: "updateTag('cache-lab:nondet')" })
|
|
32
|
-
.click();
|
|
33
|
-
await page.waitForLoadState('networkidle');
|
|
34
|
-
|
|
35
|
-
await expect(random1).toBeVisible();
|
|
36
|
-
|
|
37
|
-
const afterInvalidateRandom = await random1.textContent();
|
|
38
|
-
const afterInvalidateNow = await now.textContent();
|
|
39
|
-
|
|
40
|
-
expect(afterInvalidateRandom).not.toBe(beforeRandom);
|
|
41
|
-
expect(afterInvalidateNow).not.toBe(beforeNow);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('tag invalidation changes cached values (updateTag + revalidateTag)', async ({
|
|
45
|
-
page,
|
|
46
|
-
}) => {
|
|
47
|
-
await page.goto('/cache-lab/tag-invalidation');
|
|
48
|
-
|
|
49
|
-
const createdAt = page.getByTestId('createdAt');
|
|
50
|
-
const value = page.getByTestId('value');
|
|
51
|
-
|
|
52
|
-
await expect(createdAt).toBeVisible();
|
|
53
|
-
|
|
54
|
-
const beforeCreatedAt = await createdAt.textContent();
|
|
55
|
-
const beforeValue = await value.textContent();
|
|
56
|
-
|
|
57
|
-
await page.reload();
|
|
58
|
-
await expect(createdAt).toBeVisible();
|
|
59
|
-
expect(await createdAt.textContent()).toBe(beforeCreatedAt);
|
|
60
|
-
expect(await value.textContent()).toBe(beforeValue);
|
|
61
|
-
|
|
62
|
-
await page
|
|
63
|
-
.getByRole('button', { name: "updateTag('cache-lab:tag')" })
|
|
64
|
-
.click();
|
|
65
|
-
await page.waitForLoadState('networkidle');
|
|
66
|
-
|
|
67
|
-
await expect(createdAt).toBeVisible();
|
|
68
|
-
expect(await createdAt.textContent()).not.toBe(beforeCreatedAt);
|
|
69
|
-
expect(await value.textContent()).not.toBe(beforeValue);
|
|
70
|
-
|
|
71
|
-
const afterUpdateCreatedAt = await createdAt.textContent();
|
|
72
|
-
const afterUpdateValue = await value.textContent();
|
|
73
|
-
|
|
74
|
-
await page
|
|
75
|
-
.getByRole('button', { name: "revalidateTag('cache-lab:tag')" })
|
|
76
|
-
.click();
|
|
77
|
-
await page.waitForLoadState('networkidle');
|
|
78
|
-
|
|
79
|
-
await expect(createdAt).toBeVisible();
|
|
80
|
-
|
|
81
|
-
const maybeStaleCreatedAt = await createdAt.textContent();
|
|
82
|
-
const maybeStaleValue = await value.textContent();
|
|
83
|
-
|
|
84
|
-
// Revalidate can be SWR; allow either immediate refresh or stale served,
|
|
85
|
-
// but the value should eventually change on subsequent reloads.
|
|
86
|
-
if (maybeStaleCreatedAt === afterUpdateCreatedAt) {
|
|
87
|
-
// give background refresh some time
|
|
88
|
-
await page.waitForTimeout(4000);
|
|
89
|
-
await page.reload();
|
|
90
|
-
await expect(createdAt).toBeVisible();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
expect(await createdAt.textContent()).not.toBe(afterUpdateCreatedAt);
|
|
94
|
-
expect(await value.textContent()).not.toBe(afterUpdateValue);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test('runtime cookie changes cache key (cached payload differs per cookie)', async ({
|
|
98
|
-
page,
|
|
99
|
-
}) => {
|
|
100
|
-
await page.goto('/cache-lab/runtime-data-suspense');
|
|
101
|
-
|
|
102
|
-
const cookieValue = page.getByTestId('cookie');
|
|
103
|
-
const payload = page.getByTestId('payload');
|
|
104
|
-
|
|
105
|
-
await expect(cookieValue).toBeVisible();
|
|
106
|
-
|
|
107
|
-
await page.getByRole('button', { name: 'Set cookie: user-a' }).click();
|
|
108
|
-
await page.waitForLoadState('networkidle');
|
|
109
|
-
|
|
110
|
-
await expect(cookieValue).toHaveText('user-a');
|
|
111
|
-
const payloadA1 = await payload.textContent();
|
|
112
|
-
|
|
113
|
-
await page.reload();
|
|
114
|
-
await expect(cookieValue).toHaveText('user-a');
|
|
115
|
-
const payloadA2 = await payload.textContent();
|
|
116
|
-
expect(payloadA2).toBe(payloadA1);
|
|
117
|
-
|
|
118
|
-
await page.getByRole('button', { name: 'Set cookie: user-b' }).click();
|
|
119
|
-
await page.waitForLoadState('networkidle');
|
|
120
|
-
|
|
121
|
-
await expect(cookieValue).toHaveText('user-b');
|
|
122
|
-
const payloadB = await payload.textContent();
|
|
123
|
-
|
|
124
|
-
expect(payloadB).not.toBe(payloadA1);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('use cache: remote values are stable until updateTag', async ({
|
|
128
|
-
page,
|
|
129
|
-
}) => {
|
|
130
|
-
await page.goto('/cache-lab/use-cache-remote');
|
|
131
|
-
|
|
132
|
-
const computedAt = page.getByTestId('computedAt');
|
|
133
|
-
const value = page.getByTestId('value');
|
|
134
|
-
|
|
135
|
-
await expect(computedAt).toBeVisible();
|
|
136
|
-
|
|
137
|
-
const beforeComputedAt = await computedAt.textContent();
|
|
138
|
-
const beforeValue = await value.textContent();
|
|
139
|
-
|
|
140
|
-
await page.reload();
|
|
141
|
-
await expect(computedAt).toBeVisible();
|
|
142
|
-
expect(await computedAt.textContent()).toBe(beforeComputedAt);
|
|
143
|
-
expect(await value.textContent()).toBe(beforeValue);
|
|
144
|
-
|
|
145
|
-
await page
|
|
146
|
-
.getByRole('button', { name: "updateTag('cache-lab:remote')" })
|
|
147
|
-
.click();
|
|
148
|
-
await page.waitForLoadState('networkidle');
|
|
149
|
-
|
|
150
|
-
await expect(computedAt).toBeVisible();
|
|
151
|
-
expect(await computedAt.textContent()).not.toBe(beforeComputedAt);
|
|
152
|
-
expect(await value.textContent()).not.toBe(beforeValue);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
test('revalidateTag with durations can serve stale values before refresh completes', async ({
|
|
156
|
-
page,
|
|
157
|
-
}) => {
|
|
158
|
-
await page.goto('/cache-lab/revalidate-durations');
|
|
159
|
-
|
|
160
|
-
const computedAt = page.getByTestId('computedAt');
|
|
161
|
-
const value = page.getByTestId('value');
|
|
162
|
-
|
|
163
|
-
await expect(computedAt).toBeVisible();
|
|
164
|
-
|
|
165
|
-
const beforeComputedAt = await computedAt.textContent();
|
|
166
|
-
const beforeValue = await value.textContent();
|
|
167
|
-
|
|
168
|
-
const actionResponse = page.waitForResponse(
|
|
169
|
-
(res) =>
|
|
170
|
-
res.request().method() === 'POST' &&
|
|
171
|
-
res.url().includes('/cache-lab/revalidate-durations'),
|
|
172
|
-
);
|
|
173
|
-
await page
|
|
174
|
-
.getByRole('button', {
|
|
175
|
-
name: "revalidateTag('cache-lab:durations', { expire: 2 })",
|
|
176
|
-
})
|
|
177
|
-
.click();
|
|
178
|
-
await actionResponse;
|
|
179
|
-
|
|
180
|
-
// Reload as soon as the Server Action has landed. Do not wait for
|
|
181
|
-
// networkidle — that can let the ~2.5s background refresh finish first.
|
|
182
|
-
await page.reload();
|
|
183
|
-
await expect(computedAt).toBeVisible();
|
|
184
|
-
|
|
185
|
-
const afterRevalidateComputedAt = await computedAt.textContent();
|
|
186
|
-
const afterRevalidateValue = await value.textContent();
|
|
187
|
-
|
|
188
|
-
// SWR: ideally the first reload still serves previous values. If background
|
|
189
|
-
// refresh already completed, skip the stale assertion and verify eventual refresh.
|
|
190
|
-
if (afterRevalidateComputedAt === beforeComputedAt) {
|
|
191
|
-
expect(afterRevalidateValue).toBe(beforeValue);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
await page.waitForTimeout(5000);
|
|
195
|
-
await page.reload();
|
|
196
|
-
await expect(computedAt).toBeVisible();
|
|
197
|
-
|
|
198
|
-
expect(await computedAt.textContent()).not.toBe(beforeComputedAt);
|
|
199
|
-
expect(await value.textContent()).not.toBe(beforeValue);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
test('stale-while-revalidate demo eventually produces a new value after revalidateTag', async ({
|
|
203
|
-
page,
|
|
204
|
-
}) => {
|
|
205
|
-
await page.goto('/cache-lab/stale-while-revalidate');
|
|
206
|
-
|
|
207
|
-
const computedAt = page.getByTestId('computedAt');
|
|
208
|
-
const value = page.getByTestId('value');
|
|
209
|
-
|
|
210
|
-
await expect(computedAt).toBeVisible();
|
|
211
|
-
|
|
212
|
-
const beforeComputedAt = await computedAt.textContent();
|
|
213
|
-
const beforeValue = await value.textContent();
|
|
214
|
-
|
|
215
|
-
// Ensure it becomes stale.
|
|
216
|
-
await page.waitForTimeout(3000);
|
|
217
|
-
|
|
218
|
-
await page
|
|
219
|
-
.getByRole('button', { name: "revalidateTag('cache-lab:swr')" })
|
|
220
|
-
.click();
|
|
221
|
-
await page.waitForLoadState('networkidle');
|
|
222
|
-
|
|
223
|
-
// Allow some time for background refresh to potentially complete.
|
|
224
|
-
await page.waitForTimeout(4500);
|
|
225
|
-
|
|
226
|
-
await page.reload();
|
|
227
|
-
await expect(computedAt).toBeVisible();
|
|
228
|
-
|
|
229
|
-
expect(await computedAt.textContent()).not.toBe(beforeComputedAt);
|
|
230
|
-
expect(await value.textContent()).not.toBe(beforeValue);
|
|
231
|
-
});
|
|
232
|
-
});
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
// This test assumes the Next 16 app is already running, e.g.:
|
|
4
|
-
// cd test/nextjs-test-projects/next-app-16-0-11 && pnpm dev
|
|
5
|
-
// on the same origin as baseURL.
|
|
6
|
-
|
|
7
|
-
test('button click triggers Server Action using updateTag', async ({
|
|
8
|
-
page,
|
|
9
|
-
}) => {
|
|
10
|
-
await page.goto('/update-tag-test');
|
|
11
|
-
|
|
12
|
-
await expect(page.getByText('UpdateTag Test')).toBeVisible();
|
|
13
|
-
|
|
14
|
-
const clicks = page.getByTestId('clicks');
|
|
15
|
-
const before = await clicks.textContent();
|
|
16
|
-
|
|
17
|
-
await page.getByRole('button', { name: 'Increment' }).click();
|
|
18
|
-
|
|
19
|
-
// Wait for network and any navigation caused by the Server Action
|
|
20
|
-
await page.waitForLoadState('networkidle');
|
|
21
|
-
|
|
22
|
-
const after = await clicks.textContent();
|
|
23
|
-
|
|
24
|
-
// Server Action should have run and updated the UI
|
|
25
|
-
expect(after).not.toBe(before);
|
|
26
|
-
|
|
27
|
-
// Ensure there is no error message about updateTag usage
|
|
28
|
-
const errorLocator = page.getByText(
|
|
29
|
-
'updateTag can only be called from within a Server Action',
|
|
30
|
-
{ exact: false },
|
|
31
|
-
);
|
|
32
|
-
await expect(errorLocator).toHaveCount(0);
|
|
33
|
-
});
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
2
|
-
import { spawn, ChildProcessWithoutNullStreams } from 'child_process';
|
|
3
|
-
import { createClient, RedisClientType } from 'redis';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import fetch from 'node-fetch';
|
|
7
|
-
|
|
8
|
-
const NEXT_APP = 'next-app-15-4-11';
|
|
9
|
-
const PORT = 3075;
|
|
10
|
-
const BASE_URL = `http://localhost:${PORT}`;
|
|
11
|
-
|
|
12
|
-
async function waitForServer(url: string, timeout = 20000) {
|
|
13
|
-
const start = Date.now();
|
|
14
|
-
while (Date.now() - start < timeout) {
|
|
15
|
-
try {
|
|
16
|
-
const res = await fetch(url + '/api/cached-static-fetch');
|
|
17
|
-
if (res.ok) return;
|
|
18
|
-
} catch {}
|
|
19
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
20
|
-
}
|
|
21
|
-
throw new Error('Next.js server did not start in time');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
describe('BUILD_ID-based key prefix (Next handlers)', () => {
|
|
25
|
-
let nextProcess: ChildProcessWithoutNullStreams | undefined;
|
|
26
|
-
let redis: RedisClientType;
|
|
27
|
-
let appDir: string;
|
|
28
|
-
let buildId: string;
|
|
29
|
-
|
|
30
|
-
beforeAll(async () => {
|
|
31
|
-
appDir = path.join(__dirname, '..', '..', 'nextjs-test-projects', NEXT_APP);
|
|
32
|
-
|
|
33
|
-
// Ensure clean env so BUILD_ID precedence kicks in
|
|
34
|
-
delete (process.env as Record<string, string | undefined>).KEY_PREFIX;
|
|
35
|
-
delete (process.env as Record<string, string | undefined>).VERCEL_URL;
|
|
36
|
-
process.env.VERCEL_ENV = 'production';
|
|
37
|
-
process.env.REDISHOST = process.env.REDISHOST || 'localhost';
|
|
38
|
-
process.env.REDISPORT = process.env.REDISPORT || '6379';
|
|
39
|
-
|
|
40
|
-
// Install + build
|
|
41
|
-
await new Promise<void>((resolve, reject) => {
|
|
42
|
-
const p = spawn('pnpm', ['install'], { cwd: appDir, stdio: 'inherit' });
|
|
43
|
-
p.on('close', (code) =>
|
|
44
|
-
code === 0 ? resolve() : reject(new Error('pnpm i failed')),
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
await new Promise<void>((resolve, reject) => {
|
|
48
|
-
const p = spawn('pnpm', ['build'], { cwd: appDir, stdio: 'inherit' });
|
|
49
|
-
p.on('close', (code) =>
|
|
50
|
-
code === 0 ? resolve() : reject(new Error('pnpm build failed')),
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Read BUILD_ID from the built app
|
|
55
|
-
buildId = fs
|
|
56
|
-
.readFileSync(path.join(appDir, '.next', 'BUILD_ID'), 'utf8')
|
|
57
|
-
.trim();
|
|
58
|
-
|
|
59
|
-
// Start server without KEY_PREFIX/VERCEL_URL
|
|
60
|
-
nextProcess = spawn('npx', ['next', 'start', '-p', String(PORT)], {
|
|
61
|
-
cwd: appDir,
|
|
62
|
-
env: { ...process.env, SKIP_KEYSPACE_CONFIG_CHECK: 'true' },
|
|
63
|
-
stdio: 'pipe',
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
nextProcess.stderr?.on(
|
|
67
|
-
'data',
|
|
68
|
-
(d) => process.env.DEBUG_INTEGRATION && console.error(String(d)),
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
await waitForServer(BASE_URL);
|
|
72
|
-
|
|
73
|
-
// Connect Redis
|
|
74
|
-
redis = createClient({
|
|
75
|
-
url: `redis://${process.env.REDISHOST}:${process.env.REDISPORT}`,
|
|
76
|
-
});
|
|
77
|
-
await redis.connect();
|
|
78
|
-
}, 180000);
|
|
79
|
-
|
|
80
|
-
afterAll(async () => {
|
|
81
|
-
try {
|
|
82
|
-
if (redis) await redis.quit();
|
|
83
|
-
} finally {
|
|
84
|
-
if (nextProcess) nextProcess.kill();
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('uses BUILD_ID as the Redis key prefix when no KEY_PREFIX/VERCEL_URL set', async () => {
|
|
89
|
-
// Warm cache twice to ensure a set occurs even if first was during startup
|
|
90
|
-
const res1 = await fetch(BASE_URL + '/api/cached-static-fetch');
|
|
91
|
-
expect(res1.ok).toBe(true);
|
|
92
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
93
|
-
const res2 = await fetch(BASE_URL + '/api/cached-static-fetch');
|
|
94
|
-
expect(res2.ok).toBe(true);
|
|
95
|
-
|
|
96
|
-
// Allow background syncs
|
|
97
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
98
|
-
|
|
99
|
-
const keys = await redis.keys(`${buildId}*`);
|
|
100
|
-
expect(keys.length).toBeGreaterThan(0);
|
|
101
|
-
});
|
|
102
|
-
});
|