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

@libstack/router

v1.0.0

Published

An extreme powerful Express Routing machine

Downloads

2

Readme

@libstack/router

An extreme powerful Express Routing machine

What is it ?

This module adds the async/await to your express app. In addition to promise, you can add endpoint configurations so you can intercept the request and do everything you want.

Installation

npm install @libstack/router --save

Usage

You can create routes and interceptors. Let's first take a look on how to create routers.

Routers

Routers are entrypoints on your application, you can define one with multiple endpoints, which have the default start path from the router.

import { RestController, GET, POST, BadRequestError } from '@libstack/router';
// Supported methods: GET, POST, PUT, DELETE

@RestController('/myController')
class TestRouter {

  // The second argument is used for Interceptors (will be described in the next section)
  @GET('/', { addProperty: true })
  async get() {
    const result = await someModule.execAsyncCall();
    return result; 
  }

  @GET('/customEnd')
  async customEnd(req:Request, res:Response) {
    res.end('my custom end');
    // you can define the response you want by just calling res.end (from the express)
  }

  @POST('/throwError')
  async throwError() {
    throw new BadRequestError('My error message');
    // this error, when thrown, will return a 400 status code with this structure
    // { "message": "My error message" }
  }
}

Interceptors

So, what is exactly an interceptor? Interceptors are business logics that needs to be executed on specific endpoints or all endpoits, it's up to you. Examples of interceptors are:

  • Error Interceptor: Interceptor to catch one specific Error and return data to the API
  • Validation Interceptor: Catch body and check if the request is valid
  • Authentication Interceptor: Used to allow only authenticated users
  • ACL Interceptor: Used to allow only authenticated users that have roles to perform a request

Alright, so how can we create interceptors? So, let's give an example of interceptor that adds a property to the response body (just an example).

import { Request, Response } from 'express';
import { UnauthorizedError, CallableStack, Interceptor, RestInterceptor } from '@libstack/router';
import { getUserData, User } from './MyUserService';

@RestInterceptor
class ChangeResponseInterceptor implements Interceptor {
  /**
    * This method will be called on every request and the parameters are defined
    * on the second argument on @GET @POST @PUT and @DELETE decorators
    */
  intercepts(parameters: any): boolean {
    // so, for example, we created an interceptor that intercepts ALL requests
    return true;
  }

  /**
    * This method will only be executed if the condition on `intercepts` is true
    */
  async execute(parameters: any, req: Request, res: Response, stack: CallableStack): Promise<any> {
    /*
     * What exactly is this stack?
     * This is the interceptor execution stack. All interceptors
     * are linked within the Callable Stack and in order to continue
     * the execution you need to call next(). If you don't call next() it will
     * halt the request stack.
     */
    const response: any = await stack.next();
    
    // here we are changing the response
    if (response) {
      response.hello = 'Hello World';
    }
    return response; // if you don't return, there will be no response
  }
}

Errors

There are some predefined errors on the module

  • BadRequestError: Will return 400
  • NotFoundError: Will return 404
  • UnauthorizedError: Will return 401
  • ForbiddenError: Will return 403

But you can also create your own HTTP error by just extending HttpError

import { HttpError } from '@libstack/router';

export class UnauthorizedError extends HttpError {
  constructor(message: string, data?: any) {
    super(message, 401, data);
  }
}

As you can see, there's a data property on HttpErrors, they are used to send additional information about the error, for example, validation error must return which fields weren't properly set.

Linking @libstack/router on your express application

So, let's pretend we have created a router on ./routers/MyRouter.ts and an interceptor on ./interceptors/MyInterceptor.ts

import express from 'express';
import controller from '@libstack/router';

// then you will need to import the routers and interceptors in order to be loaded
// just import the router and interceptors and they'll be attached to the `controller`
import './routers/MyRouter';
import './interceptors/MyInterceptor';

const app = express();

app.use(controller.router); // use plugin the @libstack/router to your express app
app.listen(process.env.PORT || 8080);