Skip to content

Commit

Permalink
chore: Create helper function for ui errors
Browse files Browse the repository at this point in the history
  • Loading branch information
panteliselef committed May 20, 2024
1 parent 37376b0 commit c3baf8b
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 45 deletions.
9 changes: 2 additions & 7 deletions packages/next/src/client/components/is-next-router-error.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { isNotFoundError } from './not-found'
import { isRedirectError } from './redirect'
import { isForbiddenError } from './forbidden'
import { matchUIError } from '../../shared/lib/ui-error-types'

export function isNextRouterError(error: any): boolean {
return (
error &&
error.digest &&
(isRedirectError(error) ||
isNotFoundError(error) ||
isForbiddenError(error))
error && error.digest && (isRedirectError(error) || !!matchUIError(error))
)
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { isNotFoundError } from '../../client/components/not-found'
import { isRedirectError } from '../../client/components/redirect'
import { isForbiddenError } from '../../client/components/forbidden'
import { matchUIError } from '../../shared/lib/ui-error-types'

/**
* Returns true if the error is a navigation signal error. These errors are
* thrown by user code to perform navigation operations and interrupt the React
* render.
*/
export const isNavigationSignalError = (err: unknown) =>
isNotFoundError(err) || isRedirectError(err) || isForbiddenError(err)
isRedirectError(err) || !!matchUIError(err)
14 changes: 6 additions & 8 deletions packages/next/src/server/app-render/action-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ import { selectWorkerForForwarding } from './action-utils'
import { isNodeNextRequest, isWebNextRequest } from '../base-http/helpers'
import { isNextRouterError } from '../../client/components/is-next-router-error'
import {
getUIErrorStatusCode,
matchUIError,
type UIErrorFileType,
uiErrorFileTypes,
uiErrorsWithStatusCodesMap,
} from '../../shared/lib/ui-error-types'

function formDataFromSearchQueryString(query: string) {
Expand Down Expand Up @@ -852,12 +852,10 @@ export async function handleAction({
}
// Any next router error but redirect
} else if (isNextRouterError(err)) {
const errorType = uiErrorFileTypes.find((type) =>
uiErrorsWithStatusCodesMap[type].matcher(err)
)!
const errorTypeObj = uiErrorsWithStatusCodesMap[errorType]

res.statusCode = errorTypeObj.statusCode
const errorType = matchUIError(err)!
if (errorType) {
res.statusCode = getUIErrorStatusCode(errorType)
}

await addRevalidationHeader(res, {
staticGenerationStore,
Expand Down
27 changes: 10 additions & 17 deletions packages/next/src/server/app-render/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ import { createServerModuleMap } from './action-utils'
import { isNodeNextRequest } from '../base-http/helpers'
import { parseParameter } from '../../shared/lib/router/utils/route-regex'
import {
uiErrorFileTypes,
uiErrorsWithStatusCodesMap,
getUIErrorHelperName,
getUIErrorStatusCode,
matchUIError,
uiErrorStatusCodes,
} from '../../shared/lib/ui-error-types'

export type GetDynamicParamFromSegment = (
Expand Down Expand Up @@ -1245,14 +1247,11 @@ async function renderToHTMLOrFlightImpl(
throw err
}

const uiErrorType = uiErrorFileTypes.find((errorType) =>
uiErrorsWithStatusCodesMap[errorType].matcher(err)
)

const uiErrorType = matchUIError(err)
if (uiErrorType) {
const errorTypeObj = uiErrorsWithStatusCodesMap[uiErrorType]
res.statusCode = errorTypeObj.statusCode
res.statusCode = getUIErrorStatusCode(uiErrorType)
}

let hasRedirectError = false
if (isRedirectError(err)) {
hasRedirectError = true
Expand All @@ -1272,12 +1271,9 @@ async function renderToHTMLOrFlightImpl(
)
setHeader('Location', redirectUrl)
}
const internalHandledStatusCodes = Object.values(
uiErrorsWithStatusCodesMap
).map((x) => +x.statusCode)

if (
!internalHandledStatusCodes.includes(res.statusCode || 0) &&
!uiErrorStatusCodes.includes(res.statusCode || 0) &&
!hasRedirectError &&
!shouldBailoutToCSR
) {
Expand All @@ -1286,9 +1282,7 @@ async function renderToHTMLOrFlightImpl(

// TODO(@panteliselef): Maybe create specific type for `forbidden`
// This is probably is used to generate metadata.
const errorType = internalHandledStatusCodes.includes(
res.statusCode || 0
)
const errorType = uiErrorStatusCodes.includes(res.statusCode || 0)
? 'not-found'
: hasRedirectError
? 'redirect'
Expand Down Expand Up @@ -1362,8 +1356,7 @@ async function renderToHTMLOrFlightImpl(
require('../../client/components/dev-root-ui-error-boundary').bailOnUIError

if (uiErrorType) {
const errorTypeObj = uiErrorsWithStatusCodesMap[uiErrorType]
bailOnUIError(errorTypeObj.helperName)
bailOnUIError(getUIErrorHelperName(uiErrorType))
}
}
throw finalErr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {
} from '../../../../../client/components/redirect'
import { handleRedirectResponse } from '../../helpers/response-handlers'
import {
uiErrorFileTypes,
uiErrorsWithStatusCodesMap,
getUIErrorStatusCode,
matchUIError,
} from '../../../../../shared/lib/ui-error-types'

export function resolveHandlerError(err: any): Response | false {
Expand All @@ -22,13 +22,11 @@ export function resolveHandlerError(err: any): Response | false {
return handleRedirectResponse(redirect, err.mutableCookies, status)
}

const uiError = uiErrorFileTypes.find((errorType) =>
uiErrorsWithStatusCodesMap[errorType].matcher(err)
)
const uiError = matchUIError(err)

if (uiError) {
return new Response(null, {
status: uiErrorsWithStatusCodesMap[uiError].statusCode,
status: getUIErrorStatusCode(uiError),
})
}

Expand Down
32 changes: 28 additions & 4 deletions packages/next/src/shared/lib/ui-error-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,40 @@ const uiErrorsWithStatusCodesMap = {
},
} as const

type UIErrorsWithStatusCodesMap = typeof uiErrorsWithStatusCodesMap
type UIErrorFileType = keyof UIErrorsWithStatusCodesMap

const uiErrorFileTypes = Object.keys(
uiErrorsWithStatusCodesMap
) as (keyof typeof uiErrorsWithStatusCodesMap)[]
) as UIErrorFileType[]

type UIErrorsWithStatusCodesMap = typeof uiErrorsWithStatusCodesMap
const uiErrorStatusCodes = Object.values(uiErrorsWithStatusCodesMap).map(
(x) => +x.statusCode
)

type UIErrorFileType = keyof UIErrorsWithStatusCodesMap
function matchUIError(err: unknown) {
return uiErrorFileTypes.find((errorType) =>
uiErrorsWithStatusCodesMap[errorType].matcher(err)
)
}

function getUIErrorStatusCode(type: UIErrorFileType) {
return uiErrorsWithStatusCodesMap[type].statusCode
}

function getUIErrorHelperName(type: UIErrorFileType) {
return uiErrorsWithStatusCodesMap[type].helperName
}

type UIErrorHelper = UIErrorsWithStatusCodesMap[UIErrorFileType]['helperName']

export { uiErrorFileTypes, uiErrorsWithStatusCodesMap }
export {
uiErrorFileTypes,
uiErrorsWithStatusCodesMap,
uiErrorStatusCodes,
matchUIError,
getUIErrorStatusCode,
getUIErrorHelperName,
}

export type { UIErrorFileType, UIErrorHelper }

0 comments on commit c3baf8b

Please sign in to comment.