sveltejs / kit

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

Functions for routes #11141

Open AlexRMU opened 11 months ago

AlexRMU commented 11 months ago

Describe the problem

.

Describe the proposed solution

I think it is necessary to add such functions :

Alternatives considered

No response

Importance

nice to have

Additional Information

It is necessary to take into account:

dimfeld commented 11 months ago

https://kit.svelte.dev/docs/modules#sveltejs-kit-resolvepath is a step towards the first item on your list.

It's not a complete solution (e.g. no type checking that the route ID actually exists in the current app), but once some of the other issues you linked are done, it should work nicely. I agree that better support for type-safe route url creation would be great.

AlexRMU commented 11 months ago

I see the solution to this issue like this (excluding https://github.com/sveltejs/kit/issues/647):

show ```ts /* /src/types.d.ts */ declare global { /** absolute path with the base */ export type Path = string; export type PathURL = Path | URL; /** params generic missing parameters cause a type error and are equal to undefined if undefined, the argument can be either undefined or missing */ export type ParamsT = Record | undefined; /** generated- */ export type IDtoParams = { "/(main)/user": undefined; "/(main)/user/[uuid]": { uuid: string }; }; export type DynamicIDtoID = { "profile page": "/(main)/user/[uuid]"; }; /** -generated */ export type ID_Union = keyof IDtoParams; export type DynamicID_Union = keyof DynamicIDtoID; export type IDtoSymbol = { [ID in ID_Union]: PageSymbol; }; export type DynamicIDtoSymbol = { [DynamicID in DynamicID_Union]: DynamicPageSymbol; }; /** or is it better to call it a page rune :) ? */ export type PageSymbol = { match: (path: PathURL) => boolean; stringify: (params: IDtoParams[ID]) => Path; parse: (path: PathURL) => Partial | undefined; id: ID; }; export type DynamicPageSymbol< ID extends ID_Union, Description extends string | undefined = undefined, > = PageSymbol & { description: Description; }; } declare module "$app/navigation" { export const parse_path: parse_path; interface parse_path { (path: PathURL): Parsed | undefined; (path: PathURL): Parsed | undefined; } interface Parsed { id: ID; params: Partial | undefined; } export const id_to_path: id_to_path; interface id_to_path { (id: ID, params: IDtoParams[ID]): Path; (id: ID_Union, params: Params): Path; } export const id_from_path: id_from_path; interface id_from_path { (path: PathURL): ID | undefined; (path: PathURL): ID_Union | undefined; } /** the symbol map it is creating and changing dynamically */ export const id_symbol_map: IDtoSymbol; export const create_page_symbol: create_page_symbol; interface create_page_symbol { (description: DynamicID): DynamicIDtoSymbol[DynamicID]; ( description: NewID, ): { error: "wait until the types are generated"; }; } } declare module "$app/stores" { /** also in the load function */ export const page1: import("svelte/store").Readable< import("@sveltejs/kit").Page & { /** current PageSymbol from the page context or undefined from outside the kit */ page_symbol: PageSymbol | undefined; } >; } export {}; ``` ```ts /* /src/lib/index.ts */ import { create_page_symbol, parse_path, id_to_path, id_from_path, id_symbol_map } from "$app/navigation"; const all_path_ids = Object.keys(id_symbol_map); const all_symbols = Object.values(id_symbol_map); const parsed1 = parse_path("/user/undefined"); parsed1!.id; // "/(main)/user" | "/(main)/user/[uuid]" parsed1!.params == undefined; const parsed2 = parse_path<"/(main)/user/[uuid]">("/user/undefined"); parsed2!.id == "/(main)/user/[uuid]"; parsed2!.params!.uuid! == "1234"; const parsed3 = parse_path(""); parsed3 == undefined; id_to_path("/(main)/user/[uuid]") == "/user/undefined"; // type error id_to_path("/(main)/user/[uuid]", {}) == "/user/undefined"; id_to_path("/(main)/user/[uuid]", { qwe: "asd" }) == "/user/undefined"; id_to_path("/(main)/user/[uuid]", { uuid: "1234" }) == "/user/1234"; id_from_path("") == undefined; id_from_path("/user/undefined") == "/(main)/user/[uuid]"; id_from_path("/user/1234") == "/(main)/user/[uuid]"; export const profile_page = create_page_symbol("profile page"); const literal = "profile page"; const profile_page1 = create_page_symbol(literal); // using the literal const new_symbol = create_page_symbol("new page"); // new symbol, without types profile_page.description == "profile page"; profile_page.id == "/(main)/user/[uuid]"; // dynamically changing - when you move the +page file, it will become a false profile_page.match("/user/1234") == true; profile_page.match("/user/undefined") == true; profile_page.match("/user") == false; profile_page.stringify() == "/user/undefined"; // type error profile_page.stringify({}) == "/user/undefined"; // type error profile_page.stringify({ uuid: "1234" }) == "/user/1234"; const parsed_params1 = profile_page.parse(""); parsed_params1 == undefined; const parsed_params2 = profile_page.parse("/user/undefined"); parsed_params2!.uuid == undefined; const parsed_params3 = profile_page.parse("/user/1234"); parsed_params2!.uuid == "1234"; ``` ```ts /* /src/routes/(main)/user/[uuid]/+page.ts */ import { profile_page } from "$lib"; export const symbol = profile_page; // if the symbol is not used anywhere or has been used several times - a type error and an error will appear during the build ``` ```svelte ```
AlexRMU commented 8 months ago

https://nextjs.org/docs/app/building-your-application/configuring/typescript#statically-typed-links https://github.com/tatethurston/nextjs-routes https://github.com/jagaapple/next-typed-routes https://github.com/ckastbjerg/next-type-safe-routes https://dev.to/qaynam/trying-out-type-safe-navigation-in-sveltekit-jk4 https://github.com/victorgarciaesgi/nuxt-typed-router https://router.vuejs.org/guide/advanced/typed-routes https://github.com/fenok/react-router-typesafe-routes https://github.com/zilch/type-route https://github.com/JacobFischer/ts-typed-routes https://github.com/fongandrew/typed-routes https://tanstack.com/router/latest https://intervene.dev/guide/typed-routes/ https://docs.expo.dev/router/reference/typed-routes/

AlexRMU commented 4 months ago

Additionally: route metadata https://router.vuejs.org/guide/advanced/meta https://github.com/dword-design/nuxt-route-meta https://docs.nestjs.com/custom-decorators https://docs.nestjs.com/graphql/extensions