| 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) |
| } |
|
|