This commit is contained in:
Kismet Hasanaj
2026-05-02 20:07:02 +02:00
parent ce8672e283
commit 34dc9aec52
9428 changed files with 1733330 additions and 0 deletions
@@ -0,0 +1,96 @@
export type Instant = InstantConfigStatic | InstantConfigRuntime | false;
export type InstantConfigForTypeCheckInternal = __GenericInstantConfig | Instant;
interface __GenericInstantConfig {
prefetch: string;
samples?: Array<WideInstantSample>;
from?: string[];
unstable_disableValidation?: boolean;
unstable_disableDevValidation?: boolean;
unstable_disableBuildValidation?: boolean;
}
interface InstantConfigStatic {
prefetch: 'static';
samples?: Array<InstantSample>;
from?: string[];
unstable_disableValidation?: true;
unstable_disableDevValidation?: true;
unstable_disableBuildValidation?: true;
}
interface InstantConfigRuntime {
prefetch: 'runtime';
samples: Array<InstantSample>;
from?: string[];
unstable_disableValidation?: true;
unstable_disableDevValidation?: true;
unstable_disableBuildValidation?: true;
}
type WideInstantSample = {
cookies?: InstantSample['cookies'];
headers?: Array<string[]>;
params?: InstantSample['params'];
searchParams?: InstantSample['searchParams'];
};
export type InstantSample = {
cookies?: Array<{
name: string;
value: string | null;
}>;
headers?: Array<[string, string | null]>;
params?: {
[key: string]: string | string[];
};
searchParams?: {
[key: string]: string | string[] | null;
};
};
/**
* Parse the app segment config.
* @param data - The data to parse.
* @param route - The route of the app.
* @returns The parsed app segment config.
*/
export declare function parseAppSegmentConfig(data: unknown, route: string): AppSegmentConfig;
/**
* The configuration for a page.
*/
export type AppSegmentConfig = {
/**
* The revalidation period for the page in seconds, or false to disable ISR.
*/
revalidate?: number | false;
/**
* Whether the page supports dynamic parameters.
*/
dynamicParams?: boolean;
/**
* The dynamic behavior of the page.
*/
dynamic?: 'auto' | 'error' | 'force-static' | 'force-dynamic';
/**
* The caching behavior of the page.
*/
fetchCache?: 'auto' | 'default-cache' | 'default-no-store' | 'force-cache' | 'force-no-store' | 'only-cache' | 'only-no-store';
/**
* How this segment should be prefetched.
*/
unstable_instant?: Instant;
/**
* The stale time for dynamic responses in seconds.
* Controls how long the client-side router cache retains dynamic page data.
* Pages only — not allowed in layouts.
*/
unstable_dynamicStaleTime?: number;
/**
* The preferred region for the page.
*/
preferredRegion?: string | string[];
/**
* The runtime to use for the page.
*/
runtime?: 'edge' | 'nodejs';
/**
* The maximum duration for the page in seconds.
*/
maxDuration?: number;
};
export {};
+162
View File
@@ -0,0 +1,162 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
AppSegmentConfigSchemaKeys: null,
parseAppSegmentConfig: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
AppSegmentConfigSchemaKeys: function() {
return AppSegmentConfigSchemaKeys;
},
parseAppSegmentConfig: function() {
return parseAppSegmentConfig;
}
});
const _zod = require("next/dist/compiled/zod");
const _zod1 = require("../../../shared/lib/zod");
const CookieSchema = _zod.z.object({
name: _zod.z.string(),
value: _zod.z.string().or(_zod.z.null())
}).strict();
const RuntimeSampleSchema = _zod.z.object({
cookies: _zod.z.array(CookieSchema).optional(),
headers: _zod.z.array(_zod.z.tuple([
_zod.z.string(),
_zod.z.string().or(_zod.z.null())
])).optional(),
params: _zod.z.record(_zod.z.union([
_zod.z.string(),
_zod.z.array(_zod.z.string())
])).optional(),
searchParams: _zod.z.record(_zod.z.union([
_zod.z.string(),
_zod.z.array(_zod.z.string()),
_zod.z.null()
])).optional()
}).strict();
const InstantConfigStaticSchema = _zod.z.object({
prefetch: _zod.z.literal('static'),
samples: _zod.z.array(RuntimeSampleSchema).min(1).optional(),
from: _zod.z.array(_zod.z.string()).optional(),
unstable_disableValidation: _zod.z.literal(true).optional(),
unstable_disableDevValidation: _zod.z.literal(true).optional(),
unstable_disableBuildValidation: _zod.z.literal(true).optional()
}).strict();
const InstantConfigRuntimeSchema = _zod.z.object({
prefetch: _zod.z.literal('runtime'),
samples: _zod.z.array(RuntimeSampleSchema).min(1),
from: _zod.z.array(_zod.z.string()).optional(),
unstable_disableValidation: _zod.z.literal(true).optional(),
unstable_disableDevValidation: _zod.z.literal(true).optional(),
unstable_disableBuildValidation: _zod.z.literal(true).optional()
}).strict();
const InstantConfigSchema = _zod.z.union([
_zod.z.discriminatedUnion('prefetch', [
InstantConfigStaticSchema,
InstantConfigRuntimeSchema
]),
_zod.z.literal(false)
]);
/**
* The schema for configuration for a page.
*/ const AppSegmentConfigSchema = _zod.z.object({
/**
* The number of seconds to revalidate the page or false to disable revalidation.
*/ revalidate: _zod.z.union([
_zod.z.number().int().nonnegative(),
_zod.z.literal(false)
]).optional(),
/**
* Whether the page supports dynamic parameters.
*/ dynamicParams: _zod.z.boolean().optional(),
/**
* The dynamic behavior of the page.
*/ dynamic: _zod.z.enum([
'auto',
'error',
'force-static',
'force-dynamic'
]).optional(),
/**
* The caching behavior of the page.
*/ fetchCache: _zod.z.enum([
'auto',
'default-cache',
'only-cache',
'force-cache',
'force-no-store',
'default-no-store',
'only-no-store'
]).optional(),
/**
* How this segment should be prefetched.
*/ unstable_instant: InstantConfigSchema.optional(),
/**
* The stale time for dynamic responses in seconds.
* Controls how long the client-side router cache retains dynamic page data.
* Pages only — not allowed in layouts.
*/ unstable_dynamicStaleTime: _zod.z.number().int().nonnegative().optional(),
/**
* The preferred region for the page.
*/ preferredRegion: _zod.z.union([
_zod.z.string(),
_zod.z.array(_zod.z.string())
]).optional(),
/**
* The runtime to use for the page.
*/ runtime: _zod.z.enum([
'edge',
'nodejs'
]).optional(),
/**
* The maximum duration for the page in seconds.
*/ maxDuration: _zod.z.number().int().nonnegative().optional()
});
function parseAppSegmentConfig(data, route) {
const parsed = AppSegmentConfigSchema.safeParse(data, {
errorMap: (issue, ctx)=>{
if (issue.path.length === 1) {
switch(issue.path[0]){
case 'revalidate':
{
return {
message: `Invalid revalidate value ${JSON.stringify(ctx.data)} on "${route}", must be a non-negative number or false`
};
}
case 'unstable_instant':
{
return {
// @TODO replace this link with a link to the docs when they are written
message: `Invalid unstable_instant value ${JSON.stringify(ctx.data)} on "${route}", must be an object with \`prefetch: "static"\` or \`prefetch: "runtime"\`, or \`false\`. Read more at https://nextjs.org/docs/messages/invalid-instant-configuration`
};
}
case 'unstable_dynamicStaleTime':
{
return {
message: `Invalid unstable_dynamicStaleTime value ${JSON.stringify(ctx.data)} on "${route}", must be a non-negative number`
};
}
default:
}
}
return {
message: ctx.defaultError
};
}
});
if (!parsed.success) {
throw (0, _zod1.formatZodError)(`Invalid segment configuration options detected for "${route}". Read more at https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config`, parsed.error);
}
return parsed.data;
}
const AppSegmentConfigSchemaKeys = AppSegmentConfigSchema.keyof().options;
//# sourceMappingURL=app-segment-config.js.map
File diff suppressed because one or more lines are too long
+24
View File
@@ -0,0 +1,24 @@
import type { Params } from '../../../server/request/params';
import type { AppPageRouteModule } from '../../../server/route-modules/app-page/module.compiled';
import type { AppRouteRouteModule } from '../../../server/route-modules/app-route/module.compiled';
import { type AppSegmentConfig } from './app-segment-config';
import type { DynamicParamTypes } from '../../../shared/lib/app-router-types';
type GenerateStaticParams = (options: {
params?: Params;
}) => Promise<Params[]>;
export type AppSegment = {
name: string;
paramName: string | undefined;
paramType: DynamicParamTypes | undefined;
filePath: string | undefined;
config: AppSegmentConfig | undefined;
generateStaticParams: GenerateStaticParams | undefined;
};
/**
* Collects the segments for a given route module.
*
* @param components the loaded components
* @returns the segments for the route module
*/
export declare function collectSegments(routeModule: AppRouteRouteModule | AppPageRouteModule): Promise<AppSegment[]> | AppSegment[];
export {};
+137
View File
@@ -0,0 +1,137 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "collectSegments", {
enumerable: true,
get: function() {
return collectSegments;
}
});
const _appsegmentconfig = require("./app-segment-config");
const _invarianterror = require("../../../shared/lib/invariant-error");
const _checks = require("../../../server/route-modules/checks");
const _clientandserverreferences = require("../../../lib/client-and-server-references");
const _getsegmentparam = require("../../../shared/lib/router/utils/get-segment-param");
const _appdirmodule = require("../../../server/lib/app-dir-module");
/**
* Parses the app config and attaches it to the segment.
*/ function attach(segment, userland, route) {
// If the userland is not an object, then we can't do anything with it.
if (typeof userland !== 'object' || userland === null) {
return;
}
// Try to parse the application configuration.
const config = (0, _appsegmentconfig.parseAppSegmentConfig)(userland, route);
// If there was any keys on the config, then attach it to the segment.
if (Object.keys(config).length > 0) {
segment.config = config;
}
if ('generateStaticParams' in userland && typeof userland.generateStaticParams === 'function') {
var _segment_config;
segment.generateStaticParams = userland.generateStaticParams;
// Validate that `generateStaticParams` makes sense in this context.
if (((_segment_config = segment.config) == null ? void 0 : _segment_config.runtime) === 'edge') {
throw Object.defineProperty(new Error('Edge runtime is not supported with `generateStaticParams`.'), "__NEXT_ERROR_CODE", {
value: "E502",
enumerable: false,
configurable: true
});
}
}
}
/**
* Walks the loader tree and collects the generate parameters for each segment.
*
* @param routeModule the app page route module
* @returns the segments for the app page route module
*/ async function collectAppPageSegments(routeModule) {
// We keep track of unique segments, since with parallel routes, it's possible
// to see the same segment multiple times.
const segments = [];
// Queue will store loader trees.
const queue = [
routeModule.userland.loaderTree
];
while(queue.length > 0){
const loaderTree = queue.shift();
const [name, parallelRoutes] = loaderTree;
// Process current node
const { mod: userland, filePath } = await (0, _appdirmodule.getLayoutOrPageModule)(loaderTree);
const isClientComponent = userland && (0, _clientandserverreferences.isClientReference)(userland);
const param = (0, _getsegmentparam.getSegmentParam)(name);
const segment = {
name,
paramName: param == null ? void 0 : param.paramName,
paramType: param == null ? void 0 : param.paramType,
filePath,
config: undefined,
generateStaticParams: undefined
};
// Only server components can have app segment configurations
if (!isClientComponent) {
attach(segment, userland, routeModule.definition.pathname);
}
// If this segment doesn't already exist, then add it to the segments array.
// The list of segments is short so we just use a list traversal to check
// for duplicates and spare us needing to maintain the string key.
if (segments.every((s)=>s.name !== segment.name || s.paramName !== segment.paramName || s.paramType !== segment.paramType || s.filePath !== segment.filePath)) {
segments.push(segment);
}
// Add all parallel routes to the queue
for (const parallelRoute of Object.values(parallelRoutes)){
queue.push(parallelRoute);
}
}
return segments;
}
/**
* Collects the segments for a given app route module.
*
* @param routeModule the app route module
* @returns the segments for the app route module
*/ function collectAppRouteSegments(routeModule) {
// Get the pathname parts, slice off the first element (which is empty).
const parts = routeModule.definition.pathname.split('/').slice(1);
if (parts.length === 0) {
throw Object.defineProperty(new _invarianterror.InvariantError('Expected at least one segment'), "__NEXT_ERROR_CODE", {
value: "E580",
enumerable: false,
configurable: true
});
}
// Generate all the segments.
const segments = parts.map((name)=>{
const param = (0, _getsegmentparam.getSegmentParam)(name);
return {
name,
paramName: param == null ? void 0 : param.paramName,
paramType: param == null ? void 0 : param.paramType,
filePath: undefined,
config: undefined,
generateStaticParams: undefined
};
});
// We know we have at least one, we verified this above. We should get the
// last segment which represents the root route module.
const segment = segments[segments.length - 1];
segment.filePath = routeModule.definition.filename;
// Extract the segment config from the userland module.
attach(segment, routeModule.userland, routeModule.definition.pathname);
return segments;
}
function collectSegments(routeModule) {
if ((0, _checks.isAppRouteRouteModule)(routeModule)) {
return collectAppRouteSegments(routeModule);
}
if ((0, _checks.isAppPageRouteModule)(routeModule)) {
return collectAppPageSegments(routeModule);
}
throw Object.defineProperty(new _invarianterror.InvariantError('Expected a route module to be one of app route or page'), "__NEXT_ERROR_CODE", {
value: "E568",
enumerable: false,
configurable: true
});
}
//# sourceMappingURL=app-segments.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
import type { RouteModule } from '../../../server/route-modules/route-module';
/**
* Collects the segments for a given route module.
*
* @param components the loaded components
* @returns the segments for the route module
*/
export declare function collectRootParamKeys(routeModule: RouteModule): readonly string[];
@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "collectRootParamKeys", {
enumerable: true,
get: function() {
return collectRootParamKeys;
}
});
const _getsegmentparam = require("../../../shared/lib/router/utils/get-segment-param");
const _checks = require("../../../server/route-modules/checks");
const _invarianterror = require("../../../shared/lib/invariant-error");
function collectAppPageRootParamKeys(routeModule) {
let rootParams = [];
let current = routeModule.userland.loaderTree;
while(current){
var _getSegmentParam;
const [name, parallelRoutes, modules] = current;
// If this is a dynamic segment, then we collect the param.
const paramName = (_getSegmentParam = (0, _getsegmentparam.getSegmentParam)(name)) == null ? void 0 : _getSegmentParam.paramName;
if (paramName) {
rootParams.push(paramName);
}
// If this has a layout module, then we've found the root layout because
// we return once we found the first layout.
if (typeof modules.layout !== 'undefined') {
return rootParams;
}
// This didn't include a root layout, so we need to continue. We don't need
// to collect from other parallel routes because we can't have a parallel
// route above a root layout.
current = parallelRoutes.children;
}
// If we didn't find a root layout, then we don't have any params.
return [];
}
function collectRootParamKeys(routeModule) {
if ((0, _checks.isAppRouteRouteModule)(routeModule)) {
return [];
}
if ((0, _checks.isAppPageRouteModule)(routeModule)) {
return collectAppPageRootParamKeys(routeModule);
}
throw Object.defineProperty(new _invarianterror.InvariantError('Expected a route module to be one of app route or page'), "__NEXT_ERROR_CODE", {
value: "E568",
enumerable: false,
configurable: true
});
}
//# sourceMappingURL=collect-root-param-keys.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/segment-config/app/collect-root-param-keys.ts"],"sourcesContent":["import { getSegmentParam } from '../../../shared/lib/router/utils/get-segment-param'\nimport type AppPageRouteModule from '../../../server/route-modules/app-page/module'\nimport {\n isAppPageRouteModule,\n isAppRouteRouteModule,\n} from '../../../server/route-modules/checks'\nimport type { RouteModule } from '../../../server/route-modules/route-module'\nimport { InvariantError } from '../../../shared/lib/invariant-error'\n\nfunction collectAppPageRootParamKeys(\n routeModule: AppPageRouteModule\n): readonly string[] {\n let rootParams: string[] = []\n\n let current = routeModule.userland.loaderTree\n while (current) {\n const [name, parallelRoutes, modules] = current\n\n // If this is a dynamic segment, then we collect the param.\n const paramName = getSegmentParam(name)?.paramName\n if (paramName) {\n rootParams.push(paramName)\n }\n\n // If this has a layout module, then we've found the root layout because\n // we return once we found the first layout.\n if (typeof modules.layout !== 'undefined') {\n return rootParams\n }\n\n // This didn't include a root layout, so we need to continue. We don't need\n // to collect from other parallel routes because we can't have a parallel\n // route above a root layout.\n current = parallelRoutes.children\n }\n\n // If we didn't find a root layout, then we don't have any params.\n return []\n}\n\n/**\n * Collects the segments for a given route module.\n *\n * @param components the loaded components\n * @returns the segments for the route module\n */\nexport function collectRootParamKeys(\n routeModule: RouteModule\n): readonly string[] {\n if (isAppRouteRouteModule(routeModule)) {\n return []\n }\n\n if (isAppPageRouteModule(routeModule)) {\n return collectAppPageRootParamKeys(routeModule)\n }\n\n throw new InvariantError(\n 'Expected a route module to be one of app route or page'\n )\n}\n"],"names":["collectRootParamKeys","collectAppPageRootParamKeys","routeModule","rootParams","current","userland","loaderTree","getSegmentParam","name","parallelRoutes","modules","paramName","push","layout","children","isAppRouteRouteModule","isAppPageRouteModule","InvariantError"],"mappings":";;;;+BA8CgBA;;;eAAAA;;;iCA9CgB;wBAKzB;gCAEwB;AAE/B,SAASC,4BACPC,WAA+B;IAE/B,IAAIC,aAAuB,EAAE;IAE7B,IAAIC,UAAUF,YAAYG,QAAQ,CAACC,UAAU;IAC7C,MAAOF,QAAS;YAIIG;QAHlB,MAAM,CAACC,MAAMC,gBAAgBC,QAAQ,GAAGN;QAExC,2DAA2D;QAC3D,MAAMO,aAAYJ,mBAAAA,IAAAA,gCAAe,EAACC,0BAAhBD,iBAAuBI,SAAS;QAClD,IAAIA,WAAW;YACbR,WAAWS,IAAI,CAACD;QAClB;QAEA,wEAAwE;QACxE,4CAA4C;QAC5C,IAAI,OAAOD,QAAQG,MAAM,KAAK,aAAa;YACzC,OAAOV;QACT;QAEA,2EAA2E;QAC3E,yEAAyE;QACzE,6BAA6B;QAC7BC,UAAUK,eAAeK,QAAQ;IACnC;IAEA,kEAAkE;IAClE,OAAO,EAAE;AACX;AAQO,SAASd,qBACdE,WAAwB;IAExB,IAAIa,IAAAA,6BAAqB,EAACb,cAAc;QACtC,OAAO,EAAE;IACX;IAEA,IAAIc,IAAAA,4BAAoB,EAACd,cAAc;QACrC,OAAOD,4BAA4BC;IACrC;IAEA,MAAM,qBAEL,CAFK,IAAIe,8BAAc,CACtB,2DADI,qBAAA;eAAA;oBAAA;sBAAA;IAEN;AACF","ignoreList":[0]}