1.2.0 • Published 1 year ago

vue-lite-route v1.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

vue-lite-route

Vue routing reimagined.

Table of Contents

Features

  • Simpler routes registration with high-level API
  • Route groups with nesting and group modifiers
  • Middleware support on a per-route level
  • Middleware pipelines (chains) support

Getting started

Install the package from npm:

$ npm install vue-lite-route

Now you should register the middleware pipelines processing for your router instance.
registerMiddlewareProcessing function will register the beforeEach guard which will process the middleware pipelines for each registered route.

import { createRouter } from 'vue-router';
import { registerMiddlewareProcessing } from 'vue-lite-route';

export const router = createRouter({...});
registerMiddlewareProcessing(router);

Usage

Now you can proceed to the route registration.
Let's take a couple of examples of route registrar usage.

Registering routes:

//// Routes.ts
import { Route } from 'vue-lite-route';
import ProfilePage from '.../ProfilePage.vue';
import OtherSectionPage from '.../OtherSectionPage.vue';

Route.add('/profile', { component: ProfilePage }).name('profile');
Route.add('/other/section', { component: OtherSectionPage }).name('other.section');

export const routes = Route.buildRoutes();
// After this you should pass the routes to your router instance

//// Router.ts
import { createRouter } from 'vue-router';
import { registerMiddlewareProcessing } from 'vue-lite-route';

export const router = createRouter({
    routes
});
registerMiddlewareProcessing(router);

// The code above will produce the routes equivalent to:
export const routes = [
    {
        path: '/profile',
        component: ProfilePage,
        name: 'profile'
    },
    {
        path: '/other/section',
        component: OtherSectionPage,
        name: 'other.section'
    }
];

Registering routes using group:

//// Routes.ts
import { Route } from 'vue-lite-route';
//... your Vue component imports

Route.group({ prefix: '/path/prefix', name: 'name.prefix' }, () => {
    Route.add('/profile', { component: ProfilePage }).name('.profile');
    Route.add(
        '/other/section',
        { components: {
            default: SomeContent,
            LeftSideBar,
            FooterSection    
        }}
    ).name('.other.section');
    Route.group({ prefix: '/another/prefix', name: '.another.prefix' }, () => {
        Route.add('/deep', { redirect: { name: 'name.prefix.profile' } }).name('.deep');
    })
});

export const routes = Route.buildRoutes();

// The code above will produce the routes equivalent to:
export const routes = [
    {
        path: '/path/prefix/profile',
        component: ProfilePage,
        name: 'name.prefix.profile'
    },
    {
        path: '/path/prefix/other/section',
        components: {
            default: SomeContent,
            LeftSideBar,
            FooterSection
        },
        name: 'name.prefix.other.section'
    },
    {
        path: '/path/prefix/profile',
        redirect: { name: 'name.prefix.profile' },
        name: 'name.prefix.another.prefix.deep'
    }
];

With group usage, you can nest the routes without the need to write the same path or name prefixes everywhere.
This also simplifies the process of the path and name updating for a group of routes because you need to change them only in one place.

Registering routes using childrenGroup:

//// Routes.ts
import { Route } from 'vue-lite-route';
//... your Vue component imports

Route.childrenGroup('/parent', { action: { component: ParentComponent }, name: 'parent' }, () => {
    Route.add('nested-child', { component: NestedPage }).name('nestedPage');
});

export const routes = Route.buildRoutes();

// The code above will produce the routes equivalent to:
export const routes = [
    {
        path: '/parent',
        component: ParentComponent,
        name: 'parent',
        children: [
            {
                path: 'nested-child',
                component: NestedPage,
                name: 'nestedPage'
            }
        ]
    }
]

Route Middleware

The middleware processing is one of the main features of this package because it provides an easy way to make complex middleware pipelines with different logic.

There are two ways to create a middleware:

  • Create a class that implements a Middleware contract.
  • Create a function that implements a MiddlewareFunction contract.

Let's take an example of each option:

//// CheckToken.ts
export class CheckToken implements Middleware {
    async handle(context: MiddlewareContext): Promise<boolean | undefined | RouteLocationRaw> {
        const token = 'some_token';
        // ... some logic to check the token

        // Important thing is to return this context.next() 
        // because it calls the next middleware in the pipeline.
        return await context.next();
    }
}

//// CheckOption.ts
export const CheckOption: MiddlewareFunction = async (context) => {
    const option = 'option_here';
    // ... some logic to check the option

    // Important thing is to return this context.next() 
    // because it calls the next middleware in the pipeline.
    return await context.next();
}

There is an option to break the middleware chain execution at some specific middleware by returning false value or the route for redirect.

Common situation is the middleware for checking user authentication:

//// Auth.ts
export const Auth: MiddlewareFunction = async (context) => {
    // ... some logic to retrieve the user

    const user = null; // The user is not authenticated because we can't retrieve it

    if(!user) {
        return { name: 'login' }; // We redirect the user to route 'login'
    }

    return await context.next();
}

// Basic example with this middleware protection in routes registration
Route.group({ middleware: [Auth] }, () => {
    // Routes here are protected by Auth middleware
    Route.add('/profile', { component: ProfilePage }).name('profile');
    Route.add('/payment-info', { component: PaymentInfoPage }).name('paymentInfo');
});
// We can also add this middleware protection for the specific route without group
Route.add('/password-change', { component: PasswordChangePage }).middleware([Auth]).name('passwordChange');

API Documentation

Interfaces

RouteActionSingleView

This is an action that represents one Vue component assigned for the route.

Properties:

RouteActionMultipleViews

This is an action that represents multiple Vue components assigned for the route.

Properties:

RouteActionRedirect

This is an action that represents a redirect assigned for the route.

Properties:

  • redirect: RouteRecordRedirectOption

RouteActionChildrenGroupSingleView

This is an action that represents one Vue component assigned for the route with children section. This action is used only in childrenGroup() registration method

Properties:

RouteActionChildrenGroupMultipleViews

This is an action that represents multiple Vue components assigned for the route with children section. This action is used only in childrenGroup() registration method

Properties:

Modifier

This is an object that represents a modifier for a route group registration.

Properties:

NormalizedModifier

The same as Modifier but the middleware is always stored as array.

Properties:

Middleware

A contract for the class-based middleware declarations.

Methods:

MiddlewareFunction

A contract for the function-based middleware declarations.

(context: MiddlewareContext): Promise<boolean | undefined | RouteLocationRaw>

MiddlewareContext

This is a contract for the context that is passed in each middleware during the chain execution.

Properties:

Type aliases

RouteAction

RouteAction = RouteActionSingleView | RouteActionMultipleViews | RouteActionRedirect
An object that represents possible action bindings for routes (component, components, redirect)

RouteActionChildrenGroup

RouteActionChildrenGroup = RouteActionChildrenGroupSingleView | RouteActionChildrenGroupMultipleViews
An object that represents possible action bindings for childrenGroup() method.
Similar to the RouteAction but supports only routes that are registered with children section.

RawMiddleware

RawMiddleware = Middleware | MiddlewareFunction | Array<Middleware | MiddlewareFunction> A type that specifies all possible declarations of a middleware registration.

Classes and functions:

RouteRegistrar

new RouteRegistrar()

Creates a new RouteRegistrar instance with clear routes collection.

The Route instance that you import for usage is actually an exported instance of this class

get routes(): PreparedRouteRecord[]

Getter that retrieves the internal route registrar array of PreparedRouteRecord instances.

clear(): this

Clears all registered routes from internal collection.

addRoute(path: string, action: RouteAction | RouteActionChildrenGroup): PreparedRouteRecord

Registers a new route into route registrar collection.

add(path: string, action: RouteAction | RouteActionChildrenGroup): PreparedRouteRecord

An alias of addRoute().

group(modifier: Modifier, routesRegistrationClosure: () => void)

Makes a group for the routes registration with provided modifier object.
The modifier is applied only inside scope of closure function that is provided as 2nd parameter.

childrenGroup(path: string, { action: RouteActionChildrenGroup, middleware?: RawMiddleware, name?: string, meta?: RouteMeta) }, routesRegistrationClosure: () => void)

Registers a route that will have children section inside.
All routes that are registered inside routesRegistrationClosure will be placed inside this children section.

buildRoutes(): RouteRecordRaw[]

Builds the final routes collection for the Vue router from the internal PreparedRouteRecord array.

PreparedRouteRecord

new PreparedRouteRecord({ path: string, action: RouteAction | RouteActionChildrenGroup, attachedModifier?: NormalizedModifier })

Creates a new PreparedRouteRecord with specified path and action.
If the attachedModifier is passed then it is getting saved into this instance.

path(path: string): this

Assignment of the new path for the record.
If this record has attachedModifier and the modifier contains a prefix then it makes a prefix for a new path.

middleware(middleware: RawMiddleware): this

Assignment of the new middleware for the record. If this record has attachedModifier and the modifier contains a middleware array then it makes a prefix for a new middleware.

name(name: string): this

Assignment of the new name for the record.
If this record has attachedModifier and the modifier contains a prefix then it makes a prefix for a new name.

meta(meta: RouteMeta): this

Assignment of the new route meta for the record.

addChild(child: PreparedRouteRecord): this

Add a new child record to the internal state.
After route build the children records will be located under the children section.

props(props: _RouteRecordProps | (Record<string, _RouteRecordProps> | boolean)): this

Add route props section.
Acts the same as in standard vue-router routes.

toRawRoute(): RouteRecordRaw

Builds the standard vue-router route from this record.
Result route can be directly consumed by the vue-router instance.

Functions

registerMiddlewareProcessing(router: Router): Router

This function accepts the Vue router instance and registers the middleware processing guard for it.

Resources

Credits

The vue-lite-route package is heavily inspired by the Laravel Router. This package is an effort to provide the same easy way for route registration and middleware processing as in Laravel framework.

License

MIT

1.2.0

1 year ago

1.1.0

1 year ago

1.0.1

1 year ago

1.0.0

2 years ago