npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

router-wrapper-js

v3.0.1

Published

A router wrapper for Express and Fastify

Downloads

28

Readme

RouterWrapperJS

RouterWrapperJS is a wrapper for backend frameworks routes, making them more compact with better chaining and custom middleware sharing. Abstracting middlewares and other functions.

Currently supported frameworks:

  • Express
  • Fastify

Getting Started

Install RouterWrapperJS via npm:

npm i router-wrapper-js

Install RouterWrapperJS via yarn:

yarn add router-wrapper-js

Usage

The basic structure for route params:

  • Express
    {
        path: string;
        handler: Function; // Controller function
        middleware?: any[]; // Middlewares
    }
  • Fastify
    {
        path: string;
        handler: Function; // Controller function
        schema?: {};
        preHandler?: any[]; // Middlewares
    }

Usage with Express

An example of express router wrapper usage:

import express, { Request } from "express";
import { ExpressRouterWrapper } from "router-wrapper-js";

const app = express();

const router = new ExpressRouterWrapper({ auth?: YOUR_AUTH_MIDDLEWARE })
    .get({
        path: "/",
        handler: async () => await homeController(),
        middleware: [MIDDLWARE_1, MIDDLWARE_2, MIDDLWARE_3]
    })
    .protectedGet({
        path: "/user",
        handler: async (req: Request) => await userController(req),
        middleware: [MIDDLWARE_1, MIDDLWARE_2, MIDDLWARE_3]
    })
    .post({
        path: "/user",
        handler: async (req: Request) => await newUserController(req)
    })
    .protectedPost({
        path: "/book",
        handler: async (req: Request) => await newBookController(req)
    })
    .patch({
        path: "/user",
        handler: async (req: Request) => await editUserController(req)
    })
    .protectedPatch({
        path: "/book",
        handler: async (req: Request) => await editBookController(req)
    })
    .delete({
        path: "/user/:id",
        handler: async (req: Request) => await deleteUserController(req)
    })
    .protectedDelete({
        path: "/book/:id",
        handler: async (req: Request) => await deleteBookController(req)
    })
    .make();

app.use("/", router);

app.listen(5000);

Usage with Fastify

An example of fastify router wrapper usage:

import Fastify, { FastifyReply, FastifyRequest } from "fastify";
import { FastifyRouterWrapper } from "router-wrapper-js";

const fastify = Fastify();

const route = new FastifyRouterWrapper(fastify, { auth?: YOUR_AUTH_MIDDLEWARE })
    .get({
        path: "/",
        handler: async () => await homeController(),
        preHandler: [MIDDLWARE_1, MIDDLWARE_2, MIDDLWARE_3]
    })
    .protectedGet({
        path: "/user",
        handler: async (req: FastifyRequest, reply: FastifyReply) => await userController(req),
        preHandler: [MIDDLWARE_1, MIDDLWARE_2, MIDDLWARE_3]
    })
    .post({
        path: "/user",
        handler: async (req: FastifyRequest, reply: FastifyReply) => await newUserController(req),
        schema: userSchema
    })
    .protectedPost({
        path: "/book",
        handler: async (req: FastifyRequest, reply: FastifyReply) => await newBookController(req),
        schema: bookSchema,
        preHandler: [MIDDLEWARE_1, MIDDLEWARE_2]
    })
    .patch({
        path: "/user",
        handler: async (req: FastifyRequest, reply: FastifyReply) => await editUserController(req)
    })
    .protectedPatch({
        path: "/book",
        handler: async (req: FastifyRequest, reply: FastifyReply) => await editBookController(req)
    })
    .delete({
        path: "/user/:id",
        handler: async (req: FastifyRequest, reply: FastifyReply) => await deleteUserController(req)
    })
    .protectedDelete({
        path: "/book/:id",
        handler: async (req: FastifyRequest, reply: FastifyReply) => await deleteBookController(req)
    })
    .make();

fastify.register(route);

fastify.listen({ port: 5000 });

Sharing Middleware

Sharing middleware in both Express and Fastify router wrappers, allows middleware to be applied for some routes which are in the shared middleware array and ignoring routes not in the array. Usage example:

With Express

const router = new ExpressRouterWrapper(
    { auth: AUTH },
    [SHARED_MIDDLEWARE_1, SHARED_MIDDLEWARE_2, ..., SHARED_MIDDLEWARE_N] // Shared middleware
)
    /**
     * Routes which share middleware - This function has to always be before route methods
     * It also applies to the multiple method routes, i.e, using the multiple()
     * Here, only GET /user route will have shared middleware applied to it
     * While PATCH /user and GET /user/data will not have the shared middleware
     */
    .shareTo(["GET /user"])
    .get({
        path: "/user",
        handler: async (req: Request) => await userController(req)
    })
    .patch({
        path: "/user",
        handler: async (req: Request) => await editUserController(req),
        middleware: [MIDDLEWARE]
    })
    .protectedGet({
        path: "/user/data",
        handler: async (req: Request) => await userDataController(req),
        middleware: [MIDDLEWARE]
    })
    .make();

With Fastify

const routes = new FastifyRouterWrapper(fastify, { auth }, [
    SHARED_MIDDLEWARE_1, SHARED_MIDDLEWARE_2, ..., SHARED_MIDDLEWARE_N
])
    .shareTo(["GET /user"])
    .multiple(
        "/user",
        ["get", "post"],
        [
            {
                handler: async (request: FastifyRequest, reply: FastifyReply) => await getUserController(req)
                preHandler: [MIDDLEWARE_1]
            },
            {
                handler: async (request: FastifyRequest, reply: FastifyReply) => await createUserController(req)
            }
        ]
    )
    .protectedGet({
        path: "/user",
        handler: async (request: FastifyRequest, reply: FastifyReply) => await userController(req),
        preHandler: [PREHANDLERS]
    })
    .patch({
        path: "/book",
        handler: async (request: FastifyRequest, reply: FastifyReply) => await bookController(req),
        preHandler: [PREHANDLERS]
    })
    .make();

Multiple Methods per Route

Using multiple() accepts multiple methods with their handlers and middleware for a single route.
The objects containing handlers and middlewares array are ordered relatively to the order of the the methods array.

With Express

const router = new ExpressRouterWrapper(
    { auth: AUTH },
    [SHARED_MIDDLEWARE_1, SHARED_MIDDLEWARE_2, ..., SHARED_MIDDLEWARE_N] // Shared middleware
)
    .shareTo(["GET /user"])
    /**
     * Allowing multiple methods to a route
     * Order of methods defines the order of route handlers
     */
    .multiple(
        "/user",
        ["get", "post"],
        [
            {
                // Here the handler is for the GET method
                handler: async (req: Request) => await getUserController(req)
                middleware: [MIDDLEWARE_1]
            },
            {
                // And here the handler is for the POST method
                handler: async (req: Request) => await createUserController(req)
            }
        ]
    )
    .make();

With Fastify

const routes = new FastifyRouterWrapper(fastify, { auth }, [
    SHARED_MIDDLEWARE_1, SHARED_MIDDLEWARE_2, ..., SHARED_MIDDLEWARE_N
])
    .shareTo(["GET /user"])
    .multiple(
        "/user",
        ["get", "post"],
        [
            {
                handler: async (request: FastifyRequest, reply: FastifyReply) => await getUserController(req)
                middleware: [MIDDLEWARE_1]
            },
            {
                handler: async (request: FastifyRequest, reply: FastifyReply) => await createUserController(req)
            }
        ]
    )
    .make();

Controller Handler

The router wrapper has an internal controller handler wrapper for both the Express and Fastify. Basically wrapping the controller function passed to the route function. The format of the expected returned data object from the controller function in your app is supposed to look like this:

{
    status: number, // Status code of the operation
    success: boolean, // Success state of the operation
    data: {} // Data returned from the operation
}

Example

Taking the newUserController() as an example:

const newUserController = async (req: Request) => {
  const res = await addNewUserService(req);

  return {
    status: res.status,
    success: res.success,
    data: res.data,
  };
};

Open to contributors

To add a middleware which might be useful in general use with the router wrapper, kindly, make a pull request with your extended implementation.
Also, looking forward to extend the wrapping beyond ExpressJs and Fastify to include router wrapping for other JS backend frameworks!

Thank you:)

License

MIT