# @libstack/router

> An extreme powerful Express Routing machine

Latest version **1.0.0** (published 2019-11-28) · MIT license · 0 weekly downloads

## Install

```sh
npm install @libstack/router
pnpm add @libstack/router
yarn add @libstack/router
bun add @libstack/router
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.0 |
| Published | 2019-11-28 |
| First published | 2019-10-25 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 26.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Sérgio Marcelino |
| Maintainers | sergiofilhow |
| Keywords | express, router, interceptor, typescript |

## Links

- npm: https://www.npmjs.com/package/@libstack/router
- Repository: https://github.com/sergiofilhowz/libstack
- Homepage: https://github.com/sergiofilhowz/libstack#readme
- Issues: https://github.com/sergiofilhowz/libstack/issues
- npm.io page: https://npm.io/package/@libstack/router

## Dependencies (1)

- [express](https://npm.io/package/express.md) ^4.17.1

## Alternatives

- [express-promise-router](https://npm.io/package/express-promise-router.md) — 736.1K weekly downloads
- [next-usequerystate](https://npm.io/package/next-usequerystate.md) — 29.8K weekly downloads
- [@bitkyc08/opencodex](https://npm.io/package/@bitkyc08/opencodex.md) — 4.6K weekly downloads
- [lynkr](https://npm.io/package/lynkr.md) — 575 weekly downloads
- [baremetal.js](https://npm.io/package/baremetal.js.md) — 42 weekly downloads

## Recent versions

- 1.0.0 (latest) — 2019-11-28
- 1.0.0-rc.1 — 2019-11-24
- 1.0.0-dev.2 — 2019-11-14
- 1.0.0-dev.1 — 2019-10-25

## 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.

```typescript
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).

```typescript
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`

```typescript
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`

```typescript
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);
```

---
_Source: https://npm.io/package/@libstack/router · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
