a63b89b140
### What #51394 introduced a pretty strict type of return value of route type that causing failure with `next build`. There're few ways of writing a app route, it could contain few return values based on the usage: * return a `Response` or promise of it * return `NextResponse` of promise of it, since it's extended from `Response`, same type * use `redirect()` or `notFound(), since it returns `never`, and the below code is not reached, the handler itself could still return void. e.g. using `redirect` in a `GET` route We loosed the type so `redirect()` can be still allowed without specifying the return value there. Related typescript issue: https://github.com/microsoft/TypeScript/issues/16608#issuecomment-309327984 ### How * Re-enable the bail on types / build error in the app-routes tests * Separate the tests, move runtime erroring ones to `test/e2e/app-dir/app-routes-errors` * Add new case to app-routes tests of mixed return value Closes #55623 Related #55604
77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
import type { ReadonlyHeaders } from 'next/dist/server/web/spec-extension/adapters/headers'
|
|
import type { ReadonlyRequestCookies } from 'next/dist/server/web/spec-extension/adapters/request-cookies'
|
|
|
|
const KEY = 'x-request-meta'
|
|
|
|
/**
|
|
* Adds a new header to the headers object and serializes it. To be used in
|
|
* conjunction with the `getRequestMeta` function in tests to verify request
|
|
* data from the handler.
|
|
*
|
|
* @param meta metadata to inject into the headers
|
|
* @param headers the existing headers on the response to merge with
|
|
* @returns the merged headers with the request meta added
|
|
*/
|
|
export function withRequestMeta(
|
|
meta: Record<string, any>,
|
|
headers: Record<string, string> = {}
|
|
): Record<string, string> {
|
|
return {
|
|
...headers,
|
|
[KEY]: JSON.stringify(meta),
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a cookie to the headers with the provided request metadata. Existing
|
|
* cookies will be merged, but it will not merge request metadata that already
|
|
* exists on an existing cookie.
|
|
*
|
|
* @param meta metadata to inject into the headers via a cookie
|
|
* @param headers the existing headers on the response to merge with
|
|
* @returns the merged headers with the request meta added as a cookie
|
|
*/
|
|
export function cookieWithRequestMeta(
|
|
meta: Record<string, any>,
|
|
{ cookie = '', ...headers }: Record<string, string> = {}
|
|
): Record<string, string> {
|
|
if (cookie) cookie += '; '
|
|
|
|
// We encode this with `btoa` because the JSON string can contain characters
|
|
// that are invalid in a cookie value.
|
|
cookie += `${KEY}=${btoa(JSON.stringify(meta))}`
|
|
|
|
return {
|
|
...headers,
|
|
cookie,
|
|
}
|
|
}
|
|
|
|
type Cookies = {
|
|
get(name: string): { name: string; value: string } | undefined
|
|
}
|
|
|
|
/**
|
|
* Gets request metadata from the response headers or cookie.
|
|
*
|
|
* @param headersOrCookies response headers from the request or cookies object
|
|
* @returns any injected metadata on the request
|
|
*/
|
|
export function getRequestMeta(
|
|
headersOrCookies:
|
|
| Headers
|
|
| Cookies
|
|
| ReadonlyHeaders
|
|
| ReadonlyRequestCookies
|
|
| import('next/dist/compiled/node-fetch').Headers
|
|
): Record<string, any> {
|
|
const headerOrCookie = headersOrCookies.get(KEY)
|
|
if (!headerOrCookie) return {}
|
|
|
|
// If the value is a string, then parse it now, it was headers.
|
|
if (typeof headerOrCookie === 'string') return JSON.parse(headerOrCookie)
|
|
|
|
// It's a cookie! Parse it now. The cookie value should be encoded with
|
|
// `btoa`, hence the use of `atob`.
|
|
return JSON.parse(atob(headerOrCookie.value))
|
|
}
|