From 37e2c0e1ba10c7a147dda5a6e01bf732f17ac203 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sat, 23 Nov 2024 05:52:41 +0100 Subject: [PATCH 1/2] refactor redirect helpers --- .../client/components/is-next-router-error.ts | 2 +- .../src/client/components/redirect-error.ts | 45 +++++++++++++++++ .../next/src/client/components/redirect.ts | 50 +++---------------- 3 files changed, 52 insertions(+), 45 deletions(-) create mode 100644 packages/next/src/client/components/redirect-error.ts diff --git a/packages/next/src/client/components/is-next-router-error.ts b/packages/next/src/client/components/is-next-router-error.ts index 284bbfffead97..537f8fbf9f892 100644 --- a/packages/next/src/client/components/is-next-router-error.ts +++ b/packages/next/src/client/components/is-next-router-error.ts @@ -2,7 +2,7 @@ import { isHTTPAccessFallbackError, type HTTPAccessFallbackError, } from './http-access-fallback/http-access-fallback' -import { isRedirectError, type RedirectError } from './redirect' +import { isRedirectError, type RedirectError } from './redirect-error' /** * Returns true if the error is a navigation signal error. These errors are diff --git a/packages/next/src/client/components/redirect-error.ts b/packages/next/src/client/components/redirect-error.ts new file mode 100644 index 0000000000000..35589bdaa5311 --- /dev/null +++ b/packages/next/src/client/components/redirect-error.ts @@ -0,0 +1,45 @@ +import { RedirectStatusCode } from './redirect-status-code' + +export const REDIRECT_ERROR_CODE = 'NEXT_REDIRECT' + +export enum RedirectType { + push = 'push', + replace = 'replace', +} + +export type RedirectError = Error & { + digest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};` +} + +/** + * Checks an error to determine if it's an error generated by the + * `redirect(url)` helper. + * + * @param error the error that may reference a redirect error + * @returns true if the error is a redirect error + */ +export function isRedirectError(error: unknown): error is RedirectError { + if ( + typeof error !== 'object' || + error === null || + !('digest' in error) || + typeof error.digest !== 'string' + ) { + return false + } + + const digest = error.digest.split(';') + const [errorCode, type] = digest + const destination = digest.slice(2, -2).join(';') + const status = digest.at(-2) + + const statusCode = Number(status) + + return ( + errorCode === REDIRECT_ERROR_CODE && + (type === 'replace' || type === 'push') && + typeof destination === 'string' && + !isNaN(statusCode) && + statusCode in RedirectStatusCode + ) +} diff --git a/packages/next/src/client/components/redirect.ts b/packages/next/src/client/components/redirect.ts index 00946a27e6d69..4c1464143e5a3 100644 --- a/packages/next/src/client/components/redirect.ts +++ b/packages/next/src/client/components/redirect.ts @@ -1,16 +1,11 @@ import { actionAsyncStorage } from '../../server/app-render/action-async-storage.external' import { RedirectStatusCode } from './redirect-status-code' - -const REDIRECT_ERROR_CODE = 'NEXT_REDIRECT' - -export enum RedirectType { - push = 'push', - replace = 'replace', -} - -export type RedirectError = Error & { - digest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};` -} +import { + RedirectType, + type RedirectError, + isRedirectError, + REDIRECT_ERROR_CODE, +} from './redirect-error' export function getRedirectError( url: string, @@ -68,39 +63,6 @@ export function permanentRedirect( throw getRedirectError(url, type, RedirectStatusCode.PermanentRedirect) } -/** - * Checks an error to determine if it's an error generated by the - * `redirect(url)` helper. - * - * @param error the error that may reference a redirect error - * @returns true if the error is a redirect error - */ -export function isRedirectError(error: unknown): error is RedirectError { - if ( - typeof error !== 'object' || - error === null || - !('digest' in error) || - typeof error.digest !== 'string' - ) { - return false - } - - const digest = error.digest.split(';') - const [errorCode, type] = digest - const destination = digest.slice(2, -2).join(';') - const status = digest.at(-2) - - const statusCode = Number(status) - - return ( - errorCode === REDIRECT_ERROR_CODE && - (type === 'replace' || type === 'push') && - typeof destination === 'string' && - !isNaN(statusCode) && - statusCode in RedirectStatusCode - ) -} - /** * Returns the encoded URL from the error if it's a RedirectError, null * otherwise. Note that this does not validate the URL returned. From a8204592eae912a463690a510c5f0c7613a51c47 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sat, 23 Nov 2024 06:00:57 +0100 Subject: [PATCH 2/2] update imports --- packages/next/src/client/components/app-router.tsx | 9 ++------- .../src/client/components/navigation.react-server.ts | 3 ++- .../next/src/client/components/redirect-boundary.tsx | 8 ++------ packages/next/src/client/components/redirect.test.ts | 4 +++- .../router-reducer/reducers/server-action-reducer.ts | 3 ++- packages/next/src/server/app-render/action-handler.ts | 4 +++- packages/next/src/server/app-render/app-render.tsx | 2 +- .../server/app-render/make-get-server-inserted-html.tsx | 2 +- .../next/src/server/route-modules/app-route/module.ts | 4 +++- 9 files changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/next/src/client/components/app-router.tsx b/packages/next/src/client/components/app-router.tsx index 1bc1eb4a2e2e5..391b4f4cc9283 100644 --- a/packages/next/src/client/components/app-router.tsx +++ b/packages/next/src/client/components/app-router.tsx @@ -55,13 +55,8 @@ import { useNavFailureHandler } from './nav-failure-handler' import { useServerActionDispatcher } from '../app-call-server' import type { AppRouterActionQueue } from '../../shared/lib/router/action-queue' import { prefetch as prefetchWithSegmentCache } from '../components/segment-cache/prefetch' - -import { - getRedirectTypeFromError, - getURLFromRedirectError, - isRedirectError, - RedirectType, -} from './redirect' +import { getRedirectTypeFromError, getURLFromRedirectError } from './redirect' +import { isRedirectError, RedirectType } from './redirect-error' const globalMutable: { pendingMpaPath?: string diff --git a/packages/next/src/client/components/navigation.react-server.ts b/packages/next/src/client/components/navigation.react-server.ts index 33873cfba6a6a..5f767c8ef433e 100644 --- a/packages/next/src/client/components/navigation.react-server.ts +++ b/packages/next/src/client/components/navigation.react-server.ts @@ -26,7 +26,8 @@ class ReadonlyURLSearchParams extends URLSearchParams { } } -export { redirect, permanentRedirect, RedirectType } from './redirect' +export { redirect, permanentRedirect } from './redirect' +export { RedirectType } from './redirect-error' export { notFound } from './not-found' export { forbidden } from './forbidden' export { unauthorized } from './unauthorized' diff --git a/packages/next/src/client/components/redirect-boundary.tsx b/packages/next/src/client/components/redirect-boundary.tsx index 1f4c5cb88e718..03ea9553b40bf 100644 --- a/packages/next/src/client/components/redirect-boundary.tsx +++ b/packages/next/src/client/components/redirect-boundary.tsx @@ -2,12 +2,8 @@ import React, { useEffect } from 'react' import type { AppRouterInstance } from '../../shared/lib/app-router-context.shared-runtime' import { useRouter } from './navigation' -import { - RedirectType, - getRedirectTypeFromError, - getURLFromRedirectError, - isRedirectError, -} from './redirect' +import { getRedirectTypeFromError, getURLFromRedirectError } from './redirect' +import { RedirectType, isRedirectError } from './redirect-error' interface RedirectBoundaryProps { router: AppRouterInstance diff --git a/packages/next/src/client/components/redirect.test.ts b/packages/next/src/client/components/redirect.test.ts index 8ca51b96e76a6..d443e8bd81c75 100644 --- a/packages/next/src/client/components/redirect.test.ts +++ b/packages/next/src/client/components/redirect.test.ts @@ -1,4 +1,6 @@ -import { getURLFromRedirectError, isRedirectError, redirect } from './redirect' +import { getURLFromRedirectError, redirect } from './redirect' +import { isRedirectError } from './redirect-error' + describe('test', () => { it('should throw a redirect error', () => { try { diff --git a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts index 40567f37ea246..90dcaca64c382 100644 --- a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts @@ -47,7 +47,8 @@ import { normalizeFlightData, type NormalizedFlightData, } from '../../../flight-data-helpers' -import { getRedirectError, RedirectType } from '../../redirect' +import { getRedirectError } from '../../redirect' +import { RedirectType } from '../../redirect-error' import { createSeededPrefetchCacheEntry } from '../prefetch-cache-utils' import { removeBasePath } from '../../../remove-base-path' import { hasBasePath } from '../../../has-base-path' diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts index 52c57280d07fe..35225d2334e25 100644 --- a/packages/next/src/server/app-render/action-handler.ts +++ b/packages/next/src/server/app-render/action-handler.ts @@ -18,9 +18,11 @@ import { import { getRedirectTypeFromError, getURLFromRedirectError, +} from '../../client/components/redirect' +import { isRedirectError, type RedirectType, -} from '../../client/components/redirect' +} from '../../client/components/redirect-error' import RenderResult from '../render-result' import type { WorkStore } from '../app-render/work-async-storage.external' import { FlightRenderResult } from './flight-render-result' diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index f98dd1f43ddb2..0a70918d33604 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -66,9 +66,9 @@ import { } from '../../client/components/http-access-fallback/http-access-fallback' import { getURLFromRedirectError, - isRedirectError, getRedirectStatusCodeFromError, } from '../../client/components/redirect' +import { isRedirectError } from '../../client/components/redirect-error' import { getImplicitTags } from '../lib/implicit-tags' import { AppRenderSpan, NextNodeServerSpan } from '../lib/trace/constants' import { getTracer } from '../lib/trace/tracer' diff --git a/packages/next/src/server/app-render/make-get-server-inserted-html.tsx b/packages/next/src/server/app-render/make-get-server-inserted-html.tsx index 42a2b9e36bdf8..8aa8f35804fc6 100644 --- a/packages/next/src/server/app-render/make-get-server-inserted-html.tsx +++ b/packages/next/src/server/app-render/make-get-server-inserted-html.tsx @@ -2,9 +2,9 @@ import React, { type JSX } from 'react' import { isHTTPAccessFallbackError } from '../../client/components/http-access-fallback/http-access-fallback' import { getURLFromRedirectError, - isRedirectError, getRedirectStatusCodeFromError, } from '../../client/components/redirect' +import { isRedirectError } from '../../client/components/redirect-error' import { renderToReadableStream } from 'react-dom/server.edge' import { streamToString } from '../stream-utils/node-web-streams-helper' import { RedirectStatusCode } from '../../client/components/redirect-status-code' diff --git a/packages/next/src/server/route-modules/app-route/module.ts b/packages/next/src/server/route-modules/app-route/module.ts index 0d90f2daf1976..0424c1f5c4f1b 100644 --- a/packages/next/src/server/route-modules/app-route/module.ts +++ b/packages/next/src/server/route-modules/app-route/module.ts @@ -71,9 +71,11 @@ import type { AppSegment } from '../../../build/segment-config/app/app-segments' import { getRedirectStatusCodeFromError, getURLFromRedirectError, +} from '../../../client/components/redirect' +import { isRedirectError, type RedirectError, -} from '../../../client/components/redirect' +} from '../../../client/components/redirect-error' import { getAccessFallbackHTTPStatus, isHTTPAccessFallbackError,