UNPKG

ts-routes

Version:
48 lines (47 loc) 3.67 kB
import { IParseOptions, IStringifyOptions } from "qs"; import { Optionality } from "./helpers"; import PathParamDescription from "./PathParamDescription"; import QueryParamDescription from "./QueryParamDescription"; import RouteDescription from "./RouteDescription"; type MapToRoute<TRouteDescription extends RouteDescription<any, any, any>> = { (...params: [...args: PathPatternArgs<TRouteDescription>, stringifyOptions?: IStringifyOptions]): string; parseQuery: (query: string, parseOptions?: IParseOptions) => GetParsedQuery<TRouteDescription>; pattern: string; } & { [TKey in keyof RouteChildren<TRouteDescription>]: MapToRoute<AddParams<RouteChildren<TRouteDescription>[TKey], TRouteDescription>>; }; type RouteChildren<TRouteDescription extends RouteDescription<any, any, any>> = TRouteDescription extends RouteDescription<any, any, infer TChildren> ? TChildren : never; type AddParams<TDestRoute extends RouteDescription<any, any, any>, TSourceRoute extends RouteDescription<any, any, any>> = TDestRoute extends RouteDescription<infer TDestPathParamsDescription, infer TDestQueryParamsDesrciption, infer TChildren> ? TSourceRoute extends RouteDescription<infer TSourcePathParamsDescription, infer TSourceQueryParamsDescription, any> ? RouteDescription<[ ...TSourcePathParamsDescription, ...TDestPathParamsDescription ], TDestQueryParamsDesrciption & TSourceQueryParamsDescription, TChildren> : never : never; type MakeOptional<T> = {} extends T ? [T?] : [T]; type PathPatternArgs<TRouteDescription extends RouteDescription<any, any, any>> = [ ...pathParams: MakeOptional<MapPathParams<GetPathParams<TRouteDescription>>>, ...queryParams: MakeOptional<MapQueryParams<GetQueryParams<TRouteDescription>>> ]; type GetPathParams<TRouteDescription extends RouteDescription<any, any, any>> = TRouteDescription extends RouteDescription<infer TPathParams, any, any> ? TPathParams : never; type GetQueryParams<TRouteDescription extends RouteDescription<any, any, any>> = TRouteDescription extends RouteDescription<any, infer TQueryParams, any> ? TQueryParams : never; type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never; type MapPathParams<TPathParams extends PathParamDescription<string, Optionality>[]> = UnionToIntersection<{ [T in keyof TPathParams]: GetParam<TPathParams[T]>; }[number]>; type SingleOrArray<T> = T | T[]; type MapQueryParams<TQueryParams extends Record<string, QueryParamDescription<any, Optionality>>> = { [TName in keyof TQueryParams as TQueryParams[TName] extends QueryParamDescription<any, "optional"> ? TName : never]?: SingleOrArray<GetQueryResultType<TQueryParams[TName]>>; } & { [TName in keyof TQueryParams as TQueryParams[TName] extends QueryParamDescription<any, "required"> ? TName : never]: SingleOrArray<GetQueryResultType<TQueryParams[TName]>>; }; type GetQueryResultType<TQueryParam extends QueryParamDescription<any, Optionality>> = TQueryParam extends QueryParamDescription<infer TReturnType, Optionality> ? TReturnType : never; type GetParam<TPathParam> = TPathParam extends PathParamDescription<infer TName, infer TOptional> ? TOptional extends "optional" ? { [T in TName]?: string; } : { [T in TName]: string; } : never; type GetParsedQuery<TRouteDescription extends RouteDescription<any, any, any>> = MapQueryParams<GetQueryParams<TRouteDescription>>; export default function createRouting<TRoutes extends { readonly [name: string]: RouteDescription<any, any, any>; }>(routes: TRoutes, options?: IParseOptions & IStringifyOptions): { readonly [TKey in keyof TRoutes]: MapToRoute<TRoutes[TKey]>; }; export {};