Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions .changeset/act-event-compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@tanstack/redact": patch
---

Flush renderer work and effects through the public act utility, including nested and awaited scopes, and preserve synchronous errors. Share the implementation with react-dom/test-utils.

Correct pointer-capture event names, bubble focus and blur handlers, and accept native change events for text fields without repeating an input notification.
11 changes: 11 additions & 0 deletions .changeset/next-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@tanstack/redact": minor
---

Add `withRedact` for Next.js 15.5 and 16.0 through 16.4 with Turbopack and Webpack. Keep native React for server rendering and Server Components while Redact renders in the browser. Support both routers, Cache Components, streamed Suspense, hydration IDs, async actions, forms, metadata, and Fast Refresh.

Keep visible transitions independent of suspended hidden Activity trees, preserve retained DOM and effect lifecycles, and expose promised children in the public types. Keep action hooks and pending transition inspection working with React DevTools. Reduce shared runtime code so both the full client and default Vite client remain below their pre-integration bundle limits.

Require complete packed-package compatibility checks across all pinned versions, three browser engines, development, production, standalone output, and static export before release publication. Reject prerelease and untested Next.js minor versions at configuration time.

Correct Next 16.2 development cache detection through a version-scoped browser loader, preserving cached debug-channel replay without changing installed Next files.
11 changes: 11 additions & 0 deletions .changeset/vinext-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@tanstack/redact": minor
---

Add a Vinext browser adapter that keeps native React for SSR and Server Components. Resolve browser entries per Vite environment so server imports remain intact.

Retain committed content during suspended transitions and deferred updates, rebase urgent and transition updates in source order, and preserve error boundaries and class callbacks. Preserve hydration, refs, controlled and uncontrolled form resets, and the existing bundle limits.

Require paired native React and Redact verification from an unpatched npm install. Cover mixed App and Pages Router apps and separate Pages-only apps across Node, standalone output, static export, and local Workers in Chromium, Firefox, and WebKit. Use stable Cloudflare tooling and keep setup, browser, and completeness failures in the release gate.

Ship maintained Vinext module-identity and Pages data corrections, plus an optional Cloudflare integration with the development evaluator fix. Keep native React controls on the same corrected platform. Validate development Flight timing bounds without suppressing real application errors. Upgrade the verification toolchain to the published Undici and fflate security fixes through standard dependency overrides.
167 changes: 167 additions & 0 deletions .github/workflows/next.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
name: Next compatibility

on:
workflow_call:
workflow_dispatch:

permissions:
contents: read

jobs:
next:
name: Next ${{ matrix.version }} (${{ matrix.rendering }}, ${{ matrix.bundler }}, ${{ matrix.mode }})
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
version: ['15.5.28', '16.0.11', '16.1.7', '16.2.12', '16.3.8', '16.4.3']
bundler: [turbopack, webpack]
mode: [development, production]
rendering: [standard, cache-components]
exclude:
- version: '15.5.28'
rendering: cache-components
env:
PLAYWRIGHT_CHANNEL: chromium
NEXT_TELEMETRY_DISABLED: '1'
NEXT_TEST_CACHE_COMPONENTS: ${{ matrix.rendering == 'cache-components' && '1' || '0' }}
NEXT_TEST_TRACE: ${{ matrix.mode == 'development' && matrix.bundler == 'webpack' && '1' || '' }}
steps:
- name: Set test paths
run: |
echo "NEXT_TEST_DIR=$RUNNER_TEMP/redact-next" >> "$GITHUB_ENV"
echo "NEXT_TEST_RESULT=$RUNNER_TEMP/next-results/${{ matrix.version }}-${{ matrix.rendering }}-${{ matrix.bundler }}-${{ matrix.mode }}.json" >> "$GITHUB_ENV"
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Tools
uses: TanStack/config/.github/setup@e4b48f16568324f76f467aa4c2aac2f05db632c3
- name: Build Redact
run: pnpm build
- name: Install browsers
run: pnpm exec playwright install --with-deps chromium firefox webkit
- name: Prepare packed fixture
id: fixture
run: node scripts/prepare-next-fixture.mjs ${{ matrix.version }} "$NEXT_TEST_DIR" next-demo ${{ matrix.rendering }}
- name: Verify browser actions
if: matrix.version == '16.4.3' && matrix.bundler == 'turbopack' && matrix.mode == 'development' && matrix.rendering == 'cache-components'
run: |
status=0
for browser in chromium firefox webkit; do
PLAYWRIGHT_BROWSER=$browser pnpm test:browser:actions || status=1
PLAYWRIGHT_BROWSER=$browser node scripts/test-browser-lifecycle.mjs || status=1
PLAYWRIGHT_BROWSER=$browser node scripts/test-browser-reload.mjs || status=1
done
exit "$status"
- name: Verify Next.js
id: verify
if: ${{ !cancelled() && steps.fixture.outcome == 'success' }}
run: node scripts/test-next.mjs ${{ matrix.mode == 'production' && '--production' || '' }} ${{ matrix.bundler == 'webpack' && '--webpack' || '' }}
- name: Compare failing cases with native React
if: ${{ !cancelled() && steps.verify.outcome == 'failure' }}
run: node scripts/test-next-controls.mjs ${{ matrix.mode == 'production' && '--production' || '' }} ${{ matrix.bundler == 'webpack' && '--webpack' || '' }}
- name: Save native React diagnostics
if: ${{ !cancelled() && steps.verify.outcome == 'failure' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9
with:
name: native-next-${{ matrix.version }}-${{ matrix.rendering }}-${{ matrix.bundler }}-${{ matrix.mode }}
path: ${{ env.NEXT_TEST_RESULT }}.native.json
if-no-files-found: warn
- name: Save compatibility results
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: next-${{ matrix.version }}-${{ matrix.rendering }}-${{ matrix.bundler }}-${{ matrix.mode }}
path: ${{ env.NEXT_TEST_RESULT }}
if-no-files-found: error

next-deployment:
name: Next ${{ matrix.version }} (${{ matrix.rendering }}, ${{ matrix.deployment }}, ${{ matrix.bundler }})
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
version: ['15.5.28', '16.4.3']
bundler: [turbopack, webpack]
deployment: [standalone, static-export]
rendering: [standard, cache-components]
exclude:
- version: '15.5.28'
rendering: cache-components
- deployment: static-export
rendering: cache-components
env:
NEXT_TELEMETRY_DISABLED: '1'
NEXT_TEST_BASE_PATH: /coverage
NEXT_TEST_CACHE_COMPONENTS: ${{ matrix.rendering == 'cache-components' && '1' || '0' }}
steps:
- name: Set test paths
run: |
echo "NEXT_TEST_DIR=$RUNNER_TEMP/redact-next-deployment" >> "$GITHUB_ENV"
echo "NEXT_TEST_RESULT=$RUNNER_TEMP/next-results/${{ matrix.version }}-${{ matrix.rendering }}-${{ matrix.bundler }}-${{ matrix.deployment }}.json" >> "$GITHUB_ENV"
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false
- name: Setup Tools
uses: TanStack/config/.github/setup@e4b48f16568324f76f467aa4c2aac2f05db632c3
- name: Build Redact
run: pnpm build
- name: Install browsers
run: pnpm exec playwright install --with-deps chromium firefox webkit
- name: Prepare packed fixture
run: node scripts/prepare-next-fixture.mjs ${{ matrix.version }} "$NEXT_TEST_DIR" ${{ matrix.deployment == 'static-export' && 'next-static' || 'next-demo' }} ${{ matrix.rendering }}
- name: Verify standalone output
id: verify
if: matrix.deployment == 'standalone'
run: node scripts/test-next.mjs --production --standalone ${{ matrix.bundler == 'webpack' && '--webpack' || '' }}
- name: Verify static output
if: matrix.deployment == 'static-export'
run: node scripts/test-next-static.mjs ${{ matrix.bundler == 'webpack' && '--webpack' || '' }}
- name: Compare failing cases with native React
if: ${{ !cancelled() && steps.verify.outcome == 'failure' }}
run: node scripts/test-next-controls.mjs --production --standalone ${{ matrix.bundler == 'webpack' && '--webpack' || '' }}
- name: Save native React diagnostics
if: ${{ !cancelled() && steps.verify.outcome == 'failure' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9
with:
name: native-next-${{ matrix.version }}-${{ matrix.rendering }}-${{ matrix.bundler }}-${{ matrix.deployment }}
path: ${{ env.NEXT_TEST_RESULT }}.native.json
if-no-files-found: warn
- name: Save compatibility results
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: next-${{ matrix.version }}-${{ matrix.rendering }}-${{ matrix.bundler }}-${{ matrix.deployment }}
path: ${{ env.NEXT_TEST_RESULT }}
if-no-files-found: error

next-coverage:
name: Next coverage report
needs: [next, next-deployment]
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false
- name: Download compatibility results
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: next-*
path: ${{ runner.temp }}/next-results
merge-multiple: true
- name: Require the complete matrix
run: node scripts/report-next-coverage.mjs "$RUNNER_TEMP/next-results"
- name: Save coverage report
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: next-coverage-report
path: ${{ runner.temp }}/next-results/coverage.json
if-no-files-found: error
6 changes: 6 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@ jobs:
uses: TanStack/config/.github/setup@e4b48f16568324f76f467aa4c2aac2f05db632c3
- name: Run Checks
run: pnpm run test:pr

next-compatibility:
uses: ./.github/workflows/next.yml

vinext-compatibility:
uses: ./.github/workflows/vinext.yml
11 changes: 11 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,19 @@ permissions:
pull-requests: write

jobs:
next-compatibility:
uses: ./.github/workflows/next.yml
permissions:
contents: read

vinext-compatibility:
uses: ./.github/workflows/vinext.yml
permissions:
contents: read

release:
name: Release
needs: [next-compatibility, vinext-compatibility]
if: github.repository_owner == 'TanStack'
runs-on: ubuntu-latest
steps:
Expand Down
57 changes: 57 additions & 0 deletions .github/workflows/vinext.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Vinext compatibility

on:
workflow_dispatch:
workflow_call:

concurrency:
group: ${{ github.workflow }}-vinext-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
verify:
runs-on: ubuntu-latest
timeout-minutes: 60
env:
NEXT_TELEMETRY_DISABLED: '1'
VINEXT_TEST_CONCURRENCY: '2'
steps:
- name: Set test paths
run: |
echo "VINEXT_TEST_RESULTS=$RUNNER_TEMP/vinext-results" >> "$GITHUB_ENV"
echo "VINEXT_TEST_CONSUMER=$RUNNER_TEMP/vinext-consumer" >> "$GITHUB_ENV"
echo "VINEXT_TEST_PAGES_RESULTS=$RUNNER_TEMP/vinext-pages-results" >> "$GITHUB_ENV"
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false
- name: Setup pnpm
uses: pnpm/action-setup@739bfe42ca9233c5e6aca07c1a25a9d34aca49b0
- name: Setup Node for Cloudflare tooling
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: '24.22.0'
package-manager-cache: false
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check runtime, types, package and unchanged size limits
run: pnpm test:ci
- name: Install browsers
run: pnpm exec playwright install --with-deps chromium firefox webkit
- name: Verify both routers against native React from an unpatched npm install
run: node scripts/test-vinext-consumer.mjs
- name: Verify hosted state and cache contracts locally
if: ${{ !cancelled() }}
run: node scripts/test-vinext-hosted-state.mjs
- name: Save compatibility evidence
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9
with:
name: vinext-compatibility
path: |
${{ env.VINEXT_TEST_RESULTS }}
${{ env.VINEXT_TEST_PAGES_RESULTS }}
if-no-files-found: error
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ dist-ssr

# Local tanstack.com test copy for shim iteration
tanstack-com-test/

# The licensed Cloudflare distribution is maintained source, not build output.
!packages/redact/vendor/cloudflare-vite-plugin/dist/
!packages/redact/vendor/cloudflare-vite-plugin/dist/**
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24.14.1
24.22.0
Loading
Loading