one
Version:
One is a new React Framework that makes Vite serve both native and web.
117 lines (116 loc) • 5.8 kB
JavaScript
import { getContextKey, matchGroupName } from "../router/matchers";
import { sortRoutes } from "../router/sortRoutes";
function isNotFoundRoute(route) {
return !!(route.dynamic && route.dynamic[route.dynamic.length - 1].notFound);
}
function getServerManifest(route) {
function getFlatNodes(route2, layouts) {
if (route2.children.length)
return route2.children.flatMap((child) => getFlatNodes(child, [...layouts || [], route2]));
let key;
if (route2.type === "api")
key = getContextKey(route2.contextKey).replace(/\/index$/, "") || "/";
else {
const parentSegments = layouts?.flatMap((route3) => {
const key2 = getContextKey(route3.route).replace(/\/index$/, "") || "/";
return key2 === "/" || key2.startsWith("/(") ? [] : [key2];
});
key = (parentSegments ? parentSegments.join("") : "") + getContextKey(route2.route).replace(/\/index$/, "") || "/";
}
return [[key, { ...route2, layouts }]];
}
const flat = getFlatNodes(route).sort(([, a], [, b]) => sortRoutes(b, a)).reverse(), pathToRoute = {};
for (const [path, route2] of flat)
pathToRoute[path] && (console.warn(`
[one] \u274C Duplicate routes error`), console.warn(
" Multiple routes at the same path! One route will always win over the other."
), console.warn(` path: ${path}`), console.warn(` first route: ${pathToRoute[path].contextKey}`), console.warn(` second route: ${route2.contextKey}
`)), pathToRoute[path] = route2;
const apiRoutes = [], middlewareRoutes = [], pageRoutes = [], allRoutes = [], addedMiddlewares = {};
for (const [path, node] of flat) {
if (node.type === "api") {
const route3 = getGeneratedNamedRouteRegex(path, node);
apiRoutes.push(route3), allRoutes.push(route3);
continue;
}
if (node.middlewares?.length)
for (const middleware of node.middlewares)
addedMiddlewares[middleware.contextKey] || (addedMiddlewares[middleware.contextKey] = !0, middlewareRoutes.push(getGeneratedNamedRouteRegex(path, middleware)));
const route2 = getGeneratedNamedRouteRegex(path, node);
pageRoutes.push(route2), allRoutes.push(route2);
}
return {
apiRoutes,
middlewareRoutes,
pageRoutes,
allRoutes
};
}
function getGeneratedNamedRouteRegex(normalizedRoute, node) {
return {
...getRouteEntry(normalizedRoute, node),
generated: !0,
isNotFound: isNotFoundRoute(node)
};
}
function getRouteEntry(normalizedRoute, node) {
const result = getPathMeta(normalizedRoute);
return {
file: node.contextKey,
page: getContextKey(node.route),
type: node.type,
namedRegex: result.namedRegex,
urlPath: result.urlPath,
urlCleanPath: result.urlCleanPath,
routeKeys: result.routeKeys,
layouts: node.layouts,
middlewares: node.middlewares
};
}
function buildGetSafeRouteKey() {
let currentCharCode = 96, currentLength = 1;
return () => {
let result = "", incrementNext = !0;
for (let i = 0; i < currentLength; i++)
incrementNext && (currentCharCode++, currentCharCode > 122 ? (currentCharCode = 97, incrementNext = !0) : incrementNext = !1), result = String.fromCharCode(currentCharCode) + result;
return incrementNext && (currentLength++, currentCharCode = 96), result;
};
}
function removeTrailingSlash(route) {
return route.replace(/\/$/, "") || "/";
}
function getPathMeta(route) {
const segments = removeTrailingSlash(route).slice(1).split("/"), getSafeRouteKey = buildGetSafeRouteKey(), routeKeys = {}, urlPathParts = [], routeSegments = segments.map((segment, index) => {
if (segment === "+not-found" && index === segments.length - 1 && (segment = "[...not-found]"), /^\[.*\]$/.test(segment)) {
const { name, optional, repeat } = parseParam(segment);
let cleanedKey = name.replace(/\W/g, ""), invalidKey = !1;
return (cleanedKey.length === 0 || cleanedKey.length > 30) && (invalidKey = !0), Number.isNaN(Number.parseInt(cleanedKey.slice(0, 1), 10)) || (invalidKey = !0), cleanedKey in routeKeys && (invalidKey = !0), invalidKey && (cleanedKey = getSafeRouteKey()), urlPathParts.push({
content: repeat ? "/*" : `/:${name}${optional ? "?" : ""}`
}), routeKeys[cleanedKey] = name, repeat ? optional ? `(?:/(?<${cleanedKey}>.+?))?` : `/(?<${cleanedKey}>.+?)` : `/(?<${cleanedKey}>[^/]+?)`;
}
if (insideParensRegex.test(segment)) {
const groupName = matchGroupName(segment).split(",").map((group) => group.trim()).filter(Boolean);
return urlPathParts.push({ content: `/:${groupName}?`, type: "group" }), groupName.length > 1 ? `(?:/${`\\((?:${groupName.map(escapeStringRegexp).join("|")})\\)`})?` : `(?:/${escapeStringRegexp(segment)})?`;
}
return urlPathParts.push({ content: `/${segment}` }), `/${escapeStringRegexp(segment)}`;
}).join(""), urlPath = urlPathParts.map((p) => p.content).join(""), urlCleanPath = urlPathParts.filter((p) => p.type !== "group").map((p) => p.content).join("");
return {
namedRegex: `^${routeSegments}(?:/)?$`,
urlPath: urlPath === "" ? "/" : urlPath,
urlCleanPath: urlCleanPath === "" ? "/" : urlCleanPath,
routeKeys
};
}
const insideBracketsRegex = /^\[.*\]$/, insideParensRegex = /^\(.*\)$/, tripleDotRegex = /^\.\.\./, replaceRegex = /[|\\{}()[\]^$+*?.-]/g, hasRegExpRegex = /[|\\{}()[\]^$+*?.-]/;
function escapeStringRegexp(str) {
return hasRegExpRegex.test(str) ? str.replace(replaceRegex, "\\$&") : str;
}
function parseParam(param) {
let repeat = !1, optional = !1, name = param;
return insideBracketsRegex.test(name) && (optional = !0, name = name.slice(1, -1)), tripleDotRegex.test(name) && (repeat = !0, name = name.slice(3)), { name, repeat, optional };
}
export {
getServerManifest,
parseParam
};
//# sourceMappingURL=getServerManifest.js.map