UNPKG

rwsdk

Version:

Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime

57 lines (56 loc) 1.96 kB
/** * Creates a type-safe link generation function from route patterns. * * @example * // Define your routes * const link = defineLinks([ * "/", * "/about", * "/users/:id", * "/files/*", * ] as const) * * // Generate links with type checking * link("/") // "/" * link("/about") // "/about" * link("/users/:id", { id: "123" }) // "/users/123" * link("/files/*", { $0: "docs/guide.pdf" }) // "/files/docs/guide.pdf" */ export function defineLinks(routes) { // Validate routes at runtime routes.forEach((route) => { if (typeof route !== "string") { throw new Error(`Invalid route: ${route}. Routes must be strings.`); } }); return (path, params) => { if (!routes.includes(path)) { throw new Error(`Invalid route: ${path}`); } if (!params) return path; let result = path; // Replace named parameters for (const [key, value] of Object.entries(params)) { if (key.startsWith("$")) { // Replace each star with its corresponding $ parameter const starIndex = parseInt(key.slice(1)); const stars = result.match(/\*/g) || []; if (starIndex >= stars.length) { throw new Error(`Parameter ${key} has no corresponding * in route`); } // Replace the nth star with the value let count = 0; result = result.replace(/\*/g, (match) => count++ === starIndex ? value : match); } else { // Handle named parameters if (typeof value !== "string") { throw new Error(`Parameter ${key} must be a string`); } result = result.replace(`:${key}`, value); } } return result; }; }