From c3cf55347b435a505ac77137c95805aa99f23701 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 12:24:19 +0200 Subject: [PATCH 1/4] chore(deps): update dependency netlify-cli to v23.9.2 (#3184) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michal Piechowiak --- .github/workflows/run-tests.yml | 4 + .github/workflows/test-e2e.yml | 1 + e2e-report/package-lock.json | 649 +++++++++++++++++++++++++++----- e2e-report/package.json | 2 +- package-lock.json | 476 +++++++++++++++-------- package.json | 2 +- tests/e2e/page-router.test.ts | 2 +- tools/fetch-retry.mjs | 41 ++ 8 files changed, 925 insertions(+), 252 deletions(-) create mode 100644 tools/fetch-retry.mjs diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 4d4d56c649..181a3ca783 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -124,6 +124,7 @@ jobs: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NEXT_VERSION: ${{ matrix.version }} NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }} + NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs - name: Upload blob report to GitHub Actions Artifacts uses: actions/upload-artifact@v4 if: always() @@ -220,6 +221,7 @@ jobs: env: NEXT_VERSION: ${{ matrix.version }} NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }} + NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs - name: 'Unit and integration tests' run: npm run test:ci:unit-and-integration -- --shard=${{ matrix.shard }}/8 env: @@ -227,6 +229,7 @@ jobs: NEXT_VERSION: ${{ matrix.version }} NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }} TEMP: ${{ github.workspace }}/.. + NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs smoke: if: always() @@ -289,6 +292,7 @@ jobs: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NEXT_VERSION: ${{ matrix.version }} NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }} + NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs merge-reports: if: always() diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 7a955daf4f..e87a4f2ea9 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -239,6 +239,7 @@ jobs: NEXT_RESOLVED_VERSION: ${{ matrix.version_spec.version }} IS_WEBPACK_TEST: ${{ steps.decide-default-bundler.outputs.default_bundler == 'webpack' && '1' || '' }} IS_TURBOPACK_TEST: ${{ steps.decide-default-bundler.outputs.default_bundler == 'turbopack' && '1' || '' }} + NODE_OPTIONS: --import ${{ github.workspace }}/${{ env.runtime-path}}/tools/fetch-retry.mjs run: node run-tests.js -g ${{ matrix.group }}/${{ needs.setup.outputs.total }} -c ${TEST_CONCURRENCY} --type e2e working-directory: ${{ env.next-path }} diff --git a/e2e-report/package-lock.json b/e2e-report/package-lock.json index 1a9bc4f4c5..61d2db830d 100644 --- a/e2e-report/package-lock.json +++ b/e2e-report/package-lock.json @@ -18,7 +18,7 @@ "daisyui": "^4.12.2", "eslint": "^9.34.0", "eslint-config-next": "^15.5.0", - "netlify-cli": "^23.9.1", + "netlify-cli": "^23.9.2", "postcss": "^8.4.38", "sass": "^1.77.1", "tailwindcss": "^3.4.4" @@ -4789,29 +4789,29 @@ "dev": true }, "node_modules/netlify-cli": { - "version": "23.9.1", - "resolved": "https://registry.npmjs.org/netlify-cli/-/netlify-cli-23.9.1.tgz", - "integrity": "sha512-Wg67zCFbg/bgWw0ub3vrG+7TSXDP9gNeGsAU7JvFR7Wy+KP47ELTNeP5uZKAwf9h0HIw0sUCvyDIYS5RD2ttsQ==", + "version": "23.9.2", + "resolved": "https://registry.npmjs.org/netlify-cli/-/netlify-cli-23.9.2.tgz", + "integrity": "sha512-VxgQVV+1rFN967+4/6XqwhYkA5LCQjFG0bIfpchdZcVHjyusClJuXvOyguLNda/5JUuyCLIvhgc7axc+bD+Yrg==", "dev": true, "hasInstallScript": true, "hasShrinkwrap": true, "license": "MIT", "dependencies": { "@fastify/static": "7.0.4", - "@netlify/ai": "0.2.1", - "@netlify/api": "14.0.6", - "@netlify/blobs": "10.0.11", - "@netlify/build": "35.1.8", - "@netlify/build-info": "10.0.8", - "@netlify/config": "24.0.4", + "@netlify/ai": "0.3.0", + "@netlify/api": "14.0.7", + "@netlify/blobs": "10.1.0", + "@netlify/build": "35.2.1", + "@netlify/build-info": "10.0.9", + "@netlify/config": "24.0.6", "@netlify/dev-utils": "4.2.0", "@netlify/edge-bundler": "14.5.6", - "@netlify/edge-functions": "2.18.1", + "@netlify/edge-functions": "2.19.0", "@netlify/edge-functions-bootstrap": "2.17.1", "@netlify/headers-parser": "9.0.2", "@netlify/local-functions-proxy": "2.0.3", "@netlify/redirect-parser": "15.0.3", - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "@octokit/rest": "22.0.0", "@opentelemetry/api": "1.8.0", "@pnpm/tabtab": "0.5.4", @@ -6218,9 +6218,9 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/ai": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@netlify/ai/-/ai-0.2.1.tgz", - "integrity": "sha512-pc30UjYtmoP9XyY6b+xyD/Xh3RYtuc3VcboKU0Ojdv3fX27NUEy3ZLYlmhHB+8E1zVHhyHsoBHqTt/He/YuhXw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@netlify/ai/-/ai-0.3.0.tgz", + "integrity": "sha512-nMsJS6VXDRrwdqkKdmq4fAn4idyl+sDGwXPB+fjdeX/cX1etWynkKAWK5DifxshjgWlfCAp5GD7ZtVR5bpZQJA==", "dev": true, "dependencies": { "@netlify/api": "^14.0.4" @@ -6233,13 +6233,13 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/api": { - "version": "14.0.6", - "resolved": "https://registry.npmjs.org/@netlify/api/-/api-14.0.6.tgz", - "integrity": "sha512-tlG/gqA80WeAbJFYzcLdSP7v8jg1WgtJX+kQD20rMbU+Efga5XxwaiCHgjvpLvFi5hQMe1t2bG60CudxMN1T5g==", + "version": "14.0.7", + "resolved": "https://registry.npmjs.org/@netlify/api/-/api-14.0.7.tgz", + "integrity": "sha512-smSD3MnyUwi+rdcvRlD2EAGEpzK9RRMiGxaXzKW7FGqIlZSEe08aPySuC0d5BXwl/7EmT43hOkBHH4KtP8DxcQ==", "dev": true, "license": "MIT", "dependencies": { - "@netlify/open-api": "^2.39.0", + "@netlify/open-api": "^2.40.0", "node-fetch": "^3.0.0", "p-wait-for": "^5.0.0", "picoquery": "^2.5.0" @@ -6255,36 +6255,74 @@ "dev": true }, "node_modules/netlify-cli/node_modules/@netlify/blobs": { - "version": "10.0.11", - "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.0.11.tgz", - "integrity": "sha512-/pa7eD2gxkhJ6aUIJULrRu3tvAaimy+sA6vHUuGRMvncjOuRpeatXLHxuzdn8DyK1CZCjN3E33oXsdEpoqG7SA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.1.0.tgz", + "integrity": "sha512-dFpqDc6/x5LEu9L7kblCQu00CFEchH8J42jmQoXPuhKoE7avajzeLTbVKA8Olk3S/c2m9ejegrgbhL8NRA2Jyw==", "dev": true, + "license": "MIT", "dependencies": { - "@netlify/dev-utils": "4.2.0", - "@netlify/runtime-utils": "2.1.0" + "@netlify/dev-utils": "4.3.0", + "@netlify/runtime-utils": "2.2.0" }, "engines": { "node": "^14.16.0 || >=16.0.0" } }, + "node_modules/netlify-cli/node_modules/@netlify/blobs/node_modules/@netlify/dev-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.3.0.tgz", + "integrity": "sha512-vZAL8pMuj3yPQlmHSgyaA/UQFxc6pZgU0LucFJ1+IPWGJtIzBXHRvuR4acpoP72HtyQPUHJ42s7U9GaaSGVNHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@whatwg-node/server": "^0.10.0", + "ansis": "^4.1.0", + "chokidar": "^4.0.1", + "decache": "^4.6.2", + "dettle": "^1.0.5", + "dot-prop": "9.0.0", + "empathic": "^2.0.0", + "env-paths": "^3.0.0", + "image-size": "^2.0.2", + "js-image-generator": "^1.0.4", + "parse-gitignore": "^2.0.0", + "semver": "^7.7.2", + "tmp-promise": "^3.0.3", + "uuid": "^11.1.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || >=20" + } + }, + "node_modules/netlify-cli/node_modules/@netlify/blobs/node_modules/@netlify/runtime-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.2.0.tgz", + "integrity": "sha512-K3kWIxIMucibzQsATU2xw2JI+OpS9PZfPW/a+81gmeLC8tLv5YAxTVT0NFY/3imk1kcOJb9g7658jPLqDJaiAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || >=20" + } + }, "node_modules/netlify-cli/node_modules/@netlify/build": { - "version": "35.1.8", - "resolved": "https://registry.npmjs.org/@netlify/build/-/build-35.1.8.tgz", - "integrity": "sha512-Kbi5vRAwaiosJNtd6BvCyqkza0e40ATSrBiTgDMPqTiX+1cNutJMP05R/rqSYr8LYW5vYVgBl5soeIaH1Yx4pg==", + "version": "35.2.1", + "resolved": "https://registry.npmjs.org/@netlify/build/-/build-35.2.1.tgz", + "integrity": "sha512-4KXEzAN5Qpls2mpvofTnnZYFEJYOXgQ8VniDerctJNPmmXA2J4scdsU53Lu+uGHHI0yqH+2FpKl7X7tmczgkAA==", "dev": true, "license": "MIT", "dependencies": { "@bugsnag/js": "^8.0.0", - "@netlify/blobs": "^10.0.11", + "@netlify/blobs": "^10.1.0", "@netlify/cache-utils": "^6.0.4", - "@netlify/config": "^24.0.4", + "@netlify/config": "^24.0.6", "@netlify/edge-bundler": "14.5.6", - "@netlify/functions-utils": "^6.2.8", + "@netlify/functions-utils": "^6.2.11", "@netlify/git-utils": "^6.0.2", "@netlify/opentelemetry-utils": "^2.0.1", "@netlify/plugins-list": "^6.80.0", "@netlify/run-utils": "^6.0.2", - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "@sindresorhus/slugify": "^2.0.0", "ansi-escapes": "^7.0.0", "ansis": "^4.1.0", @@ -6293,7 +6331,7 @@ "fdir": "^6.0.1", "figures": "^6.0.0", "filter-obj": "^6.0.0", - "hot-shots": "11.1.0", + "hot-shots": "11.2.0", "indent-string": "^5.0.0", "is-plain-obj": "^4.0.0", "keep-func-props": "^6.0.0", @@ -6343,10 +6381,11 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/build-info": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/@netlify/build-info/-/build-info-10.0.8.tgz", - "integrity": "sha512-IotJn/+dizJpWIOJcSHiSFpIPpB0b2+s11Y0OekY3XFr58Wt3UGjbCNdO0cG4i3gsQEjzM2+lDQYgJ85TqPmSw==", + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@netlify/build-info/-/build-info-10.0.9.tgz", + "integrity": "sha512-lkcEejs4D0gwDIVtyRpIXXIv4SPZOii9cstGI5eOsMwoMTlZRL/jniZOSeMk2ZS147l9ncD6vtKxaZPnW1MJew==", "dev": true, + "license": "MIT", "dependencies": { "@bugsnag/js": "^8.0.0", "@iarna/toml": "^2.2.5", @@ -6519,13 +6558,14 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/config": { - "version": "24.0.4", - "resolved": "https://registry.npmjs.org/@netlify/config/-/config-24.0.4.tgz", - "integrity": "sha512-u5RyiCN5Fu165qMBpaQEP7fvnjWzcWwnZ6e+h9obQmNtTF5XPMiaxTITT9Qotsqw1Tz9I486I+nbqwDSE/Dp7g==", + "version": "24.0.6", + "resolved": "https://registry.npmjs.org/@netlify/config/-/config-24.0.6.tgz", + "integrity": "sha512-ARlsTjoxzjeQQrXqQvTXaGZIHnxZJ99YZId4j3nN4v0gEDtK5Dehsx/Q71+UCYig3uZDjPFP0kyFK52DA++7Aw==", "dev": true, + "license": "MIT", "dependencies": { "@iarna/toml": "^2.2.5", - "@netlify/api": "^14.0.5", + "@netlify/api": "^14.0.7", "@netlify/headers-parser": "^9.0.2", "@netlify/redirect-parser": "^15.0.3", "chalk": "^5.0.0", @@ -6562,6 +6602,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -6585,6 +6626,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -6597,6 +6639,7 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } @@ -6606,6 +6649,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -6618,6 +6662,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -6633,6 +6678,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -6648,6 +6694,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -6660,6 +6707,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -6668,10 +6716,11 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/config/node_modules/zod": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz", - "integrity": "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -6866,16 +6915,17 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/edge-functions": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/@netlify/edge-functions/-/edge-functions-2.18.1.tgz", - "integrity": "sha512-Cd/ddhbIyLPkEZ9yMnRIXzKH8UcnUlPAAa1iQva9bypKNjXyFcunt5eNMjfNxMsRMDao/PkDbp1OMGkTRQnwTg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/@netlify/edge-functions/-/edge-functions-2.19.0.tgz", + "integrity": "sha512-OsTi1Ch59MRmr0/8QUqPADbtpcoGapBU7NLScfax1tKi43tTIleZRynIKlY4fx2X7orJc4tzU+zErf1JXOQZ8A==", "dev": true, + "license": "MIT", "dependencies": { - "@netlify/dev-utils": "4.2.0", + "@netlify/dev-utils": "4.3.0", "@netlify/edge-bundler": "^14.5.2", "@netlify/edge-functions-bootstrap": "2.16.0", - "@netlify/runtime-utils": "2.1.0", - "@netlify/types": "2.0.3", + "@netlify/runtime-utils": "2.2.0", + "@netlify/types": "2.1.0", "get-port": "^7.1.0" }, "engines": { @@ -6889,17 +6939,56 @@ "dev": true, "license": "MIT" }, + "node_modules/netlify-cli/node_modules/@netlify/edge-functions/node_modules/@netlify/dev-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.3.0.tgz", + "integrity": "sha512-vZAL8pMuj3yPQlmHSgyaA/UQFxc6pZgU0LucFJ1+IPWGJtIzBXHRvuR4acpoP72HtyQPUHJ42s7U9GaaSGVNHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@whatwg-node/server": "^0.10.0", + "ansis": "^4.1.0", + "chokidar": "^4.0.1", + "decache": "^4.6.2", + "dettle": "^1.0.5", + "dot-prop": "9.0.0", + "empathic": "^2.0.0", + "env-paths": "^3.0.0", + "image-size": "^2.0.2", + "js-image-generator": "^1.0.4", + "parse-gitignore": "^2.0.0", + "semver": "^7.7.2", + "tmp-promise": "^3.0.3", + "uuid": "^11.1.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || >=20" + } + }, "node_modules/netlify-cli/node_modules/@netlify/edge-functions/node_modules/@netlify/edge-functions-bootstrap": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/@netlify/edge-functions-bootstrap/-/edge-functions-bootstrap-2.16.0.tgz", "integrity": "sha512-v8QQihSbBHj3JxtJsHoepXALpNumD9M7egHoc8z62FYl5it34dWczkaJoFFopEyhiBVKi4K/n0ZYpdzwfujd6g==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/netlify-cli/node_modules/@netlify/edge-functions/node_modules/@netlify/runtime-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.2.0.tgz", + "integrity": "sha512-K3kWIxIMucibzQsATU2xw2JI+OpS9PZfPW/a+81gmeLC8tLv5YAxTVT0NFY/3imk1kcOJb9g7658jPLqDJaiAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || >=20" + } }, "node_modules/netlify-cli/node_modules/@netlify/edge-functions/node_modules/get-port": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -6908,12 +6997,13 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/functions-utils": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@netlify/functions-utils/-/functions-utils-6.2.8.tgz", - "integrity": "sha512-RkvLcfa8Q4Ff19Qgzhfb0ORDL3PZXI5WJfMwEjjjSOW3HKPRrd+JTOEO+fgkScuzkMhG/DzvvTUs/JRpjWZmXw==", + "version": "6.2.11", + "resolved": "https://registry.npmjs.org/@netlify/functions-utils/-/functions-utils-6.2.11.tgz", + "integrity": "sha512-gCCjXtCtBShvZvCZwO2IxWYVjHUssnrSDea/JRoVBFc4DP3qbNoa1hdwsZ8fydguMOQaf5zFIqnDF4DKXaMA6Q==", "dev": true, + "license": "MIT", "dependencies": { - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "cpy": "^11.0.0", "path-exists": "^5.0.0" }, @@ -7280,9 +7370,9 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/open-api": { - "version": "2.39.0", - "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.39.0.tgz", - "integrity": "sha512-PMBktDmSRBS5act/GxHL3kvbRww5HPFZ9HIHXOrBu6vQesWYapoJaDiU/KDbqmkW1TyelGmURVcwsYr00qSAFg==", + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.40.0.tgz", + "integrity": "sha512-Dp4lilDnkRKGWnljGkFVxfoh1wsWqxheE5/ZOf/sMZPsh3jGu5QZ4hVLEidzXYB/zIKFFqLaUbP2XYVxTqWqyQ==", "dev": true, "license": "MIT", "engines": { @@ -7447,34 +7537,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/netlify-cli/node_modules/@netlify/runtime-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.1.0.tgz", - "integrity": "sha512-z1h+wjB7IVYUsFZsuIYyNxiw5WWuylseY+eXaUDHBxNeLTlqziy+lz03QkR67CUR4Y790xGIhaHV00aOR2KAtw==", - "dev": true, - "engines": { - "node": "^18.14.0 || >=20" - } - }, "node_modules/netlify-cli/node_modules/@netlify/types": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@netlify/types/-/types-2.0.3.tgz", - "integrity": "sha512-OcV8ivKTdsyANqVSQzbusOA7FVtE9s6zwxNCGR/aNnQaVxMUgm93UzKgfR7cZ1nnQNZHAbjd0dKJKaAUqrzbMw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@netlify/types/-/types-2.1.0.tgz", + "integrity": "sha512-ktUb5d58pt1lQGXO5E9S0F1ljM0g+CoQuGTVII0IxBc0apmPq5RI0o3OWLY7U3ZERRiYTg5UfjiMihBEzuZsuw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.14.0 || >=20" } }, "node_modules/netlify-cli/node_modules/@netlify/zip-it-and-ship-it": { - "version": "14.1.8", - "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-14.1.8.tgz", - "integrity": "sha512-APPNgGUAb1kSe4e9KxhRAeQIPGx8EAfwZ3S61eGyZXXGXgjnKmC2Ho7jsFnLsElbt8Ailyzmi/wAjh0NHZjGjA==", + "version": "14.1.11", + "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-14.1.11.tgz", + "integrity": "sha512-5Ed9XH1JVPL7pAdq9zpC2WHjqHhHkaghuV3r2bvTTpx9JrTdzZxPeNnjZRjJMkjQAi8xSped5hNFJuD0QYmOuw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.22.5", "@babel/types": "7.28.4", "@netlify/binary-info": "^1.0.0", - "@netlify/serverless-functions-api": "^2.5.0", + "@netlify/serverless-functions-api": "^2.7.1", "@vercel/nft": "0.29.4", "archiver": "^7.0.0", "common-path-prefix": "^3.0.0", @@ -7512,10 +7595,11 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/zip-it-and-ship-it/node_modules/@netlify/serverless-functions-api": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.5.0.tgz", - "integrity": "sha512-0Hl6POpkEs3aan8T+EQvPIj5/gNc+64nwNv93VY4JoxFSrLPKYWmUyXJhT9lG93VxwGfmbxrCOV8U4sq2eWgTw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.7.1.tgz", + "integrity": "sha512-NQcLB8BHbIsgSBPk9A/OBR5mGpc6dOAg1iRsYHWK0IoKsvwQ9a7bZc2+E40nE41Mnk24UjfK09vDLxP85O/zwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18.0.0" } @@ -7525,6 +7609,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -7548,6 +7633,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -7560,6 +7646,7 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } @@ -7569,6 +7656,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -7581,6 +7669,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -7596,6 +7685,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -7611,6 +7701,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -7623,6 +7714,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -8264,6 +8356,292 @@ } } }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.2.tgz", + "integrity": "sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.2.tgz", + "integrity": "sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.2.tgz", + "integrity": "sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.2.tgz", + "integrity": "sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.2.tgz", + "integrity": "sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.2.tgz", + "integrity": "sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.2.tgz", + "integrity": "sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.2.tgz", + "integrity": "sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.2.tgz", + "integrity": "sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.2.tgz", + "integrity": "sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.2.tgz", + "integrity": "sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.2.tgz", + "integrity": "sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.2.tgz", + "integrity": "sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.2.tgz", + "integrity": "sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.2.tgz", + "integrity": "sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.2.tgz", + "integrity": "sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.2.tgz", + "integrity": "sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.2.tgz", + "integrity": "sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.2.tgz", + "integrity": "sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.2.tgz", + "integrity": "sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.2.tgz", + "integrity": "sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/netlify-cli/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.2.tgz", + "integrity": "sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/netlify-cli/node_modules/@sec-ant/readable-stream": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", @@ -8351,18 +8729,59 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/netlify-cli/node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "optional": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/netlify-cli/node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/netlify-cli/node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true }, + "node_modules/netlify-cli/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/netlify-cli/node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "dev": true }, + "node_modules/netlify-cli/node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "optional": true + }, "node_modules/netlify-cli/node_modules/@types/http-proxy": { "version": "1.17.16", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", @@ -8372,10 +8791,17 @@ "@types/node": "*" } }, + "node_modules/netlify-cli/node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "optional": true + }, "node_modules/netlify-cli/node_modules/@types/node": { - "version": "22.18.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.7.tgz", - "integrity": "sha512-3E97nlWEVp2V6J7aMkR8eOnw/w0pArPwf/5/W0865f+xzBoGL/ZuHkTAKAGN7cOWNwd+sG+hZOqj+fjzeHS75g==", + "version": "22.18.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.11.tgz", + "integrity": "sha512-Gd33J2XIrXurb+eT2ktze3rJAfAp9ZNjlBdh4SVgyrKEOADwCbdUDaK7QgJno8Ue4kcajscsKqu6n8OBG3hhCQ==", "dev": true, "license": "MIT", "peer": true, @@ -8389,12 +8815,49 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, + "node_modules/netlify-cli/node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "optional": true + }, + "node_modules/netlify-cli/node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "optional": true + }, "node_modules/netlify-cli/node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "dev": true }, + "node_modules/netlify-cli/node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "optional": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/netlify-cli/node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "optional": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, "node_modules/netlify-cli/node_modules/@types/triple-beam": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", @@ -12105,6 +12568,20 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/netlify-cli/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/netlify-cli/node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -12484,12 +12961,13 @@ "dev": true }, "node_modules/netlify-cli/node_modules/hot-shots": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-11.1.0.tgz", - "integrity": "sha512-D4iAs/145g7EJ/wIzBLVANEpysTPthUy/K+4EUIw02YJQTqvzD1vUpYiM3vwR0qPAQj4FhQpQz8wBpY8KDcM0g==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-11.2.0.tgz", + "integrity": "sha512-cGiFSgTZtVODx0yMW67gPICgref3XuxkTMrXP0h5cSd1HHG3OG7L2C6+aW70MAtlUNl+9+DOq/xXyJUVKDyeUg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=16.0.0" }, "optionalDependencies": { "unix-dgram": "2.x" @@ -15374,10 +15852,11 @@ "dev": true }, "node_modules/netlify-cli/node_modules/pino": { - "version": "9.11.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.11.0.tgz", - "integrity": "sha512-+YIodBB9sxcWeR8PrXC2K3gEDyfkUuVEITOcbqrfcj+z5QW4ioIcqZfYFbrLTYLsmAwunbS7nfU/dpBB6PZc1g==", + "version": "9.9.5", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.9.5.tgz", + "integrity": "sha512-d1s98p8/4TfYhsJ09r/Azt30aYELRi6NNnZtEbqFw6BoGsdPVf5lKNK3kUwH8BmJJfpTLNuicjUQjaMbd93dVg==", "dev": true, + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", diff --git a/e2e-report/package.json b/e2e-report/package.json index 18514ca8fd..5d47c83b6e 100644 --- a/e2e-report/package.json +++ b/e2e-report/package.json @@ -19,7 +19,7 @@ "daisyui": "^4.12.2", "eslint": "^9.34.0", "eslint-config-next": "^15.5.0", - "netlify-cli": "^23.9.1", + "netlify-cli": "^23.9.2", "postcss": "^8.4.38", "sass": "^1.77.1", "tailwindcss": "^3.4.4" diff --git a/package-lock.json b/package-lock.json index 0aaed5a515..9ca21faee7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,7 @@ "memfs": "^4.9.2", "mock-require": "^3.0.3", "msw": "^2.0.7", - "netlify-cli": "23.9.1", + "netlify-cli": "23.9.2", "next": "^15.0.0-canary.28", "next-with-cache-handler-v2": "npm:next@15.3.0-canary.13", "os": "^0.1.2", @@ -13562,28 +13562,28 @@ "dev": true }, "node_modules/netlify-cli": { - "version": "23.9.1", - "resolved": "https://registry.npmjs.org/netlify-cli/-/netlify-cli-23.9.1.tgz", - "integrity": "sha512-Wg67zCFbg/bgWw0ub3vrG+7TSXDP9gNeGsAU7JvFR7Wy+KP47ELTNeP5uZKAwf9h0HIw0sUCvyDIYS5RD2ttsQ==", + "version": "23.9.2", + "resolved": "https://registry.npmjs.org/netlify-cli/-/netlify-cli-23.9.2.tgz", + "integrity": "sha512-VxgQVV+1rFN967+4/6XqwhYkA5LCQjFG0bIfpchdZcVHjyusClJuXvOyguLNda/5JUuyCLIvhgc7axc+bD+Yrg==", "dev": true, "hasInstallScript": true, "hasShrinkwrap": true, "dependencies": { "@fastify/static": "7.0.4", - "@netlify/ai": "0.2.1", - "@netlify/api": "14.0.6", - "@netlify/blobs": "10.0.11", - "@netlify/build": "35.1.8", - "@netlify/build-info": "10.0.8", - "@netlify/config": "24.0.4", + "@netlify/ai": "0.3.0", + "@netlify/api": "14.0.7", + "@netlify/blobs": "10.1.0", + "@netlify/build": "35.2.1", + "@netlify/build-info": "10.0.9", + "@netlify/config": "24.0.6", "@netlify/dev-utils": "4.2.0", "@netlify/edge-bundler": "14.5.6", - "@netlify/edge-functions": "2.18.1", + "@netlify/edge-functions": "2.19.0", "@netlify/edge-functions-bootstrap": "2.17.1", "@netlify/headers-parser": "9.0.2", "@netlify/local-functions-proxy": "2.0.3", "@netlify/redirect-parser": "15.0.3", - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "@octokit/rest": "22.0.0", "@opentelemetry/api": "1.8.0", "@pnpm/tabtab": "0.5.4", @@ -14990,9 +14990,9 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/ai": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@netlify/ai/-/ai-0.2.1.tgz", - "integrity": "sha512-pc30UjYtmoP9XyY6b+xyD/Xh3RYtuc3VcboKU0Ojdv3fX27NUEy3ZLYlmhHB+8E1zVHhyHsoBHqTt/He/YuhXw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@netlify/ai/-/ai-0.3.0.tgz", + "integrity": "sha512-nMsJS6VXDRrwdqkKdmq4fAn4idyl+sDGwXPB+fjdeX/cX1etWynkKAWK5DifxshjgWlfCAp5GD7ZtVR5bpZQJA==", "dev": true, "dependencies": { "@netlify/api": "^14.0.4" @@ -15005,13 +15005,13 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/api": { - "version": "14.0.6", - "resolved": "https://registry.npmjs.org/@netlify/api/-/api-14.0.6.tgz", - "integrity": "sha512-tlG/gqA80WeAbJFYzcLdSP7v8jg1WgtJX+kQD20rMbU+Efga5XxwaiCHgjvpLvFi5hQMe1t2bG60CudxMN1T5g==", + "version": "14.0.7", + "resolved": "https://registry.npmjs.org/@netlify/api/-/api-14.0.7.tgz", + "integrity": "sha512-smSD3MnyUwi+rdcvRlD2EAGEpzK9RRMiGxaXzKW7FGqIlZSEe08aPySuC0d5BXwl/7EmT43hOkBHH4KtP8DxcQ==", "dev": true, "license": "MIT", "dependencies": { - "@netlify/open-api": "^2.39.0", + "@netlify/open-api": "^2.40.0", "node-fetch": "^3.0.0", "p-wait-for": "^5.0.0", "picoquery": "^2.5.0" @@ -15027,36 +15027,74 @@ "dev": true }, "node_modules/netlify-cli/node_modules/@netlify/blobs": { - "version": "10.0.11", - "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.0.11.tgz", - "integrity": "sha512-/pa7eD2gxkhJ6aUIJULrRu3tvAaimy+sA6vHUuGRMvncjOuRpeatXLHxuzdn8DyK1CZCjN3E33oXsdEpoqG7SA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.1.0.tgz", + "integrity": "sha512-dFpqDc6/x5LEu9L7kblCQu00CFEchH8J42jmQoXPuhKoE7avajzeLTbVKA8Olk3S/c2m9ejegrgbhL8NRA2Jyw==", "dev": true, + "license": "MIT", "dependencies": { - "@netlify/dev-utils": "4.2.0", - "@netlify/runtime-utils": "2.1.0" + "@netlify/dev-utils": "4.3.0", + "@netlify/runtime-utils": "2.2.0" }, "engines": { "node": "^14.16.0 || >=16.0.0" } }, + "node_modules/netlify-cli/node_modules/@netlify/blobs/node_modules/@netlify/dev-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.3.0.tgz", + "integrity": "sha512-vZAL8pMuj3yPQlmHSgyaA/UQFxc6pZgU0LucFJ1+IPWGJtIzBXHRvuR4acpoP72HtyQPUHJ42s7U9GaaSGVNHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@whatwg-node/server": "^0.10.0", + "ansis": "^4.1.0", + "chokidar": "^4.0.1", + "decache": "^4.6.2", + "dettle": "^1.0.5", + "dot-prop": "9.0.0", + "empathic": "^2.0.0", + "env-paths": "^3.0.0", + "image-size": "^2.0.2", + "js-image-generator": "^1.0.4", + "parse-gitignore": "^2.0.0", + "semver": "^7.7.2", + "tmp-promise": "^3.0.3", + "uuid": "^11.1.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || >=20" + } + }, + "node_modules/netlify-cli/node_modules/@netlify/blobs/node_modules/@netlify/runtime-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.2.0.tgz", + "integrity": "sha512-K3kWIxIMucibzQsATU2xw2JI+OpS9PZfPW/a+81gmeLC8tLv5YAxTVT0NFY/3imk1kcOJb9g7658jPLqDJaiAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || >=20" + } + }, "node_modules/netlify-cli/node_modules/@netlify/build": { - "version": "35.1.8", - "resolved": "https://registry.npmjs.org/@netlify/build/-/build-35.1.8.tgz", - "integrity": "sha512-Kbi5vRAwaiosJNtd6BvCyqkza0e40ATSrBiTgDMPqTiX+1cNutJMP05R/rqSYr8LYW5vYVgBl5soeIaH1Yx4pg==", + "version": "35.2.1", + "resolved": "https://registry.npmjs.org/@netlify/build/-/build-35.2.1.tgz", + "integrity": "sha512-4KXEzAN5Qpls2mpvofTnnZYFEJYOXgQ8VniDerctJNPmmXA2J4scdsU53Lu+uGHHI0yqH+2FpKl7X7tmczgkAA==", "dev": true, "license": "MIT", "dependencies": { "@bugsnag/js": "^8.0.0", - "@netlify/blobs": "^10.0.11", + "@netlify/blobs": "^10.1.0", "@netlify/cache-utils": "^6.0.4", - "@netlify/config": "^24.0.4", + "@netlify/config": "^24.0.6", "@netlify/edge-bundler": "14.5.6", - "@netlify/functions-utils": "^6.2.8", + "@netlify/functions-utils": "^6.2.11", "@netlify/git-utils": "^6.0.2", "@netlify/opentelemetry-utils": "^2.0.1", "@netlify/plugins-list": "^6.80.0", "@netlify/run-utils": "^6.0.2", - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "@sindresorhus/slugify": "^2.0.0", "ansi-escapes": "^7.0.0", "ansis": "^4.1.0", @@ -15065,7 +15103,7 @@ "fdir": "^6.0.1", "figures": "^6.0.0", "filter-obj": "^6.0.0", - "hot-shots": "11.1.0", + "hot-shots": "11.2.0", "indent-string": "^5.0.0", "is-plain-obj": "^4.0.0", "keep-func-props": "^6.0.0", @@ -15115,10 +15153,11 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/build-info": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/@netlify/build-info/-/build-info-10.0.8.tgz", - "integrity": "sha512-IotJn/+dizJpWIOJcSHiSFpIPpB0b2+s11Y0OekY3XFr58Wt3UGjbCNdO0cG4i3gsQEjzM2+lDQYgJ85TqPmSw==", + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@netlify/build-info/-/build-info-10.0.9.tgz", + "integrity": "sha512-lkcEejs4D0gwDIVtyRpIXXIv4SPZOii9cstGI5eOsMwoMTlZRL/jniZOSeMk2ZS147l9ncD6vtKxaZPnW1MJew==", "dev": true, + "license": "MIT", "dependencies": { "@bugsnag/js": "^8.0.0", "@iarna/toml": "^2.2.5", @@ -15291,13 +15330,14 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/config": { - "version": "24.0.4", - "resolved": "https://registry.npmjs.org/@netlify/config/-/config-24.0.4.tgz", - "integrity": "sha512-u5RyiCN5Fu165qMBpaQEP7fvnjWzcWwnZ6e+h9obQmNtTF5XPMiaxTITT9Qotsqw1Tz9I486I+nbqwDSE/Dp7g==", + "version": "24.0.6", + "resolved": "https://registry.npmjs.org/@netlify/config/-/config-24.0.6.tgz", + "integrity": "sha512-ARlsTjoxzjeQQrXqQvTXaGZIHnxZJ99YZId4j3nN4v0gEDtK5Dehsx/Q71+UCYig3uZDjPFP0kyFK52DA++7Aw==", "dev": true, + "license": "MIT", "dependencies": { "@iarna/toml": "^2.2.5", - "@netlify/api": "^14.0.5", + "@netlify/api": "^14.0.7", "@netlify/headers-parser": "^9.0.2", "@netlify/redirect-parser": "^15.0.3", "chalk": "^5.0.0", @@ -15334,6 +15374,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -15357,6 +15398,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -15369,6 +15411,7 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } @@ -15378,6 +15421,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -15390,6 +15434,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -15405,6 +15450,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -15420,6 +15466,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -15432,6 +15479,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -15440,10 +15488,11 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/config/node_modules/zod": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz", - "integrity": "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -15638,16 +15687,17 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/edge-functions": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/@netlify/edge-functions/-/edge-functions-2.18.1.tgz", - "integrity": "sha512-Cd/ddhbIyLPkEZ9yMnRIXzKH8UcnUlPAAa1iQva9bypKNjXyFcunt5eNMjfNxMsRMDao/PkDbp1OMGkTRQnwTg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/@netlify/edge-functions/-/edge-functions-2.19.0.tgz", + "integrity": "sha512-OsTi1Ch59MRmr0/8QUqPADbtpcoGapBU7NLScfax1tKi43tTIleZRynIKlY4fx2X7orJc4tzU+zErf1JXOQZ8A==", "dev": true, + "license": "MIT", "dependencies": { - "@netlify/dev-utils": "4.2.0", + "@netlify/dev-utils": "4.3.0", "@netlify/edge-bundler": "^14.5.2", "@netlify/edge-functions-bootstrap": "2.16.0", - "@netlify/runtime-utils": "2.1.0", - "@netlify/types": "2.0.3", + "@netlify/runtime-utils": "2.2.0", + "@netlify/types": "2.1.0", "get-port": "^7.1.0" }, "engines": { @@ -15661,17 +15711,56 @@ "dev": true, "license": "MIT" }, + "node_modules/netlify-cli/node_modules/@netlify/edge-functions/node_modules/@netlify/dev-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.3.0.tgz", + "integrity": "sha512-vZAL8pMuj3yPQlmHSgyaA/UQFxc6pZgU0LucFJ1+IPWGJtIzBXHRvuR4acpoP72HtyQPUHJ42s7U9GaaSGVNHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@whatwg-node/server": "^0.10.0", + "ansis": "^4.1.0", + "chokidar": "^4.0.1", + "decache": "^4.6.2", + "dettle": "^1.0.5", + "dot-prop": "9.0.0", + "empathic": "^2.0.0", + "env-paths": "^3.0.0", + "image-size": "^2.0.2", + "js-image-generator": "^1.0.4", + "parse-gitignore": "^2.0.0", + "semver": "^7.7.2", + "tmp-promise": "^3.0.3", + "uuid": "^11.1.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || >=20" + } + }, "node_modules/netlify-cli/node_modules/@netlify/edge-functions/node_modules/@netlify/edge-functions-bootstrap": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/@netlify/edge-functions-bootstrap/-/edge-functions-bootstrap-2.16.0.tgz", "integrity": "sha512-v8QQihSbBHj3JxtJsHoepXALpNumD9M7egHoc8z62FYl5it34dWczkaJoFFopEyhiBVKi4K/n0ZYpdzwfujd6g==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/netlify-cli/node_modules/@netlify/edge-functions/node_modules/@netlify/runtime-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.2.0.tgz", + "integrity": "sha512-K3kWIxIMucibzQsATU2xw2JI+OpS9PZfPW/a+81gmeLC8tLv5YAxTVT0NFY/3imk1kcOJb9g7658jPLqDJaiAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || >=20" + } }, "node_modules/netlify-cli/node_modules/@netlify/edge-functions/node_modules/get-port": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -15680,12 +15769,13 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/functions-utils": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@netlify/functions-utils/-/functions-utils-6.2.8.tgz", - "integrity": "sha512-RkvLcfa8Q4Ff19Qgzhfb0ORDL3PZXI5WJfMwEjjjSOW3HKPRrd+JTOEO+fgkScuzkMhG/DzvvTUs/JRpjWZmXw==", + "version": "6.2.11", + "resolved": "https://registry.npmjs.org/@netlify/functions-utils/-/functions-utils-6.2.11.tgz", + "integrity": "sha512-gCCjXtCtBShvZvCZwO2IxWYVjHUssnrSDea/JRoVBFc4DP3qbNoa1hdwsZ8fydguMOQaf5zFIqnDF4DKXaMA6Q==", "dev": true, + "license": "MIT", "dependencies": { - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "cpy": "^11.0.0", "path-exists": "^5.0.0" }, @@ -16052,9 +16142,9 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/open-api": { - "version": "2.39.0", - "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.39.0.tgz", - "integrity": "sha512-PMBktDmSRBS5act/GxHL3kvbRww5HPFZ9HIHXOrBu6vQesWYapoJaDiU/KDbqmkW1TyelGmURVcwsYr00qSAFg==", + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.40.0.tgz", + "integrity": "sha512-Dp4lilDnkRKGWnljGkFVxfoh1wsWqxheE5/ZOf/sMZPsh3jGu5QZ4hVLEidzXYB/zIKFFqLaUbP2XYVxTqWqyQ==", "dev": true, "license": "MIT", "engines": { @@ -16219,34 +16309,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/netlify-cli/node_modules/@netlify/runtime-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.1.0.tgz", - "integrity": "sha512-z1h+wjB7IVYUsFZsuIYyNxiw5WWuylseY+eXaUDHBxNeLTlqziy+lz03QkR67CUR4Y790xGIhaHV00aOR2KAtw==", - "dev": true, - "engines": { - "node": "^18.14.0 || >=20" - } - }, "node_modules/netlify-cli/node_modules/@netlify/types": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@netlify/types/-/types-2.0.3.tgz", - "integrity": "sha512-OcV8ivKTdsyANqVSQzbusOA7FVtE9s6zwxNCGR/aNnQaVxMUgm93UzKgfR7cZ1nnQNZHAbjd0dKJKaAUqrzbMw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@netlify/types/-/types-2.1.0.tgz", + "integrity": "sha512-ktUb5d58pt1lQGXO5E9S0F1ljM0g+CoQuGTVII0IxBc0apmPq5RI0o3OWLY7U3ZERRiYTg5UfjiMihBEzuZsuw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.14.0 || >=20" } }, "node_modules/netlify-cli/node_modules/@netlify/zip-it-and-ship-it": { - "version": "14.1.8", - "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-14.1.8.tgz", - "integrity": "sha512-APPNgGUAb1kSe4e9KxhRAeQIPGx8EAfwZ3S61eGyZXXGXgjnKmC2Ho7jsFnLsElbt8Ailyzmi/wAjh0NHZjGjA==", + "version": "14.1.11", + "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-14.1.11.tgz", + "integrity": "sha512-5Ed9XH1JVPL7pAdq9zpC2WHjqHhHkaghuV3r2bvTTpx9JrTdzZxPeNnjZRjJMkjQAi8xSped5hNFJuD0QYmOuw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.22.5", "@babel/types": "7.28.4", "@netlify/binary-info": "^1.0.0", - "@netlify/serverless-functions-api": "^2.5.0", + "@netlify/serverless-functions-api": "^2.7.1", "@vercel/nft": "0.29.4", "archiver": "^7.0.0", "common-path-prefix": "^3.0.0", @@ -16284,10 +16367,11 @@ } }, "node_modules/netlify-cli/node_modules/@netlify/zip-it-and-ship-it/node_modules/@netlify/serverless-functions-api": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.5.0.tgz", - "integrity": "sha512-0Hl6POpkEs3aan8T+EQvPIj5/gNc+64nwNv93VY4JoxFSrLPKYWmUyXJhT9lG93VxwGfmbxrCOV8U4sq2eWgTw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.7.1.tgz", + "integrity": "sha512-NQcLB8BHbIsgSBPk9A/OBR5mGpc6dOAg1iRsYHWK0IoKsvwQ9a7bZc2+E40nE41Mnk24UjfK09vDLxP85O/zwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18.0.0" } @@ -16297,6 +16381,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -16320,6 +16405,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -16332,6 +16418,7 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } @@ -16341,6 +16428,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -16353,6 +16441,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -16368,6 +16457,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -16383,6 +16473,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -16395,6 +16486,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -17519,9 +17611,9 @@ "peer": true }, "node_modules/netlify-cli/node_modules/@types/node": { - "version": "22.18.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.7.tgz", - "integrity": "sha512-3E97nlWEVp2V6J7aMkR8eOnw/w0pArPwf/5/W0865f+xzBoGL/ZuHkTAKAGN7cOWNwd+sG+hZOqj+fjzeHS75g==", + "version": "22.18.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.11.tgz", + "integrity": "sha512-Gd33J2XIrXurb+eT2ktze3rJAfAp9ZNjlBdh4SVgyrKEOADwCbdUDaK7QgJno8Ue4kcajscsKqu6n8OBG3hhCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -21683,12 +21775,13 @@ "dev": true }, "node_modules/netlify-cli/node_modules/hot-shots": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-11.1.0.tgz", - "integrity": "sha512-D4iAs/145g7EJ/wIzBLVANEpysTPthUy/K+4EUIw02YJQTqvzD1vUpYiM3vwR0qPAQj4FhQpQz8wBpY8KDcM0g==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-11.2.0.tgz", + "integrity": "sha512-cGiFSgTZtVODx0yMW67gPICgref3XuxkTMrXP0h5cSd1HHG3OG7L2C6+aW70MAtlUNl+9+DOq/xXyJUVKDyeUg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=16.0.0" }, "optionalDependencies": { "unix-dgram": "2.x" @@ -24572,10 +24665,11 @@ "dev": true }, "node_modules/netlify-cli/node_modules/pino": { - "version": "9.11.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.11.0.tgz", - "integrity": "sha512-+YIodBB9sxcWeR8PrXC2K3gEDyfkUuVEITOcbqrfcj+z5QW4ioIcqZfYFbrLTYLsmAwunbS7nfU/dpBB6PZc1g==", + "version": "9.9.5", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.9.5.tgz", + "integrity": "sha512-d1s98p8/4TfYhsJ09r/Azt30aYELRi6NNnZtEbqFw6BoGsdPVf5lKNK3kUwH8BmJJfpTLNuicjUQjaMbd93dVg==", "dev": true, + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", @@ -42187,26 +42281,26 @@ "dev": true }, "netlify-cli": { - "version": "23.9.1", - "resolved": "https://registry.npmjs.org/netlify-cli/-/netlify-cli-23.9.1.tgz", - "integrity": "sha512-Wg67zCFbg/bgWw0ub3vrG+7TSXDP9gNeGsAU7JvFR7Wy+KP47ELTNeP5uZKAwf9h0HIw0sUCvyDIYS5RD2ttsQ==", + "version": "23.9.2", + "resolved": "https://registry.npmjs.org/netlify-cli/-/netlify-cli-23.9.2.tgz", + "integrity": "sha512-VxgQVV+1rFN967+4/6XqwhYkA5LCQjFG0bIfpchdZcVHjyusClJuXvOyguLNda/5JUuyCLIvhgc7axc+bD+Yrg==", "dev": true, "requires": { "@fastify/static": "7.0.4", - "@netlify/ai": "0.2.1", - "@netlify/api": "14.0.6", - "@netlify/blobs": "10.0.11", - "@netlify/build": "35.1.8", - "@netlify/build-info": "10.0.8", - "@netlify/config": "24.0.4", + "@netlify/ai": "0.3.0", + "@netlify/api": "14.0.7", + "@netlify/blobs": "10.1.0", + "@netlify/build": "35.2.1", + "@netlify/build-info": "10.0.9", + "@netlify/config": "24.0.6", "@netlify/dev-utils": "4.2.0", "@netlify/edge-bundler": "14.5.6", - "@netlify/edge-functions": "2.18.1", + "@netlify/edge-functions": "2.19.0", "@netlify/edge-functions-bootstrap": "2.17.1", "@netlify/headers-parser": "9.0.2", "@netlify/local-functions-proxy": "2.0.3", "@netlify/redirect-parser": "15.0.3", - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "@octokit/rest": "22.0.0", "@opentelemetry/api": "1.8.0", "@pnpm/tabtab": "0.5.4", @@ -43049,21 +43143,21 @@ } }, "@netlify/ai": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@netlify/ai/-/ai-0.2.1.tgz", - "integrity": "sha512-pc30UjYtmoP9XyY6b+xyD/Xh3RYtuc3VcboKU0Ojdv3fX27NUEy3ZLYlmhHB+8E1zVHhyHsoBHqTt/He/YuhXw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@netlify/ai/-/ai-0.3.0.tgz", + "integrity": "sha512-nMsJS6VXDRrwdqkKdmq4fAn4idyl+sDGwXPB+fjdeX/cX1etWynkKAWK5DifxshjgWlfCAp5GD7ZtVR5bpZQJA==", "dev": true, "requires": { "@netlify/api": "^14.0.4" } }, "@netlify/api": { - "version": "14.0.6", - "resolved": "https://registry.npmjs.org/@netlify/api/-/api-14.0.6.tgz", - "integrity": "sha512-tlG/gqA80WeAbJFYzcLdSP7v8jg1WgtJX+kQD20rMbU+Efga5XxwaiCHgjvpLvFi5hQMe1t2bG60CudxMN1T5g==", + "version": "14.0.7", + "resolved": "https://registry.npmjs.org/@netlify/api/-/api-14.0.7.tgz", + "integrity": "sha512-smSD3MnyUwi+rdcvRlD2EAGEpzK9RRMiGxaXzKW7FGqIlZSEe08aPySuC0d5BXwl/7EmT43hOkBHH4KtP8DxcQ==", "dev": true, "requires": { - "@netlify/open-api": "^2.39.0", + "@netlify/open-api": "^2.40.0", "node-fetch": "^3.0.0", "p-wait-for": "^5.0.0", "picoquery": "^2.5.0" @@ -43076,32 +43170,63 @@ "dev": true }, "@netlify/blobs": { - "version": "10.0.11", - "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.0.11.tgz", - "integrity": "sha512-/pa7eD2gxkhJ6aUIJULrRu3tvAaimy+sA6vHUuGRMvncjOuRpeatXLHxuzdn8DyK1CZCjN3E33oXsdEpoqG7SA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.1.0.tgz", + "integrity": "sha512-dFpqDc6/x5LEu9L7kblCQu00CFEchH8J42jmQoXPuhKoE7avajzeLTbVKA8Olk3S/c2m9ejegrgbhL8NRA2Jyw==", "dev": true, "requires": { - "@netlify/dev-utils": "4.2.0", - "@netlify/runtime-utils": "2.1.0" + "@netlify/dev-utils": "4.3.0", + "@netlify/runtime-utils": "2.2.0" + }, + "dependencies": { + "@netlify/dev-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.3.0.tgz", + "integrity": "sha512-vZAL8pMuj3yPQlmHSgyaA/UQFxc6pZgU0LucFJ1+IPWGJtIzBXHRvuR4acpoP72HtyQPUHJ42s7U9GaaSGVNHg==", + "dev": true, + "requires": { + "@whatwg-node/server": "^0.10.0", + "ansis": "^4.1.0", + "chokidar": "^4.0.1", + "decache": "^4.6.2", + "dettle": "^1.0.5", + "dot-prop": "9.0.0", + "empathic": "^2.0.0", + "env-paths": "^3.0.0", + "image-size": "^2.0.2", + "js-image-generator": "^1.0.4", + "parse-gitignore": "^2.0.0", + "semver": "^7.7.2", + "tmp-promise": "^3.0.3", + "uuid": "^11.1.0", + "write-file-atomic": "^5.0.1" + } + }, + "@netlify/runtime-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.2.0.tgz", + "integrity": "sha512-K3kWIxIMucibzQsATU2xw2JI+OpS9PZfPW/a+81gmeLC8tLv5YAxTVT0NFY/3imk1kcOJb9g7658jPLqDJaiAw==", + "dev": true + } } }, "@netlify/build": { - "version": "35.1.8", - "resolved": "https://registry.npmjs.org/@netlify/build/-/build-35.1.8.tgz", - "integrity": "sha512-Kbi5vRAwaiosJNtd6BvCyqkza0e40ATSrBiTgDMPqTiX+1cNutJMP05R/rqSYr8LYW5vYVgBl5soeIaH1Yx4pg==", + "version": "35.2.1", + "resolved": "https://registry.npmjs.org/@netlify/build/-/build-35.2.1.tgz", + "integrity": "sha512-4KXEzAN5Qpls2mpvofTnnZYFEJYOXgQ8VniDerctJNPmmXA2J4scdsU53Lu+uGHHI0yqH+2FpKl7X7tmczgkAA==", "dev": true, "requires": { "@bugsnag/js": "^8.0.0", - "@netlify/blobs": "^10.0.11", + "@netlify/blobs": "^10.1.0", "@netlify/cache-utils": "^6.0.4", - "@netlify/config": "^24.0.4", + "@netlify/config": "^24.0.6", "@netlify/edge-bundler": "14.5.6", - "@netlify/functions-utils": "^6.2.8", + "@netlify/functions-utils": "^6.2.11", "@netlify/git-utils": "^6.0.2", "@netlify/opentelemetry-utils": "^2.0.1", "@netlify/plugins-list": "^6.80.0", "@netlify/run-utils": "^6.0.2", - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "@sindresorhus/slugify": "^2.0.0", "ansi-escapes": "^7.0.0", "ansis": "^4.1.0", @@ -43110,7 +43235,7 @@ "fdir": "^6.0.1", "figures": "^6.0.0", "filter-obj": "^6.0.0", - "hot-shots": "11.1.0", + "hot-shots": "11.2.0", "indent-string": "^5.0.0", "is-plain-obj": "^4.0.0", "keep-func-props": "^6.0.0", @@ -43222,9 +43347,9 @@ } }, "@netlify/build-info": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/@netlify/build-info/-/build-info-10.0.8.tgz", - "integrity": "sha512-IotJn/+dizJpWIOJcSHiSFpIPpB0b2+s11Y0OekY3XFr58Wt3UGjbCNdO0cG4i3gsQEjzM2+lDQYgJ85TqPmSw==", + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@netlify/build-info/-/build-info-10.0.9.tgz", + "integrity": "sha512-lkcEejs4D0gwDIVtyRpIXXIv4SPZOii9cstGI5eOsMwoMTlZRL/jniZOSeMk2ZS147l9ncD6vtKxaZPnW1MJew==", "dev": true, "requires": { "@bugsnag/js": "^8.0.0", @@ -43254,13 +43379,13 @@ } }, "@netlify/config": { - "version": "24.0.4", - "resolved": "https://registry.npmjs.org/@netlify/config/-/config-24.0.4.tgz", - "integrity": "sha512-u5RyiCN5Fu165qMBpaQEP7fvnjWzcWwnZ6e+h9obQmNtTF5XPMiaxTITT9Qotsqw1Tz9I486I+nbqwDSE/Dp7g==", + "version": "24.0.6", + "resolved": "https://registry.npmjs.org/@netlify/config/-/config-24.0.6.tgz", + "integrity": "sha512-ARlsTjoxzjeQQrXqQvTXaGZIHnxZJ99YZId4j3nN4v0gEDtK5Dehsx/Q71+UCYig3uZDjPFP0kyFK52DA++7Aw==", "dev": true, "requires": { "@iarna/toml": "^2.2.5", - "@netlify/api": "^14.0.5", + "@netlify/api": "^14.0.7", "@netlify/headers-parser": "^9.0.2", "@netlify/redirect-parser": "^15.0.3", "chalk": "^5.0.0", @@ -43352,9 +43477,9 @@ "dev": true }, "zod": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz", - "integrity": "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "dev": true } } @@ -43484,25 +43609,54 @@ } }, "@netlify/edge-functions": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/@netlify/edge-functions/-/edge-functions-2.18.1.tgz", - "integrity": "sha512-Cd/ddhbIyLPkEZ9yMnRIXzKH8UcnUlPAAa1iQva9bypKNjXyFcunt5eNMjfNxMsRMDao/PkDbp1OMGkTRQnwTg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/@netlify/edge-functions/-/edge-functions-2.19.0.tgz", + "integrity": "sha512-OsTi1Ch59MRmr0/8QUqPADbtpcoGapBU7NLScfax1tKi43tTIleZRynIKlY4fx2X7orJc4tzU+zErf1JXOQZ8A==", "dev": true, "requires": { - "@netlify/dev-utils": "4.2.0", + "@netlify/dev-utils": "4.3.0", "@netlify/edge-bundler": "^14.5.2", "@netlify/edge-functions-bootstrap": "2.16.0", - "@netlify/runtime-utils": "2.1.0", - "@netlify/types": "2.0.3", + "@netlify/runtime-utils": "2.2.0", + "@netlify/types": "2.1.0", "get-port": "^7.1.0" }, "dependencies": { + "@netlify/dev-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.3.0.tgz", + "integrity": "sha512-vZAL8pMuj3yPQlmHSgyaA/UQFxc6pZgU0LucFJ1+IPWGJtIzBXHRvuR4acpoP72HtyQPUHJ42s7U9GaaSGVNHg==", + "dev": true, + "requires": { + "@whatwg-node/server": "^0.10.0", + "ansis": "^4.1.0", + "chokidar": "^4.0.1", + "decache": "^4.6.2", + "dettle": "^1.0.5", + "dot-prop": "9.0.0", + "empathic": "^2.0.0", + "env-paths": "^3.0.0", + "image-size": "^2.0.2", + "js-image-generator": "^1.0.4", + "parse-gitignore": "^2.0.0", + "semver": "^7.7.2", + "tmp-promise": "^3.0.3", + "uuid": "^11.1.0", + "write-file-atomic": "^5.0.1" + } + }, "@netlify/edge-functions-bootstrap": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/@netlify/edge-functions-bootstrap/-/edge-functions-bootstrap-2.16.0.tgz", "integrity": "sha512-v8QQihSbBHj3JxtJsHoepXALpNumD9M7egHoc8z62FYl5it34dWczkaJoFFopEyhiBVKi4K/n0ZYpdzwfujd6g==", "dev": true }, + "@netlify/runtime-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.2.0.tgz", + "integrity": "sha512-K3kWIxIMucibzQsATU2xw2JI+OpS9PZfPW/a+81gmeLC8tLv5YAxTVT0NFY/3imk1kcOJb9g7658jPLqDJaiAw==", + "dev": true + }, "get-port": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", @@ -43518,12 +43672,12 @@ "dev": true }, "@netlify/functions-utils": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@netlify/functions-utils/-/functions-utils-6.2.8.tgz", - "integrity": "sha512-RkvLcfa8Q4Ff19Qgzhfb0ORDL3PZXI5WJfMwEjjjSOW3HKPRrd+JTOEO+fgkScuzkMhG/DzvvTUs/JRpjWZmXw==", + "version": "6.2.11", + "resolved": "https://registry.npmjs.org/@netlify/functions-utils/-/functions-utils-6.2.11.tgz", + "integrity": "sha512-gCCjXtCtBShvZvCZwO2IxWYVjHUssnrSDea/JRoVBFc4DP3qbNoa1hdwsZ8fydguMOQaf5zFIqnDF4DKXaMA6Q==", "dev": true, "requires": { - "@netlify/zip-it-and-ship-it": "14.1.8", + "@netlify/zip-it-and-ship-it": "14.1.11", "cpy": "^11.0.0", "path-exists": "^5.0.0" } @@ -43727,9 +43881,9 @@ "optional": true }, "@netlify/open-api": { - "version": "2.39.0", - "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.39.0.tgz", - "integrity": "sha512-PMBktDmSRBS5act/GxHL3kvbRww5HPFZ9HIHXOrBu6vQesWYapoJaDiU/KDbqmkW1TyelGmURVcwsYr00qSAFg==", + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.40.0.tgz", + "integrity": "sha512-Dp4lilDnkRKGWnljGkFVxfoh1wsWqxheE5/ZOf/sMZPsh3jGu5QZ4hVLEidzXYB/zIKFFqLaUbP2XYVxTqWqyQ==", "dev": true }, "@netlify/opentelemetry-utils": { @@ -43833,28 +43987,22 @@ } } }, - "@netlify/runtime-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.1.0.tgz", - "integrity": "sha512-z1h+wjB7IVYUsFZsuIYyNxiw5WWuylseY+eXaUDHBxNeLTlqziy+lz03QkR67CUR4Y790xGIhaHV00aOR2KAtw==", - "dev": true - }, "@netlify/types": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@netlify/types/-/types-2.0.3.tgz", - "integrity": "sha512-OcV8ivKTdsyANqVSQzbusOA7FVtE9s6zwxNCGR/aNnQaVxMUgm93UzKgfR7cZ1nnQNZHAbjd0dKJKaAUqrzbMw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@netlify/types/-/types-2.1.0.tgz", + "integrity": "sha512-ktUb5d58pt1lQGXO5E9S0F1ljM0g+CoQuGTVII0IxBc0apmPq5RI0o3OWLY7U3ZERRiYTg5UfjiMihBEzuZsuw==", "dev": true }, "@netlify/zip-it-and-ship-it": { - "version": "14.1.8", - "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-14.1.8.tgz", - "integrity": "sha512-APPNgGUAb1kSe4e9KxhRAeQIPGx8EAfwZ3S61eGyZXXGXgjnKmC2Ho7jsFnLsElbt8Ailyzmi/wAjh0NHZjGjA==", + "version": "14.1.11", + "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-14.1.11.tgz", + "integrity": "sha512-5Ed9XH1JVPL7pAdq9zpC2WHjqHhHkaghuV3r2bvTTpx9JrTdzZxPeNnjZRjJMkjQAi8xSped5hNFJuD0QYmOuw==", "dev": true, "requires": { "@babel/parser": "^7.22.5", "@babel/types": "7.28.4", "@netlify/binary-info": "^1.0.0", - "@netlify/serverless-functions-api": "^2.5.0", + "@netlify/serverless-functions-api": "^2.7.1", "@vercel/nft": "0.29.4", "archiver": "^7.0.0", "common-path-prefix": "^3.0.0", @@ -43886,9 +44034,9 @@ }, "dependencies": { "@netlify/serverless-functions-api": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.5.0.tgz", - "integrity": "sha512-0Hl6POpkEs3aan8T+EQvPIj5/gNc+64nwNv93VY4JoxFSrLPKYWmUyXJhT9lG93VxwGfmbxrCOV8U4sq2eWgTw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.7.1.tgz", + "integrity": "sha512-NQcLB8BHbIsgSBPk9A/OBR5mGpc6dOAg1iRsYHWK0IoKsvwQ9a7bZc2+E40nE41Mnk24UjfK09vDLxP85O/zwA==", "dev": true }, "execa": { @@ -44643,9 +44791,9 @@ "peer": true }, "@types/node": { - "version": "22.18.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.7.tgz", - "integrity": "sha512-3E97nlWEVp2V6J7aMkR8eOnw/w0pArPwf/5/W0865f+xzBoGL/ZuHkTAKAGN7cOWNwd+sG+hZOqj+fjzeHS75g==", + "version": "22.18.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.11.tgz", + "integrity": "sha512-Gd33J2XIrXurb+eT2ktze3rJAfAp9ZNjlBdh4SVgyrKEOADwCbdUDaK7QgJno8Ue4kcajscsKqu6n8OBG3hhCQ==", "dev": true, "requires": { "undici-types": "~6.21.0" @@ -47697,9 +47845,9 @@ } }, "hot-shots": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-11.1.0.tgz", - "integrity": "sha512-D4iAs/145g7EJ/wIzBLVANEpysTPthUy/K+4EUIw02YJQTqvzD1vUpYiM3vwR0qPAQj4FhQpQz8wBpY8KDcM0g==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-11.2.0.tgz", + "integrity": "sha512-cGiFSgTZtVODx0yMW67gPICgref3XuxkTMrXP0h5cSd1HHG3OG7L2C6+aW70MAtlUNl+9+DOq/xXyJUVKDyeUg==", "dev": true, "requires": { "unix-dgram": "2.x" @@ -49750,9 +49898,9 @@ "dev": true }, "pino": { - "version": "9.11.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.11.0.tgz", - "integrity": "sha512-+YIodBB9sxcWeR8PrXC2K3gEDyfkUuVEITOcbqrfcj+z5QW4ioIcqZfYFbrLTYLsmAwunbS7nfU/dpBB6PZc1g==", + "version": "9.9.5", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.9.5.tgz", + "integrity": "sha512-d1s98p8/4TfYhsJ09r/Azt30aYELRi6NNnZtEbqFw6BoGsdPVf5lKNK3kUwH8BmJJfpTLNuicjUQjaMbd93dVg==", "dev": true, "requires": { "atomic-sleep": "^1.0.0", diff --git a/package.json b/package.json index 9402203de6..203b470ffa 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "memfs": "^4.9.2", "mock-require": "^3.0.3", "msw": "^2.0.7", - "netlify-cli": "23.9.1", + "netlify-cli": "23.9.2", "next": "^15.0.0-canary.28", "next-with-cache-handler-v2": "npm:next@15.3.0-canary.13", "os": "^0.1.2", diff --git a/tests/e2e/page-router.test.ts b/tests/e2e/page-router.test.ts index 759928c7b2..0de4dbbe32 100644 --- a/tests/e2e/page-router.test.ts +++ b/tests/e2e/page-router.test.ts @@ -425,7 +425,7 @@ test.describe('Simple Page Router (no basePath, no i18n)', () => { const response2 = await page.goto(new URL(pathname, pageRouter.url).href) expect(response2?.status()).toBe(200) expect(response2?.headers()['cache-status']).toMatch( - /("Netlify Edge"; hit; fwd=stale|"Netlify Durable"; hit; ttl=-[0-9]+)/m, + /("Netlify Edge"; fwd=stale|"Netlify Durable"; hit; ttl=-[0-9]+)/m, ) expect(response2?.headers()['debug-netlify-cdn-cache-control']).toMatch( /s-maxage=60, stale-while-revalidate=[0-9]+, durable/, diff --git a/tools/fetch-retry.mjs b/tools/fetch-retry.mjs new file mode 100644 index 0000000000..84a0fce9d4 --- /dev/null +++ b/tools/fetch-retry.mjs @@ -0,0 +1,41 @@ +// We are seeing quite a bit of 'fetch failed' cases in Github Actions that don't really reproduce +// locally. We are likely hitting some limits there when attempting to parallelize. They are not consistent +// so instead of reducing parallelism, we add a retry with backoff here. + +const originalFetch = globalThis.fetch + +const NUM_RETRIES = 5 + +globalThis.fetch = async (...args) => { + let backoff = 100 + for (let attempt = 1; attempt <= NUM_RETRIES; attempt++) { + try { + return await originalFetch.apply(globalThis, args) + } catch (error) { + let shouldRetry = false + // not ideal, but there is no error code for that + if (error.message === 'fetch failed' && attempt < NUM_RETRIES) { + // on this error we try again + shouldRetry = true + } + + if (shouldRetry) { + // leave some trace in logs what's happening + console.error('[fetch-retry] fetch thrown, retrying...', { + args, + attempt, + errorMsg: error.message, + }) + + const currentBackoff = backoff + await new Promise((resolve) => { + setTimeout(resolve, currentBackoff) + }) + backoff *= 2 + continue + } + + throw error + } + } +} From a4576af33b2648cde04bfbff484e3608c90e276a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 11:31:46 +0000 Subject: [PATCH 2/4] chore(deps): update dependency @netlify/blobs to v10 (#2967) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Mateusz Bocian Co-authored-by: Michal Piechowiak --- package-lock.json | 164 +++++++++++----------- package.json | 2 +- tests/integration/cache-handler.test.ts | 32 ++--- tests/integration/fetch-handler.test.ts | 2 +- tests/integration/request-context.test.ts | 4 +- tests/integration/revalidate-path.test.ts | 12 +- tests/integration/revalidate-tags.test.ts | 14 +- tests/utils/contexts.ts | 6 +- tests/utils/helpers.ts | 12 +- 9 files changed, 124 insertions(+), 124 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9ca21faee7..34f1073409 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "devDependencies": { "@fastly/http-compute-js": "1.1.5", - "@netlify/blobs": "^8.2.0", + "@netlify/blobs": "^10.1.0", "@netlify/build": "^35.1.7", "@netlify/config": "^24.0.4", "@netlify/edge-bundler": "^14.5.5", @@ -3764,14 +3764,53 @@ "dev": true }, "node_modules/@netlify/blobs": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-8.2.0.tgz", - "integrity": "sha512-9djLZHBKsoKk8XCgwWSEPK9QnT8qqxEQGuYh48gFIcNLvpBKkLnHbDZuyUxmNemCfDz7h0HnMXgSPnnUVgARhg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.1.0.tgz", + "integrity": "sha512-dFpqDc6/x5LEu9L7kblCQu00CFEchH8J42jmQoXPuhKoE7avajzeLTbVKA8Olk3S/c2m9ejegrgbhL8NRA2Jyw==", "dev": true, + "dependencies": { + "@netlify/dev-utils": "4.3.0", + "@netlify/runtime-utils": "2.2.0" + }, "engines": { "node": "^14.16.0 || >=16.0.0" } }, + "node_modules/@netlify/blobs/node_modules/@netlify/dev-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.3.0.tgz", + "integrity": "sha512-vZAL8pMuj3yPQlmHSgyaA/UQFxc6pZgU0LucFJ1+IPWGJtIzBXHRvuR4acpoP72HtyQPUHJ42s7U9GaaSGVNHg==", + "dev": true, + "dependencies": { + "@whatwg-node/server": "^0.10.0", + "ansis": "^4.1.0", + "chokidar": "^4.0.1", + "decache": "^4.6.2", + "dettle": "^1.0.5", + "dot-prop": "9.0.0", + "empathic": "^2.0.0", + "env-paths": "^3.0.0", + "image-size": "^2.0.2", + "js-image-generator": "^1.0.4", + "parse-gitignore": "^2.0.0", + "semver": "^7.7.2", + "tmp-promise": "^3.0.3", + "uuid": "^11.1.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || >=20" + } + }, + "node_modules/@netlify/blobs/node_modules/@netlify/runtime-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.2.0.tgz", + "integrity": "sha512-K3kWIxIMucibzQsATU2xw2JI+OpS9PZfPW/a+81gmeLC8tLv5YAxTVT0NFY/3imk1kcOJb9g7658jPLqDJaiAw==", + "dev": true, + "engines": { + "node": "^18.14.0 || >=20" + } + }, "node_modules/@netlify/build": { "version": "35.1.7", "resolved": "https://registry.npmjs.org/@netlify/build/-/build-35.1.7.tgz", @@ -3846,45 +3885,6 @@ } } }, - "node_modules/@netlify/build/node_modules/@netlify/blobs": { - "version": "10.0.11", - "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.0.11.tgz", - "integrity": "sha512-/pa7eD2gxkhJ6aUIJULrRu3tvAaimy+sA6vHUuGRMvncjOuRpeatXLHxuzdn8DyK1CZCjN3E33oXsdEpoqG7SA==", - "dev": true, - "dependencies": { - "@netlify/dev-utils": "4.2.0", - "@netlify/runtime-utils": "2.1.0" - }, - "engines": { - "node": "^14.16.0 || >=16.0.0" - } - }, - "node_modules/@netlify/build/node_modules/@netlify/dev-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.2.0.tgz", - "integrity": "sha512-P/uLJ5IKB4DhUOd6Q4Mpk7N0YKrnijUhAL3C05dEftNi3U3xJB98YekYfsL3G6GkS3L35pKGMx+vKJRwUHpP1Q==", - "dev": true, - "dependencies": { - "@whatwg-node/server": "^0.10.0", - "ansis": "^4.1.0", - "chokidar": "^4.0.1", - "decache": "^4.6.2", - "dettle": "^1.0.5", - "dot-prop": "9.0.0", - "empathic": "^2.0.0", - "env-paths": "^3.0.0", - "image-size": "^2.0.2", - "js-image-generator": "^1.0.4", - "parse-gitignore": "^2.0.0", - "semver": "^7.7.2", - "tmp-promise": "^3.0.3", - "uuid": "^11.1.0", - "write-file-atomic": "^5.0.1" - }, - "engines": { - "node": "^18.14.0 || >=20" - } - }, "node_modules/@netlify/cache-utils": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/@netlify/cache-utils/-/cache-utils-6.0.4.tgz", @@ -35220,10 +35220,45 @@ "dev": true }, "@netlify/blobs": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-8.2.0.tgz", - "integrity": "sha512-9djLZHBKsoKk8XCgwWSEPK9QnT8qqxEQGuYh48gFIcNLvpBKkLnHbDZuyUxmNemCfDz7h0HnMXgSPnnUVgARhg==", - "dev": true + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.1.0.tgz", + "integrity": "sha512-dFpqDc6/x5LEu9L7kblCQu00CFEchH8J42jmQoXPuhKoE7avajzeLTbVKA8Olk3S/c2m9ejegrgbhL8NRA2Jyw==", + "dev": true, + "requires": { + "@netlify/dev-utils": "4.3.0", + "@netlify/runtime-utils": "2.2.0" + }, + "dependencies": { + "@netlify/dev-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.3.0.tgz", + "integrity": "sha512-vZAL8pMuj3yPQlmHSgyaA/UQFxc6pZgU0LucFJ1+IPWGJtIzBXHRvuR4acpoP72HtyQPUHJ42s7U9GaaSGVNHg==", + "dev": true, + "requires": { + "@whatwg-node/server": "^0.10.0", + "ansis": "^4.1.0", + "chokidar": "^4.0.1", + "decache": "^4.6.2", + "dettle": "^1.0.5", + "dot-prop": "9.0.0", + "empathic": "^2.0.0", + "env-paths": "^3.0.0", + "image-size": "^2.0.2", + "js-image-generator": "^1.0.4", + "parse-gitignore": "^2.0.0", + "semver": "^7.7.2", + "tmp-promise": "^3.0.3", + "uuid": "^11.1.0", + "write-file-atomic": "^5.0.1" + } + }, + "@netlify/runtime-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.2.0.tgz", + "integrity": "sha512-K3kWIxIMucibzQsATU2xw2JI+OpS9PZfPW/a+81gmeLC8tLv5YAxTVT0NFY/3imk1kcOJb9g7658jPLqDJaiAw==", + "dev": true + } + } }, "@netlify/build": { "version": "35.1.7", @@ -35282,41 +35317,6 @@ "yaml": "^2.8.0", "yargs": "^17.6.0", "zod": "^3.25.76" - }, - "dependencies": { - "@netlify/blobs": { - "version": "10.0.11", - "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.0.11.tgz", - "integrity": "sha512-/pa7eD2gxkhJ6aUIJULrRu3tvAaimy+sA6vHUuGRMvncjOuRpeatXLHxuzdn8DyK1CZCjN3E33oXsdEpoqG7SA==", - "dev": true, - "requires": { - "@netlify/dev-utils": "4.2.0", - "@netlify/runtime-utils": "2.1.0" - } - }, - "@netlify/dev-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.2.0.tgz", - "integrity": "sha512-P/uLJ5IKB4DhUOd6Q4Mpk7N0YKrnijUhAL3C05dEftNi3U3xJB98YekYfsL3G6GkS3L35pKGMx+vKJRwUHpP1Q==", - "dev": true, - "requires": { - "@whatwg-node/server": "^0.10.0", - "ansis": "^4.1.0", - "chokidar": "^4.0.1", - "decache": "^4.6.2", - "dettle": "^1.0.5", - "dot-prop": "9.0.0", - "empathic": "^2.0.0", - "env-paths": "^3.0.0", - "image-size": "^2.0.2", - "js-image-generator": "^1.0.4", - "parse-gitignore": "^2.0.0", - "semver": "^7.7.2", - "tmp-promise": "^3.0.3", - "uuid": "^11.1.0", - "write-file-atomic": "^5.0.1" - } - } } }, "@netlify/cache-utils": { diff --git a/package.json b/package.json index 203b470ffa..855f01083a 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "homepage": "https://opennext.js.org/netlify", "devDependencies": { "@fastly/http-compute-js": "1.1.5", - "@netlify/blobs": "^8.2.0", + "@netlify/blobs": "^10.1.0", "@netlify/build": "^35.1.7", "@netlify/config": "^24.0.4", "@netlify/edge-bundler": "^14.5.5", diff --git a/tests/integration/cache-handler.test.ts b/tests/integration/cache-handler.test.ts index b459d62559..23e27101ca 100644 --- a/tests/integration/cache-handler.test.ts +++ b/tests/integration/cache-handler.test.ts @@ -82,7 +82,7 @@ describe('page router', () => { countOfBlobServerGetsForKey(ctx, '/static/revalidate-automatic'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // wait to have page regenerated in the background await new Promise((resolve) => setTimeout(resolve, 1000)) @@ -116,7 +116,7 @@ describe('page router', () => { countOfBlobServerGetsForKey(ctx, '/static/revalidate-automatic'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // ping that should serve the stale page for static/revalidate-slow, while revalidating in background await invokeFunction(ctx, { url: 'static/revalidate-slow' }) @@ -125,7 +125,7 @@ describe('page router', () => { countOfBlobServerGetsForKey(ctx, '/static/revalidate-slow'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // wait to have a stale page await new Promise((resolve) => setTimeout(resolve, 6_000)) @@ -136,7 +136,7 @@ describe('page router', () => { countOfBlobServerGetsForKey(ctx, '/static/revalidate-slow'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // over 5 seconds since it was regenerated, so we should get stale response, // while fresh is generated in the background @@ -160,7 +160,7 @@ describe('page router', () => { countOfBlobServerGetsForKey(ctx, '/static/revalidate-automatic'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // Slow revalidate should still be a hit, but the maxage should be updated const callLater2 = await invokeFunction(ctx, { url: 'static/revalidate-slow' }) @@ -177,7 +177,7 @@ describe('page router', () => { countOfBlobServerGetsForKey(ctx, '/static/revalidate-slow'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // it does not wait for the cache.set so we have to manually wait here until the blob storage got populated await new Promise((resolve) => setTimeout(resolve, 1000)) @@ -204,7 +204,7 @@ describe('page router', () => { countOfBlobServerGetsForKey(ctx, '/static/revalidate-automatic'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() }) }) @@ -245,7 +245,7 @@ describe('app router', () => { countOfBlobServerGetsForKey(ctx, '/posts/1'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // test a prerendered page without TTL const post2 = await invokeFunction(ctx, { url: '/' }) @@ -263,7 +263,7 @@ describe('app router', () => { countOfBlobServerGetsForKey(ctx, '/index'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() expect(await ctx.blobStore.get(encodeBlobKey('/posts/3'))).toBeNull() // this page is not pre-rendered and should result in a cache miss @@ -293,7 +293,7 @@ describe('app router', () => { countOfBlobServerGetsForKey(ctx, '/posts/1'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // it should've been regenerated in the background after the first call // so the date should be different expect(staleDate, 'the date was cached and is matching the initial one').not.toBe(post1Date) @@ -320,7 +320,7 @@ describe('app router', () => { countOfBlobServerGetsForKey(ctx, '/posts/1'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() }) test("not-prerendered pages should be permanently cached when produced by sandboxed invocations that don't share memory", async (ctx) => { @@ -405,7 +405,7 @@ describe('route', () => { }) expect(blobEntry).not.toBeNull() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // test the first invocation of the route - we should get stale response while fresh is generated in the background const call1 = await invokeFunction(ctx, { url: '/api/revalidate-handler' }) @@ -428,7 +428,7 @@ describe('route', () => { countOfBlobServerGetsForKey(ctx, '/api/revalidate-handler'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // it does not wait for the cache.set so we have to manually wait here until the blob storage got populated await new Promise((resolve) => setTimeout(resolve, 1000)) @@ -458,7 +458,7 @@ describe('route', () => { countOfBlobServerGetsForKey(ctx, '/api/revalidate-handler'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // wait to have a stale route again await new Promise((resolve) => setTimeout(resolve, 8_000)) @@ -485,7 +485,7 @@ describe('route', () => { countOfBlobServerGetsForKey(ctx, '/api/revalidate-handler'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // it does not wait for the cache.set so we have to manually wait here until the blob storage got populated await new Promise((resolve) => setTimeout(resolve, 1000)) @@ -510,7 +510,7 @@ describe('route', () => { countOfBlobServerGetsForKey(ctx, '/api/revalidate-handler'), 'should only try to get value once from blob store (date calculation should not trigger additional blobs.get)', ).toBe(1) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() }) test('cacheable route handler response not produced at build is served correctly', async (ctx) => { diff --git a/tests/integration/fetch-handler.test.ts b/tests/integration/fetch-handler.test.ts index c90bf44af3..3901bf0997 100644 --- a/tests/integration/fetch-handler.test.ts +++ b/tests/integration/fetch-handler.test.ts @@ -363,7 +363,7 @@ test('does not fetch same cached fetch data from blobs twice 'expected blobs for all types of values to be retrieved at most once per key (including fetch data, tag manifests, static files)', ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() handlerCalled = 0 const request2 = await invokeFunction(ctx, { url: 'same-fetch-multiple-times/99', diff --git a/tests/integration/request-context.test.ts b/tests/integration/request-context.test.ts index 31788cdf91..9b9efe0cb6 100644 --- a/tests/integration/request-context.test.ts +++ b/tests/integration/request-context.test.ts @@ -106,7 +106,7 @@ describe('request-context does NOT leak between concurrent requests', () => { lastModified: new Date(mockedDateForRevalidateSlow).getTime(), }) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const waitForCacheHandlerGetAndPausePromise = waitForCacheHandlerGetAndPause('/static/revalidate-slow') @@ -182,7 +182,7 @@ describe('request-context does NOT leak between concurrent requests', () => { lastModified: new Date(mockedDateForStaticFetch2).getTime(), }) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const waitForCacheHandlerGetAndPausePromise = waitForCacheHandlerGetAndPause('/static-fetch/2') const slowCallPromise = invokeFunction(ctx, { diff --git a/tests/integration/revalidate-path.test.ts b/tests/integration/revalidate-path.test.ts index f326eea0b6..ed7d9a4f66 100644 --- a/tests/integration/revalidate-path.test.ts +++ b/tests/integration/revalidate-path.test.ts @@ -58,7 +58,7 @@ test('should revalidate a route by path', async (ctx) => { expect(await ctx.blobStore.get(encodeBlobKey('/static-fetch/1'))).not.toBeNull() expect(await ctx.blobStore.get(encodeBlobKey('_N_T_/static-fetch/[id]/page'))).toBeNull() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // test the function call const post1 = await invokeFunction(ctx, { url: '/static-fetch/1' }) @@ -78,7 +78,7 @@ test('should revalidate a route by path', async (ctx) => { getBlobServerGets(ctx, isTagManifest), `expected tag manifests to be retrieved at most once per tag`, ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const post1Route2 = await invokeFunction(ctx, { url: '/static-fetch/2' }) expect(post1Route2.statusCode).toBe(200) @@ -95,7 +95,7 @@ test('should revalidate a route by path', async (ctx) => { getBlobServerGets(ctx, isTagManifest), `expected tag manifests to be retrieved at most once per tag`, ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const revalidate = await invokeFunction(ctx, { url: '/api/on-demand-revalidate/path' }) expect(revalidate.statusCode).toBe(200) @@ -106,7 +106,7 @@ test('should revalidate a route by path', async (ctx) => { expect(await ctx.blobStore.get(encodeBlobKey('_N_T_/static-fetch/[id]/page'))).not.toBeNull() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const post2 = await invokeFunction(ctx, { url: '/static-fetch/1' }) const post2Date = load(post2.body)('[data-testid="date-now"]').text() @@ -126,7 +126,7 @@ test('should revalidate a route by path', async (ctx) => { getBlobServerGets(ctx, isTagManifest), `expected tag manifests to be retrieved at most once per tag`, ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const post2Route2 = await invokeFunction(ctx, { url: '/static-fetch/2' }) @@ -144,5 +144,5 @@ test('should revalidate a route by path', async (ctx) => { getBlobServerGets(ctx, isTagManifest), `expected tag manifests to be retrieved at most once per tag`, ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() }) diff --git a/tests/integration/revalidate-tags.test.ts b/tests/integration/revalidate-tags.test.ts index c93f45a980..87316cbda8 100644 --- a/tests/integration/revalidate-tags.test.ts +++ b/tests/integration/revalidate-tags.test.ts @@ -57,7 +57,7 @@ test('should revalidate a route by tag', async (ctx) => { expect(await ctx.blobStore.get(encodeBlobKey('/static-fetch-1'))).not.toBeNull() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // test the function call const post1 = await invokeFunction(ctx, { url: '/static-fetch-1' }) @@ -78,7 +78,7 @@ test('should revalidate a route by tag', async (ctx) => { getBlobServerGets(ctx, isTagManifest), `expected tag manifests to be retrieved at most once per tag`, ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const revalidate = await invokeFunction(ctx, { url: '/api/on-demand-revalidate/tag' }) expect(revalidate.statusCode).toBe(200) @@ -87,7 +87,7 @@ test('should revalidate a route by tag', async (ctx) => { // it does not wait for the revalidation await new Promise((resolve) => setTimeout(resolve, 100)) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const post2 = await invokeFunction(ctx, { url: '/static-fetch-1' }) const post2Date = load(post2.body)('[data-testid="date-now"]').text() @@ -109,7 +109,7 @@ test('should revalidate a route by tag', async (ctx) => { getBlobServerGets(ctx, isTagManifest), `expected tag manifests to be retrieved at most once per tag`, ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() // it does not wait for the cache.set so we have to manually wait here until the blob storage got populated await new Promise((resolve) => setTimeout(resolve, 100)) @@ -134,7 +134,7 @@ test('should revalidate a route by tag', async (ctx) => { getBlobServerGets(ctx, isTagManifest), `expected tag manifests to be retrieved at most once per tag`, ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const revalidate2 = await invokeFunction(ctx, { url: '/api/on-demand-revalidate/tag' }) expect(revalidate2.statusCode).toBe(200) @@ -143,7 +143,7 @@ test('should revalidate a route by tag', async (ctx) => { // it does not wait for the revalidation await new Promise((resolve) => setTimeout(resolve, 100)) - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() const post4 = await invokeFunction(ctx, { url: '/static-fetch-1' }) const post4Date = load(post4.body)('[data-testid="date-now"]').text() @@ -165,5 +165,5 @@ test('should revalidate a route by tag', async (ctx) => { getBlobServerGets(ctx, isTagManifest), `expected tag manifests to be retrieved at most once per tag`, ).toBeDistinct() - ctx.blobServerGetSpy.mockClear() + ctx.blobServerOnRequestSpy.mockClear() }) diff --git a/tests/utils/contexts.ts b/tests/utils/contexts.ts index 874dc8d2b6..bc2bebe99f 100644 --- a/tests/utils/contexts.ts +++ b/tests/utils/contexts.ts @@ -1,7 +1,7 @@ -import { type getStore } from '@netlify/blobs' +import type { getStore } from '@netlify/blobs' import { BlobsServer } from '@netlify/blobs/server' import { type WriteStream } from 'node:fs' -import { MockInstance, TestContext } from 'vitest' +import { TestContext } from 'vitest' export interface FixtureTestContext extends TestContext { cwd: string @@ -10,7 +10,7 @@ export interface FixtureTestContext extends TestContext { blobStoreHost: string blobStorePort: number blobServer: BlobsServer - blobServerGetSpy: MockInstance, ReturnType> + blobServerOnRequestSpy: BlobsServer['onRequest'] blobStore: ReturnType functionDist: string edgeFunctionPort: number diff --git a/tests/utils/helpers.ts b/tests/utils/helpers.ts index b540aea7c3..99f741fb6e 100644 --- a/tests/utils/helpers.ts +++ b/tests/utils/helpers.ts @@ -1,7 +1,7 @@ import getPort from 'get-port' import { getDeployStore } from '@netlify/blobs' -import { BlobsServer } from '@netlify/blobs/server' +import { BlobsServer, Operation } from '@netlify/blobs/server' import type { NetlifyPluginUtils } from '@netlify/build' import { Buffer } from 'node:buffer' import { mkdtemp } from 'node:fs/promises' @@ -34,13 +34,14 @@ export const generateRandomObjectID = () => { export const startMockBlobStore = async (ctx: FixtureTestContext) => { const port = await getPort() // create new blob store server + ctx.blobServerOnRequestSpy = vi.fn() ctx.blobServer = new BlobsServer({ port, token: BLOB_TOKEN, + onRequest: ctx.blobServerOnRequestSpy, directory: await mkdtemp(join(tmpdir(), 'opennextjs-netlify-blob-')), }) await ctx.blobServer.start() - ctx.blobServerGetSpy = vi.spyOn(ctx.blobServer, 'get') ctx.blobStoreHost = `localhost:${port}` ctx.blobStorePort = port vi.stubEnv('NETLIFY_BLOBS_CONTEXT', createBlobContext(ctx)) @@ -72,11 +73,10 @@ export const getBlobEntries = async (ctx: FixtureTestContext) => { export function getBlobServerGets(ctx: FixtureTestContext, predicate?: (key: string) => boolean) { const isString = (arg: unknown): arg is string => typeof arg === 'string' - return ctx.blobServerGetSpy.mock.calls + return ctx.blobServerOnRequestSpy.mock.calls .map(([request]) => { - if (typeof request.url !== 'string') { - return undefined - } + if (request.type !== Operation.GET) return undefined + if (!isString(request.url)) return undefined let urlSegments = request.url.split('/').slice(1) From a90d2e5228bbb77bf657929f83729945480d83e5 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Tue, 21 Oct 2025 16:01:02 +0200 Subject: [PATCH 3/4] fix: support revalidateTag SWR in 'use cache' handler (#3180) --- .github/workflows/test-e2e.yml | 9 +- package-lock.json | 1023 +++++++++++++++++ package.json | 1 + src/run/handlers/request-context.cts | 1 + src/run/handlers/tags-handler.cts | 22 +- src/run/handlers/use-cache-handler.ts | 76 +- .../app/api/revalidate/[...slug]/route.ts | 6 +- .../dynamic/ttl-1year/[slug]/page.tsx | 2 +- .../dynamic/ttl-5seconds/[slug]/page.tsx | 2 +- .../static/ttl-10seconds/[slug]/page.tsx | 2 +- .../static/ttl-1year/[slug]/page.tsx | 2 +- .../dynamic/ttl-1year/[slug]/page.tsx | 2 +- .../dynamic/ttl-5seconds/[slug]/page.tsx | 2 +- .../static/ttl-10seconds/[slug]/page.tsx | 2 +- .../static/ttl-1year/[slug]/page.tsx | 2 +- .../dynamic/ttl-1year/[slug]/page.tsx | 2 +- .../dynamic/ttl-5seconds/[slug]/page.tsx | 2 +- .../static/ttl-10seconds/[slug]/page.tsx | 2 +- .../static/ttl-1year/[slug]/page.tsx | 2 +- tests/fixtures/use-cache/app/next-cache.ts | 20 + tests/integration/use-cache.test.ts | 48 + tests/utils/create-e2e-fixture.ts | 6 + 22 files changed, 1198 insertions(+), 38 deletions(-) create mode 100644 tests/fixtures/use-cache/app/next-cache.ts diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index e87a4f2ea9..b3a165643c 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -5,11 +5,11 @@ on: pull_request: branches: [main] schedule: - - cron: '0 3 * * *' # Run every day at 3am UTC + - cron: "0 3 * * *" # Run every day at 3am UTC workflow_dispatch: inputs: versions: - description: 'The versions of Next.js to test against (escape-quoted and comma separated)' + description: "The versions of Next.js to test against (escape-quoted and comma separated)" required: false # TODO(serhalp) Ideally this would simply accept bare quotes but we're having trouble # parsing that so this will do for now. @@ -52,7 +52,6 @@ jobs: group: ${{ steps.set-matrix.outputs.group }} total: ${{ steps.set-matrix.outputs.total }} steps: - - name: Set Next.js versions to test id: set-matrix run: | @@ -240,7 +239,7 @@ jobs: IS_WEBPACK_TEST: ${{ steps.decide-default-bundler.outputs.default_bundler == 'webpack' && '1' || '' }} IS_TURBOPACK_TEST: ${{ steps.decide-default-bundler.outputs.default_bundler == 'turbopack' && '1' || '' }} NODE_OPTIONS: --import ${{ github.workspace }}/${{ env.runtime-path}}/tools/fetch-retry.mjs - run: node run-tests.js -g ${{ matrix.group }}/${{ needs.setup.outputs.total }} -c ${TEST_CONCURRENCY} --type e2e + run: node run-tests.js -g ${{ matrix.group }}/${{ needs.setup.outputs.total }} -c ${TEST_CONCURRENCY} --type e2e --retries 5 working-directory: ${{ env.next-path }} - name: Upload Test Results @@ -250,7 +249,7 @@ jobs: name: test-result-${{matrix.version_spec.selector}}-${{ matrix.group }} path: ${{ env.next-path }}/test/${{steps.decide-default-bundler.outputs.default_bundler == 'turbopack' && 'turbopack-test-junit-report' || 'test-junit-report'}}/*.xml publish-test-results: - name: 'E2E Test Summary (${{matrix.version_spec.selector}})' + name: "E2E Test Summary (${{matrix.version_spec.selector}})" needs: - e2e - setup diff --git a/package-lock.json b/package-lock.json index 34f1073409..0349d4fc9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "netlify-cli": "23.9.2", "next": "^15.0.0-canary.28", "next-with-cache-handler-v2": "npm:next@15.3.0-canary.13", + "next-with-cache-handler-v3": "npm:next@16.0.0-beta.0", "os": "^0.1.2", "outdent": "^0.8.0", "p-limit": "^6.0.0", @@ -2852,6 +2853,17 @@ "dev": true, "license": "ISC" }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", @@ -2966,6 +2978,23 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", + "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-libvips-linux-s390x": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", @@ -3080,6 +3109,29 @@ "@img/sharp-libvips-linux-arm64": "1.0.4" } }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", + "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.3" + } + }, "node_modules/@img/sharp-linux-s390x": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", @@ -3192,6 +3244,26 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", + "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-win32-ia32": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", @@ -27972,6 +28044,637 @@ "tslib": "^2.8.0" } }, + "node_modules/next-with-cache-handler-v3": { + "name": "next", + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/next/-/next-16.0.0-beta.0.tgz", + "integrity": "sha512-RrpQl/FkN4v+hwcfsgj+ukTDyf3uQ1mcbNs229M9H0POMc8P0LhgrNDAWEiQHviYicLZorWJ47RoQYCzVddkww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/env": "16.0.0-beta.0", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.0.0-beta.0", + "@next/swc-darwin-x64": "16.0.0-beta.0", + "@next/swc-linux-arm64-gnu": "16.0.0-beta.0", + "@next/swc-linux-arm64-musl": "16.0.0-beta.0", + "@next/swc-linux-x64-gnu": "16.0.0-beta.0", + "@next/swc-linux-x64-musl": "16.0.0-beta.0", + "@next/swc-win32-arm64-msvc": "16.0.0-beta.0", + "@next/swc-win32-x64-msvc": "16.0.0-beta.0", + "sharp": "^0.34.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", + "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.3" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-darwin-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", + "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.3" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", + "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", + "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", + "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", + "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", + "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", + "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-linux-arm": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", + "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.3" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-linux-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", + "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.3" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-linux-s390x": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", + "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.3" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-linux-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", + "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.3" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", + "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", + "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.3" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-wasm32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", + "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.5.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-win32-ia32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", + "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@img/sharp-win32-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", + "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/env": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.0-beta.0.tgz", + "integrity": "sha512-OWeEhUmIxA9zuQansxKXHWTszsPcvSvar8ym1BOElhU6Lgnb4yLXGshKSoPXoHOHRFcxuYmhI86OA+5Z9TvSSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/swc-darwin-arm64": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.0-beta.0.tgz", + "integrity": "sha512-8IdA5j+xOGQNP+4yBqG5pvNhrDrVp/IMyJSn38t2h3XOhw+BZ63j+m0SyJuj2OKgIBgJLvkHUXEWiSD9u5nfBw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/swc-darwin-x64": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.0-beta.0.tgz", + "integrity": "sha512-SEAPWkMPHnLMTmDw/b0XnIgMsdUZvAGLYzAz9VZxtie1x5dnus3t/n2DP0nmg8O8LkfKJcicnm6fMrNeHJQs9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.0-beta.0.tgz", + "integrity": "sha512-qeccINBs3eWt5EbiaABNUZBWyMRToZfgzSD5tRED1UuZpfxt3asebkanV1GFS/ZQ+z3+pVEzMwhaGwCBbfCa5w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/swc-linux-arm64-musl": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.0-beta.0.tgz", + "integrity": "sha512-vhhfBp7CNTVHq0tuY+enPKvE91QgjhiWs539EQ0VXCbQMoAuxWr1uOgS3kjfah78oI89icQin4HAO7ePu3KUtw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/swc-linux-x64-gnu": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.0-beta.0.tgz", + "integrity": "sha512-2+aMU293kgg0UJLEyhgXy3KwyI0RcSfKHrWT8SnzW8FqcrUcOWYw7qWCP+JcRT5SwQCcjByEOwH+cw+1nBTeIA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/swc-linux-x64-musl": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.0-beta.0.tgz", + "integrity": "sha512-Jgu9BvRLG82DhkeSF+3OTOkZXf6azXlOlQ3TOWHRzh+Cap+fhlO8yp+cYI5jDsopDIfaBW+3ToAL1YLE1n+dGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.0-beta.0.tgz", + "integrity": "sha512-5cGucadLwCWUl9v1aOJLzDpyiYpdrFBiApvGVy4GKAFo6uK34mtgCSZcVUQ+DeLjAx0G5B3AgNxVnzMfXKsv5g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@next/swc-win32-x64-msvc": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.0-beta.0.tgz", + "integrity": "sha512-gq0WvicjqmoiakDtW7TeabgT58i+5mQ+wy+qYuwCHBbWbed9PMh/wl4ZomsOe2IzlinRPylRGA01jXLPOrX/Nw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/next-with-cache-handler-v3/node_modules/sharp": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", + "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.0", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.4", + "@img/sharp-darwin-x64": "0.34.4", + "@img/sharp-libvips-darwin-arm64": "1.2.3", + "@img/sharp-libvips-darwin-x64": "1.2.3", + "@img/sharp-libvips-linux-arm": "1.2.3", + "@img/sharp-libvips-linux-arm64": "1.2.3", + "@img/sharp-libvips-linux-ppc64": "1.2.3", + "@img/sharp-libvips-linux-s390x": "1.2.3", + "@img/sharp-libvips-linux-x64": "1.2.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", + "@img/sharp-libvips-linuxmusl-x64": "1.2.3", + "@img/sharp-linux-arm": "0.34.4", + "@img/sharp-linux-arm64": "0.34.4", + "@img/sharp-linux-ppc64": "0.34.4", + "@img/sharp-linux-s390x": "0.34.4", + "@img/sharp-linux-x64": "0.34.4", + "@img/sharp-linuxmusl-arm64": "0.34.4", + "@img/sharp-linuxmusl-x64": "0.34.4", + "@img/sharp-wasm32": "0.34.4", + "@img/sharp-win32-arm64": "0.34.4", + "@img/sharp-win32-ia32": "0.34.4", + "@img/sharp-win32-x64": "0.34.4" + } + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -34705,6 +35408,13 @@ "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", "dev": true }, + "@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "dev": true, + "optional": true + }, "@img/sharp-darwin-arm64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", @@ -34753,6 +35463,13 @@ "dev": true, "optional": true }, + "@img/sharp-libvips-linux-ppc64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", + "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", + "dev": true, + "optional": true + }, "@img/sharp-libvips-linux-s390x": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", @@ -34801,6 +35518,16 @@ "@img/sharp-libvips-linux-arm64": "1.0.4" } }, + "@img/sharp-linux-ppc64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", + "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-linux-ppc64": "1.2.3" + } + }, "@img/sharp-linux-s390x": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", @@ -34851,6 +35578,13 @@ "@emnapi/runtime": "^1.2.0" } }, + "@img/sharp-win32-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", + "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", + "dev": true, + "optional": true + }, "@img/sharp-win32-ia32": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", @@ -52216,6 +52950,295 @@ } } }, + "next-with-cache-handler-v3": { + "version": "npm:next@16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/next/-/next-16.0.0-beta.0.tgz", + "integrity": "sha512-RrpQl/FkN4v+hwcfsgj+ukTDyf3uQ1mcbNs229M9H0POMc8P0LhgrNDAWEiQHviYicLZorWJ47RoQYCzVddkww==", + "dev": true, + "requires": { + "@next/env": "16.0.0-beta.0", + "@next/swc-darwin-arm64": "16.0.0-beta.0", + "@next/swc-darwin-x64": "16.0.0-beta.0", + "@next/swc-linux-arm64-gnu": "16.0.0-beta.0", + "@next/swc-linux-arm64-musl": "16.0.0-beta.0", + "@next/swc-linux-x64-gnu": "16.0.0-beta.0", + "@next/swc-linux-x64-musl": "16.0.0-beta.0", + "@next/swc-win32-arm64-msvc": "16.0.0-beta.0", + "@next/swc-win32-x64-msvc": "16.0.0-beta.0", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "sharp": "^0.34.4", + "styled-jsx": "5.1.6" + }, + "dependencies": { + "@img/sharp-darwin-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", + "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-darwin-arm64": "1.2.3" + } + }, + "@img/sharp-darwin-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", + "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-darwin-x64": "1.2.3" + } + }, + "@img/sharp-libvips-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "dev": true, + "optional": true + }, + "@img/sharp-libvips-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", + "dev": true, + "optional": true + }, + "@img/sharp-libvips-linux-arm": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", + "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", + "dev": true, + "optional": true + }, + "@img/sharp-libvips-linux-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", + "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", + "dev": true, + "optional": true + }, + "@img/sharp-libvips-linux-s390x": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", + "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", + "dev": true, + "optional": true + }, + "@img/sharp-libvips-linux-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", + "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", + "dev": true, + "optional": true + }, + "@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", + "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", + "dev": true, + "optional": true + }, + "@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", + "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", + "dev": true, + "optional": true + }, + "@img/sharp-linux-arm": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", + "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-linux-arm": "1.2.3" + } + }, + "@img/sharp-linux-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", + "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-linux-arm64": "1.2.3" + } + }, + "@img/sharp-linux-s390x": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", + "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-linux-s390x": "1.2.3" + } + }, + "@img/sharp-linux-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", + "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-linux-x64": "1.2.3" + } + }, + "@img/sharp-linuxmusl-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", + "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" + } + }, + "@img/sharp-linuxmusl-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", + "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", + "dev": true, + "optional": true, + "requires": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.3" + } + }, + "@img/sharp-wasm32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", + "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", + "dev": true, + "optional": true, + "requires": { + "@emnapi/runtime": "^1.5.0" + } + }, + "@img/sharp-win32-ia32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", + "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", + "dev": true, + "optional": true + }, + "@img/sharp-win32-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", + "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", + "dev": true, + "optional": true + }, + "@next/env": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.0-beta.0.tgz", + "integrity": "sha512-OWeEhUmIxA9zuQansxKXHWTszsPcvSvar8ym1BOElhU6Lgnb4yLXGshKSoPXoHOHRFcxuYmhI86OA+5Z9TvSSQ==", + "dev": true + }, + "@next/swc-darwin-arm64": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.0-beta.0.tgz", + "integrity": "sha512-8IdA5j+xOGQNP+4yBqG5pvNhrDrVp/IMyJSn38t2h3XOhw+BZ63j+m0SyJuj2OKgIBgJLvkHUXEWiSD9u5nfBw==", + "dev": true, + "optional": true + }, + "@next/swc-darwin-x64": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.0-beta.0.tgz", + "integrity": "sha512-SEAPWkMPHnLMTmDw/b0XnIgMsdUZvAGLYzAz9VZxtie1x5dnus3t/n2DP0nmg8O8LkfKJcicnm6fMrNeHJQs9w==", + "dev": true, + "optional": true + }, + "@next/swc-linux-arm64-gnu": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.0-beta.0.tgz", + "integrity": "sha512-qeccINBs3eWt5EbiaABNUZBWyMRToZfgzSD5tRED1UuZpfxt3asebkanV1GFS/ZQ+z3+pVEzMwhaGwCBbfCa5w==", + "dev": true, + "optional": true + }, + "@next/swc-linux-arm64-musl": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.0-beta.0.tgz", + "integrity": "sha512-vhhfBp7CNTVHq0tuY+enPKvE91QgjhiWs539EQ0VXCbQMoAuxWr1uOgS3kjfah78oI89icQin4HAO7ePu3KUtw==", + "dev": true, + "optional": true + }, + "@next/swc-linux-x64-gnu": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.0-beta.0.tgz", + "integrity": "sha512-2+aMU293kgg0UJLEyhgXy3KwyI0RcSfKHrWT8SnzW8FqcrUcOWYw7qWCP+JcRT5SwQCcjByEOwH+cw+1nBTeIA==", + "dev": true, + "optional": true + }, + "@next/swc-linux-x64-musl": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.0-beta.0.tgz", + "integrity": "sha512-Jgu9BvRLG82DhkeSF+3OTOkZXf6azXlOlQ3TOWHRzh+Cap+fhlO8yp+cYI5jDsopDIfaBW+3ToAL1YLE1n+dGg==", + "dev": true, + "optional": true + }, + "@next/swc-win32-arm64-msvc": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.0-beta.0.tgz", + "integrity": "sha512-5cGucadLwCWUl9v1aOJLzDpyiYpdrFBiApvGVy4GKAFo6uK34mtgCSZcVUQ+DeLjAx0G5B3AgNxVnzMfXKsv5g==", + "dev": true, + "optional": true + }, + "@next/swc-win32-x64-msvc": { + "version": "16.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.0-beta.0.tgz", + "integrity": "sha512-gq0WvicjqmoiakDtW7TeabgT58i+5mQ+wy+qYuwCHBbWbed9PMh/wl4ZomsOe2IzlinRPylRGA01jXLPOrX/Nw==", + "dev": true, + "optional": true + }, + "@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "dev": true, + "requires": { + "tslib": "^2.8.0" + } + }, + "sharp": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", + "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==", + "dev": true, + "optional": true, + "requires": { + "@img/colour": "^1.0.0", + "@img/sharp-darwin-arm64": "0.34.4", + "@img/sharp-darwin-x64": "0.34.4", + "@img/sharp-libvips-darwin-arm64": "1.2.3", + "@img/sharp-libvips-darwin-x64": "1.2.3", + "@img/sharp-libvips-linux-arm": "1.2.3", + "@img/sharp-libvips-linux-arm64": "1.2.3", + "@img/sharp-libvips-linux-ppc64": "1.2.3", + "@img/sharp-libvips-linux-s390x": "1.2.3", + "@img/sharp-libvips-linux-x64": "1.2.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", + "@img/sharp-libvips-linuxmusl-x64": "1.2.3", + "@img/sharp-linux-arm": "0.34.4", + "@img/sharp-linux-arm64": "0.34.4", + "@img/sharp-linux-ppc64": "0.34.4", + "@img/sharp-linux-s390x": "0.34.4", + "@img/sharp-linux-x64": "0.34.4", + "@img/sharp-linuxmusl-arm64": "0.34.4", + "@img/sharp-linuxmusl-x64": "0.34.4", + "@img/sharp-wasm32": "0.34.4", + "@img/sharp-win32-arm64": "0.34.4", + "@img/sharp-win32-ia32": "0.34.4", + "@img/sharp-win32-x64": "0.34.4", + "detect-libc": "^2.1.0", + "semver": "^7.7.2" + } + } + } + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", diff --git a/package.json b/package.json index 855f01083a..97bc7d50d4 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "netlify-cli": "23.9.2", "next": "^15.0.0-canary.28", "next-with-cache-handler-v2": "npm:next@15.3.0-canary.13", + "next-with-cache-handler-v3": "npm:next@16.0.0-beta.0", "os": "^0.1.2", "outdent": "^0.8.0", "p-limit": "^6.0.0", diff --git a/src/run/handlers/request-context.cts b/src/run/handlers/request-context.cts index 9aabb7ca0a..fd8a13139e 100644 --- a/src/run/handlers/request-context.cts +++ b/src/run/handlers/request-context.cts @@ -21,6 +21,7 @@ export type RequestContext = { serverTiming?: string routeHandlerRevalidate?: NetlifyCachedRouteValue['revalidate'] pageHandlerRevalidate?: NetlifyCachedRouteValue['revalidate'] + ongoingRevalidations?: Map> /** * Track promise running in the background and need to be waited for. * Uses `context.waitUntil` if available, otherwise stores promises to diff --git a/src/run/handlers/tags-handler.cts b/src/run/handlers/tags-handler.cts index 3f896b6722..f354ab3d58 100644 --- a/src/run/handlers/tags-handler.cts +++ b/src/run/handlers/tags-handler.cts @@ -214,10 +214,30 @@ export function markTagsAsStaleAndPurgeEdgeCache( ) { const tags = getCacheTagsFromTagOrTags(tagOrTags) + // Next.js is calling classic CacheHandler.revalidateTag and 'use cache' CacheHandler expireTags/updateTags separately + // this results in duplicate work being done (it doesn't cause problems, but it is inefficient) + // See https://github.com/vercel/next.js/blob/8cab15c0c947a71eb8606ba29da719a2e121fc88/packages/next/src/server/revalidation-utils.ts#L170-L180 + // Deduping those within context of a single request might catch unrelated invalidations, so instead of using just request context + // we will check if they happened in same event loop tick as well. + const revalidationKey = JSON.stringify({ tags, durations }) + const requestContext = getRequestContext() + + if (requestContext) { + const ongoingRevalidation = requestContext.ongoingRevalidations?.get(revalidationKey) + if (ongoingRevalidation) { + // If we already have an ongoing revalidation for this key, we can use it + return ongoingRevalidation + } + } + const revalidateTagPromise = doRevalidateTagAndPurgeEdgeCache(tags, durations) - const requestContext = getRequestContext() if (requestContext) { + requestContext.ongoingRevalidations ??= new Map() + requestContext.ongoingRevalidations.set(revalidationKey, revalidateTagPromise) + process.nextTick(() => { + requestContext.ongoingRevalidations?.delete(revalidationKey) + }) requestContext.trackBackgroundWork(revalidateTagPromise) } diff --git a/src/run/handlers/use-cache-handler.ts b/src/run/handlers/use-cache-handler.ts index 510a2087b5..0f0d7a7d4a 100644 --- a/src/run/handlers/use-cache-handler.ts +++ b/src/run/handlers/use-cache-handler.ts @@ -5,14 +5,16 @@ import type { CacheEntry, // only supporting latest variant (https://github.com/vercel/next.js/pull/76687) // first released in v15.3.0-canary.13 - CacheHandlerV2 as CacheHandler, + CacheHandlerV2, } from 'next-with-cache-handler-v2/dist/server/lib/cache-handlers/types.js' +import type { CacheHandler as CacheHandlerWithUpdateTag } from 'next-with-cache-handler-v3/dist/server/lib/cache-handlers/types.js' import { getLogger } from './request-context.cjs' import { getMostRecentTagExpirationTimestamp, isAnyTagStaleOrExpired, markTagsAsStaleAndPurgeEdgeCache, + RevalidateTagDurations, } from './tags-handler.cjs' import { getTracer } from './tracer.cjs' @@ -38,6 +40,8 @@ type PrivateCacheEntry = { type CacheHandleLRUCache = LRUCache type PendingSets = Map> +type MultiVersionCacheHandler = CacheHandlerV2 & CacheHandlerWithUpdateTag + const LRU_CACHE_GLOBAL_KEY = Symbol.for('nf-use-cache-handler-lru-cache') const PENDING_SETS_GLOBAL_KEY = Symbol.for('nf-use-cache-handler-pending-sets') const cacheHandlersSymbol = Symbol.for('@next/cache-handlers') @@ -51,8 +55,8 @@ const extendedGlobalThis = globalThis as typeof globalThis & { // Used by Next.js to provide implementation of cache handlers [cacheHandlersSymbol]?: { - RemoteCache?: CacheHandler - DefaultCache?: CacheHandler + RemoteCache?: MultiVersionCacheHandler + DefaultCache?: MultiVersionCacheHandler } } @@ -86,10 +90,10 @@ function getPendingSets(): PendingSets { const tmpResolvePendingBeforeCreatingAPromise = () => {} export const NetlifyDefaultUseCacheHandler = { - get(cacheKey: string): ReturnType { + get(cacheKey: string): ReturnType { return getTracer().withActiveSpan( 'DefaultUseCacheHandler.get', - async (span): ReturnType => { + async (span): ReturnType => { getLogger().withFields({ cacheKey }).debug(`[NetlifyDefaultUseCacheHandler] get`) span.setAttributes({ cacheKey, @@ -127,45 +131,54 @@ export const NetlifyDefaultUseCacheHandler = { return undefined } - const { stale } = await isAnyTagStaleOrExpired(entry.tags, entry.timestamp) + const { stale, expired } = await isAnyTagStaleOrExpired(entry.tags, entry.timestamp) - if (stale) { + if (expired) { getLogger() - .withFields({ cacheKey, ttl, status: 'STALE BY TAG' }) + .withFields({ cacheKey, ttl, status: 'EXPIRED BY TAG' }) .debug(`[NetlifyDefaultUseCacheHandler] get result`) span.setAttributes({ - cacheStatus: 'stale tag, discarded', + cacheStatus: 'expired tag, discarded', ttl, }) return undefined } + let { revalidate, value } = entry + if (stale) { + revalidate = -1 + } + // returning entry will cause stream to be consumed // so we need to clone it first, so in-memory cache can // be used again - const [returnStream, newSaved] = entry.value.tee() + const [returnStream, newSaved] = value.tee() entry.value = newSaved getLogger() - .withFields({ cacheKey, ttl, status: 'HIT' }) + .withFields({ cacheKey, ttl, status: stale ? 'STALE' : 'HIT' }) .debug(`[NetlifyDefaultUseCacheHandler] get result`) span.setAttributes({ - cacheStatus: 'hit', + cacheStatus: stale ? 'stale' : 'hit', ttl, }) return { ...entry, + revalidate, value: returnStream, } }, ) }, - set(cacheKey: string, pendingEntry: Promise): ReturnType { + set( + cacheKey: string, + pendingEntry: Promise, + ): ReturnType { return getTracer().withActiveSpan( 'DefaultUseCacheHandler.set', - async (span): ReturnType => { + async (span): ReturnType => { getLogger().withFields({ cacheKey }).debug(`[NetlifyDefaultUseCacheHandler]: set`) span.setAttributes({ cacheKey, @@ -223,10 +236,15 @@ export const NetlifyDefaultUseCacheHandler = { // we would need to check more tags than current request needs // while blocking pipeline }, - getExpiration: function (...tags: string[]): ReturnType { + getExpiration: function ( + // supporting both (...tags: string[]) and (tags: string[]) signatures + ...notNormalizedTags: string[] | string[][] + ): ReturnType { return getTracer().withActiveSpan( 'DefaultUseCacheHandler.getExpiration', - async (span): ReturnType => { + async (span): ReturnType => { + const tags = notNormalizedTags.flat() + span.setAttributes({ tags, }) @@ -244,10 +262,11 @@ export const NetlifyDefaultUseCacheHandler = { }, ) }, - expireTags(...tags: string[]): ReturnType { + // this is for CacheHandlerV2 + expireTags(...tags: string[]): ReturnType { return getTracer().withActiveSpan( 'DefaultUseCacheHandler.expireTags', - async (span): ReturnType => { + async (span): ReturnType => { getLogger().withFields({ tags }).debug(`[NetlifyDefaultUseCacheHandler] expireTags`) span.setAttributes({ tags, @@ -257,7 +276,26 @@ export const NetlifyDefaultUseCacheHandler = { }, ) }, -} satisfies CacheHandler + // this is for CacheHandlerV3 / Next 16 + updateTags( + tags: string[], + durations: RevalidateTagDurations, + ): ReturnType { + return getTracer().withActiveSpan( + 'DefaultUseCacheHandler.updateTags', + async (span): ReturnType => { + getLogger() + .withFields({ tags, durations }) + .debug(`[NetlifyDefaultUseCacheHandler] updateTags`) + span.setAttributes({ + tags, + durations: JSON.stringify(durations), + }) + await markTagsAsStaleAndPurgeEdgeCache(tags, durations) + }, + ) + }, +} satisfies MultiVersionCacheHandler export function configureUseCacheHandlers() { extendedGlobalThis[cacheHandlersSymbol] = { diff --git a/tests/fixtures/use-cache/app/api/revalidate/[...slug]/route.ts b/tests/fixtures/use-cache/app/api/revalidate/[...slug]/route.ts index 519d5c0267..56e22416c2 100644 --- a/tests/fixtures/use-cache/app/api/revalidate/[...slug]/route.ts +++ b/tests/fixtures/use-cache/app/api/revalidate/[...slug]/route.ts @@ -9,8 +9,12 @@ export async function GET(request: NextRequest, { params }) { const { slug } = await params const tagToInvalidate = slug.join('/') + let profile = undefined + if (request.nextUrl.searchParams.has('expire')) { + profile = { expire: parseInt(request.nextUrl.searchParams.get('expire')) } + } - revalidateTag(tagToInvalidate) + revalidateTag(tagToInvalidate, profile) return Response.json({ tagToInvalidate }) } diff --git a/tests/fixtures/use-cache/app/default/use-cache-component/dynamic/ttl-1year/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-component/dynamic/ttl-1year/[slug]/page.tsx index b6cb766e3e..024b115a88 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-component/dynamic/ttl-1year/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-component/dynamic/ttl-1year/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, getDataImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-component/dynamic/ttl-5seconds/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-component/dynamic/ttl-5seconds/[slug]/page.tsx index 2376bcefa5..52498d28a9 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-component/dynamic/ttl-5seconds/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-component/dynamic/ttl-5seconds/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, getDataImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-component/static/ttl-10seconds/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-component/static/ttl-10seconds/[slug]/page.tsx index 4e79023f1d..317b652200 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-component/static/ttl-10seconds/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-component/static/ttl-10seconds/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, generateStaticParamsImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-component/static/ttl-1year/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-component/static/ttl-1year/[slug]/page.tsx index 63fe621296..7c5d306a6b 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-component/static/ttl-1year/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-component/static/ttl-1year/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, generateStaticParamsImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-data/dynamic/ttl-1year/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-data/dynamic/ttl-1year/[slug]/page.tsx index f07a3e05e4..8733d513ec 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-data/dynamic/ttl-1year/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-data/dynamic/ttl-1year/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, getDataImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-data/dynamic/ttl-5seconds/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-data/dynamic/ttl-5seconds/[slug]/page.tsx index 25517481fd..e00d29689d 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-data/dynamic/ttl-5seconds/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-data/dynamic/ttl-5seconds/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, getDataImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-data/static/ttl-10seconds/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-data/static/ttl-10seconds/[slug]/page.tsx index 32374f0910..ae05c72f12 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-data/static/ttl-10seconds/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-data/static/ttl-10seconds/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, generateStaticParamsImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-data/static/ttl-1year/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-data/static/ttl-1year/[slug]/page.tsx index 4da6621b65..f83ba80ec6 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-data/static/ttl-1year/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-data/static/ttl-1year/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, generateStaticParamsImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-page/dynamic/ttl-1year/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-page/dynamic/ttl-1year/[slug]/page.tsx index 416e2d9ac5..4c4ef7b1a2 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-page/dynamic/ttl-1year/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-page/dynamic/ttl-1year/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, getDataImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-page/dynamic/ttl-5seconds/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-page/dynamic/ttl-5seconds/[slug]/page.tsx index a4939f2597..0a9e3c3426 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-page/dynamic/ttl-5seconds/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-page/dynamic/ttl-5seconds/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, getDataImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-page/static/ttl-10seconds/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-page/static/ttl-10seconds/[slug]/page.tsx index bc50627f89..1e99da84fe 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-page/static/ttl-10seconds/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-page/static/ttl-10seconds/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, generateStaticParamsImplementation, diff --git a/tests/fixtures/use-cache/app/default/use-cache-page/static/ttl-1year/[slug]/page.tsx b/tests/fixtures/use-cache/app/default/use-cache-page/static/ttl-1year/[slug]/page.tsx index ed6c3e68dc..7552666d96 100644 --- a/tests/fixtures/use-cache/app/default/use-cache-page/static/ttl-1year/[slug]/page.tsx +++ b/tests/fixtures/use-cache/app/default/use-cache-page/static/ttl-1year/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache' +import { cacheLife, cacheTag } from '../../../../../next-cache' import { BasePageComponentProps, generateStaticParamsImplementation, diff --git a/tests/fixtures/use-cache/app/next-cache.ts b/tests/fixtures/use-cache/app/next-cache.ts new file mode 100644 index 0000000000..d761050c98 --- /dev/null +++ b/tests/fixtures/use-cache/app/next-cache.ts @@ -0,0 +1,20 @@ +import * as NextCacheTyped from 'next/cache' + +const NextCache = NextCacheTyped as any + +export const cacheLife: any = + 'cacheLife' in NextCache + ? NextCache.cacheLife + : 'unstable_cacheLife' in NextCache + ? NextCache.unstable_cacheLife + : () => { + throw new Error('both unstable_cacheLife and cacheLife are missing from next/cache') + } +export const cacheTag: any = + 'cacheTag' in NextCache + ? NextCache.cacheTag + : 'unstable_cacheTag' in NextCache + ? NextCache.unstable_cacheTag + : () => { + throw new Error('both unstable_cacheTag and cacheTag are missing from next/cache') + } diff --git a/tests/integration/use-cache.test.ts b/tests/integration/use-cache.test.ts index 93d22b1b90..558e165445 100644 --- a/tests/integration/use-cache.test.ts +++ b/tests/integration/use-cache.test.ts @@ -290,6 +290,54 @@ describe.skipIf(!nextVersionSatisfies('>=15.3.0-canary.13'))('use cache', () => pageComponentTimeShouldBeEqual: false, }) }) + + test.skipIf(!nextVersionSatisfies('>=16.0.0-alpha.0'))( + 'invalidating tag with SWR on one lambda result in invalidating them on all lambdas', + async () => { + const url = `${routeRoot}/different-lambdas-tag-invalidation` + + const { invokeFunction: invokeFunctionLambda1 } = await loadSandboxedFunction(ctx) + const { invokeFunction: invokeFunctionLambda2 } = await loadSandboxedFunction(ctx) + + const call1 = await invokeFunctionLambda1({ url }) + expect(call1).not.toBeCacheableResponse() + + await invokeFunctionLambda2({ + url: `/api/revalidate/${useCacheTagPrefix}/${url}?expire=5`, + }) + + const call2 = await invokeFunctionLambda1({ url }) + expect(call2).toHaveExpectedCachingBehavior( + call1, + // if we hit before 5 second expire timeframe passes, we expect to get stale response + expectedCachingBehaviorWhenUseCacheRegenerates, + ) + + const call3 = await invokeFunctionLambda1({ url }) + expect(call3).toHaveExpectedCachingBehavior(call2, { + // previous request should trigger revalidation in background and cause everything to be fresh on this request + getDataTimeShouldBeEqual: false, + resultWrapperComponentTimeShouldBeEqual: false, + pageComponentTimeShouldBeEqual: false, + }) + + await invokeFunctionLambda2({ + url: `/api/revalidate/${useCacheTagPrefix}/${url}?expire=5`, + }) + + // let's sleep for expire period to test that expire period is honored + await new Promise((resolve) => setTimeout(resolve, 6000)) + + const call4 = await invokeFunctionLambda1({ url }) + expect(call4).toHaveExpectedCachingBehavior(call3, { + // we are not getting stale response here because we issued request after expire period + // so everything should be fresh + getDataTimeShouldBeEqual: false, + resultWrapperComponentTimeShouldBeEqual: false, + pageComponentTimeShouldBeEqual: false, + }) + }, + ) }) describe('TTL=5 seconds', () => { diff --git a/tests/utils/create-e2e-fixture.ts b/tests/utils/create-e2e-fixture.ts index a03be0fe05..0af1e20a1d 100644 --- a/tests/utils/create-e2e-fixture.ts +++ b/tests/utils/create-e2e-fixture.ts @@ -542,12 +542,18 @@ export const fixtureFactories = { packagePath: 'apps/next-app', buildCommand: 'nx run next-app:build', publishDirectory: 'dist/apps/next-app/.next', + env: { + NX_ISOLATE_PLUGINS: 'false', + }, }), nxIntegratedDistDir: () => createE2EFixture('nx-integrated', { packagePath: 'apps/custom-dist-dir', buildCommand: 'nx run custom-dist-dir:build', publishDirectory: 'dist/apps/custom-dist-dir/dist', + env: { + NX_ISOLATE_PLUGINS: 'false', + }, }), cliBeforeRegionalBlobsSupport: () => createE2EFixture('cli-before-regional-blobs-support', { From cbdd9dae10dbc24860c1ec91701f2987aa6f8b89 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:06:57 +0200 Subject: [PATCH 4/4] chore(main): release 5.14.1 (#3186) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7fb4b5aae6..ee2c4a94f6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "5.14.0" + ".": "5.14.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index e39e6faf57..386e690800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [5.14.1](https://github.com/opennextjs/opennextjs-netlify/compare/v5.14.0...v5.14.1) (2025-10-21) + + +### Bug Fixes + +* support revalidateTag SWR in 'use cache' handler ([#3180](https://github.com/opennextjs/opennextjs-netlify/issues/3180)) ([a90d2e5](https://github.com/opennextjs/opennextjs-netlify/commit/a90d2e5228bbb77bf657929f83729945480d83e5)) + ## [5.14.0](https://github.com/opennextjs/opennextjs-netlify/compare/v5.13.5...v5.14.0) (2025-10-14) diff --git a/package-lock.json b/package-lock.json index 0349d4fc9a..34d7ff88d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@netlify/plugin-nextjs", - "version": "5.14.0", + "version": "5.14.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@netlify/plugin-nextjs", - "version": "5.14.0", + "version": "5.14.1", "license": "MIT", "devDependencies": { "@fastly/http-compute-js": "1.1.5", diff --git a/package.json b/package.json index 97bc7d50d4..8d00004c21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@netlify/plugin-nextjs", - "version": "5.14.0", + "version": "5.14.1", "description": "Run Next.js seamlessly on Netlify", "main": "./dist/index.js", "type": "module",