UNPKG

@respond-run/router

Version:

Filesystem-based router for Vite-powered Cloudflare Workers

54 lines (53 loc) 1.89 kB
/** * Creates a route handler from a Vite import.meta.glob() result */ export function createRouter(globs) { const routeMap = Object.entries(globs).map(([filePath, loader]) => { let routePath = filePath.replace(/^.*\/routes/, '').replace(/\.ts$/, ''); if (routePath.endsWith('/index')) { routePath = routePath.replace(/\/index$/, '') || '/'; } const paramNames = []; const regex = new RegExp('^' + routePath.replace(/\[(\w+)\]/g, (_, name) => { paramNames.push(name); return '([^/]+)'; }) + '$'); return { filePath, loader: loader, regex, paramNames }; }); return async function handleRoutes(request, env, ctx) { const url = new URL(request.url); const pathname = url.pathname.replace(/\/$/, '') || '/'; const method = request.method.toUpperCase(); for (const { regex, paramNames, loader } of routeMap) { const match = pathname.match(regex); if (!match) continue; const params = Object.fromEntries(paramNames.map((key, i) => [key, match[i + 1]])); const mod = await loader(); const handler = mod[method]; if (!handler) { return new Response('Method Not Allowed', { status: 405 }); } const reqWithParams = new Proxy(request, { get(target, prop) { if (prop === 'params') return params; return target[prop]; } }); return handler(reqWithParams, env, ctx); } return new Response('Not Found', { status: 404 }); }; } /** * Optional helper for defining routes with strong type hints. */ export function defineRoute(fn) { return fn; }