| | import { InvariantError } from '../../shared/lib/invariant-error' |
| | import { |
| | postponeWithTracking, |
| | throwToInterruptStaticGeneration, |
| | } from '../app-render/dynamic-rendering' |
| | import { |
| | workAsyncStorage, |
| | type WorkStore, |
| | } from '../app-render/work-async-storage.external' |
| | import { |
| | workUnitAsyncStorage, |
| | type PrerenderStoreLegacy, |
| | type PrerenderStorePPR, |
| | type StaticPrerenderStore, |
| | } from '../app-render/work-unit-async-storage.external' |
| | import { makeHangingPromise } from '../dynamic-rendering-utils' |
| | import type { ParamValue } from './params' |
| | import { describeStringPropertyAccess } from '../../shared/lib/utils/reflect-utils' |
| | import { actionAsyncStorage } from '../app-render/action-async-storage.external' |
| |
|
| | |
| | |
| | |
| | |
| | export function getRootParam(paramName: string): Promise<ParamValue> { |
| | const apiName = `\`import('next/root-params').${paramName}()\`` |
| |
|
| | const workStore = workAsyncStorage.getStore() |
| | if (!workStore) { |
| | throw new InvariantError(`Missing workStore in ${apiName}`) |
| | } |
| |
|
| | const workUnitStore = workUnitAsyncStorage.getStore() |
| | if (!workUnitStore) { |
| | throw new Error( |
| | `Route ${workStore.route} used ${apiName} outside of a Server Component. This is not allowed.` |
| | ) |
| | } |
| |
|
| | const actionStore = actionAsyncStorage.getStore() |
| | if (actionStore) { |
| | if (actionStore.isAppRoute) { |
| | |
| | throw new Error( |
| | `Route ${workStore.route} used ${apiName} inside a Route Handler. Support for this API in Route Handlers is planned for a future version of Next.js.` |
| | ) |
| | } |
| | if (actionStore.isAction && workUnitStore.phase === 'action') { |
| | |
| | |
| | |
| | |
| | throw new Error( |
| | `${apiName} was used inside a Server Action. This is not supported. Functions from 'next/root-params' can only be called in the context of a route.` |
| | ) |
| | } |
| | } |
| |
|
| | switch (workUnitStore.type) { |
| | case 'unstable-cache': |
| | case 'cache': { |
| | throw new Error( |
| | `Route ${workStore.route} used ${apiName} inside \`"use cache"\` or \`unstable_cache\`. Support for this API inside cache scopes is planned for a future version of Next.js.` |
| | ) |
| | } |
| | case 'prerender': |
| | case 'prerender-client': |
| | case 'prerender-ppr': |
| | case 'prerender-legacy': { |
| | return createPrerenderRootParamPromise( |
| | paramName, |
| | workStore, |
| | workUnitStore, |
| | apiName |
| | ) |
| | } |
| | case 'private-cache': |
| | case 'prerender-runtime': |
| | case 'request': { |
| | break |
| | } |
| | default: { |
| | workUnitStore satisfies never |
| | } |
| | } |
| | return Promise.resolve(workUnitStore.rootParams[paramName]) |
| | } |
| |
|
| | function createPrerenderRootParamPromise( |
| | paramName: string, |
| | workStore: WorkStore, |
| | prerenderStore: StaticPrerenderStore, |
| | apiName: string |
| | ): Promise<ParamValue> { |
| | switch (prerenderStore.type) { |
| | case 'prerender-client': { |
| | throw new InvariantError( |
| | `${apiName} must not be used within a client component. Next.js should be preventing ${apiName} from being included in client components statically, but did not in this case.` |
| | ) |
| | } |
| | case 'prerender': |
| | case 'prerender-legacy': |
| | case 'prerender-ppr': |
| | default: |
| | } |
| |
|
| | const underlyingParams = prerenderStore.rootParams |
| |
|
| | switch (prerenderStore.type) { |
| | case 'prerender': { |
| | |
| | |
| | if ( |
| | prerenderStore.fallbackRouteParams && |
| | prerenderStore.fallbackRouteParams.has(paramName) |
| | ) { |
| | return makeHangingPromise<ParamValue>( |
| | prerenderStore.renderSignal, |
| | workStore.route, |
| | apiName |
| | ) |
| | } |
| | break |
| | } |
| | case 'prerender-ppr': { |
| | |
| | |
| | if ( |
| | prerenderStore.fallbackRouteParams && |
| | prerenderStore.fallbackRouteParams.has(paramName) |
| | ) { |
| | return makeErroringRootParamPromise( |
| | paramName, |
| | workStore, |
| | prerenderStore, |
| | apiName |
| | ) |
| | } |
| | break |
| | } |
| | case 'prerender-legacy': { |
| | |
| | break |
| | } |
| | default: { |
| | prerenderStore satisfies never |
| | } |
| | } |
| |
|
| | |
| | return Promise.resolve(underlyingParams[paramName]) |
| | } |
| |
|
| | |
| | async function makeErroringRootParamPromise( |
| | paramName: string, |
| | workStore: WorkStore, |
| | prerenderStore: PrerenderStorePPR | PrerenderStoreLegacy, |
| | apiName: string |
| | ): Promise<ParamValue> { |
| | const expression = describeStringPropertyAccess(apiName, paramName) |
| | |
| | |
| | |
| | |
| | switch (prerenderStore.type) { |
| | case 'prerender-ppr': { |
| | return postponeWithTracking( |
| | workStore.route, |
| | expression, |
| | prerenderStore.dynamicTracking |
| | ) |
| | } |
| | case 'prerender-legacy': { |
| | return throwToInterruptStaticGeneration( |
| | expression, |
| | workStore, |
| | prerenderStore |
| | ) |
| | } |
| | default: { |
| | prerenderStore satisfies never |
| | } |
| | } |
| | } |
| |
|