feat(blog): add file-based blog with dynamic slugs, MDX content and layout shell

- Introduced blog routing using Next.js App Router
- Implemented dynamic [slug] pages for blog posts
- Added MDX-based content loading via lib/posts
- Integrated shared TopBar layout with navigation
- Established clear content, lib and component separation
This commit is contained in:
PascalSchattenburg
2026-01-22 14:14:15 +01:00
parent b717952234
commit d147843c76
10412 changed files with 2475583 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
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';
/**
* This function allows you to indicate that you require an actual user Request before continuing.
*
* During prerendering it will never resolve and during rendering it resolves immediately.
*/ export function connection() {
const callingExpression = 'connection';
const workStore = workAsyncStorage.getStore();
const workUnitStore = workUnitAsyncStorage.getStore();
if (workStore) {
if (workUnitStore && workUnitStore.phase === 'after' && !isRequestAPICallableInsideAfter()) {
throw Object.defineProperty(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`), "__NEXT_ERROR_CODE", {
value: "E827",
enumerable: false,
configurable: true
});
}
if (workStore.forceStatic) {
// When using forceStatic, we override all other logic and always just
// return a resolving promise without tracking.
return Promise.resolve(undefined);
}
if (workStore.dynamicShouldError) {
throw Object.defineProperty(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`), "__NEXT_ERROR_CODE", {
value: "E847",
enumerable: false,
configurable: true
});
}
if (workUnitStore) {
switch(workUnitStore.type){
case 'cache':
{
const error = Object.defineProperty(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`), "__NEXT_ERROR_CODE", {
value: "E841",
enumerable: false,
configurable: true
});
Error.captureStackTrace(error, connection);
workStore.invalidDynamicUsageError ??= error;
throw error;
}
case 'private-cache':
{
// It might not be intuitive to throw for private caches as well, but
// we don't consider runtime prefetches as "actual requests" (in the
// navigation sense), despite allowing them to read cookies.
const error = Object.defineProperty(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`), "__NEXT_ERROR_CODE", {
value: "E837",
enumerable: false,
configurable: true
});
Error.captureStackTrace(error, connection);
workStore.invalidDynamicUsageError ??= error;
throw error;
}
case 'unstable-cache':
throw Object.defineProperty(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`), "__NEXT_ERROR_CODE", {
value: "E840",
enumerable: false,
configurable: true
});
case 'prerender':
case 'prerender-client':
case 'prerender-runtime':
// We return a promise that never resolves to allow the prerender to
// stall at this point.
return makeHangingPromise(workUnitStore.renderSignal, workStore.route, '`connection()`');
case 'prerender-ppr':
// We use React's postpone API to interrupt rendering here to create a
// dynamic hole
return postponeWithTracking(workStore.route, 'connection', workUnitStore.dynamicTracking);
case 'prerender-legacy':
// We throw an error here to interrupt prerendering to mark the route
// as dynamic
return throwToInterruptStaticGeneration('connection', workStore, workUnitStore);
case 'request':
trackDynamicDataInDynamicRender(workUnitStore);
if (process.env.NODE_ENV === 'development') {
// Semantically we only need the dev tracking when running in `next dev`
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
if (workUnitStore.asyncApiPromises) {
return workUnitStore.asyncApiPromises.connection;
}
return makeDevtoolsIOAwarePromise(undefined, workUnitStore, RenderStage.Dynamic);
} else {
return Promise.resolve(undefined);
}
default:
workUnitStore;
}
}
}
// If we end up here, there was no work store or work unit store present.
throwForMissingRequestStore(callingExpression);
}
//# sourceMappingURL=connection.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,210 @@
import { areCookiesMutableInCurrentPhase, RequestCookiesAdapter } from '../web/spec-extension/adapters/request-cookies';
import { RequestCookies } from '../web/spec-extension/cookies';
import { workAsyncStorage } from '../app-render/work-async-storage.external';
import { throwForMissingRequestStore, workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external';
import { delayUntilRuntimeStage, postponeWithTracking, throwToInterruptStaticGeneration, trackDynamicDataInDynamicRender } from '../app-render/dynamic-rendering';
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout';
import { makeDevtoolsIOAwarePromise, makeHangingPromise } from '../dynamic-rendering-utils';
import { createDedupedByCallsiteServerErrorLoggerDev } from '../create-deduped-by-callsite-server-error-logger';
import { isRequestAPICallableInsideAfter } from './utils';
import { InvariantError } from '../../shared/lib/invariant-error';
import { RenderStage } from '../app-render/staged-rendering';
export function cookies() {
const callingExpression = 'cookies';
const workStore = workAsyncStorage.getStore();
const workUnitStore = workUnitAsyncStorage.getStore();
if (workStore) {
if (workUnitStore && workUnitStore.phase === 'after' && !isRequestAPICallableInsideAfter()) {
throw Object.defineProperty(new Error(// TODO(after): clarify that this only applies to pages?
`Route ${workStore.route} used \`cookies()\` inside \`after()\`. This is not supported. If you need this data inside an \`after()\` callback, use \`cookies()\` outside of the callback. See more info here: https://nextjs.org/docs/canary/app/api-reference/functions/after`), "__NEXT_ERROR_CODE", {
value: "E843",
enumerable: false,
configurable: true
});
}
if (workStore.forceStatic) {
// When using forceStatic we override all other logic and always just return an empty
// cookies object without tracking
const underlyingCookies = createEmptyCookies();
return makeUntrackedCookies(underlyingCookies);
}
if (workStore.dynamicShouldError) {
throw Object.defineProperty(new StaticGenBailoutError(`Route ${workStore.route} with \`dynamic = "error"\` couldn't be rendered statically because it used \`cookies()\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`), "__NEXT_ERROR_CODE", {
value: "E849",
enumerable: false,
configurable: true
});
}
if (workUnitStore) {
switch(workUnitStore.type){
case 'cache':
const error = Object.defineProperty(new Error(`Route ${workStore.route} used \`cookies()\` inside "use cache". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use \`cookies()\` outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`), "__NEXT_ERROR_CODE", {
value: "E831",
enumerable: false,
configurable: true
});
Error.captureStackTrace(error, cookies);
workStore.invalidDynamicUsageError ??= error;
throw error;
case 'unstable-cache':
throw Object.defineProperty(new Error(`Route ${workStore.route} used \`cookies()\` inside a function cached with \`unstable_cache()\`. Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use \`cookies()\` outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`), "__NEXT_ERROR_CODE", {
value: "E846",
enumerable: false,
configurable: true
});
case 'prerender':
return makeHangingCookies(workStore, workUnitStore);
case 'prerender-client':
const exportName = '`cookies`';
throw Object.defineProperty(new InvariantError(`${exportName} must not be used within a Client Component. Next.js should be preventing ${exportName} from being included in Client Components statically, but did not in this case.`), "__NEXT_ERROR_CODE", {
value: "E832",
enumerable: false,
configurable: true
});
case 'prerender-ppr':
// We need track dynamic access here eagerly to keep continuity with
// how cookies has worked in PPR without cacheComponents.
return postponeWithTracking(workStore.route, callingExpression, workUnitStore.dynamicTracking);
case 'prerender-legacy':
// We track dynamic access here so we don't need to wrap the cookies
// in individual property access tracking.
return throwToInterruptStaticGeneration(callingExpression, workStore, workUnitStore);
case 'prerender-runtime':
return delayUntilRuntimeStage(workUnitStore, makeUntrackedCookies(workUnitStore.cookies));
case 'private-cache':
// Private caches are delayed until the runtime stage in use-cache-wrapper,
// so we don't need an additional delay here.
return makeUntrackedCookies(workUnitStore.cookies);
case 'request':
trackDynamicDataInDynamicRender(workUnitStore);
let underlyingCookies;
if (areCookiesMutableInCurrentPhase(workUnitStore)) {
// We can't conditionally return different types here based on the context.
// To avoid confusion, we always return the readonly type here.
underlyingCookies = workUnitStore.userspaceMutableCookies;
} else {
underlyingCookies = workUnitStore.cookies;
}
if (process.env.NODE_ENV === 'development') {
// Semantically we only need the dev tracking when running in `next dev`
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
return makeUntrackedCookiesWithDevWarnings(workUnitStore, underlyingCookies, workStore == null ? void 0 : workStore.route);
} else {
return makeUntrackedCookies(underlyingCookies);
}
default:
workUnitStore;
}
}
}
// If we end up here, there was no work store or work unit store present.
throwForMissingRequestStore(callingExpression);
}
function createEmptyCookies() {
return RequestCookiesAdapter.seal(new RequestCookies(new Headers({})));
}
const CachedCookies = new WeakMap();
function makeHangingCookies(workStore, prerenderStore) {
const cachedPromise = CachedCookies.get(prerenderStore);
if (cachedPromise) {
return cachedPromise;
}
const promise = makeHangingPromise(prerenderStore.renderSignal, workStore.route, '`cookies()`');
CachedCookies.set(prerenderStore, promise);
return promise;
}
function makeUntrackedCookies(underlyingCookies) {
const cachedCookies = CachedCookies.get(underlyingCookies);
if (cachedCookies) {
return cachedCookies;
}
const promise = Promise.resolve(underlyingCookies);
CachedCookies.set(underlyingCookies, promise);
return promise;
}
function makeUntrackedCookiesWithDevWarnings(requestStore, underlyingCookies, route) {
if (requestStore.asyncApiPromises) {
let promise;
if (underlyingCookies === requestStore.mutableCookies) {
promise = requestStore.asyncApiPromises.mutableCookies;
} else if (underlyingCookies === requestStore.cookies) {
promise = requestStore.asyncApiPromises.cookies;
} else {
throw Object.defineProperty(new InvariantError('Received an underlying cookies object that does not match either `cookies` or `mutableCookies`'), "__NEXT_ERROR_CODE", {
value: "E890",
enumerable: false,
configurable: true
});
}
return instrumentCookiesPromiseWithDevWarnings(promise, route);
}
const cachedCookies = CachedCookies.get(underlyingCookies);
if (cachedCookies) {
return cachedCookies;
}
const promise = makeDevtoolsIOAwarePromise(underlyingCookies, requestStore, RenderStage.Runtime);
const proxiedPromise = instrumentCookiesPromiseWithDevWarnings(promise, route);
CachedCookies.set(underlyingCookies, proxiedPromise);
return proxiedPromise;
}
const warnForSyncAccess = createDedupedByCallsiteServerErrorLoggerDev(createCookiesAccessError);
function instrumentCookiesPromiseWithDevWarnings(promise, route) {
Object.defineProperties(promise, {
[Symbol.iterator]: replaceableWarningDescriptorForSymbolIterator(promise, route),
size: replaceableWarningDescriptor(promise, 'size', route),
get: replaceableWarningDescriptor(promise, 'get', route),
getAll: replaceableWarningDescriptor(promise, 'getAll', route),
has: replaceableWarningDescriptor(promise, 'has', route),
set: replaceableWarningDescriptor(promise, 'set', route),
delete: replaceableWarningDescriptor(promise, 'delete', route),
clear: replaceableWarningDescriptor(promise, 'clear', route),
toString: replaceableWarningDescriptor(promise, 'toString', route)
});
return promise;
}
function replaceableWarningDescriptor(target, prop, route) {
return {
enumerable: false,
get () {
warnForSyncAccess(route, `\`cookies().${prop}\``);
return undefined;
},
set (value) {
Object.defineProperty(target, prop, {
value,
writable: true,
configurable: true
});
},
configurable: true
};
}
function replaceableWarningDescriptorForSymbolIterator(target, route) {
return {
enumerable: false,
get () {
warnForSyncAccess(route, '`...cookies()` or similar iteration');
return undefined;
},
set (value) {
Object.defineProperty(target, Symbol.iterator, {
value,
writable: true,
enumerable: true,
configurable: true
});
},
configurable: true
};
}
function createCookiesAccessError(route, expression) {
const prefix = route ? `Route "${route}" ` : 'This route ';
return Object.defineProperty(new Error(`${prefix}used ${expression}. ` + `\`cookies()\` returns a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. ` + `Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`), "__NEXT_ERROR_CODE", {
value: "E830",
enumerable: false,
configurable: true
});
}
//# sourceMappingURL=cookies.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,198 @@
import { getDraftModeProviderForCacheScope, throwForMissingRequestStore } from '../app-render/work-unit-async-storage.external';
import { workAsyncStorage } from '../app-render/work-async-storage.external';
import { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external';
import { abortAndThrowOnSynchronousRequestDataAccess, delayUntilRuntimeStage, postponeWithTracking, trackDynamicDataInDynamicRender } from '../app-render/dynamic-rendering';
import { createDedupedByCallsiteServerErrorLoggerDev } from '../create-deduped-by-callsite-server-error-logger';
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout';
import { DynamicServerError } from '../../client/components/hooks-server-context';
import { InvariantError } from '../../shared/lib/invariant-error';
import { ReflectAdapter } from '../web/spec-extension/adapters/reflect';
export function draftMode() {
const callingExpression = 'draftMode';
const workStore = workAsyncStorage.getStore();
const workUnitStore = workUnitAsyncStorage.getStore();
if (!workStore || !workUnitStore) {
throwForMissingRequestStore(callingExpression);
}
switch(workUnitStore.type){
case 'prerender-runtime':
// TODO(runtime-ppr): does it make sense to delay this? normally it's always microtasky
return delayUntilRuntimeStage(workUnitStore, createOrGetCachedDraftMode(workUnitStore.draftMode, workStore));
case 'request':
return createOrGetCachedDraftMode(workUnitStore.draftMode, workStore);
case 'cache':
case 'private-cache':
case 'unstable-cache':
// Inside of `"use cache"` or `unstable_cache`, draft mode is available if
// the outmost work unit store is a request store (or a runtime prerender),
// and if draft mode is enabled.
const draftModeProvider = getDraftModeProviderForCacheScope(workStore, workUnitStore);
if (draftModeProvider) {
return createOrGetCachedDraftMode(draftModeProvider, workStore);
}
// Otherwise, we fall through to providing an empty draft mode.
// eslint-disable-next-line no-fallthrough
case 'prerender':
case 'prerender-client':
case 'prerender-ppr':
case 'prerender-legacy':
// Return empty draft mode
return createOrGetCachedDraftMode(null, workStore);
default:
return workUnitStore;
}
}
function createOrGetCachedDraftMode(draftModeProvider, workStore) {
const cacheKey = draftModeProvider ?? NullDraftMode;
const cachedDraftMode = CachedDraftModes.get(cacheKey);
if (cachedDraftMode) {
return cachedDraftMode;
}
if (process.env.NODE_ENV === 'development' && !(workStore == null ? void 0 : workStore.isPrefetchRequest)) {
const route = workStore == null ? void 0 : workStore.route;
return createDraftModeWithDevWarnings(draftModeProvider, route);
} else {
return Promise.resolve(new DraftMode(draftModeProvider));
}
}
const NullDraftMode = {};
const CachedDraftModes = new WeakMap();
function createDraftModeWithDevWarnings(underlyingProvider, route) {
const instance = new DraftMode(underlyingProvider);
const promise = Promise.resolve(instance);
const proxiedPromise = new Proxy(promise, {
get (target, prop, receiver) {
switch(prop){
case 'isEnabled':
warnForSyncAccess(route, `\`draftMode().${prop}\``);
break;
case 'enable':
case 'disable':
{
warnForSyncAccess(route, `\`draftMode().${prop}()\``);
break;
}
default:
{
// We only warn for well-defined properties of the draftMode object.
}
}
return ReflectAdapter.get(target, prop, receiver);
}
});
return proxiedPromise;
}
class DraftMode {
constructor(provider){
this._provider = provider;
}
get isEnabled() {
if (this._provider !== null) {
return this._provider.isEnabled;
}
return false;
}
enable() {
// We have a store we want to track dynamic data access to ensure we
// don't statically generate routes that manipulate draft mode.
trackDynamicDraftMode('draftMode().enable()', this.enable);
if (this._provider !== null) {
this._provider.enable();
}
}
disable() {
trackDynamicDraftMode('draftMode().disable()', this.disable);
if (this._provider !== null) {
this._provider.disable();
}
}
}
const warnForSyncAccess = createDedupedByCallsiteServerErrorLoggerDev(createDraftModeAccessError);
function createDraftModeAccessError(route, expression) {
const prefix = route ? `Route "${route}" ` : 'This route ';
return Object.defineProperty(new Error(`${prefix}used ${expression}. ` + `\`draftMode()\` returns a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. ` + `Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`), "__NEXT_ERROR_CODE", {
value: "E835",
enumerable: false,
configurable: true
});
}
function trackDynamicDraftMode(expression, constructorOpt) {
const workStore = workAsyncStorage.getStore();
const workUnitStore = workUnitAsyncStorage.getStore();
if (workStore) {
// We have a store we want to track dynamic data access to ensure we
// don't statically generate routes that manipulate draft mode.
if ((workUnitStore == null ? void 0 : workUnitStore.phase) === 'after') {
throw Object.defineProperty(new Error(`Route ${workStore.route} used "${expression}" inside \`after()\`. The enabled status of \`draftMode()\` can be read inside \`after()\` but you cannot enable or disable \`draftMode()\`. See more info here: https://nextjs.org/docs/app/api-reference/functions/after`), "__NEXT_ERROR_CODE", {
value: "E845",
enumerable: false,
configurable: true
});
}
if (workStore.dynamicShouldError) {
throw Object.defineProperty(new StaticGenBailoutError(`Route ${workStore.route} with \`dynamic = "error"\` couldn't be rendered statically because it used \`${expression}\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`), "__NEXT_ERROR_CODE", {
value: "E553",
enumerable: false,
configurable: true
});
}
if (workUnitStore) {
switch(workUnitStore.type){
case 'cache':
case 'private-cache':
{
const error = Object.defineProperty(new Error(`Route ${workStore.route} used "${expression}" inside "use cache". The enabled status of \`draftMode()\` can be read in caches but you must not enable or disable \`draftMode()\` inside a cache. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`), "__NEXT_ERROR_CODE", {
value: "E829",
enumerable: false,
configurable: true
});
Error.captureStackTrace(error, constructorOpt);
workStore.invalidDynamicUsageError ??= error;
throw error;
}
case 'unstable-cache':
throw Object.defineProperty(new Error(`Route ${workStore.route} used "${expression}" inside a function cached with \`unstable_cache()\`. The enabled status of \`draftMode()\` can be read in caches but you must not enable or disable \`draftMode()\` inside a cache. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`), "__NEXT_ERROR_CODE", {
value: "E844",
enumerable: false,
configurable: true
});
case 'prerender':
case 'prerender-runtime':
{
const error = Object.defineProperty(new Error(`Route ${workStore.route} used ${expression} without first calling \`await connection()\`. See more info here: https://nextjs.org/docs/messages/next-prerender-sync-headers`), "__NEXT_ERROR_CODE", {
value: "E126",
enumerable: false,
configurable: true
});
return abortAndThrowOnSynchronousRequestDataAccess(workStore.route, expression, error, workUnitStore);
}
case 'prerender-client':
const exportName = '`draftMode`';
throw Object.defineProperty(new InvariantError(`${exportName} must not be used within a Client Component. Next.js should be preventing ${exportName} from being included in Client Components statically, but did not in this case.`), "__NEXT_ERROR_CODE", {
value: "E832",
enumerable: false,
configurable: true
});
case 'prerender-ppr':
return postponeWithTracking(workStore.route, expression, workUnitStore.dynamicTracking);
case 'prerender-legacy':
workUnitStore.revalidate = 0;
const err = Object.defineProperty(new DynamicServerError(`Route ${workStore.route} couldn't be rendered statically because it used \`${expression}\`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error`), "__NEXT_ERROR_CODE", {
value: "E558",
enumerable: false,
configurable: true
});
workStore.dynamicUsageDescription = expression;
workStore.dynamicUsageStack = err.stack;
throw err;
case 'request':
trackDynamicDataInDynamicRender(workUnitStore);
break;
default:
workUnitStore;
}
}
}
}
//# sourceMappingURL=draft-mode.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,60 @@
import { resolveRouteParamsFromTree } from '../../build/static-paths/utils';
import { dynamicParamTypes } from '../app-render/get-short-dynamic-param-type';
import { parseAppRoute } from '../../shared/lib/router/routes/app';
import { extractPathnameRouteParamSegmentsFromLoaderTree } from '../../build/static-paths/app/extract-pathname-route-param-segments-from-loader-tree';
/**
* Creates an opaque fallback route params object from the fallback route params.
*
* @param fallbackRouteParams the fallback route params
* @returns the opaque fallback route params
*/ export function createOpaqueFallbackRouteParams(fallbackRouteParams) {
// If there are no fallback route params, we can return early.
if (fallbackRouteParams.length === 0) return null;
// As we're creating unique keys for each of the dynamic route params, we only
// need to generate a unique ID once per request because each of the keys will
// be also be unique.
const uniqueID = Math.random().toString(16).slice(2);
const keys = new Map();
// Generate a unique key for the fallback route param, if this key is found
// in the static output, it represents a bug in cache components.
for (const { paramName, paramType } of fallbackRouteParams){
keys.set(paramName, [
`%%drp:${paramName}:${uniqueID}%%`,
dynamicParamTypes[paramType]
]);
}
return keys;
}
/**
* Gets the fallback route params for a given page. This is an expensive
* operation because it requires parsing the loader tree to extract the fallback
* route params.
*
* @param page the page
* @param routeModule the route module
* @returns the opaque fallback route params
*/ export function getFallbackRouteParams(page, routeModule) {
const route = parseAppRoute(page, true);
// Extract the pathname-contributing segments from the loader tree. This
// mirrors the logic in buildAppStaticPaths where we determine which segments
// actually contribute to the pathname.
const { pathnameRouteParamSegments, params } = extractPathnameRouteParamSegmentsFromLoaderTree(routeModule.userland.loaderTree, route);
// Create fallback route params for the pathname segments.
const fallbackRouteParams = pathnameRouteParamSegments.map(({ paramName, paramType })=>({
paramName,
paramType
}));
// Resolve route params from the loader tree. This mutates the
// fallbackRouteParams array to add any route params that are
// unknown at request time.
//
// The page parameter contains placeholders like [slug], which helps
// resolveRouteParamsFromTree determine which params are unknown.
resolveRouteParamsFromTree(routeModule.userland.loaderTree, params, route, fallbackRouteParams // Will be mutated to add route params
);
// Convert the fallback route params to an opaque format that can be safely
// used in the postponed state without exposing implementation details.
return createOpaqueFallbackRouteParams(fallbackRouteParams);
}
//# sourceMappingURL=fallback-params.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,217 @@
import { HeadersAdapter } from '../web/spec-extension/adapters/headers';
import { workAsyncStorage } from '../app-render/work-async-storage.external';
import { throwForMissingRequestStore, workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external';
import { delayUntilRuntimeStage, postponeWithTracking, throwToInterruptStaticGeneration, trackDynamicDataInDynamicRender } from '../app-render/dynamic-rendering';
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout';
import { makeDevtoolsIOAwarePromise, makeHangingPromise } from '../dynamic-rendering-utils';
import { createDedupedByCallsiteServerErrorLoggerDev } from '../create-deduped-by-callsite-server-error-logger';
import { isRequestAPICallableInsideAfter } from './utils';
import { InvariantError } from '../../shared/lib/invariant-error';
import { RenderStage } from '../app-render/staged-rendering';
/**
* This function allows you to read the HTTP incoming request headers in
* [Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components),
* [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations),
* [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) and
* [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware).
*
* Read more: [Next.js Docs: `headers`](https://nextjs.org/docs/app/api-reference/functions/headers)
*/ export function headers() {
const callingExpression = 'headers';
const workStore = workAsyncStorage.getStore();
const workUnitStore = workUnitAsyncStorage.getStore();
if (workStore) {
if (workUnitStore && workUnitStore.phase === 'after' && !isRequestAPICallableInsideAfter()) {
throw Object.defineProperty(new Error(`Route ${workStore.route} used \`headers()\` inside \`after()\`. This is not supported. If you need this data inside an \`after()\` callback, use \`headers()\` outside of the callback. See more info here: https://nextjs.org/docs/canary/app/api-reference/functions/after`), "__NEXT_ERROR_CODE", {
value: "E839",
enumerable: false,
configurable: true
});
}
if (workStore.forceStatic) {
// When using forceStatic we override all other logic and always just return an empty
// headers object without tracking
const underlyingHeaders = HeadersAdapter.seal(new Headers({}));
return makeUntrackedHeaders(underlyingHeaders);
}
if (workUnitStore) {
switch(workUnitStore.type){
case 'cache':
{
const error = Object.defineProperty(new Error(`Route ${workStore.route} used \`headers()\` inside "use cache". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use \`headers()\` outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`), "__NEXT_ERROR_CODE", {
value: "E833",
enumerable: false,
configurable: true
});
Error.captureStackTrace(error, headers);
workStore.invalidDynamicUsageError ??= error;
throw error;
}
case 'unstable-cache':
throw Object.defineProperty(new Error(`Route ${workStore.route} used \`headers()\` inside a function cached with \`unstable_cache()\`. Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use \`headers()\` outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`), "__NEXT_ERROR_CODE", {
value: "E838",
enumerable: false,
configurable: true
});
case 'prerender':
case 'prerender-client':
case 'private-cache':
case 'prerender-runtime':
case 'prerender-ppr':
case 'prerender-legacy':
case 'request':
break;
default:
workUnitStore;
}
}
if (workStore.dynamicShouldError) {
throw Object.defineProperty(new StaticGenBailoutError(`Route ${workStore.route} with \`dynamic = "error"\` couldn't be rendered statically because it used \`headers()\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`), "__NEXT_ERROR_CODE", {
value: "E828",
enumerable: false,
configurable: true
});
}
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
return makeHangingHeaders(workStore, workUnitStore);
case 'prerender-client':
const exportName = '`headers`';
throw Object.defineProperty(new InvariantError(`${exportName} must not be used within a client component. Next.js should be preventing ${exportName} from being included in client components statically, but did not in this case.`), "__NEXT_ERROR_CODE", {
value: "E693",
enumerable: false,
configurable: true
});
case 'prerender-ppr':
// PPR Prerender (no cacheComponents)
// We are prerendering with PPR. We need track dynamic access here eagerly
// to keep continuity with how headers has worked in PPR without cacheComponents.
// TODO consider switching the semantic to throw on property access instead
return postponeWithTracking(workStore.route, callingExpression, workUnitStore.dynamicTracking);
case 'prerender-legacy':
// Legacy Prerender
// We are in a legacy static generation mode while prerendering
// We track dynamic access here so we don't need to wrap the headers in
// individual property access tracking.
return throwToInterruptStaticGeneration(callingExpression, workStore, workUnitStore);
case 'prerender-runtime':
return delayUntilRuntimeStage(workUnitStore, makeUntrackedHeaders(workUnitStore.headers));
case 'private-cache':
// Private caches are delayed until the runtime stage in use-cache-wrapper,
// so we don't need an additional delay here.
return makeUntrackedHeaders(workUnitStore.headers);
case 'request':
trackDynamicDataInDynamicRender(workUnitStore);
if (process.env.NODE_ENV === 'development') {
// Semantically we only need the dev tracking when running in `next dev`
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
return makeUntrackedHeadersWithDevWarnings(workUnitStore.headers, workStore == null ? void 0 : workStore.route, workUnitStore);
} else {
return makeUntrackedHeaders(workUnitStore.headers);
}
break;
default:
workUnitStore;
}
}
}
// If we end up here, there was no work store or work unit store present.
throwForMissingRequestStore(callingExpression);
}
const CachedHeaders = new WeakMap();
function makeHangingHeaders(workStore, prerenderStore) {
const cachedHeaders = CachedHeaders.get(prerenderStore);
if (cachedHeaders) {
return cachedHeaders;
}
const promise = makeHangingPromise(prerenderStore.renderSignal, workStore.route, '`headers()`');
CachedHeaders.set(prerenderStore, promise);
return promise;
}
function makeUntrackedHeaders(underlyingHeaders) {
const cachedHeaders = CachedHeaders.get(underlyingHeaders);
if (cachedHeaders) {
return cachedHeaders;
}
const promise = Promise.resolve(underlyingHeaders);
CachedHeaders.set(underlyingHeaders, promise);
return promise;
}
function makeUntrackedHeadersWithDevWarnings(underlyingHeaders, route, requestStore) {
if (requestStore.asyncApiPromises) {
const promise = requestStore.asyncApiPromises.headers;
return instrumentHeadersPromiseWithDevWarnings(promise, route);
}
const cachedHeaders = CachedHeaders.get(underlyingHeaders);
if (cachedHeaders) {
return cachedHeaders;
}
const promise = makeDevtoolsIOAwarePromise(underlyingHeaders, requestStore, RenderStage.Runtime);
const proxiedPromise = instrumentHeadersPromiseWithDevWarnings(promise, route);
CachedHeaders.set(underlyingHeaders, proxiedPromise);
return proxiedPromise;
}
const warnForSyncAccess = createDedupedByCallsiteServerErrorLoggerDev(createHeadersAccessError);
function instrumentHeadersPromiseWithDevWarnings(promise, route) {
Object.defineProperties(promise, {
[Symbol.iterator]: replaceableWarningDescriptorForSymbolIterator(promise, route),
append: replaceableWarningDescriptor(promise, 'append', route),
delete: replaceableWarningDescriptor(promise, 'delete', route),
get: replaceableWarningDescriptor(promise, 'get', route),
has: replaceableWarningDescriptor(promise, 'has', route),
set: replaceableWarningDescriptor(promise, 'set', route),
getSetCookie: replaceableWarningDescriptor(promise, 'getSetCookie', route),
forEach: replaceableWarningDescriptor(promise, 'forEach', route),
keys: replaceableWarningDescriptor(promise, 'keys', route),
values: replaceableWarningDescriptor(promise, 'values', route),
entries: replaceableWarningDescriptor(promise, 'entries', route)
});
return promise;
}
function replaceableWarningDescriptor(target, prop, route) {
return {
enumerable: false,
get () {
warnForSyncAccess(route, `\`headers().${prop}\``);
return undefined;
},
set (value) {
Object.defineProperty(target, prop, {
value,
writable: true,
configurable: true
});
},
configurable: true
};
}
function replaceableWarningDescriptorForSymbolIterator(target, route) {
return {
enumerable: false,
get () {
warnForSyncAccess(route, '`...headers()` or similar iteration');
return undefined;
},
set (value) {
Object.defineProperty(target, Symbol.iterator, {
value,
writable: true,
enumerable: true,
configurable: true
});
},
configurable: true
};
}
function createHeadersAccessError(route, expression) {
const prefix = route ? `Route "${route}" ` : 'This route ';
return Object.defineProperty(new Error(`${prefix}used ${expression}. ` + `\`headers()\` returns a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. ` + `Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`), "__NEXT_ERROR_CODE", {
value: "E836",
enumerable: false,
configurable: true
});
}
//# sourceMappingURL=headers.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,382 @@
import { workAsyncStorage } from '../app-render/work-async-storage.external';
import { ReflectAdapter } from '../web/spec-extension/adapters/reflect';
import { throwToInterruptStaticGeneration, postponeWithTracking, delayUntilRuntimeStage } from '../app-render/dynamic-rendering';
import { workUnitAsyncStorage, throwInvariantForMissingStore } from '../app-render/work-unit-async-storage.external';
import { InvariantError } from '../../shared/lib/invariant-error';
import { describeStringPropertyAccess, wellKnownProperties } from '../../shared/lib/utils/reflect-utils';
import { makeDevtoolsIOAwarePromise, makeHangingPromise } from '../dynamic-rendering-utils';
import { createDedupedByCallsiteServerErrorLoggerDev } from '../create-deduped-by-callsite-server-error-logger';
import { dynamicAccessAsyncStorage } from '../app-render/dynamic-access-async-storage.external';
import { RenderStage } from '../app-render/staged-rendering';
export function createParamsFromClient(underlyingParams, workStore) {
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
case 'prerender-client':
case 'prerender-ppr':
case 'prerender-legacy':
return createStaticPrerenderParams(underlyingParams, workStore, workUnitStore);
case 'cache':
case 'private-cache':
case 'unstable-cache':
throw Object.defineProperty(new InvariantError('createParamsFromClient should not be called in cache contexts.'), "__NEXT_ERROR_CODE", {
value: "E736",
enumerable: false,
configurable: true
});
case 'prerender-runtime':
throw Object.defineProperty(new InvariantError('createParamsFromClient should not be called in a runtime prerender.'), "__NEXT_ERROR_CODE", {
value: "E770",
enumerable: false,
configurable: true
});
case 'request':
if (process.env.NODE_ENV === 'development') {
// Semantically we only need the dev tracking when running in `next dev`
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
const devFallbackParams = workUnitStore.devFallbackParams;
return createRenderParamsInDev(underlyingParams, devFallbackParams, workStore, workUnitStore);
} else {
return createRenderParamsInProd(underlyingParams);
}
default:
workUnitStore;
}
}
throwInvariantForMissingStore();
}
export const createServerParamsForMetadata = createServerParamsForServerSegment;
// routes always runs in RSC context so it is equivalent to a Server Page Component
export function createServerParamsForRoute(underlyingParams, workStore) {
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
case 'prerender-client':
case 'prerender-ppr':
case 'prerender-legacy':
return createStaticPrerenderParams(underlyingParams, workStore, workUnitStore);
case 'cache':
case 'private-cache':
case 'unstable-cache':
throw Object.defineProperty(new InvariantError('createServerParamsForRoute should not be called in cache contexts.'), "__NEXT_ERROR_CODE", {
value: "E738",
enumerable: false,
configurable: true
});
case 'prerender-runtime':
return createRuntimePrerenderParams(underlyingParams, workUnitStore);
case 'request':
if (process.env.NODE_ENV === 'development') {
// Semantically we only need the dev tracking when running in `next dev`
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
const devFallbackParams = workUnitStore.devFallbackParams;
return createRenderParamsInDev(underlyingParams, devFallbackParams, workStore, workUnitStore);
} else {
return createRenderParamsInProd(underlyingParams);
}
default:
workUnitStore;
}
}
throwInvariantForMissingStore();
}
export function createServerParamsForServerSegment(underlyingParams, workStore) {
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
case 'prerender-client':
case 'prerender-ppr':
case 'prerender-legacy':
return createStaticPrerenderParams(underlyingParams, workStore, workUnitStore);
case 'cache':
case 'private-cache':
case 'unstable-cache':
throw Object.defineProperty(new InvariantError('createServerParamsForServerSegment should not be called in cache contexts.'), "__NEXT_ERROR_CODE", {
value: "E743",
enumerable: false,
configurable: true
});
case 'prerender-runtime':
return createRuntimePrerenderParams(underlyingParams, workUnitStore);
case 'request':
if (process.env.NODE_ENV === 'development') {
// Semantically we only need the dev tracking when running in `next dev`
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
const devFallbackParams = workUnitStore.devFallbackParams;
return createRenderParamsInDev(underlyingParams, devFallbackParams, workStore, workUnitStore);
} else {
return createRenderParamsInProd(underlyingParams);
}
default:
workUnitStore;
}
}
throwInvariantForMissingStore();
}
export function createPrerenderParamsForClientSegment(underlyingParams) {
const workStore = workAsyncStorage.getStore();
if (!workStore) {
throw Object.defineProperty(new InvariantError('Missing workStore in createPrerenderParamsForClientSegment'), "__NEXT_ERROR_CODE", {
value: "E773",
enumerable: false,
configurable: true
});
}
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
case 'prerender-client':
const fallbackParams = workUnitStore.fallbackRouteParams;
if (fallbackParams) {
for(let key in underlyingParams){
if (fallbackParams.has(key)) {
// This params object has one or more fallback params, so we need
// to consider the awaiting of this params object "dynamic". Since
// we are in cacheComponents mode we encode this as a promise that never
// resolves.
return makeHangingPromise(workUnitStore.renderSignal, workStore.route, '`params`');
}
}
}
break;
case 'cache':
case 'private-cache':
case 'unstable-cache':
throw Object.defineProperty(new InvariantError('createPrerenderParamsForClientSegment should not be called in cache contexts.'), "__NEXT_ERROR_CODE", {
value: "E734",
enumerable: false,
configurable: true
});
case 'prerender-ppr':
case 'prerender-legacy':
case 'prerender-runtime':
case 'request':
break;
default:
workUnitStore;
}
}
// We're prerendering in a mode that does not abort. We resolve the promise without
// any tracking because we're just transporting a value from server to client where the tracking
// will be applied.
return Promise.resolve(underlyingParams);
}
function createStaticPrerenderParams(underlyingParams, workStore, prerenderStore) {
switch(prerenderStore.type){
case 'prerender':
case 'prerender-client':
{
const fallbackParams = prerenderStore.fallbackRouteParams;
if (fallbackParams) {
for(const key in underlyingParams){
if (fallbackParams.has(key)) {
// This params object has one or more fallback params, so we need
// to consider the awaiting of this params object "dynamic". Since
// we are in cacheComponents mode we encode this as a promise that never
// resolves.
return makeHangingParams(underlyingParams, workStore, prerenderStore);
}
}
}
break;
}
case 'prerender-ppr':
{
const fallbackParams = prerenderStore.fallbackRouteParams;
if (fallbackParams) {
for(const key in underlyingParams){
if (fallbackParams.has(key)) {
return makeErroringParams(underlyingParams, fallbackParams, workStore, prerenderStore);
}
}
}
break;
}
case 'prerender-legacy':
break;
default:
prerenderStore;
}
return makeUntrackedParams(underlyingParams);
}
function createRuntimePrerenderParams(underlyingParams, workUnitStore) {
return delayUntilRuntimeStage(workUnitStore, makeUntrackedParams(underlyingParams));
}
function createRenderParamsInProd(underlyingParams) {
return makeUntrackedParams(underlyingParams);
}
function createRenderParamsInDev(underlyingParams, devFallbackParams, workStore, requestStore) {
let hasFallbackParams = false;
if (devFallbackParams) {
for(let key in underlyingParams){
if (devFallbackParams.has(key)) {
hasFallbackParams = true;
break;
}
}
}
return makeDynamicallyTrackedParamsWithDevWarnings(underlyingParams, hasFallbackParams, workStore, requestStore);
}
const CachedParams = new WeakMap();
const fallbackParamsProxyHandler = {
get: function get(target, prop, receiver) {
if (prop === 'then' || prop === 'catch' || prop === 'finally') {
const originalMethod = ReflectAdapter.get(target, prop, receiver);
return ({
[prop]: (...args)=>{
const store = dynamicAccessAsyncStorage.getStore();
if (store) {
store.abortController.abort(Object.defineProperty(new Error(`Accessed fallback \`params\` during prerendering.`), "__NEXT_ERROR_CODE", {
value: "E691",
enumerable: false,
configurable: true
}));
}
return new Proxy(originalMethod.apply(target, args), fallbackParamsProxyHandler);
}
})[prop];
}
return ReflectAdapter.get(target, prop, receiver);
}
};
function makeHangingParams(underlyingParams, workStore, prerenderStore) {
const cachedParams = CachedParams.get(underlyingParams);
if (cachedParams) {
return cachedParams;
}
const promise = new Proxy(makeHangingPromise(prerenderStore.renderSignal, workStore.route, '`params`'), fallbackParamsProxyHandler);
CachedParams.set(underlyingParams, promise);
return promise;
}
function makeErroringParams(underlyingParams, fallbackParams, workStore, prerenderStore) {
const cachedParams = CachedParams.get(underlyingParams);
if (cachedParams) {
return cachedParams;
}
const augmentedUnderlying = {
...underlyingParams
};
// We don't use makeResolvedReactPromise here because params
// supports copying with spread and we don't want to unnecessarily
// instrument the promise with spreadable properties of ReactPromise.
const promise = Promise.resolve(augmentedUnderlying);
CachedParams.set(underlyingParams, promise);
Object.keys(underlyingParams).forEach((prop)=>{
if (wellKnownProperties.has(prop)) {
// These properties cannot be shadowed because they need to be the
// true underlying value for Promises to work correctly at runtime
} else {
if (fallbackParams.has(prop)) {
Object.defineProperty(augmentedUnderlying, prop, {
get () {
const expression = describeStringPropertyAccess('params', prop);
// In most dynamic APIs we also throw if `dynamic = "error"` however
// for params is only dynamic when we're generating a fallback shell
// and even when `dynamic = "error"` we still support generating dynamic
// fallback shells
// TODO remove this comment when cacheComponents is the default since there
// will be no `dynamic = "error"`
if (prerenderStore.type === 'prerender-ppr') {
// PPR Prerender (no cacheComponents)
postponeWithTracking(workStore.route, expression, prerenderStore.dynamicTracking);
} else {
// Legacy Prerender
throwToInterruptStaticGeneration(expression, workStore, prerenderStore);
}
},
enumerable: true
});
}
}
});
return promise;
}
function makeUntrackedParams(underlyingParams) {
const cachedParams = CachedParams.get(underlyingParams);
if (cachedParams) {
return cachedParams;
}
const promise = Promise.resolve(underlyingParams);
CachedParams.set(underlyingParams, promise);
return promise;
}
function makeDynamicallyTrackedParamsWithDevWarnings(underlyingParams, hasFallbackParams, workStore, requestStore) {
if (requestStore.asyncApiPromises && hasFallbackParams) {
// We wrap each instance of params in a `new Promise()`, because deduping
// them across requests doesn't work anyway and this let us show each
// await a different set of values. This is important when all awaits
// are in third party which would otherwise track all the way to the
// internal params.
const sharedParamsParent = requestStore.asyncApiPromises.sharedParamsParent;
const promise = new Promise((resolve, reject)=>{
sharedParamsParent.then(()=>resolve(underlyingParams), reject);
});
// @ts-expect-error
promise.displayName = 'params';
return instrumentParamsPromiseWithDevWarnings(underlyingParams, promise, workStore);
}
const cachedParams = CachedParams.get(underlyingParams);
if (cachedParams) {
return cachedParams;
}
// We don't use makeResolvedReactPromise here because params
// supports copying with spread and we don't want to unnecessarily
// instrument the promise with spreadable properties of ReactPromise.
const promise = hasFallbackParams ? makeDevtoolsIOAwarePromise(underlyingParams, requestStore, RenderStage.Runtime) : Promise.resolve(underlyingParams);
const proxiedPromise = instrumentParamsPromiseWithDevWarnings(underlyingParams, promise, workStore);
CachedParams.set(underlyingParams, proxiedPromise);
return proxiedPromise;
}
function instrumentParamsPromiseWithDevWarnings(underlyingParams, promise, workStore) {
// Track which properties we should warn for.
const proxiedProperties = new Set();
Object.keys(underlyingParams).forEach((prop)=>{
if (wellKnownProperties.has(prop)) {
// These properties cannot be shadowed because they need to be the
// true underlying value for Promises to work correctly at runtime
} else {
proxiedProperties.add(prop);
}
});
return new Proxy(promise, {
get (target, prop, receiver) {
if (typeof prop === 'string') {
if (// We are accessing a property that was proxied to the promise instance
proxiedProperties.has(prop)) {
const expression = describeStringPropertyAccess('params', prop);
warnForSyncAccess(workStore.route, expression);
}
}
return ReflectAdapter.get(target, prop, receiver);
},
set (target, prop, value, receiver) {
if (typeof prop === 'string') {
proxiedProperties.delete(prop);
}
return ReflectAdapter.set(target, prop, value, receiver);
},
ownKeys (target) {
const expression = '`...params` or similar expression';
warnForSyncAccess(workStore.route, expression);
return Reflect.ownKeys(target);
}
});
}
const warnForSyncAccess = createDedupedByCallsiteServerErrorLoggerDev(createParamsAccessError);
function createParamsAccessError(route, expression) {
const prefix = route ? `Route "${route}" ` : 'This route ';
return Object.defineProperty(new Error(`${prefix}used ${expression}. ` + `\`params\` is a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. ` + `Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`), "__NEXT_ERROR_CODE", {
value: "E834",
enumerable: false,
configurable: true
});
}
//# sourceMappingURL=params.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,94 @@
import { delayUntilRuntimeStage, postponeWithTracking } from '../app-render/dynamic-rendering';
import { throwInvariantForMissingStore, workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external';
import { makeHangingPromise } from '../dynamic-rendering-utils';
import { InvariantError } from '../../shared/lib/invariant-error';
export function createServerPathnameForMetadata(underlyingPathname, workStore) {
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
case 'prerender-client':
case 'prerender-ppr':
case 'prerender-legacy':
{
return createPrerenderPathname(underlyingPathname, workStore, workUnitStore);
}
case 'cache':
case 'private-cache':
case 'unstable-cache':
throw Object.defineProperty(new InvariantError('createServerPathnameForMetadata should not be called in cache contexts.'), "__NEXT_ERROR_CODE", {
value: "E740",
enumerable: false,
configurable: true
});
case 'prerender-runtime':
return delayUntilRuntimeStage(workUnitStore, createRenderPathname(underlyingPathname));
case 'request':
return createRenderPathname(underlyingPathname);
default:
workUnitStore;
}
}
throwInvariantForMissingStore();
}
function createPrerenderPathname(underlyingPathname, workStore, prerenderStore) {
switch(prerenderStore.type){
case 'prerender-client':
throw Object.defineProperty(new InvariantError('createPrerenderPathname was called inside a client component scope.'), "__NEXT_ERROR_CODE", {
value: "E694",
enumerable: false,
configurable: true
});
case 'prerender':
{
const fallbackParams = prerenderStore.fallbackRouteParams;
if (fallbackParams && fallbackParams.size > 0) {
return makeHangingPromise(prerenderStore.renderSignal, workStore.route, '`pathname`');
}
break;
}
case 'prerender-ppr':
{
const fallbackParams = prerenderStore.fallbackRouteParams;
if (fallbackParams && fallbackParams.size > 0) {
return makeErroringPathname(workStore, prerenderStore.dynamicTracking);
}
break;
}
case 'prerender-legacy':
break;
default:
prerenderStore;
}
// We don't have any fallback params so we have an entirely static safe params object
return Promise.resolve(underlyingPathname);
}
function makeErroringPathname(workStore, dynamicTracking) {
let reject = null;
const promise = new Promise((_, re)=>{
reject = re;
});
const originalThen = promise.then.bind(promise);
// We instrument .then so that we can generate a tracking event only if you actually
// await this promise, not just that it is created.
promise.then = (onfulfilled, onrejected)=>{
if (reject) {
try {
postponeWithTracking(workStore.route, 'metadata relative url resolving', dynamicTracking);
} catch (error) {
reject(error);
reject = null;
}
}
return originalThen(onfulfilled, onrejected);
};
// We wrap in a noop proxy to trick the runtime into thinking it
// isn't a native promise (it's not really). This is so that awaiting
// the promise will call the `then` property triggering the lazy postpone
return new Proxy(promise, {});
}
function createRenderPathname(underlyingPathname) {
return Promise.resolve(underlyingPathname);
}
//# sourceMappingURL=pathname.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,150 @@
import { InvariantError } from '../../shared/lib/invariant-error';
import { postponeWithTracking, throwToInterruptStaticGeneration } from '../app-render/dynamic-rendering';
import { workAsyncStorage } from '../app-render/work-async-storage.external';
import { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external';
import { makeHangingPromise } from '../dynamic-rendering-utils';
import { describeStringPropertyAccess } from '../../shared/lib/utils/reflect-utils';
import { actionAsyncStorage } from '../app-render/action-async-storage.external';
/**
* Used for the compiler-generated `next/root-params` module.
* @internal
*/ export function getRootParam(paramName) {
const apiName = `\`import('next/root-params').${paramName}()\``;
const workStore = workAsyncStorage.getStore();
if (!workStore) {
throw Object.defineProperty(new InvariantError(`Missing workStore in ${apiName}`), "__NEXT_ERROR_CODE", {
value: "E764",
enumerable: false,
configurable: true
});
}
const workUnitStore = workUnitAsyncStorage.getStore();
if (!workUnitStore) {
throw Object.defineProperty(new Error(`Route ${workStore.route} used ${apiName} outside of a Server Component. This is not allowed.`), "__NEXT_ERROR_CODE", {
value: "E774",
enumerable: false,
configurable: true
});
}
const actionStore = actionAsyncStorage.getStore();
if (actionStore) {
if (actionStore.isAppRoute) {
// TODO(root-params): add support for route handlers
throw Object.defineProperty(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.`), "__NEXT_ERROR_CODE", {
value: "E765",
enumerable: false,
configurable: true
});
}
if (actionStore.isAction && workUnitStore.phase === 'action') {
// Actions are not fundamentally tied to a route (even if they're always submitted from some page),
// so root params would be inconsistent if an action is called from multiple roots.
// Make sure we check if the phase is "action" - we should not error in the rerender
// after an action revalidates or updates cookies (which will still have `actionStore.isAction === true`)
throw Object.defineProperty(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.`), "__NEXT_ERROR_CODE", {
value: "E766",
enumerable: false,
configurable: true
});
}
}
switch(workUnitStore.type){
case 'unstable-cache':
case 'cache':
{
throw Object.defineProperty(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.`), "__NEXT_ERROR_CODE", {
value: "E760",
enumerable: false,
configurable: true
});
}
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;
}
}
return Promise.resolve(workUnitStore.rootParams[paramName]);
}
function createPrerenderRootParamPromise(paramName, workStore, prerenderStore, apiName) {
switch(prerenderStore.type){
case 'prerender-client':
{
throw Object.defineProperty(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.`), "__NEXT_ERROR_CODE", {
value: "E693",
enumerable: false,
configurable: true
});
}
case 'prerender':
case 'prerender-legacy':
case 'prerender-ppr':
default:
}
const underlyingParams = prerenderStore.rootParams;
switch(prerenderStore.type){
case 'prerender':
{
// We are in a cacheComponents prerender.
// The param is a fallback, so it should be treated as dynamic.
if (prerenderStore.fallbackRouteParams && prerenderStore.fallbackRouteParams.has(paramName)) {
return makeHangingPromise(prerenderStore.renderSignal, workStore.route, apiName);
}
break;
}
case 'prerender-ppr':
{
// We aren't in a cacheComponents prerender, but the param is a fallback,
// so we need to make an erroring params object which will postpone/error if you access it
if (prerenderStore.fallbackRouteParams && prerenderStore.fallbackRouteParams.has(paramName)) {
return makeErroringRootParamPromise(paramName, workStore, prerenderStore, apiName);
}
break;
}
case 'prerender-legacy':
{
break;
}
default:
{
prerenderStore;
}
}
// If the param is not a fallback param, we just return the statically available value.
return Promise.resolve(underlyingParams[paramName]);
}
/** Deliberately async -- we want to create a rejected promise, not error synchronously. */ async function makeErroringRootParamPromise(paramName, workStore, prerenderStore, apiName) {
const expression = describeStringPropertyAccess(apiName, paramName);
// In most dynamic APIs, we also throw if `dynamic = "error"`.
// However, root params are only dynamic when we're generating a fallback shell,
// and even with `dynamic = "error"` we still support generating dynamic fallback shells.
// TODO: remove this comment when cacheComponents is the default since there will be no `dynamic = "error"`
switch(prerenderStore.type){
case 'prerender-ppr':
{
return postponeWithTracking(workStore.route, expression, prerenderStore.dynamicTracking);
}
case 'prerender-legacy':
{
return throwToInterruptStaticGeneration(expression, workStore, prerenderStore);
}
default:
{
prerenderStore;
}
}
}
//# sourceMappingURL=root-params.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,403 @@
import { ReflectAdapter } from '../web/spec-extension/adapters/reflect';
import { throwToInterruptStaticGeneration, postponeWithTracking, annotateDynamicAccess, delayUntilRuntimeStage } from '../app-render/dynamic-rendering';
import { workUnitAsyncStorage, throwInvariantForMissingStore } from '../app-render/work-unit-async-storage.external';
import { InvariantError } from '../../shared/lib/invariant-error';
import { makeDevtoolsIOAwarePromise, makeHangingPromise } from '../dynamic-rendering-utils';
import { createDedupedByCallsiteServerErrorLoggerDev } from '../create-deduped-by-callsite-server-error-logger';
import { describeStringPropertyAccess, describeHasCheckingStringProperty, wellKnownProperties } from '../../shared/lib/utils/reflect-utils';
import { throwWithStaticGenerationBailoutErrorWithDynamicError, throwForSearchParamsAccessInUseCache } from './utils';
import { RenderStage } from '../app-render/staged-rendering';
export function createSearchParamsFromClient(underlyingSearchParams, workStore) {
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
case 'prerender-client':
case 'prerender-ppr':
case 'prerender-legacy':
return createStaticPrerenderSearchParams(workStore, workUnitStore);
case 'prerender-runtime':
throw Object.defineProperty(new InvariantError('createSearchParamsFromClient should not be called in a runtime prerender.'), "__NEXT_ERROR_CODE", {
value: "E769",
enumerable: false,
configurable: true
});
case 'cache':
case 'private-cache':
case 'unstable-cache':
throw Object.defineProperty(new InvariantError('createSearchParamsFromClient should not be called in cache contexts.'), "__NEXT_ERROR_CODE", {
value: "E739",
enumerable: false,
configurable: true
});
case 'request':
return createRenderSearchParams(underlyingSearchParams, workStore, workUnitStore);
default:
workUnitStore;
}
}
throwInvariantForMissingStore();
}
// generateMetadata always runs in RSC context so it is equivalent to a Server Page Component
export const createServerSearchParamsForMetadata = createServerSearchParamsForServerPage;
export function createServerSearchParamsForServerPage(underlyingSearchParams, workStore) {
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
case 'prerender-client':
case 'prerender-ppr':
case 'prerender-legacy':
return createStaticPrerenderSearchParams(workStore, workUnitStore);
case 'cache':
case 'private-cache':
case 'unstable-cache':
throw Object.defineProperty(new InvariantError('createServerSearchParamsForServerPage should not be called in cache contexts.'), "__NEXT_ERROR_CODE", {
value: "E747",
enumerable: false,
configurable: true
});
case 'prerender-runtime':
return createRuntimePrerenderSearchParams(underlyingSearchParams, workUnitStore);
case 'request':
return createRenderSearchParams(underlyingSearchParams, workStore, workUnitStore);
default:
workUnitStore;
}
}
throwInvariantForMissingStore();
}
export function createPrerenderSearchParamsForClientPage(workStore) {
if (workStore.forceStatic) {
// When using forceStatic we override all other logic and always just return an empty
// dictionary object.
return Promise.resolve({});
}
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
switch(workUnitStore.type){
case 'prerender':
case 'prerender-client':
// We're prerendering in a mode that aborts (cacheComponents) and should stall
// the promise to ensure the RSC side is considered dynamic
return makeHangingPromise(workUnitStore.renderSignal, workStore.route, '`searchParams`');
case 'prerender-runtime':
throw Object.defineProperty(new InvariantError('createPrerenderSearchParamsForClientPage should not be called in a runtime prerender.'), "__NEXT_ERROR_CODE", {
value: "E768",
enumerable: false,
configurable: true
});
case 'cache':
case 'private-cache':
case 'unstable-cache':
throw Object.defineProperty(new InvariantError('createPrerenderSearchParamsForClientPage should not be called in cache contexts.'), "__NEXT_ERROR_CODE", {
value: "E746",
enumerable: false,
configurable: true
});
case 'prerender-ppr':
case 'prerender-legacy':
case 'request':
return Promise.resolve({});
default:
workUnitStore;
}
}
throwInvariantForMissingStore();
}
function createStaticPrerenderSearchParams(workStore, prerenderStore) {
if (workStore.forceStatic) {
// When using forceStatic we override all other logic and always just return an empty
// dictionary object.
return Promise.resolve({});
}
switch(prerenderStore.type){
case 'prerender':
case 'prerender-client':
// We are in a cacheComponents (PPR or otherwise) prerender
return makeHangingSearchParams(workStore, prerenderStore);
case 'prerender-ppr':
case 'prerender-legacy':
// We are in a legacy static generation and need to interrupt the
// prerender when search params are accessed.
return makeErroringSearchParams(workStore, prerenderStore);
default:
return prerenderStore;
}
}
function createRuntimePrerenderSearchParams(underlyingSearchParams, workUnitStore) {
return delayUntilRuntimeStage(workUnitStore, makeUntrackedSearchParams(underlyingSearchParams));
}
function createRenderSearchParams(underlyingSearchParams, workStore, requestStore) {
if (workStore.forceStatic) {
// When using forceStatic we override all other logic and always just return an empty
// dictionary object.
return Promise.resolve({});
} else {
if (process.env.NODE_ENV === 'development') {
// Semantically we only need the dev tracking when running in `next dev`
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
return makeUntrackedSearchParamsWithDevWarnings(underlyingSearchParams, workStore, requestStore);
} else {
return makeUntrackedSearchParams(underlyingSearchParams);
}
}
}
const CachedSearchParams = new WeakMap();
const CachedSearchParamsForUseCache = new WeakMap();
function makeHangingSearchParams(workStore, prerenderStore) {
const cachedSearchParams = CachedSearchParams.get(prerenderStore);
if (cachedSearchParams) {
return cachedSearchParams;
}
const promise = makeHangingPromise(prerenderStore.renderSignal, workStore.route, '`searchParams`');
const proxiedPromise = new Proxy(promise, {
get (target, prop, receiver) {
if (Object.hasOwn(promise, prop)) {
// The promise has this property directly. we must return it.
// We know it isn't a dynamic access because it can only be something
// that was previously written to the promise and thus not an underlying searchParam value
return ReflectAdapter.get(target, prop, receiver);
}
switch(prop){
case 'then':
{
const expression = '`await searchParams`, `searchParams.then`, or similar';
annotateDynamicAccess(expression, prerenderStore);
return ReflectAdapter.get(target, prop, receiver);
}
case 'status':
{
const expression = '`use(searchParams)`, `searchParams.status`, or similar';
annotateDynamicAccess(expression, prerenderStore);
return ReflectAdapter.get(target, prop, receiver);
}
default:
{
return ReflectAdapter.get(target, prop, receiver);
}
}
}
});
CachedSearchParams.set(prerenderStore, proxiedPromise);
return proxiedPromise;
}
function makeErroringSearchParams(workStore, prerenderStore) {
const cachedSearchParams = CachedSearchParams.get(workStore);
if (cachedSearchParams) {
return cachedSearchParams;
}
const underlyingSearchParams = {};
// For search params we don't construct a ReactPromise because we want to interrupt
// rendering on any property access that was not set from outside and so we only want
// to have properties like value and status if React sets them.
const promise = Promise.resolve(underlyingSearchParams);
const proxiedPromise = new Proxy(promise, {
get (target, prop, receiver) {
if (Object.hasOwn(promise, prop)) {
// The promise has this property directly. we must return it.
// We know it isn't a dynamic access because it can only be something
// that was previously written to the promise and thus not an underlying searchParam value
return ReflectAdapter.get(target, prop, receiver);
}
if (typeof prop === 'string' && prop === 'then') {
const expression = '`await searchParams`, `searchParams.then`, or similar';
if (workStore.dynamicShouldError) {
throwWithStaticGenerationBailoutErrorWithDynamicError(workStore.route, expression);
} else if (prerenderStore.type === 'prerender-ppr') {
// PPR Prerender (no cacheComponents)
postponeWithTracking(workStore.route, expression, prerenderStore.dynamicTracking);
} else {
// Legacy Prerender
throwToInterruptStaticGeneration(expression, workStore, prerenderStore);
}
}
return ReflectAdapter.get(target, prop, receiver);
}
});
CachedSearchParams.set(workStore, proxiedPromise);
return proxiedPromise;
}
/**
* This is a variation of `makeErroringSearchParams` that always throws an
* error on access, because accessing searchParams inside of `"use cache"` is
* not allowed.
*/ export function makeErroringSearchParamsForUseCache(workStore) {
const cachedSearchParams = CachedSearchParamsForUseCache.get(workStore);
if (cachedSearchParams) {
return cachedSearchParams;
}
const promise = Promise.resolve({});
const proxiedPromise = new Proxy(promise, {
get: function get(target, prop, receiver) {
if (Object.hasOwn(promise, prop)) {
// The promise has this property directly. we must return it. We know it
// isn't a dynamic access because it can only be something that was
// previously written to the promise and thus not an underlying
// searchParam value
return ReflectAdapter.get(target, prop, receiver);
}
if (typeof prop === 'string' && (prop === 'then' || !wellKnownProperties.has(prop))) {
throwForSearchParamsAccessInUseCache(workStore, get);
}
return ReflectAdapter.get(target, prop, receiver);
}
});
CachedSearchParamsForUseCache.set(workStore, proxiedPromise);
return proxiedPromise;
}
function makeUntrackedSearchParams(underlyingSearchParams) {
const cachedSearchParams = CachedSearchParams.get(underlyingSearchParams);
if (cachedSearchParams) {
return cachedSearchParams;
}
const promise = Promise.resolve(underlyingSearchParams);
CachedSearchParams.set(underlyingSearchParams, promise);
return promise;
}
function makeUntrackedSearchParamsWithDevWarnings(underlyingSearchParams, workStore, requestStore) {
if (requestStore.asyncApiPromises) {
// Do not cache the resulting promise. If we do, we'll only show the first "awaited at"
// across all segments that receive searchParams.
return makeUntrackedSearchParamsWithDevWarningsImpl(underlyingSearchParams, workStore, requestStore);
} else {
const cachedSearchParams = CachedSearchParams.get(underlyingSearchParams);
if (cachedSearchParams) {
return cachedSearchParams;
}
const promise = makeUntrackedSearchParamsWithDevWarningsImpl(underlyingSearchParams, workStore, requestStore);
CachedSearchParams.set(requestStore, promise);
return promise;
}
}
function makeUntrackedSearchParamsWithDevWarningsImpl(underlyingSearchParams, workStore, requestStore) {
const promiseInitialized = {
current: false
};
const proxiedUnderlying = instrumentSearchParamsObjectWithDevWarnings(underlyingSearchParams, workStore, promiseInitialized);
let promise;
if (requestStore.asyncApiPromises) {
// We wrap each instance of searchParams in a `new Promise()`.
// This is important when all awaits are in third party which would otherwise
// track all the way to the internal params.
const sharedSearchParamsParent = requestStore.asyncApiPromises.sharedSearchParamsParent;
promise = new Promise((resolve, reject)=>{
sharedSearchParamsParent.then(()=>resolve(proxiedUnderlying), reject);
});
// @ts-expect-error
promise.displayName = 'searchParams';
} else {
promise = makeDevtoolsIOAwarePromise(proxiedUnderlying, requestStore, RenderStage.Runtime);
}
promise.then(()=>{
promiseInitialized.current = true;
}, // If we're in staged rendering, this promise will reject if the render
// is aborted before it can reach the runtime stage.
// In that case, we have to prevent an unhandled rejection from the promise
// created by this `.then()` call.
// This does not affect the `promiseInitialized` logic above,
// because `proxiedUnderlying` will not be used to resolve the promise,
// so there's no risk of any of its properties being accessed and triggering
// an undesireable warning.
ignoreReject);
return instrumentSearchParamsPromiseWithDevWarnings(underlyingSearchParams, promise, workStore);
}
function ignoreReject() {}
function instrumentSearchParamsObjectWithDevWarnings(underlyingSearchParams, workStore, promiseInitialized) {
// We have an unfortunate sequence of events that requires this initialization logic. We want to instrument the underlying
// searchParams object to detect if you are accessing values in dev. This is used for warnings and for things like the static prerender
// indicator. However when we pass this proxy to our Promise.resolve() below the VM checks if the resolved value is a promise by looking
// at the `.then` property. To our dynamic tracking logic this is indistinguishable from a `then` searchParam and so we would normally trigger
// dynamic tracking. However we know that this .then is not real dynamic access, it's just how thenables resolve in sequence. So we introduce
// this initialization concept so we omit the dynamic check until after we've constructed our resolved promise.
return new Proxy(underlyingSearchParams, {
get (target, prop, receiver) {
if (typeof prop === 'string' && promiseInitialized.current) {
if (workStore.dynamicShouldError) {
const expression = describeStringPropertyAccess('searchParams', prop);
throwWithStaticGenerationBailoutErrorWithDynamicError(workStore.route, expression);
}
}
return ReflectAdapter.get(target, prop, receiver);
},
has (target, prop) {
if (typeof prop === 'string') {
if (workStore.dynamicShouldError) {
const expression = describeHasCheckingStringProperty('searchParams', prop);
throwWithStaticGenerationBailoutErrorWithDynamicError(workStore.route, expression);
}
}
return Reflect.has(target, prop);
},
ownKeys (target) {
if (workStore.dynamicShouldError) {
const expression = '`{...searchParams}`, `Object.keys(searchParams)`, or similar';
throwWithStaticGenerationBailoutErrorWithDynamicError(workStore.route, expression);
}
return Reflect.ownKeys(target);
}
});
}
function instrumentSearchParamsPromiseWithDevWarnings(underlyingSearchParams, promise, workStore) {
// Track which properties we should warn for.
const proxiedProperties = new Set();
Object.keys(underlyingSearchParams).forEach((prop)=>{
if (wellKnownProperties.has(prop)) {
// These properties cannot be shadowed because they need to be the
// true underlying value for Promises to work correctly at runtime
} else {
proxiedProperties.add(prop);
}
});
return new Proxy(promise, {
get (target, prop, receiver) {
if (prop === 'then' && workStore.dynamicShouldError) {
const expression = '`searchParams.then`';
throwWithStaticGenerationBailoutErrorWithDynamicError(workStore.route, expression);
}
if (typeof prop === 'string') {
if (!wellKnownProperties.has(prop) && (proxiedProperties.has(prop) || // We are accessing a property that doesn't exist on the promise nor
// the underlying searchParams.
Reflect.has(target, prop) === false)) {
const expression = describeStringPropertyAccess('searchParams', prop);
warnForSyncAccess(workStore.route, expression);
}
}
return ReflectAdapter.get(target, prop, receiver);
},
set (target, prop, value, receiver) {
if (typeof prop === 'string') {
proxiedProperties.delete(prop);
}
return Reflect.set(target, prop, value, receiver);
},
has (target, prop) {
if (typeof prop === 'string') {
if (!wellKnownProperties.has(prop) && (proxiedProperties.has(prop) || // We are accessing a property that doesn't exist on the promise nor
// the underlying searchParams.
Reflect.has(target, prop) === false)) {
const expression = describeHasCheckingStringProperty('searchParams', prop);
warnForSyncAccess(workStore.route, expression);
}
}
return Reflect.has(target, prop);
},
ownKeys (target) {
const expression = '`Object.keys(searchParams)` or similar';
warnForSyncAccess(workStore.route, expression);
return Reflect.ownKeys(target);
}
});
}
const warnForSyncAccess = createDedupedByCallsiteServerErrorLoggerDev(createSearchAccessError);
function createSearchAccessError(route, expression) {
const prefix = route ? `Route "${route}" ` : 'This route ';
return Object.defineProperty(new Error(`${prefix}used ${expression}. ` + `\`searchParams\` is a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. ` + `Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`), "__NEXT_ERROR_CODE", {
value: "E848",
enumerable: false,
configurable: true
});
}
//# sourceMappingURL=search-params.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout';
import { afterTaskAsyncStorage } from '../app-render/after-task-async-storage.external';
export function throwWithStaticGenerationBailoutErrorWithDynamicError(route, expression) {
throw Object.defineProperty(new StaticGenBailoutError(`Route ${route} with \`dynamic = "error"\` couldn't be rendered statically because it used ${expression}. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`), "__NEXT_ERROR_CODE", {
value: "E543",
enumerable: false,
configurable: true
});
}
export function throwForSearchParamsAccessInUseCache(workStore, constructorOpt) {
const error = Object.defineProperty(new Error(`Route ${workStore.route} used \`searchParams\` inside "use cache". Accessing dynamic request data inside a cache scope is not supported. If you need some search params inside a cached function await \`searchParams\` outside of the cached function and pass only the required search params as arguments to the cached function. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`), "__NEXT_ERROR_CODE", {
value: "E842",
enumerable: false,
configurable: true
});
Error.captureStackTrace(error, constructorOpt);
workStore.invalidDynamicUsageError ??= error;
throw error;
}
export function isRequestAPICallableInsideAfter() {
const afterTaskStore = afterTaskAsyncStorage.getStore();
return (afterTaskStore == null ? void 0 : afterTaskStore.rootTaskSpawnPhase) === 'action';
}
//# sourceMappingURL=utils.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/server/request/utils.ts"],"sourcesContent":["import { StaticGenBailoutError } from '../../client/components/static-generation-bailout'\nimport { afterTaskAsyncStorage } from '../app-render/after-task-async-storage.external'\nimport type { WorkStore } from '../app-render/work-async-storage.external'\n\nexport function throwWithStaticGenerationBailoutErrorWithDynamicError(\n route: string,\n expression: string\n): never {\n throw new StaticGenBailoutError(\n `Route ${route} with \\`dynamic = \"error\"\\` couldn't be rendered statically because it used ${expression}. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`\n )\n}\n\nexport function throwForSearchParamsAccessInUseCache(\n workStore: WorkStore,\n constructorOpt: Function\n): never {\n const error = new Error(\n `Route ${workStore.route} used \\`searchParams\\` inside \"use cache\". Accessing dynamic request data inside a cache scope is not supported. If you need some search params inside a cached function await \\`searchParams\\` outside of the cached function and pass only the required search params as arguments to the cached function. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`\n )\n\n Error.captureStackTrace(error, constructorOpt)\n workStore.invalidDynamicUsageError ??= error\n\n throw error\n}\n\nexport function isRequestAPICallableInsideAfter() {\n const afterTaskStore = afterTaskAsyncStorage.getStore()\n return afterTaskStore?.rootTaskSpawnPhase === 'action'\n}\n"],"names":["StaticGenBailoutError","afterTaskAsyncStorage","throwWithStaticGenerationBailoutErrorWithDynamicError","route","expression","throwForSearchParamsAccessInUseCache","workStore","constructorOpt","error","Error","captureStackTrace","invalidDynamicUsageError","isRequestAPICallableInsideAfter","afterTaskStore","getStore","rootTaskSpawnPhase"],"mappings":"AAAA,SAASA,qBAAqB,QAAQ,oDAAmD;AACzF,SAASC,qBAAqB,QAAQ,kDAAiD;AAGvF,OAAO,SAASC,sDACdC,KAAa,EACbC,UAAkB;IAElB,MAAM,qBAEL,CAFK,IAAIJ,sBACR,CAAC,MAAM,EAAEG,MAAM,4EAA4E,EAAEC,WAAW,0HAA0H,CAAC,GAD/N,qBAAA;eAAA;oBAAA;sBAAA;IAEN;AACF;AAEA,OAAO,SAASC,qCACdC,SAAoB,EACpBC,cAAwB;IAExB,MAAMC,QAAQ,qBAEb,CAFa,IAAIC,MAChB,CAAC,MAAM,EAAEH,UAAUH,KAAK,CAAC,2XAA2X,CAAC,GADzY,qBAAA;eAAA;oBAAA;sBAAA;IAEd;IAEAM,MAAMC,iBAAiB,CAACF,OAAOD;IAC/BD,UAAUK,wBAAwB,KAAKH;IAEvC,MAAMA;AACR;AAEA,OAAO,SAASI;IACd,MAAMC,iBAAiBZ,sBAAsBa,QAAQ;IACrD,OAAOD,CAAAA,kCAAAA,eAAgBE,kBAAkB,MAAK;AAChD","ignoreList":[0]}