Last active
July 14, 2026 23:35
-
-
Save maiah/c8d03b0b89120a100f603b2feb46e22c to your computer and use it in GitHub Desktop.
Astro Create Route for Client routing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { z } from "astro/zod"; | |
| type ExtractParams<T extends string> = | |
| T extends `${string}[${infer Param}]${infer Rest}` | |
| ? { [K in Param | keyof ExtractParams<Rest>]: string } | |
| : {}; | |
| type IsEmptyObject<T> = keyof T extends never ? true : false; | |
| type HrefArgs<T extends string, S extends z.ZodTypeAny | undefined> = | |
| IsEmptyObject<ExtractParams<T>> extends true | |
| ? S extends z.ZodTypeAny | |
| ? { searchParams: z.infer<S> } | |
| : void | |
| : S extends z.ZodTypeAny | |
| ? { params: ExtractParams<T>; searchParams: z.infer<S> } | |
| : { params: ExtractParams<T> }; | |
| type RouteConfig<T extends string, S extends z.ZodTypeAny | undefined> = { | |
| path: T; | |
| searchParams?: S; | |
| }; | |
| export function createRoute< | |
| T extends string, | |
| S extends z.ZodTypeAny | undefined = undefined, | |
| >(config: RouteConfig<T, S>) { | |
| return { | |
| getCachePath(): string { | |
| return config.path; | |
| }, | |
| getParams(): ExtractParams<T> { | |
| const patternSegments = config.path.split("/"); | |
| const pathSegments = window.location.pathname.split("/"); | |
| const params: Record<string, string> = {}; | |
| for (let i = 0; i < patternSegments.length; i++) { | |
| const seg = patternSegments[i]; | |
| const match = seg.match(/^\[(.+)\]$/); | |
| if (match) { | |
| params[match[1]] = pathSegments[i] ?? ""; | |
| } | |
| } | |
| return params as ExtractParams<T>; | |
| }, | |
| href( | |
| ...args: HrefArgs<T, S> extends void ? [] : [args: HrefArgs<T, S>] | |
| ): string { | |
| const hrefArgs = args[0] as | |
| | { | |
| params?: Record<string, string>; | |
| searchParams?: Record<string, string>; | |
| } | |
| | undefined; | |
| let url = config.path.replace( | |
| /\[([^\]]+)\]/g, | |
| (_, key: string) => hrefArgs?.params?.[key] ?? "", | |
| ); | |
| if (hrefArgs && "searchParams" in hrefArgs && hrefArgs.searchParams) { | |
| const qs = new URLSearchParams( | |
| hrefArgs.searchParams as Record<string, string>, | |
| ); | |
| url += `?${qs.toString()}`; | |
| } | |
| return url; | |
| }, | |
| }; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment