From 31cf069029bd284d5ecc15c785f9e9a92e5bcb2f Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 8 Sep 2020 14:55:14 +0200 Subject: [PATCH] docs(api): adding docs to source code --- src/errors.ts | 29 ++++++ src/index.ts | 2 +- src/location.ts | 8 +- src/matcher/index.ts | 2 +- src/matcher/pathParserRanker.ts | 8 +- src/matcher/types.ts | 6 ++ src/navigationGuards.ts | 12 +-- src/router.ts | 171 ++++++++++++++++++++++++++++---- src/types/index.ts | 40 ++++++-- 9 files changed, 241 insertions(+), 37 deletions(-) diff --git a/src/errors.ts b/src/errors.ts index bca946ab..2783af73 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -34,17 +34,46 @@ export interface MatcherError extends RouterErrorBase { currentLocation?: MatcherLocation } +/** + * Enumeration with all possible types for navigation failures. Can be passed to + * {@link isNavigationFailure} to check for specific failures. + */ export enum NavigationFailureType { + /** + * An aborted navigation is a navigation that failed because a navigation + * guard returned `false` or called `next(false)` + */ aborted = ErrorTypes.NAVIGATION_ABORTED, + /** + * A cancelled navigation is a navigation that failed because a more recent + * navigation finished started (not necessarily finished). + */ cancelled = ErrorTypes.NAVIGATION_CANCELLED, + /** + * A duplicated navigation is a navigation that failed because it was + * initiated while already being at the exact same location. + */ duplicated = ErrorTypes.NAVIGATION_DUPLICATED, } + +/** + * Extended Error that contains extra information regarding a failed navigation. + */ export interface NavigationFailure extends RouterErrorBase { + /** + * Type of the navigation. One of {@link NavigationFailureType} + */ type: | ErrorTypes.NAVIGATION_CANCELLED | ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_DUPLICATED + /** + * Route location we were navigating from + */ from: RouteLocationNormalized + /** + * Route location we were navigating to + */ to: RouteLocationNormalized } diff --git a/src/index.ts b/src/index.ts index cf38b32d..210be735 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,7 +34,7 @@ export { RouteRecordRaw, NavigationGuard, NavigationGuardNext, - PostNavigationGuard, + NavigationHookAfter, } from './types' export { createRouter, diff --git a/src/location.ts b/src/location.ts index cd175eeb..e9e43979 100644 --- a/src/location.ts +++ b/src/location.ts @@ -116,8 +116,8 @@ export function stripBase(pathname: string, base: string): string { * pointing towards the same {@link RouteRecord} and that all `params`, `query` * parameters and `hash` are the same * - * @param a first {@link RouteLocation} - * @param b second {@link RouteLocation} + * @param a - first {@link RouteLocation} + * @param b - second {@link RouteLocation} */ export function isSameRouteLocation( stringifyQuery: (query: LocationQueryRaw) => string, @@ -141,8 +141,8 @@ export function isSameRouteLocation( * Check if two `RouteRecords` are equal. Takes into account aliases: they are * considered equal to the `RouteRecord` they are aliasing. * - * @param a first {@link RouteRecord} - * @param b second {@link RouteRecord} + * @param a - first {@link RouteRecord} + * @param b - second {@link RouteRecord} */ export function isSameRouteRecord(a: RouteRecord, b: RouteRecord): boolean { // since the original record has an undefined value for aliasOf diff --git a/src/matcher/index.ts b/src/matcher/index.ts index ce957513..de015091 100644 --- a/src/matcher/index.ts +++ b/src/matcher/index.ts @@ -379,7 +379,7 @@ function isAliasRecord(record: RouteRecordMatcher | undefined): boolean { /** * Merge meta fields of an array of records * - * @param matched array of matched records + * @param matched - array of matched records */ function mergeMetaFields(matched: MatcherLocation['matched']) { return matched.reduce( diff --git a/src/matcher/pathParserRanker.ts b/src/matcher/pathParserRanker.ts index 6910e3ac..c8e998c9 100644 --- a/src/matcher/pathParserRanker.ts +++ b/src/matcher/pathParserRanker.ts @@ -44,6 +44,9 @@ export interface PathParser { stringify(params: PathParams): string } +/** + * @internal + */ export interface _PathParserOptions { /** * Makes the RegExp case sensitive. Defaults to false @@ -54,11 +57,12 @@ export interface _PathParserOptions { */ strict?: boolean /** - * Should the RegExp match from the beginning by prepending a ^. Defaults to true + * Should the RegExp match from the beginning by prepending a `^` to it. Defaults to true + * @internal */ start?: boolean /** - * Should the RegExp match until the end by appending a $. Defaults to true + * Should the RegExp match until the end by appending a `$` to it. Defaults to true */ end?: boolean } diff --git a/src/matcher/types.ts b/src/matcher/types.ts index b0a6e241..fc320bb0 100644 --- a/src/matcher/types.ts +++ b/src/matcher/types.ts @@ -8,6 +8,9 @@ import { import { ComponentPublicInstance } from 'vue' // normalize component/components into components and make every property always present +/** + * Normalized version of a {@link RouteRecord | Route Record} + */ export interface RouteRecordNormalized { /** * {@inheritDoc _RouteRecordBase.path} @@ -77,4 +80,7 @@ export interface RouteRecordNormalized { aliasOf: RouteRecordNormalized | undefined } +/** + * {@inheritDoc RouteRecordNormalized} + */ export type RouteRecord = RouteRecordNormalized diff --git a/src/navigationGuards.ts b/src/navigationGuards.ts index 1add7d04..90fd35fe 100644 --- a/src/navigationGuards.ts +++ b/src/navigationGuards.ts @@ -41,9 +41,9 @@ function registerGuard(list: NavigationGuard[], guard: NavigationGuard) { } /** - * Add a navigation guard that triggers whenever the current location is - * left. Similarly to {@link beforeRouteLeave}, it has access to the - * component instance as `this`. + * Add a navigation guard that triggers whenever the component for the current + * location is about to be left. Similar to {@link beforeRouteLeave} but can be + * used in any component. The guard is removed when the component is unmounted. * * @param leaveGuard - {@link NavigationGuard} */ @@ -68,9 +68,9 @@ export function onBeforeRouteLeave(leaveGuard: NavigationGuard) { } /** - * Add a navigation guard that triggers whenever the current location is - * updated. Similarly to {@link beforeRouteUpdate}, it has access to the - * component instance as `this`. + * Add a navigation guard that triggers whenever the current location is about + * to be updated. Similar to {@link beforeRouteUpdate} but can be used in any + * component. The guard is removed when the component is unmounted. * * @param updateGuard - {@link NavigationGuard} */ diff --git a/src/router.ts b/src/router.ts index 8575a12d..75f1f081 100644 --- a/src/router.ts +++ b/src/router.ts @@ -2,7 +2,7 @@ import { RouteLocationNormalized, RouteRecordRaw, RouteLocationRaw, - PostNavigationGuard, + NavigationHookAfter, START_LOCATION_NORMALIZED, Lazy, RouteLocationNormalizedLoaded, @@ -69,6 +69,11 @@ type OnReadyCallback = [() => void, (reason?: any) => void] type Awaitable = T | Promise export interface ScrollBehavior { + /** + * @param to - Route location where we are navigating to + * @param from - Route location where we are navigating from + * @param savedPosition - saved position if it exists, `null` otherwise + */ ( to: RouteLocationNormalized, from: RouteLocationNormalizedLoaded, @@ -98,16 +103,25 @@ export interface RouterOptions extends PathParserOptions { */ routes: RouteRecordRaw[] /** - * Function to control scrolling when navigating between pages. + * Function to control scrolling when navigating between pages. Can return a + * Promise to delay scrolling. Check {@link ScrollBehavior}. + * + * @example + * ```js + * function scrollBehavior(to, from, savedPosition) { + * // `to` and `from` are both route locations + * // `savedPosition` can be null if there isn't one + * } + * ``` */ scrollBehavior?: ScrollBehavior /** - * Custom implementation to parse a query. + * Custom implementation to parse a query. See its counterpart, + * {@link RouterOptions.stringifyQuery}. * * @example - * Let's say you want to use the package {@link https://github.com/ljharb/qs | `qs`} - * to parse queries, you would need to provide both `parseQuery` and - * {@link RouterOptions.stringifyQuery | `stringifyQuery`}: + * Let's say you want to use the package {@link https://github.com/ljharb/qs | qs} + * to parse queries, you can provide both `parseQuery` and `stringifyQuery`: * ```js * import qs from 'qs' * @@ -120,7 +134,8 @@ export interface RouterOptions extends PathParserOptions { */ parseQuery?: typeof originalParseQuery /** - * {@link RouterOptions.parseQuery | `parseQuery`} counterpart to handle query parsing. + * Custom implementation to stringify a query object. Should not prepend a leading `?`. + * {@link RouterOptions.parseQuery | parseQuery} counterpart to handle query parsing. */ stringifyQuery?: typeof originalStringifyQuery /** @@ -145,30 +160,160 @@ export interface Router { * @internal */ // readonly history: RouterHistory + /** + * Current {@link RouteLocationNormalized} + */ readonly currentRoute: Ref + /** + * Original options object passed to create the Router + */ readonly options: RouterOptions + /** + * Add a new {@link RouteRecordRaw | Route Record} as the child of an existing route. + * + * @param parentName - Parent Route Record where `route` should be appended at + * @param route - Route Record to add + */ addRoute(parentName: RouteRecordName, route: RouteRecordRaw): () => void + /** + * Add a new {@link RouteRecordRaw | route record} to the router. + * + * @param route - Route Record to add + */ addRoute(route: RouteRecordRaw): () => void + /** + * Remove an existing route by its name. + * + * @param name - Name of the route to remove + */ removeRoute(name: RouteRecordName): void + /** + * Checks if a route with a given name exists + * + * @param name - Name of the route to check + */ hasRoute(name: RouteRecordName): boolean + /** + * Get a full list of all the {@link RouteRecord | route records}. + */ getRoutes(): RouteRecord[] + /** + * Returns the {@link RouteLocation | normalized version} of a + * {@link RouteLocationRaw | route location}. Also includes an `href` property + * that includes any existing `base`. + * + * @param to - Raw route location to resolve + */ resolve(to: RouteLocationRaw): RouteLocation & { href: string } + /** + * Programmatically navigate to a new URL by pushing an entry in the history + * stack. + * + * @param to - Route location to navigate to + */ push(to: RouteLocationRaw): Promise + /** + * Programmatically navigate to a new URL by replacing the current entry in + * the history stack. + * + * @param to - Route location to navigate to + */ replace(to: RouteLocationRaw): Promise + /** + * Go back in history if possible by calling `history.back()`. Equivalent to + * `router.go(-1)`. Returns a Promise. See the limitations at + * {@link Router.go}. + */ back(): Promise + /** + * Go forward in history if possible by calling `history.forward()`. + * Equivalent to `router.go(1)`. Returns a Promise. See the limitations at + * {@link Router.go}. + */ forward(): Promise + /** + * Allows you to move forward or backward through the history. Returns a + * Promise that resolves when the navigation finishes. If it wasn't possible + * to go back, the promise never resolves or rejects + * + * @param delta - The position in the history to which you want to move, + * relative to the current page + */ go(delta: number): Promise + /** + * Add a navigation guard that executes before any navigation. Returns a + * function that removes the registered guard. + * + * @param guard - navigation guard to add + */ beforeEach(guard: NavigationGuardWithThis): () => void + /** + * Add a navigation guard that executes before navigation is about to be + * resolved. At this state all component have been fetched and other + * navigation guards have been successful. Returns a function that removes the + * registered guard. + * + * @example + * ```js + * router.beforeEach(to => { + * if (to.meta.requiresAuth && !isAuthenticated) return false + * }) + * ``` + * + * @param guard - navigation guard to add + */ beforeResolve(guard: NavigationGuardWithThis): () => void - afterEach(guard: PostNavigationGuard): () => void + /** + * Add a navigation hook that is executed after every navigation. Returns a + * function that removes the registered hook. + * + * @example + * ```js + * router.afterEach((to, from, failure) => { + * if (isNavigationFailure(failure)) { + * console.log('failed navigation', failure) + * } + * }) + * ``` + * + * @param guard - navigation hook to add + */ + afterEach(guard: NavigationHookAfter): () => void + /** + * Adds an error handler that is called every time a non caught error happens + * during navigation. This includes errors thrown synchronously and + * asynchronously, errors returned or passed to `next` in any navigation + * guard, and errors occurred when trying to resolve an async component that + * is required to render a route. + * + * @param handler - error handler to register + */ onError(handler: ErrorHandler): () => void + /** + * Returns a Promise that resolves when the router has completed the initial + * navigation, which means it has resolved all async enter hooks and async + * components that are associated with the initial route. If the initial + * navigation already happened, the promise resolves immediately. + * + * This is useful in server-side rendering to ensure consistent output on both + * the server and the client. Note that on server side, you need to manually + * push the initial location while on client side, the router automatically + * picks it up from the URL. + */ isReady(): Promise + /** + * Called automatically by `app.use(router)`. Should not be called manually by + * the user. + * + * @internal + * @param app - Application that uses the router + */ install(app: App): void } @@ -186,7 +331,7 @@ export function createRouter(options: RouterOptions): Router { const beforeGuards = useCallbacks>() const beforeResolveGuards = useCallbacks>() - const afterGuards = useCallbacks() + const afterGuards = useCallbacks() const currentRoute = shallowRef( START_LOCATION_NORMALIZED ) @@ -826,14 +971,6 @@ export function createRouter(options: RouterOptions): Router { return Promise.reject(error) } - /** - * Returns a Promise that resolves or reject when the router has finished its - * initial navigation. This will be automatic on client but requires an - * explicit `router.push` call on the server. This behavior can change - * depending on the history implementation used e.g. the defaults history - * implementation (client only) triggers this automatically but the memory one - * (should be used on server) doesn't - */ function isReady(): Promise { if (ready && currentRoute.value !== START_LOCATION_NORMALIZED) return Promise.resolve() diff --git a/src/types/index.ts b/src/types/index.ts index 026db0e8..fd48ea02 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -177,6 +177,7 @@ export type _RouteRecordProps = // TODO: could this be moved to matcher? /** * Common properties among all kind of {@link RouteRecordRaw} + * @internal */ export interface _RouteRecordBase extends PathParserOptions { /** @@ -225,6 +226,9 @@ export type RouteRecordRedirectOption = | RouteLocationRaw | ((to: RouteLocation) => RouteLocationRaw) +/** + * Route Record defining one single component with the `component` option. + */ export interface RouteRecordSingleView extends _RouteRecordBase { /** * Component to display when the URL matches this route. @@ -236,6 +240,9 @@ export interface RouteRecordSingleView extends _RouteRecordBase { props?: _RouteRecordProps } +/** + * Route Record defining multiple named components with the `components` option. + */ export interface RouteRecordMultipleViews extends _RouteRecordBase { /** * Components to display when the URL matches this route. Allow using named views. @@ -249,6 +256,10 @@ export interface RouteRecordMultipleViews extends _RouteRecordBase { props?: Record | boolean } +/** + * Route Record that defines a redirect. Cannot have `component`, `components` or + * `children` as it is never rendered. + */ export interface RouteRecordRedirect extends _RouteRecordBase { redirect: RouteRecordRedirectOption component?: never @@ -256,16 +267,26 @@ export interface RouteRecordRedirect extends _RouteRecordBase { children?: never } -export interface RouteRecordRedirectWithChildren extends _RouteRecordBase { - component?: never - children: Exclude<_RouteRecordBase['children'], undefined> -} - export type RouteRecordRaw = | RouteRecordSingleView | RouteRecordMultipleViews | RouteRecordRedirect +/** + * Initial route location where the router is. Can be used in navigation guards + * to differentiate the initial navigation. + * + * @example + * ```js + * import { START_LOCATION } from 'vue-router' + * + * router.beforeEach((to, from) => { + * if (from === START_LOCATION) { + * // initial navigation + * } + * }) + * ``` + */ export const START_LOCATION_NORMALIZED: RouteLocationNormalizedLoaded = { path: '/', name: undefined, @@ -322,6 +343,10 @@ export type NavigationGuardReturn = | boolean | NavigationGuardNextCallback +/** + * Navigation guard. See [Navigation + * Guards](/guide/advanced/navigation-guards.md). + */ export interface NavigationGuard { ( // TODO: we could maybe add extra information like replace: true/false @@ -331,6 +356,9 @@ export interface NavigationGuard { ): NavigationGuardReturn | Promise } +/** + * {@inheritDoc NavigationGuard} + */ export interface NavigationGuardWithThis { ( this: T, @@ -340,7 +368,7 @@ export interface NavigationGuardWithThis { ): NavigationGuardReturn | Promise } -export interface PostNavigationGuard { +export interface NavigationHookAfter { ( to: RouteLocationNormalized, from: RouteLocationNormalized, -- 2.47.2