next
Version:
The React Framework
286 lines (285 loc) • 11.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
convertCustomRouteSource: null,
createRouteTypesManifest: null,
extractRouteParams: null,
writeRouteTypesManifest: null,
writeValidatorFile: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
convertCustomRouteSource: function() {
return convertCustomRouteSource;
},
createRouteTypesManifest: function() {
return createRouteTypesManifest;
},
extractRouteParams: function() {
return extractRouteParams;
},
writeRouteTypesManifest: function() {
return writeRouteTypesManifest;
},
writeValidatorFile: function() {
return writeValidatorFile;
}
});
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _routeregex = require("../../../shared/lib/router/utils/route-regex");
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _typegen = require("./typegen");
const _trytoparsepath = require("../../../lib/try-to-parse-path");
const _interceptionroutes = require("../../../shared/lib/router/utils/interception-routes");
const _entryconstants = require("../../../shared/lib/entry-constants");
const _normalizepathsep = require("../../../shared/lib/page-path/normalize-path-sep");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function convertCustomRouteSource(source) {
const parseResult = (0, _trytoparsepath.tryToParsePath)(source);
if (parseResult.error || !parseResult.tokens) {
// Fallback to original source if parsing fails
return source.startsWith('/') ? [
source
] : [
'/' + source
];
}
const possibleNormalizedRoutes = [
''
];
let slugCnt = 1;
function append(suffix) {
for(let i = 0; i < possibleNormalizedRoutes.length; i++){
possibleNormalizedRoutes[i] += suffix;
}
}
function fork(suffix) {
const currentLength = possibleNormalizedRoutes.length;
for(let i = 0; i < currentLength; i++){
possibleNormalizedRoutes.push(possibleNormalizedRoutes[i] + suffix);
}
}
for (const token of parseResult.tokens){
if (typeof token === 'object') {
// Make sure the slug is always named.
const slug = token.name || (slugCnt++ === 1 ? 'slug' : `slug${slugCnt}`);
if (token.modifier === '*') {
append(`${token.prefix}[[...${slug}]]`);
} else if (token.modifier === '+') {
append(`${token.prefix}[...${slug}]`);
} else if (token.modifier === '') {
if (token.pattern === '[^\\/#\\?]+?') {
// A safe slug
append(`${token.prefix}[${slug}]`);
} else if (token.pattern === '.*') {
// An optional catch-all slug
append(`${token.prefix}[[...${slug}]]`);
} else if (token.pattern === '.+') {
// A catch-all slug
append(`${token.prefix}[...${slug}]`);
} else {
// Other regex patterns are not supported. Skip this route.
return [];
}
} else if (token.modifier === '?') {
if (/^[a-zA-Z0-9_/]*$/.test(token.pattern)) {
// An optional slug with plain text only, fork the route.
append(token.prefix);
fork(token.pattern);
} else {
// Optional modifier `?` and regex patterns are not supported.
return [];
}
}
} else if (typeof token === 'string') {
append(token);
}
}
// Ensure leading slash
return possibleNormalizedRoutes.map((route)=>route.startsWith('/') ? route : '/' + route);
}
function extractRouteParams(route) {
const regex = (0, _routeregex.getRouteRegex)(route);
return regex.groups;
}
/**
* Resolves an intercepting route to its canonical equivalent
* Example: /gallery/test/(..)photo/[id] -> /gallery/photo/[id]
*/ function resolveInterceptingRoute(route) {
// Reuse centralized interception route normalization logic
try {
if (!(0, _interceptionroutes.isInterceptionRouteAppPath)(route)) return route;
const { interceptedRoute } = (0, _interceptionroutes.extractInterceptionRouteInformation)(route);
return interceptedRoute;
} catch {
// If parsing fails, fall back to the original route
return route;
}
}
async function createRouteTypesManifest({ dir, pageRoutes, appRoutes, appRouteHandlers, pageApiRoutes, layoutRoutes, slots, redirects, rewrites, validatorFilePath }) {
// Helper function to calculate the correct relative path
const getRelativePath = (filePath)=>{
if (validatorFilePath) {
// For validator generation, calculate path relative to validator directory
return (0, _normalizepathsep.normalizePathSep)(_path.default.relative(_path.default.dirname(validatorFilePath), filePath));
}
// For other uses, calculate path relative to project directory
return (0, _normalizepathsep.normalizePathSep)(_path.default.relative(dir, filePath));
};
const manifest = {
appRoutes: {},
pageRoutes: {},
layoutRoutes: {},
appRouteHandlerRoutes: {},
redirectRoutes: {},
rewriteRoutes: {},
appRouteHandlers: new Set(appRouteHandlers.map(({ filePath })=>getRelativePath(filePath))),
pageApiRoutes: new Set(pageApiRoutes.map(({ filePath })=>getRelativePath(filePath))),
appPagePaths: new Set(appRoutes.map(({ filePath })=>getRelativePath(filePath))),
pagesRouterPagePaths: new Set(pageRoutes.map(({ filePath })=>getRelativePath(filePath))),
layoutPaths: new Set(layoutRoutes.map(({ filePath })=>getRelativePath(filePath))),
filePathToRoute: new Map([
...appRoutes.map(({ route, filePath })=>[
getRelativePath(filePath),
resolveInterceptingRoute(route)
]),
...layoutRoutes.map(({ route, filePath })=>[
getRelativePath(filePath),
resolveInterceptingRoute(route)
]),
...appRouteHandlers.map(({ route, filePath })=>[
getRelativePath(filePath),
resolveInterceptingRoute(route)
]),
...pageRoutes.map(({ route, filePath })=>[
getRelativePath(filePath),
route
]),
...pageApiRoutes.map(({ route, filePath })=>[
getRelativePath(filePath),
route
])
])
};
// Process page routes
for (const { route, filePath } of pageRoutes){
manifest.pageRoutes[route] = {
path: getRelativePath(filePath),
groups: extractRouteParams(route)
};
}
// Process layout routes (exclude internal app error/not-found layouts)
for (const { route, filePath } of layoutRoutes){
if (route === _entryconstants.UNDERSCORE_GLOBAL_ERROR_ROUTE || route === _entryconstants.UNDERSCORE_NOT_FOUND_ROUTE) continue;
// Use the resolved route (for interception routes, this gives us the canonical route)
const resolvedRoute = resolveInterceptingRoute(route);
if (!manifest.layoutRoutes[resolvedRoute]) {
manifest.layoutRoutes[resolvedRoute] = {
path: getRelativePath(filePath),
groups: extractRouteParams(resolvedRoute),
slots: []
};
}
}
// Process slots
for (const slot of slots){
if (manifest.layoutRoutes[slot.parent]) {
manifest.layoutRoutes[slot.parent].slots.push(slot.name);
}
}
// Process app routes (exclude internal app routes)
for (const { route, filePath } of appRoutes){
if (route === _entryconstants.UNDERSCORE_GLOBAL_ERROR_ROUTE || route === _entryconstants.UNDERSCORE_NOT_FOUND_ROUTE) continue;
// Don't include metadata routes or pages
if (!filePath.endsWith('page.ts') && !filePath.endsWith('page.tsx') && !filePath.endsWith('.mdx') && !filePath.endsWith('.md')) {
continue;
}
// Use the resolved route (for interception routes, this gives us the canonical route)
const resolvedRoute = resolveInterceptingRoute(route);
if (!manifest.appRoutes[resolvedRoute]) {
manifest.appRoutes[resolvedRoute] = {
path: getRelativePath(filePath),
groups: extractRouteParams(resolvedRoute)
};
}
}
// Process app route handlers
for (const { route, filePath } of appRouteHandlers){
// Use the resolved route (for interception routes, this gives us the canonical route)
const resolvedRoute = resolveInterceptingRoute(route);
if (!manifest.appRouteHandlerRoutes[resolvedRoute]) {
manifest.appRouteHandlerRoutes[resolvedRoute] = {
path: getRelativePath(filePath),
groups: extractRouteParams(resolvedRoute)
};
}
}
// Process redirects
if (typeof redirects === 'function') {
const rd = await redirects();
for (const item of rd){
const possibleRoutes = convertCustomRouteSource(item.source);
for (const route of possibleRoutes){
manifest.redirectRoutes[route] = {
path: route,
groups: extractRouteParams(route)
};
}
}
}
// Process rewrites
if (typeof rewrites === 'function') {
const rw = await rewrites();
const allSources = Array.isArray(rw) ? rw : [
...(rw == null ? void 0 : rw.beforeFiles) || [],
...(rw == null ? void 0 : rw.afterFiles) || [],
...(rw == null ? void 0 : rw.fallback) || []
];
for (const item of allSources){
const possibleRoutes = convertCustomRouteSource(item.source);
for (const route of possibleRoutes){
manifest.rewriteRoutes[route] = {
path: route,
groups: extractRouteParams(route)
};
}
}
}
return manifest;
}
async function writeRouteTypesManifest(manifest, filePath, config) {
const dirname = _path.default.dirname(filePath);
if (!_fs.default.existsSync(dirname)) {
await _fs.default.promises.mkdir(dirname, {
recursive: true
});
}
// Write the main routes.d.ts file
await _fs.default.promises.writeFile(filePath, (0, _typegen.generateRouteTypesFile)(manifest));
// Write the link.d.ts file if typedRoutes is enabled
if (config.typedRoutes === true) {
const linkTypesPath = _path.default.join(dirname, 'link.d.ts');
await _fs.default.promises.writeFile(linkTypesPath, (0, _typegen.generateLinkTypesFile)(manifest));
}
}
async function writeValidatorFile(manifest, filePath) {
const dirname = _path.default.dirname(filePath);
if (!_fs.default.existsSync(dirname)) {
await _fs.default.promises.mkdir(dirname, {
recursive: true
});
}
await _fs.default.promises.writeFile(filePath, (0, _typegen.generateValidatorFile)(manifest));
}
//# sourceMappingURL=route-types-utils.js.map