Commit Graph

1 Commits

Author SHA1 Message Date
Divanshu Chauhan (divkix) d9a5e63c32 refactor(pages): extract render orchestrator from codegen string (#1784) (#1805)
* refactor(pages): extract render orchestrator from codegen string (#1784)

Move `_renderPage` (~260 lines) and `collectAssetTags` (~85 lines) out
of the generated template string in `entries/pages-server-entry.ts` into
typed, unit-testable server modules:

- `server/pages-page-handler.ts` — `createPagesPageHandler` factory that
  owns the full Pages Router render lifecycle (i18n, route matching,
  404/500 fallback recursion, _next/data envelope, 405 method check,
  ISR cache-key derivation, SSR-context setup). Mirrors how
  `server/app-rsc-handler.ts` is structured relative to
  `entries/app-rsc-entry.ts`.

- `server/pages-asset-tags.ts` — `collectAssetTags` + manifest helpers,
  extracted from the template so they can be unit-tested directly.

- `server/pages-data-route.ts` — adds `normalizePagesDataRequest` so both
  `renderPage` and `runMiddleware` share one implementation instead of
  duplicating the buildId-check logic in the template string.

`entries/pages-server-entry.ts` is now thin wiring: route-table codegen,
embedded config/i18n/buildId, and closures that delegate to the handler.
`renderPage` keeps its exact exported signature; all callers are unaffected.

No behavior change — pure code motion. Fixed a latent bug where the
`isrCacheKey` wrapper in the handler was missing the `buildId` argument on
non-i18n paths (causing a cache-key mismatch); caught by the existing
ISR CSP-nonce test.

* refactor(pages): tighten handler types and improve tests

- Use ComponentType from react for AppComponent, DocumentComponent, and
  PageComponent closures instead of unknown — matches pages-page-response.ts
  which already uses ComponentType. Eliminates the DocumentComponent cast.

- Widen isrCacheKey router param from literal union to string — the literal
  union forced as-casts everywhere it was used indirectly. All call sites
  pass 'pages' or 'app' string literals so the widening is safe.

- Replace the shallow i18n redirect test (which just checked a route miss
  gave 404) with a test that actually exercises the 307 short-circuit:
  visiting / with Accept-Language: fr triggers resolvePagesI18nRequest to
  return redirectUrl and the handler returns 307 to /fr.

- Add second i18n test: locale prefix already present → no redirect.

- Tighten 'allows POST with gSSP' test: assert no Allow header (confirms
  the 405 guard was bypassed, not just that some non-405 came back).
2026-06-07 22:18:12 +01:00