sveltejs / kit

web development, streamlined
https://svelte.dev/docs/kit
MIT License
18.78k stars 1.96k forks source link

Add a function to map from path to routeId (inverse of resolveRoute fn) #11746

Open thundergolfer opened 10 months ago

thundergolfer commented 10 months ago

Describe the problem

We have ?next=<path> routing in our app, and want to modify <path> on the basis of whether it is from a certain routeID. If the path does not match the relevant routeID, it is left unmodified.

Currently we hardcode a list of path prefixes that can't match the routeID. More generally, we would like to take advantage of SvelteKit's filesystem based routing to get a function that maps from a string path to its RouteID (if one exists).

This problem has come up before on Reddit: https://www.reddit.com/r/sveltejs/comments/14azrdg/how_can_i_determine_the_corresponding_route_id/

Describe the proposed solution

A function of the form getRouteIdByPathname(pathname: string) -> routeId: string, or a function of that provides not just the top matching route but the actual list of matches: https://kit.svelte.dev/docs/advanced-routing#sorting.

pathname routeId
/signin /(auth)/signin
/signup /(auth)/signup
/forgot /(auth)/forgot
/archive/1 /archive/[page]
/archive/2 /archive/[page]
/news/sport/1 /news/[type]/[page]
/news/music/1 /news/[type]/[page]

We could then do if (getRouteIdByPathname(nextPath) === "/news/[type]/[page]") { ... }.

Alternatives considered

Importance

would make my life easier

Additional Information

No response

mikerowe81 commented 9 months ago

I would also like this feature.

Perhaps something like:

function resolvePath(
    path: string
): {
    id: string
    params: Record<string, string | undefined>
};

e.g.

resolvePath("/blog/page1")

returns

{
    id: "/blog/[slug]",
    params: {
        slug: "page1"
    }
}

My use case is for route based permissions where I'd like to hide menu items or links if the user does not have permission to that route.

I'm sure the functionality is already built-in, it's just a matter of making the function public.

ptrxyz commented 3 months ago

And while we are at it: can we also make it so that resolveRoute's id auto-completes known ids? I saw that all the generated $types.d.ts files already contain RouteId. Something like so:

type AllRoutes = RouteId1 | RouteId2 | ... | (string & {})
//                                           ^^^^^^^^^^^^^ Always allow string
//               ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Imported from all $types.d.ts files
declare function resolveRoute(route: AllRoutes, params: Record<string, string>): string
ptrxyz commented 3 months ago

As a workaround I made this: https://www.npmjs.com/package/vite-plugin-svelte-typed-routes

// vite.config.ts
import vitePluginSvelteTypedRoutes from 'vite-plugin-svelte-typed-routes'
export default defineConfig({
  plugins: [
    vitePluginSvelteTypedRoutes({
      runPrettier: true
    }), 
    //other plugins here
  ]
})

Simply use resolveRoute and it will automagically autocomplete the routeId.