// Code based on vue-router // Copyright (c) 2020 Eduardo San Martin Morote // Released under the MIT license // https://github.com/vuejs/vue-router-next/blob/master/LICENSE import { _RouteRecordBase } from 'vue-router' import { RawRouteComponent, NavigationGuardReturn } from '../vue-router-utils' import { RoutiderPath, RoutiderPaths, pathToString, pathsToString, Path } from '../options/path' import { RoutiderLocation, RoutiderLocationN } from './location' import { RoutiderNavigationGuardNext } from '../router/navigationGuard' import { RouteRecordName } from '../options/name' import { RoutiderRoutes } from '../options/options' /** * Typed _RouteRecordProps */ export type _RouteRecordProps< Params extends string | undefined, Queries extends string | undefined, RouteName extends RouteRecordName = RouteRecordName > = | boolean // eslint-disable-next-line @typescript-eslint/no-explicit-any | Record | (( to: RoutiderLocation // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => Record) type RoutiderRouteRecordRedirectOption< Params extends string | undefined, Queries extends string | undefined, RouteName extends RouteRecordName = RouteRecordName > = (to: RoutiderLocation) => unknown /** * Typed `NavigationGuardWithThis` for beforeEnter */ export interface RoutiderBeforeEnterGuardWithThis< T, Params extends string | undefined, Queries extends string | undefined, RouteName extends RouteRecordName = RouteRecordName > { ( this: T, to: RoutiderLocationN, from: RoutiderLocationN, next: RoutiderNavigationGuardNext> ): NavigationGuardReturn | Promise } /** * Typed RouteRecordBase */ export interface _RoutiderRouteRecordBase< Params extends string | undefined, Queries extends string | undefined, Children extends RoutiderRoutes | undefined > extends Omit< _RouteRecordBase, 'path' | 'query' | 'children' | 'beforeEnter' > { /** * `name` will be automatically set from key */ name?: never /** * Path of the record. Should start with / unless the record is the child of another record. * @example createPath`/users/${'id'}` matches `/users/1` as well as `/users/posva`. '/users' matches only `/users`. */ path: Path /** * Use `path` with an array for aliases. */ alias?: never /** * Define queries which may receive */ query?: Queries[] children?: Children redirect?: RoutiderRouteRecordRedirectOption beforeEnter?: | RoutiderBeforeEnterGuardWithThis | RoutiderBeforeEnterGuardWithThis[] } interface RoutiderRouteRecordSingleView< Params extends string | undefined, Queries extends string | undefined, Children extends RoutiderRoutes | undefined > extends _RoutiderRouteRecordBase { /** * Component to display when the URL matches this route. */ component: RawRouteComponent /** * Allow passing down params as props to the component rendered by `router-view`. */ props?: _RouteRecordProps } interface RoutiderRouteRecordMultipleViews< Params extends string | undefined, Queries extends string | undefined, Children extends RoutiderRoutes | undefined > extends _RoutiderRouteRecordBase { /** * Components to display when the URL matches this route. Allow using named views. */ components: Record /** * Allow passing down params as props to the component rendered by * `router-view`. Should be an object with the same keys as `components` or a * boolean to be applied to every component. */ props?: Record> | boolean } interface RoutiderRouteRecordRedirect< Params extends string | undefined, Queries extends string | undefined, Children extends RoutiderRoutes | undefined > extends _RoutiderRouteRecordBase { redirect: RoutiderRouteRecordRedirectOption component?: never components?: never children?: never } export type RoutiderRouteRecord< Params extends string | undefined = string | undefined, Queries extends string | undefined = string | undefined, // eslint-disable-next-line @typescript-eslint/no-explicit-any Children extends RoutiderRoutes | undefined = any > = | RoutiderRouteRecordSingleView | RoutiderRouteRecordMultipleViews | RoutiderRouteRecordRedirect export type ExtractChildren< T extends RoutiderRouteRecord > = T extends RoutiderRouteRecord< string | undefined, string | undefined, infer C > ? C : never interface PathAndAlias { path: string alias?: string[] } export const pathToPathAndAlias = ( path: RoutiderPath | string | RoutiderPaths | string[] ): PathAndAlias => { if (!Array.isArray(path)) return { path: pathToString(path) } if (path.length <= 0) { throw new Error( 'Path property in Route of RoutiderOptions must have at least 1 path.' ) } const pathStrings = pathsToString(path) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const pathProp = pathStrings.shift()! return { path: pathProp, alias: pathStrings } } type ConvertToUndefinedIfStringPath< Route extends RoutiderRouteRecord > = Route extends RoutiderRouteRecord ? string extends P ? RoutiderRouteRecord : Route : never type ConvertToUndefinedIfStringQuery< Route extends RoutiderRouteRecord > = Route extends RoutiderRouteRecord ? string extends Q ? RoutiderRouteRecord : Route : never export const createRoute = < Params extends string | undefined, Queries extends string | undefined, Children extends RoutiderRoutes | undefined = undefined >( route: RoutiderRouteRecord ): ConvertToUndefinedIfStringQuery< ConvertToUndefinedIfStringPath> > => route as ConvertToUndefinedIfStringQuery< ConvertToUndefinedIfStringPath< RoutiderRouteRecord > >