one
Version:
One is a new React Framework that makes Vite serve both native and web.
201 lines (198 loc) • 8.53 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: !0 });
}, __copyProps = (to, from, except, desc) => {
if (from && typeof from == "object" || typeof from == "function")
for (let key of __getOwnPropNames(from))
!__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
var createHandleRequest_exports = {};
__export(createHandleRequest_exports, {
compileManifest: () => compileManifest,
createHandleRequest: () => createHandleRequest,
getURLfromRequestURL: () => getURLfromRequestURL,
resolveAPIRoute: () => resolveAPIRoute,
resolveLoaderRoute: () => resolveLoaderRoute,
resolvePageRoute: () => resolvePageRoute,
runMiddlewares: () => runMiddlewares
});
module.exports = __toCommonJS(createHandleRequest_exports);
var import_constants = require("./constants"), import_cleanUrl = require("./utils/cleanUrl"), import_isResponse = require("./utils/isResponse"), import_getManifest = require("./vite/getManifest"), import_resolveResponse = require("./vite/resolveResponse");
const debugRouter = process.env.ONE_DEBUG_ROUTER;
async function runMiddlewares(handlers, request, route, getResponse) {
const middlewares = route.middlewares;
if (!middlewares?.length)
return await getResponse();
if (!handlers.loadMiddleware)
throw new Error("No middleware handler configured");
debugRouter && console.info(`[one] \u{1F517} middleware chain (${middlewares.length}) for ${route.page}`);
const context = {};
async function dispatch(index) {
const middlewareModule = middlewares[index];
if (!middlewareModule)
return debugRouter && console.info("[one] \u2713 middleware chain complete"), await getResponse();
debugRouter && console.info(`[one] \u2192 middleware[${index}]: ${middlewareModule.contextKey}`);
const exported = (await handlers.loadMiddleware(middlewareModule))?.default;
if (!exported)
throw new Error(`No valid export found in middleware: ${middlewareModule.contextKey}`);
const response = await exported({ request, next: async () => dispatch(index + 1), context });
return response ? (debugRouter && console.info(`[one] \u2190 middleware[${index}] returned early (status: ${response.status})`), response) : dispatch(index + 1);
}
return dispatch(0);
}
async function resolveAPIRoute(handlers, request, url, route) {
const { pathname } = url, params = getRouteParams(pathname, route);
return debugRouter && console.info(`[one] \u{1F4E1} API ${request.method} ${pathname} \u2192 ${route.file}`, params), await runMiddlewares(handlers, request, route, async () => {
try {
return (0, import_resolveResponse.resolveAPIEndpoint)(
() => handlers.handleAPI({
request,
route,
url,
loaderProps: {
path: pathname,
search: url.search,
params
}
}),
request,
params || {}
);
} catch (err) {
if ((0, import_isResponse.isResponse)(err))
return err;
throw process.env.NODE_ENV === "development" && console.error(`
[one] Error importing API route at ${pathname}:
${err}
If this is an import error, you can likely fix this by adding this dependency to
the "optimizeDeps.include" array in your vite.config.ts.
`), err;
}
});
}
async function resolveLoaderRoute(handlers, request, url, route) {
return debugRouter && console.info(`[one] \u{1F4E6} loader ${url.pathname} \u2192 ${route.file}`), await runMiddlewares(handlers, request, route, async () => await (0, import_resolveResponse.resolveResponse)(async () => {
const headers = new Headers();
headers.set("Content-Type", "text/javascript");
try {
const loaderResponse = await handlers.handleLoader({
request,
route,
url,
loaderProps: {
path: url.pathname,
search: url.search,
request: route.type === "ssr" ? request : void 0,
params: getLoaderParams(url, route)
}
});
return new Response(loaderResponse, {
headers
});
} catch (err) {
if ((0, import_isResponse.isResponse)(err))
return err;
throw console.error(`Error running loader: ${err}`), err;
}
}));
}
async function resolvePageRoute(handlers, request, url, route) {
const { pathname, search } = url;
return debugRouter && console.info(`[one] \u{1F4C4} page ${pathname} \u2192 ${route.file} (${route.type})`), (0, import_resolveResponse.resolveResponse)(async () => await runMiddlewares(handlers, request, route, async () => await handlers.handlePage({
request,
route,
url,
loaderProps: {
path: pathname,
search,
// Ensure SSR loaders receive the original request
request: route.type === "ssr" ? request : void 0,
params: getLoaderParams(url, route)
}
})));
}
function getURLfromRequestURL(request) {
const urlString = request.url || "";
return new URL(
urlString || "",
request.headers.get("host") ? `http://${request.headers.get("host")}` : ""
);
}
function compileRouteRegex(route) {
return {
...route,
compiledRegex: new RegExp(route.namedRegex)
};
}
function compileManifest(manifest) {
return {
pageRoutes: manifest.pageRoutes.map(compileRouteRegex),
apiRoutes: manifest.apiRoutes.map(compileRouteRegex)
};
}
function createHandleRequest(handlers, { routerRoot }) {
const manifest = (0, import_getManifest.getManifest)({ routerRoot });
if (!manifest)
throw new Error("No routes manifest");
const compiledManifest = compileManifest(manifest);
return {
manifest,
handler: async function(request) {
const url = getURLfromRequestURL(request), { pathname, search } = url;
if (pathname === "/__vxrnhmr" || pathname.startsWith("/@"))
return null;
if (handlers.handleAPI) {
const apiRoute = compiledManifest.apiRoutes.find((route) => route.compiledRegex.test(pathname));
if (apiRoute)
return debugRouter && console.info(`[one] \u26A1 ${pathname} \u2192 matched API route: ${apiRoute.page}`), await resolveAPIRoute(handlers, request, url, apiRoute);
}
if (request.method !== "GET")
return null;
if (handlers.handleLoader && pathname.endsWith(import_constants.LOADER_JS_POSTFIX_UNCACHED)) {
const originalUrl = (0, import_cleanUrl.getPathFromLoaderPath)(pathname);
for (const route of compiledManifest.pageRoutes) {
if (route.file === "")
continue;
const finalUrl = new URL(originalUrl, url.origin);
if (finalUrl.search = url.search, !route.compiledRegex.test(finalUrl.pathname))
continue;
const cleanedRequest = new Request(finalUrl, request);
return resolveLoaderRoute(handlers, cleanedRequest, finalUrl, route);
}
return process.env.NODE_ENV === "development" && console.error("No matching route found for loader!", {
originalUrl,
pathname,
routes: manifest.pageRoutes
}), Response.error();
}
if (handlers.handlePage) {
for (const route of compiledManifest.pageRoutes)
if (route.compiledRegex.test(pathname))
return debugRouter && console.info(`[one] \u26A1 ${pathname} \u2192 matched page route: ${route.page} (${route.type})`), resolvePageRoute(handlers, request, url, route);
}
return null;
}
};
}
function getLoaderParams(url, config) {
const params = {}, match = new RegExp(config.compiledRegex).exec(url.pathname);
if (match?.groups)
for (const [key, value] of Object.entries(match.groups)) {
const namedKey = config.routeKeys[key];
params[namedKey] = value;
}
return params;
}
function getRouteParams(pathname, route) {
const match = new RegExp(route.namedRegex).exec(pathname);
return match ? Object.fromEntries(
Object.entries(route.routeKeys).map(([key, value]) => [value, match.groups?.[key] || ""])
) : {};
}
//# sourceMappingURL=createHandleRequest.js.map