one
Version:
One is a new React Framework that makes Vite serve both native and web.
771 lines (769 loc) • 29.8 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all) __defProp(target, name, {
get: all[name],
enumerable: true
});
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
value: true
}), mod);
var oneServe_exports = {};
__export(oneServe_exports, {
oneServe: () => oneServe
});
module.exports = __toCommonJS(oneServe_exports);
var import_promises = require("node:fs/promises");
var import_node_path = require("node:path");
var import_constants = require("../constants.cjs");
var import_createHandleRequest = require("../createHandleRequest.cjs");
var import_cleanUrl = require("../utils/cleanUrl.cjs");
var import_toAbsolute = require("../utils/toAbsolute.cjs");
var import_ssrLoaderData = require("./ssrLoaderData.cjs");
var import_staticHtmlFetcher = require("./staticHtmlFetcher.cjs");
const debugRouter = process.env.ONE_DEBUG_ROUTER;
function forwardHeaders(response, context) {
const setCookies = response.headers.getSetCookie?.();
if (setCookies?.length) {
for (const cookie of setCookies) {
context.header("set-cookie", cookie, {
append: true
});
}
}
response.headers.forEach((value, key) => {
if (key === "set-cookie") return;
context.header(key, value);
});
}
async function readStaticHtml(htmlPath, outDir = "dist") {
const fetchStaticHtml = (0, import_staticHtmlFetcher.getFetchStaticHtml)();
if (fetchStaticHtml) {
const html = await fetchStaticHtml(htmlPath);
if (html) return html;
}
try {
return await (0, import_promises.readFile)((0, import_node_path.join)(`${outDir}/client`, htmlPath), "utf-8");
} catch {
return null;
}
}
async function oneServe(oneOptions, buildInfo, app, options) {
const outDir = buildInfo.outDir || "dist";
const {
resolveAPIRoute,
resolveLoaderRoute,
resolvePageRoute
} = await import("../createHandleRequest");
const {
isResponse
} = await import("../utils/isResponse");
const {
isStatusRedirect
} = await import("../utils/isStatus");
const {
resolveResponse
} = await import("../vite/resolveResponse");
const isAPIRequest = /* @__PURE__ */new WeakMap();
const redirects = oneOptions.web?.redirects;
if (redirects) {
for (const redirect of redirects) {
app.get(redirect.source, context => {
const destinationUrl = redirect.destination.replace(/:\w+/g, param => {
const paramName = param.substring(1);
return context.req.param(paramName) || "";
});
if (debugRouter) {
console.info(`[one] \u21AA redirect ${context.req.path} \u2192 ${destinationUrl}`);
}
return context.redirect(destinationUrl, redirect.permanent ? 301 : 302);
});
}
}
if (!buildInfo) {
throw new Error(`No build info found, have you run build?`);
}
const {
routeToBuildInfo,
routeMap
} = buildInfo;
function findNearestNotFoundPath(urlPath) {
let cur = urlPath;
while (cur) {
const parent = cur.lastIndexOf("/") > 0 ? cur.slice(0, cur.lastIndexOf("/")) : "";
if (routeMap[`${parent}/+not-found`]) {
return `${parent}/+not-found`;
}
if (!parent) break;
cur = parent;
}
return "/+not-found";
}
function make404LoaderJs(path, logReason) {
const nfPath = findNearestNotFoundPath(path);
if (logReason) {
console.error(`[one] 404 loader for ${path}: ${logReason}`);
}
return `export function loader(){return{__oneError:404,__oneErrorMessage:'Not Found',__oneNotFoundPath:${JSON.stringify(nfPath)}}}`;
}
const serverOptions = {
...oneOptions,
root: "."
};
const apiCJS = oneOptions.build?.api?.outputFormat === "cjs";
const useStreaming = !process.env.ONE_BUFFERED_SSR;
const htmlHeaders = {
"content-type": "text/html"
};
const ssrHtmlHeaders = {
"content-type": "text/html",
"cache-control": "no-cache"
};
const loaderCache = /* @__PURE__ */new Map();
const moduleImportCache = /* @__PURE__ */new Map();
const loaderCacheFnMap = /* @__PURE__ */new Map();
const pendingLoaderResults = /* @__PURE__ */new Map();
function resolveLoaderSync(serverPath, lazyKey) {
const cacheKey = lazyKey || serverPath || "";
const cached = loaderCache.get(cacheKey);
if (cached !== void 0) return cached;
return (async () => {
const pathToResolve = serverPath || lazyKey || "";
const resolvedPath = pathToResolve.includes(`${outDir}/server`) ? pathToResolve : (0, import_node_path.join)("./", `${outDir}/server`, pathToResolve);
let routeExported;
if (moduleImportCache.has(cacheKey)) {
routeExported = moduleImportCache.get(cacheKey);
} else {
routeExported = lazyKey ? options?.lazyRoutes?.pages?.[lazyKey] ? await options.lazyRoutes.pages[lazyKey]() : await import((0, import_toAbsolute.toAbsolute)(resolvedPath)) : await import((0, import_toAbsolute.toAbsolute)(serverPath));
moduleImportCache.set(cacheKey, routeExported);
}
const loader = routeExported?.loader || null;
loaderCache.set(cacheKey, loader);
const loaderCacheFn = routeExported?.loaderCache ?? null;
loaderCacheFnMap.set(cacheKey, loaderCacheFn);
return loader;
})();
}
async function importAndRunLoader(routeId, serverPath, lazyKey, loaderProps) {
if (!serverPath && !lazyKey) {
return {
loaderData: void 0,
routeId
};
}
const cacheMapKey = lazyKey || serverPath || "";
const loaderCacheFn = loaderCacheFnMap.get(cacheMapKey);
let coalFullKey;
let coalTtl = 0;
if (loaderCacheFn) {
const cacheResult = loaderCacheFn(loaderProps?.params, loaderProps?.request);
const cacheKey = typeof cacheResult === "string" ? cacheResult : cacheResult?.key;
coalTtl = typeof cacheResult === "string" ? 0 : cacheResult?.ttl ?? 0;
if (cacheKey != null) {
coalFullKey = routeId + "\0" + cacheKey;
const existing = pendingLoaderResults.get(coalFullKey);
if (existing && (!existing.expires || Date.now() < existing.expires)) {
const loaderData = await existing.promise;
return {
loaderData,
routeId
};
}
}
}
try {
const loaderOrPromise = resolveLoaderSync(serverPath, lazyKey);
const loader = loaderOrPromise instanceof Promise ? await loaderOrPromise : loaderOrPromise;
if (!loader) {
return {
loaderData: void 0,
routeId
};
}
if (coalFullKey) {
const promise = loader(loaderProps);
const entry = {
promise,
expires: 0
};
pendingLoaderResults.set(coalFullKey, entry);
promise.then(() => {
entry.expires = coalTtl > 0 ? Date.now() + coalTtl : 0;
if (coalTtl <= 0) {
Promise.resolve().then(() => pendingLoaderResults.delete(coalFullKey));
}
}, () => {
pendingLoaderResults.delete(coalFullKey);
});
const loaderData2 = await promise;
return {
loaderData: loaderData2,
routeId
};
}
const loaderData = await loader(loaderProps);
return {
loaderData,
routeId
};
} catch (err) {
if (isResponse(err)) {
throw err;
}
if (err?.code === "ENOENT") {
return {
loaderData: void 0,
routeId,
isEnoent: true
};
}
console.error(`[one] Error running loader for ${routeId}:`, err);
return {
loaderData: void 0,
routeId
};
}
}
let render = null;
let renderStream = null;
let renderLoading = null;
function ensureRenderLoaded() {
if (render) return;
if (renderLoading) return renderLoading;
renderLoading = (async () => {
const entry = options?.lazyRoutes?.serverEntry ? await options.lazyRoutes.serverEntry() : await import((0, import_node_path.resolve)(process.cwd(), `${serverOptions.root}/${outDir}/server/_virtual_one-entry.${typeof oneOptions.build?.server === "object" && oneOptions.build.server.outputFormat === "cjs" ? "c" : ""}js`));
render = entry.default.render;
renderStream = entry.default.renderStream;
})();
return renderLoading;
}
const clientDir = (0, import_node_path.join)(process.cwd(), outDir, "client");
const requestHandlers = {
async handleStaticFile(filePath) {
try {
const fullPath = (0, import_node_path.join)(clientDir, filePath);
const content = await (0, import_promises.readFile)(fullPath, "utf-8");
return new Response(content, {
headers: {
"Content-Type": "text/javascript"
}
});
} catch {
return null;
}
},
async handleAPI({
route
}) {
if (options?.lazyRoutes?.api?.[route.page]) {
return await options.lazyRoutes.api[route.page]();
}
const fileName = route.page.slice(1).replace(/\[/g, "_").replace(/\]/g, "_");
const apiFile = (0, import_node_path.join)(process.cwd(), outDir, "api", fileName + (apiCJS ? ".cjs" : ".js"));
return await import(apiFile);
},
async loadMiddleware(route) {
if (options?.lazyRoutes?.middlewares?.[route.contextKey]) {
return await options.lazyRoutes.middlewares[route.contextKey]();
}
return await import((0, import_toAbsolute.toAbsolute)(route.contextKey));
},
async handleLoader({
route,
loaderProps
}) {
const routeFile = route.routeFile || route.file;
const serverPath = route.file.includes(`${outDir}/server`) ? route.file : (0, import_node_path.join)("./", `${outDir}/server`, route.file);
let loader;
try {
const loaderResult = resolveLoaderSync(serverPath, routeFile);
loader = loaderResult instanceof Promise ? await loaderResult : loaderResult;
} catch (err) {
if (err?.code === "ERR_MODULE_NOT_FOUND") {
return null;
}
throw err;
}
if (!loader) {
return null;
}
let json;
try {
json = await loader(loaderProps);
} catch (err) {
if (err?.code === "ENOENT") {
return make404LoaderJs(loaderProps?.path || "/", `ENOENT ${err?.path || err}`);
}
throw err;
}
if (isResponse(json)) {
throw json;
}
return `export function loader() { return ${JSON.stringify(json)} }`;
},
async handlePage({
route,
url,
loaderProps
}) {
const buildInfo2 = routeToBuildInfo[route.file];
if (route.type === "ssr") {
if (!buildInfo2) {
console.error(`Error in route`, route);
throw new Error(`No buildinfo found for ${url}, route: ${route.file}, in keys:
${Object.keys(routeToBuildInfo).join("\n ")}`);
}
try {
const layoutRoutes = route.layouts || [];
const layoutLoaderPromises = [];
const noLoaderResults = [];
for (const layout of layoutRoutes) {
const serverPath = layout.loaderServerPath || layout.contextKey;
const cacheKey = layout.contextKey || serverPath || "";
const cachedLoader = loaderCache.get(cacheKey);
if (cachedLoader === null) {
noLoaderResults.push({
loaderData: void 0,
routeId: layout.contextKey
});
} else {
layoutLoaderPromises.push(importAndRunLoader(layout.contextKey, serverPath, layout.contextKey, loaderProps));
}
}
const pageLoaderPromise = importAndRunLoader(route.file, buildInfo2.serverJsPath, route.file, loaderProps);
let layoutResults;
let pageResult;
try {
if (layoutLoaderPromises.length === 0) {
layoutResults = noLoaderResults;
pageResult = await pageLoaderPromise;
} else {
const [asyncLayoutResults, pr] = await Promise.all([Promise.all(layoutLoaderPromises), pageLoaderPromise]);
layoutResults = [...noLoaderResults, ...asyncLayoutResults];
pageResult = pr;
}
} catch (err) {
if (isResponse(err)) {
return err;
}
throw err;
}
if (pageResult.isEnoent) {
const nfPath = findNearestNotFoundPath(loaderProps?.path || "/");
const nfHtml = routeMap[nfPath];
if (nfHtml) {
try {
const html = await (0, import_promises.readFile)((0, import_node_path.join)(process.cwd(), `${outDir}/client`, nfHtml), "utf-8");
return new Response(html, {
headers: {
"content-type": "text/html"
},
status: 404
});
} catch {}
}
return new Response("404 Not Found", {
status: 404
});
}
const matchPathname = loaderProps?.path || "/";
const matchParams = loaderProps?.params || {};
const matches = new Array(layoutResults.length + 1);
for (let i = 0; i < layoutResults.length; i++) {
const result = layoutResults[i];
matches[i] = {
routeId: result.routeId,
pathname: matchPathname,
params: matchParams,
loaderData: result.loaderData
};
}
matches[layoutResults.length] = {
routeId: pageResult.routeId,
pathname: matchPathname,
params: matchParams,
loaderData: pageResult.loaderData
};
const loaderData = pageResult.loaderData;
for (const layout of layoutRoutes) {
const key = layout.contextKey;
const loaderFn = loaderCache.get(key);
if (loaderFn) {
const result = layoutResults.find(r => r.routeId === key);
if (result) {
(0, import_ssrLoaderData.setSSRLoaderData)(loaderFn, result.loaderData);
}
}
}
const pageLoaderFn = loaderCache.get(route.file);
if (pageLoaderFn) {
(0, import_ssrLoaderData.setSSRLoaderData)(pageLoaderFn, pageResult.loaderData);
}
globalThis["__vxrnresetState"]?.();
const renderProps = {
mode: route.type,
loaderData,
loaderProps,
path: loaderProps?.path || "/",
preloads: buildInfo2.criticalPreloads || buildInfo2.preloads,
deferredPreloads: buildInfo2.deferredPreloads,
css: buildInfo2.css,
cssContents: buildInfo2.cssContents,
matches
};
const _rl = ensureRenderLoaded();
if (_rl) await _rl;
const status = route.isNotFound ? 404 : 200;
const responseHeaders = route.isNotFound ? htmlHeaders : ssrHtmlHeaders;
if (useStreaming) {
const stream = await renderStream(renderProps);
return new Response(stream, {
headers: responseHeaders,
status
});
}
const rendered = await render(renderProps);
return new Response(rendered, {
headers: responseHeaders,
status
});
} catch (err) {
if (isResponse(err)) {
return err;
}
console.error(`[one] Error rendering SSR route ${route.file}
${err?.["stack"] ?? err}
url: ${url}`);
}
} else {
const layoutRoutes = route.layouts || [];
const needsSpaShell = route.type === "spa" && layoutRoutes.some(layout => layout.layoutRenderMode === "ssg" || layout.layoutRenderMode === "ssr");
if (needsSpaShell) {
try {
const layoutResults = await Promise.all(layoutRoutes.map(layout => {
const serverPath = layout.loaderServerPath || layout.contextKey;
return importAndRunLoader(layout.contextKey, serverPath, layout.contextKey, loaderProps);
}));
const matches = layoutResults.map(result => ({
routeId: result.routeId,
pathname: loaderProps?.path || "/",
params: loaderProps?.params || {},
loaderData: result.loaderData
}));
globalThis["__vxrnresetState"]?.();
const _rl3 = ensureRenderLoaded();
if (_rl3) await _rl3;
const rendered = await render({
mode: "spa-shell",
// don't pass loaderData for spa-shell - the page loader runs on client
// passing {} here would make useLoaderState think data is preloaded
loaderData: void 0,
loaderProps,
path: loaderProps?.path || "/",
preloads: buildInfo2?.criticalPreloads || buildInfo2?.preloads,
deferredPreloads: buildInfo2?.deferredPreloads,
css: buildInfo2?.css,
cssContents: buildInfo2?.cssContents,
matches
});
return new Response(rendered, {
headers: htmlHeaders,
status: route.isNotFound ? 404 : 200
});
} catch (err) {
if (isResponse(err)) {
return err;
}
console.error(`[one] Error rendering spa-shell for ${route.file}
${err?.["stack"] ?? err}
url: ${url}`);
}
}
const isDynamicRoute = Object.keys(route.routeKeys).length > 0;
const routeCleanPath = route.urlCleanPath.replace(/\?/g, "");
const notFoundKey = route.isNotFound ? route.page.replace(/\[([^\]]+)\]/g, ":$1") : null;
const htmlPath = notFoundKey ? routeMap[notFoundKey] : isDynamicRoute ? routeMap[routeCleanPath] || routeMap[url.pathname] : routeMap[url.pathname] || routeMap[buildInfo2?.cleanPath];
if (htmlPath) {
const html = await readStaticHtml(htmlPath, outDir);
if (html) {
const headers = new Headers();
headers.set("content-type", "text/html");
return new Response(html, {
headers,
status: route.isNotFound ? 404 : 200
});
}
}
if (isDynamicRoute) {
const notFoundRoute = findNearestNotFoundPath(url.pathname);
const notFoundHtmlPath = routeMap[notFoundRoute];
if (notFoundHtmlPath) {
const notFoundHtml = await readStaticHtml(notFoundHtmlPath, outDir);
if (notFoundHtml) {
const notFoundMarker = `<script>window.__one404=${JSON.stringify({
originalPath: url.pathname,
notFoundPath: notFoundRoute
})}</script>`;
const injectedHtml = notFoundHtml.includes("</head>") ? notFoundHtml.replace("</head>", `${notFoundMarker}</head>`) : notFoundHtml.replace("<body", `${notFoundMarker}<body`);
const headers = new Headers();
headers.set("content-type", "text/html");
return new Response(injectedHtml, {
headers,
status: 404
});
}
}
return new Response("404 Not Found", {
status: 404
});
}
}
}
};
function createHonoHandler(route) {
const isDynamicOrNotFound = route.page.endsWith("/+not-found") || Object.keys(route.routeKeys).length > 0;
return async (context, next) => {
try {
const request = context.req.raw;
if (isDynamicOrNotFound) {
if (options?.serveStaticAssets) {
const staticAssetResponse = await options.serveStaticAssets({
context
});
if (staticAssetResponse) {
return await (0, import_createHandleRequest.runMiddlewares)(requestHandlers, request, route, async () => staticAssetResponse);
}
}
}
const reqPath = context.req.path;
if (reqPath.endsWith(".js") || reqPath.endsWith(".css")) {
return next();
}
if (route.type === "ssr" && !route.middlewares?.length && !reqPath.endsWith(import_constants.LOADER_JS_POSTFIX_UNCACHED)) {
if (debugRouter) {
console.info(`[one] \u26A1 ${reqPath} \u2192 matched page route: ${route.page} (ssr)`);
}
const pathname = reqPath;
const rawUrl = request.url;
const qIdx = rawUrl.indexOf("?");
const search = qIdx >= 0 ? rawUrl.slice(qIdx) : "";
const params = {};
const match = route.compiledRegex.exec(pathname);
if (match?.groups) {
for (const [key, value] of Object.entries(match.groups)) {
const namedKey = route.routeKeys[key];
params[namedKey] = value;
}
}
const loaderProps = {
path: pathname,
search,
subdomain: (0, import_createHandleRequest.getSubdomain)((0, import_createHandleRequest.getURLfromRequestURL)(request)),
request,
params
};
const url2 = (0, import_createHandleRequest.getURLfromRequestURL)(request);
const response2 = await resolveResponse(async () => {
try {
return await requestHandlers.handlePage({
request,
route,
url: url2,
loaderProps
});
} catch (err) {
if (isResponse(err)) {
return err;
}
throw err;
}
});
if (response2) {
if (isResponse(response2)) {
if (isStatusRedirect(response2.status)) {
const location = `${response2.headers.get("location") || ""}`;
forwardHeaders(response2, context);
return context.redirect(location, response2.status);
}
return response2;
}
return next();
}
return next();
}
const url = (0, import_createHandleRequest.getURLfromRequestURL)(request);
const response = await (() => {
if (url.pathname.endsWith(import_constants.LOADER_JS_POSTFIX_UNCACHED)) {
const originalUrl = (0, import_cleanUrl.getPathFromLoaderPath)(url.pathname);
if (route.type === "ssg" && Object.keys(route.routeKeys).length > 0) {
if (!routeMap[originalUrl]) {
return new Response(make404LoaderJs(originalUrl, "ssg route not in routeMap"), {
headers: {
"Content-Type": "text/javascript"
}
});
}
}
const finalUrl = new URL(originalUrl, url.origin);
finalUrl.search = url.search;
const cleanedRequest = new Request(finalUrl, request);
return resolveLoaderRoute(requestHandlers, cleanedRequest, finalUrl, route);
}
switch (route.type) {
case "api":
{
if (debugRouter) {
console.info(`[one] \u26A1 ${url.pathname} \u2192 matched API route: ${route.page}`);
}
return resolveAPIRoute(requestHandlers, request, url, route);
}
case "ssg":
case "spa":
case "ssr":
{
if (debugRouter) {
console.info(`[one] \u26A1 ${url.pathname} \u2192 matched page route: ${route.page} (${route.type})`);
}
return resolvePageRoute(requestHandlers, request, url, route);
}
}
})();
if (response) {
if (isResponse(response)) {
if (isStatusRedirect(response.status)) {
const location = `${response.headers.get("location") || ""}`;
forwardHeaders(response, context);
return context.redirect(location, response.status);
}
if (isAPIRequest.get(request)) {
try {
if (!response.headers.has("cache-control") && !response.headers.has("Cache-Control")) {
response.headers.set("cache-control", "no-store");
}
return response;
} catch (err) {
console.info(`Error updating cache header on api route "${context.req.path}" to no-store, it is ${response.headers.get("cache-control")}, continue`, err);
}
}
if (!response.headers.has("cache-control") && !response.headers.has("Cache-Control")) {
if (route.type === "ssg" || route.type === "spa") {
response.headers.set("cache-control", "public, s-maxage=60, stale-while-revalidate=120");
} else {
response.headers.set("cache-control", "no-cache");
}
}
return response;
}
return next();
}
} catch (err) {
console.error(` [one] Error handling request: ${err["stack"]}`);
}
return next();
};
}
const compiledManifest = (0, import_createHandleRequest.compileManifest)(buildInfo.manifest);
for (const route of compiledManifest.apiRoutes) {
app.get(route.urlPath, createHonoHandler(route));
app.put(route.urlPath, createHonoHandler(route));
app.post(route.urlPath, createHonoHandler(route));
app.delete(route.urlPath, createHonoHandler(route));
app.patch(route.urlPath, createHonoHandler(route));
if (route.urlPath !== route.urlCleanPath) {
app.get(route.urlCleanPath, createHonoHandler(route));
app.put(route.urlCleanPath, createHonoHandler(route));
app.post(route.urlCleanPath, createHonoHandler(route));
app.delete(route.urlCleanPath, createHonoHandler(route));
app.patch(route.urlCleanPath, createHonoHandler(route));
}
}
for (const route of compiledManifest.pageRoutes) {
app.get(route.urlPath, createHonoHandler(route));
if (route.urlPath !== route.urlCleanPath) {
app.get(route.urlCleanPath, createHonoHandler(route));
}
}
const {
preloads,
cssPreloads
} = buildInfo;
app.get("*", async (c, next) => {
if (c.req.path.endsWith(import_constants.PRELOAD_JS_POSTFIX)) {
if (!preloads[c.req.path]) {
c.header("Content-Type", "text/javascript");
c.status(200);
return c.body(``);
}
}
if (c.req.path.endsWith(import_constants.CSS_PRELOAD_JS_POSTFIX)) {
if (!cssPreloads?.[c.req.path]) {
c.header("Content-Type", "text/javascript");
c.status(200);
return c.body(`export default Promise.resolve()`);
}
}
if (c.req.path.endsWith(import_constants.LOADER_JS_POSTFIX_UNCACHED)) {
const request = c.req.raw;
const url = (0, import_createHandleRequest.getURLfromRequestURL)(request);
const originalUrl = (0, import_cleanUrl.getPathFromLoaderPath)(c.req.path);
for (const route of compiledManifest.pageRoutes) {
if (route.file === "") {
continue;
}
if (!route.compiledRegex.test(originalUrl)) {
continue;
}
if (route.type === "ssg" && Object.keys(route.routeKeys).length > 0 && !routeMap[originalUrl]) {
c.header("Content-Type", "text/javascript");
c.status(200);
return c.body(make404LoaderJs(originalUrl, "ssg route not in routeMap"));
}
const loaderRoute = {
...route,
routeFile: route.file,
// preserve original for lazy route lookup
file: route.loaderServerPath || c.req.path
};
const finalUrl = new URL(originalUrl, url.origin);
finalUrl.search = url.search;
const cleanedRequest = new Request(finalUrl, request);
try {
const resolved = await resolveLoaderRoute(requestHandlers, cleanedRequest, finalUrl, loaderRoute);
return resolved;
} catch (err) {
if (err?.code === "ERR_MODULE_NOT_FOUND") {
c.header("Content-Type", "text/javascript");
c.status(200);
return c.body(`export function loader() { return undefined }`);
}
console.error(`Error running loader: ${err}`);
return next();
}
}
}
return next();
});
}