[P2/high] chore(web): bump Next.js 14→15, migrate async request APIs#179
[P2/high] chore(web): bump Next.js 14→15, migrate async request APIs#179cipher813 wants to merge 2 commits into
Conversation
…s#138) Next 15 makes cookies(), headers(), params, and searchParams asynchronous. Bump next 14.2.35 -> 15.5.20 and eslint-config-next to match (React kept at 18.3.1). Ran the official `next-async-request-api` codemod, then a manual per-route pass over all 19 param/searchParam pages plus the cookies()/headers() call sites. - 19 app/**/page.tsx: params/searchParams typed as Promise<...> and awaited; two former sync redirect pages (today, transactions) converted to async. - lib/session.ts: await headers() / await cookies(). - components/demo-banner.tsx: await cookies(). - lib/entitlements.ts: previewFromCookies() made async (await cookies()); callers in page.tsx and markets-action.ts updated to await it. Replaced the codemod's UnsafeUnwrappedCookies cast, which would have thrown at runtime. Validation (web/, Node 18.20.8): `npx tsc --noEmit` clean, `npm run lint` clean, `npm run build` succeeds (all 27 routes). Closes the remaining next@14.2.35 Dependabot alerts (npm audit: 0 vulnerabilities post-bump). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
🤖 [Auto-sweep] Merge conflict due to feature development on main (LiveValuationProvider, SettledRefresher, SessionPanel, etc.) after this branch was created. This PR needs a careful rebase to incorporate both the async API migration (Next.js 15) and main's new feature components. Converted to DRAFT for manual rebase. |
|
✅ Merge conflict resolved This PR's merge conflict in
Ready to merge once the status index updates. |
|
[GROOM-SWEEP] Conflict detected: Next.js 14→15 refactor + page hierarchy restructuring. 6 files changed; 2 files have merge conflicts (holdings/page.tsx and [id]/page.tsx). The conflict is non-trivial: MAIN moved holdings to be the portfolio landing page (metron-ops-I156 redirect), while HEAD has the full page logic. This requires deliberate 3-way resolution that understands the new routing. MARKED DRAFT: needs manual resolution or rebase against latest main. |
|
Sweep: Complex conflict — needs human judgment Merge conflict in The PR branch refactors the portfolios page structure while main recently merged holdings-as-home (PR #199). These are architecturally conflicting changes that need careful reconciliation beyond mechanical merge resolution. Blocker: Requires manual conflict resolution understanding both the refactoring intent and the holdings-as-home changes. Converting to DRAFT with gate:live-run label pending resolution. |
…-params migration on top of shipped Holdings-is-home (metron-ops-I156) restructuring Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Priority: P2 · Complexity: high
Closes nousergon/metron-ops#138
Bumps the Metron web app (
web/) from Next.js 14.2.35 → 15.5.20 and migrates the App Router to Next 15's asynchronous request APIs. React is kept at 18.3.1 to minimize blast radius (Next 15 supports React 18).eslint-config-nextbumped to 15.5.20 to match.Dependabot alerts this should clear
The remaining 5 high-severity alerts originate from
next@14.2.35itself (not transitive — those were handled in #174). Bumping to 15.5.20 moves the app past every publishednext14.x advisory range.npm audit --omit=devreports 0 vulnerabilities after the bump (was 1 high on 14.2.35). Note: the CI/Dependabot API is not readable from this runner's token, so the exact alert numbers should be confirmed on the Security tab once merged.Migration approach
npx @next/codemod@latest next-async-request-api .(22 files touched).previewFromCookies— see below).Per-route changes (19 pages —
params/searchParamsnowPromise<...>, awaited)app/portfolios/[id]/page.tsxapp/portfolios/[id]/watchlist/page.tsxapp/portfolios/[id]/today/page.tsx(was sync → nowasync)app/portfolios/[id]/transactions/page.tsx(was sync → nowasync)app/portfolios/[id]/tax/page.tsxapp/portfolios/[id]/risk/page.tsxapp/portfolios/[id]/performance/page.tsxapp/portfolios/[id]/holdings/page.tsxapp/portfolios/[id]/attribution/page.tsxapp/portfolios/[id]/calendar/page.tsxapp/portfolios/[id]/alpha-engine/page.tsxapp/portfolios/[id]/advisor/page.tsxapp/portfolios/[id]/advisor/profile/page.tsxapp/portfolios/[id]/macro/page.tsxapp/portfolios/[id]/crypto/page.tsxapp/portfolios/[id]/research-intel/page.tsxapp/portfolios/[id]/settings/page.tsxapp/portfolios/[id]/tearsheet/[ticker]/page.tsxapp/portfolios/[id]/accounts/[accountId]/page.tsxcookies()/headers()call siteslib/session.ts—await headers()ingetSession,await cookies()inrequireTenantId.components/demo-banner.tsx—await cookies().lib/entitlements.ts—previewFromCookies()madeasync(await cookies()). The codemod had left it sync with anUnsafeUnwrappedCookiescast, which type-checks but would throw / read undefined at runtime under Next 15. Its two callers were updated to await it:app/portfolios/[id]/page.tsxandapp/portfolios/[id]/markets-action.ts.app/demo/route.ts,app/api/auth/[...all]/route.ts) use request/response-scoped cookies (NextResponse.cookies) — unaffected by the async change; left unchanged.useSearchParams()(account-panel.tsx,holdings-view.tsx) are unaffected.Validation (run in
web/, Node 18.20.8 / npm 10.8.2)npx tsc --noEmitnpm run lintnpm run buildAlso grepped for any remaining synchronous
cookies()/headers()/draftMode()access not preceded byawait— none remain (only comments).Why this is a DRAFT (
gate:live-run)tsc cannot catch runtime
params/searchParamsbreakage, and this repo auto-deploys on merge to main. Full runtime verification of every route against real infra was not possible here:engines: node >=20. CI/prod should run on Node 20+.better-sqlite3(native) had to benpm rebuild-ed from a prebuilt binary in this sandbox; a clean prod install should compile it normally.npm test(vitest 4 / rolldown) fails to start on Node 18 (node:util.styleTextneeds Node 20+) — unrelated to this change and not run as a gate.One command Brian runs to validate (on Node 20+, real env)
🤖 Generated with Claude Code