* fix(i18n): strip locale prefix for API routes
Mirror Next.js's behaviour where a locale-prefixed request path like
`/fr/api/ok` is matched against `pages/api/ok` after stripping the
locale segment. Previously the locale prefix was kept through the
`/api/` startsWith check, so any locale-prefixed API URL 404'd.
Add a small helper `stripI18nLocaleForApiRoute(url, i18nConfig)` in
`server/pages-i18n.ts` that mirrors Next.js's
`normalizeLocalePath().pathname` (see
packages/next/src/shared/lib/i18n/normalize-locale-path.ts) and wire it
into all three Pages Router request pipelines so dev/prod parity holds:
- dev plugin: `packages/vinext/src/index.ts`
- prod (Node): `packages/vinext/src/server/prod-server.ts`
- prod (Cloudflare worker entry): `packages/vinext/src/deploy.ts`
App Router is intentionally unchanged: Next.js does not support the
`i18n` config field with App Router, so App Router route handlers
under `app/*/route.ts` never see a locale prefix to strip.
Refs #1336 (item 3). Items 2 (sticky locale on client navigations) and
4 (default-locale path normalisation) are being handled in parallel
PRs.
Tests:
- Unit tests for `stripI18nLocaleForApiRoute` covering basic, regional
(`nl-NL`), query-preserving, unconfigured-prefix, and null-config
cases (`tests/pages-i18n.test.ts`).
- Dev integration tests (`tests/features.test.ts`) and prod integration
tests (`tests/pages-i18n-prod.test.ts`) that GET `/fr/api/ok` and
assert a 200 "ok" response against the existing
`pages-i18n-domains` fixture, ported from Next.js's
`test/e2e/middleware-redirects/test/index.test.ts` ("should redirect
to api route with locale").
- Updates to `tests/deploy.test.ts` assertions for the generated
worker-entry template strings.
* test(after-deploy): update worker-entry assertion after locale strip
The Pages Router worker entry now calls handleApiRoute(request,
apiLookupUrl, ctx) instead of using resolvedUrl directly, so this
generated-code assertion needs the new variable name.
Refs #1336 (item 3).
Pages Router API routes did not receive the per-request Workers
`ExecutionContext`, so any `after()` (or other shim) call inside a
`pages/api/*` handler had no `ctx.waitUntil()` to keep the isolate
alive past the response. Thread `ctx` through `handleApiRoute`
→ `handlePagesApiRoute`, and wrap the user handler in
`runWithExecutionContext(ctx, ...)` so the ALS surfaces the ctx
for downstream `after()` calls.
Also pass a Node-shaped execution context from `vinext start` so
behavior is consistent across the dev / start / deploy server
paths.
Closes#1365