| | import { workAsyncStorage } from '../app-render/work-async-storage.external' |
| | import { |
| | throwForMissingRequestStore, |
| | workUnitAsyncStorage, |
| | } from '../app-render/work-unit-async-storage.external' |
| | import { |
| | postponeWithTracking, |
| | throwToInterruptStaticGeneration, |
| | trackDynamicDataInDynamicRender, |
| | } from '../app-render/dynamic-rendering' |
| | import { StaticGenBailoutError } from '../../client/components/static-generation-bailout' |
| | import { |
| | makeHangingPromise, |
| | makeDevtoolsIOAwarePromise, |
| | } from '../dynamic-rendering-utils' |
| | import { isRequestAPICallableInsideAfter } from './utils' |
| | import { RenderStage } from '../app-render/staged-rendering' |
| |
|
| | |
| | |
| | |
| | |
| | |
| | export function connection(): Promise<void> { |
| | const callingExpression = 'connection' |
| | const workStore = workAsyncStorage.getStore() |
| | const workUnitStore = workUnitAsyncStorage.getStore() |
| |
|
| | if (workStore) { |
| | if ( |
| | workUnitStore && |
| | workUnitStore.phase === 'after' && |
| | !isRequestAPICallableInsideAfter() |
| | ) { |
| | throw new Error( |
| | `Route ${workStore.route} used \`connection()\` inside \`after()\`. The \`connection()\` function is used to indicate the subsequent code must only run when there is an actual Request, but \`after()\` executes after the request, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/canary/app/api-reference/functions/after` |
| | ) |
| | } |
| |
|
| | if (workStore.forceStatic) { |
| | |
| | |
| | return Promise.resolve(undefined) |
| | } |
| |
|
| | if (workStore.dynamicShouldError) { |
| | throw new StaticGenBailoutError( |
| | `Route ${workStore.route} with \`dynamic = "error"\` couldn't be rendered statically because it used \`connection()\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering` |
| | ) |
| | } |
| |
|
| | if (workUnitStore) { |
| | switch (workUnitStore.type) { |
| | case 'cache': { |
| | const error = new Error( |
| | `Route ${workStore.route} used \`connection()\` inside "use cache". The \`connection()\` function is used to indicate the subsequent code must only run when there is an actual request, but caches must be able to be produced before a request, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache` |
| | ) |
| | Error.captureStackTrace(error, connection) |
| | workStore.invalidDynamicUsageError ??= error |
| | throw error |
| | } |
| | case 'private-cache': { |
| | |
| | |
| | |
| | const error = new Error( |
| | `Route ${workStore.route} used \`connection()\` inside "use cache: private". The \`connection()\` function is used to indicate the subsequent code must only run when there is an actual navigation request, but caches must be able to be produced before a navigation request, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache` |
| | ) |
| | Error.captureStackTrace(error, connection) |
| | workStore.invalidDynamicUsageError ??= error |
| | throw error |
| | } |
| | case 'unstable-cache': |
| | throw new Error( |
| | `Route ${workStore.route} used \`connection()\` inside a function cached with \`unstable_cache()\`. The \`connection()\` function is used to indicate the subsequent code must only run when there is an actual Request, but caches must be able to be produced before a Request so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache` |
| | ) |
| | case 'prerender': |
| | case 'prerender-client': |
| | case 'prerender-runtime': |
| | |
| | |
| | return makeHangingPromise( |
| | workUnitStore.renderSignal, |
| | workStore.route, |
| | '`connection()`' |
| | ) |
| | case 'prerender-ppr': |
| | |
| | |
| | return postponeWithTracking( |
| | workStore.route, |
| | 'connection', |
| | workUnitStore.dynamicTracking |
| | ) |
| | case 'prerender-legacy': |
| | |
| | |
| | return throwToInterruptStaticGeneration( |
| | 'connection', |
| | workStore, |
| | workUnitStore |
| | ) |
| | case 'request': |
| | trackDynamicDataInDynamicRender(workUnitStore) |
| | if (process.env.NODE_ENV === 'development') { |
| | |
| | |
| | |
| | if (workUnitStore.asyncApiPromises) { |
| | return workUnitStore.asyncApiPromises.connection |
| | } |
| | return makeDevtoolsIOAwarePromise( |
| | undefined, |
| | workUnitStore, |
| | RenderStage.Dynamic |
| | ) |
| | } else { |
| | return Promise.resolve(undefined) |
| | } |
| | default: |
| | workUnitStore satisfies never |
| | } |
| | } |
| | } |
| |
|
| | |
| | throwForMissingRequestStore(callingExpression) |
| | } |
| |
|