138 lines
4.5 KiB
TypeScript
138 lines
4.5 KiB
TypeScript
// AUTO-GENERATED by `wrnexus dev` - do not edit.
|
|
// Typed routes support required, optional, and catch-all parameters.
|
|
|
|
export interface Routes {
|
|
"/": Record<string, never>;
|
|
"/about": Record<string, never>;
|
|
"/async-data": Record<string, never>;
|
|
"/chat": Record<string, never>;
|
|
"/client-only": Record<string, never>;
|
|
"/dashboard": Record<string, never>;
|
|
"/hello": Record<string, never>;
|
|
"/language-tools": Record<string, never>;
|
|
"/login": Record<string, never>;
|
|
"/modal": Record<string, never>;
|
|
"/partial-static": Record<string, never>;
|
|
"/platform-showcase": Record<string, never>;
|
|
"/reactive": Record<string, never>;
|
|
"/server-actions": Record<string, never>;
|
|
"/test": Record<string, never>;
|
|
"/ui": Record<string, never>;
|
|
}
|
|
|
|
export interface RouteNames {
|
|
"index": "/";
|
|
"about": "/about";
|
|
"async.data": "/async-data";
|
|
"chat": "/chat";
|
|
"client.only": "/client-only";
|
|
"dashboard": "/dashboard";
|
|
"hello": "/hello";
|
|
"language.tools": "/language-tools";
|
|
"login": "/login";
|
|
"modal": "/modal";
|
|
"partial.static": "/partial-static";
|
|
"platform.showcase": "/platform-showcase";
|
|
"reactive": "/reactive";
|
|
"server.actions": "/server-actions";
|
|
"test": "/test";
|
|
"ui": "/ui";
|
|
}
|
|
|
|
export interface RouteQueries {
|
|
[path: string]: Record<string, string | number | boolean | null | undefined>;
|
|
}
|
|
|
|
export type RoutePath = keyof Routes;
|
|
export type RouteName = keyof RouteNames;
|
|
export type RouteQuery<P extends RoutePath> = P extends keyof RouteQueries
|
|
? RouteQueries[P]
|
|
: Record<string, string | number | boolean | null | undefined>;
|
|
type RouteValue = string | readonly string[] | undefined;
|
|
|
|
function encodeRouteValue(value: RouteValue, catchAll: boolean): string {
|
|
if (value === undefined) return "";
|
|
const values = Array.isArray(value) ? value : catchAll ? String(value).split("/") : [String(value)];
|
|
return values.map((part) => encodeURIComponent(part)).join("/");
|
|
}
|
|
|
|
function buildHref(path: string, params: Record<string, RouteValue> = {}): string {
|
|
const output: string[] = [];
|
|
for (const segment of path.split("/").filter(Boolean)) {
|
|
let name: string | undefined;
|
|
let optional = false;
|
|
let catchAll = false;
|
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
optional = true;
|
|
name = segment.slice(2, -2);
|
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
name = segment.slice(1, -1);
|
|
if (name.endsWith("?")) {
|
|
optional = true;
|
|
name = name.slice(0, -1);
|
|
}
|
|
}
|
|
if (!name) {
|
|
output.push(segment);
|
|
continue;
|
|
}
|
|
if (name.startsWith("...")) {
|
|
catchAll = true;
|
|
name = name.slice(3);
|
|
}
|
|
const value = params[name];
|
|
if (value === undefined && optional) continue;
|
|
if (value === undefined) throw new Error(`WRN-ROUTE-MISSING-PARAM: Missing route parameter '${name}'.`);
|
|
output.push(encodeRouteValue(value, catchAll));
|
|
}
|
|
return "/" + output.filter(Boolean).join("/");
|
|
}
|
|
|
|
export function href<P extends RoutePath>(
|
|
path: P,
|
|
...args: keyof Routes[P] extends never
|
|
? []
|
|
: Record<string, never> extends Routes[P]
|
|
? [params?: Routes[P]]
|
|
: [params: Routes[P]]
|
|
): string {
|
|
const params = (args[0] ?? {}) as Record<string, RouteValue>;
|
|
return buildHref(String(path), params);
|
|
}
|
|
|
|
export function route<N extends RouteName>(
|
|
name: N,
|
|
...args: keyof Routes[RouteNames[N]] extends never
|
|
? [params?: Routes[RouteNames[N]], query?: RouteQuery<RouteNames[N]>]
|
|
: Record<string, never> extends Routes[RouteNames[N]]
|
|
? [params?: Routes[RouteNames[N]], query?: RouteQuery<RouteNames[N]>]
|
|
: [params: Routes[RouteNames[N]], query?: RouteQuery<RouteNames[N]>]
|
|
): string {
|
|
const paths: Record<RouteName, RoutePath> = {
|
|
"index": "/",
|
|
"about": "/about",
|
|
"async.data": "/async-data",
|
|
"chat": "/chat",
|
|
"client.only": "/client-only",
|
|
"dashboard": "/dashboard",
|
|
"hello": "/hello",
|
|
"language.tools": "/language-tools",
|
|
"login": "/login",
|
|
"modal": "/modal",
|
|
"partial.static": "/partial-static",
|
|
"platform.showcase": "/platform-showcase",
|
|
"reactive": "/reactive",
|
|
"server.actions": "/server-actions",
|
|
"test": "/test",
|
|
"ui": "/ui"
|
|
} as Record<RouteName, RoutePath>;
|
|
const output = buildHref(paths[name], (args[0] ?? {}) as Record<string, RouteValue>);
|
|
const query = args[1];
|
|
if (!query) return output;
|
|
const search = new URLSearchParams();
|
|
for (const [key, value] of Object.entries(query))
|
|
if (value !== undefined && value !== null) search.set(key, String(value));
|
|
const text = search.toString();
|
|
return text ? `${output}?${text}` : output;
|
|
}
|