nestia-helper

Nestia Helper

Usage no npm install needed!

<script type="module">
  import nestiaHelper from 'https://cdn.skypack.dev/nestia-helper';
</script>

README

Nestia Helper

npm install --save nestia-helper

GitHub license npm version Downloads Build Status

Helper library of the NestJS with nestia.

nestia-helper is a type of helper library for Nestia by enhancing decorator functions. Also, all of the decorator functions provided by this nestia-helper are all fully compatible with the nestia, who can generate SDK library by analyzing NestJS controller classes in the compilation level.

Of course, this nestia-helper is not essential for utilizing the NestJS and nestia. You can generate SDK library of your NestJS developed backend server without this nestia-helper. However, as decorator functions of this nestia-helper is enough strong, I recommend you to adapt this nestia-helper when using NestJS and nestia.

Features

EncryptedRoute

Encrypted router decorator functions.

EncryptedRoute is an utility class containing encrypted router decorator functions. Unlike the basic router decorator functions provided from the NestJS like nest.Get() or nest.Post(), router decorator functions in the EncryptedRoute encrypts the response body with AES-128/256 algorithm. Also, they support the ExceptionManager who can convert custom error classes to the regular nest.HttpException class.

Therefore, with the EncryptedRoute and ExceptionManager, you can manage your custom error classes much systematically. You can avoid 500 internal server error or hard coding implementations about the custom error classes.

Furthermore, you can enhance security of your HTTP server by encrypting the response body through this EncryptedRoute. Also, don't be annoying about such AES-128/256 encryption and decryption. If you build an SDK library of your HTTP server through the nestia, such encryption and decryption would be automatically done in the SDK level.

@nest.Controller("bbs/articles")
export class BbsArticlesController
{
    @helper.EncryptedRoute.Get(":id")
    public async at
        (
            @nest.Param("id") id: string
        ): Promise<IBbsArticle>;
}

EncryptedBody

Encrypted body decorator.

EncryptedBody is a decorator function getting special JSON data from the HTTP request who've encrypted by the AES-125/256 algorithm. Therefore, EncryptedBody is suitable for enhancing security by hiding request body data from the client.

Also you don't need to worry about the annyoing encryption and decryption. If you build an SDK library of your HTTP server through the nestia, such encryption would be automatically done in the SDK level.

@nest.Controller("bbs/articles")
export class BbsArticlesController
{
    @helper.EncryptedRoute.Post()
    public async store
        (
            @helper.EncryptedBody() input: IBbsArticle.IStore
        ): Promise<IBbsArticle>;

    @helper.EncryptedRoute.Put(":id")
    public async update
        (
            @nest.Param("id") id: string,
            @helper.EncryptedBody() input: IBbsArticle.IUpdate
        ): Promise<IBbsArticle.IContent>;
}

EncryptedController

Encrypted controller.

EncryptedController is an extension of the nest.Controller class decorator function who configures encryption password of the AES-128/256 algorithm. The encryption algorithm and password would be used by EncryptedRoute and EncryptedBody to encrypt the request and response body of the HTTP protocol.

By the way, you can configure the encryption password in the global level by using EncryptedModule instead of the nest.Module in the module level. In that case, you don't need to use this EncryptedController more. Just use the nest.Controller without duplicated encryption password definitions.

Of course, if you want to use different encryption password from the EncryptedModule, this EncryptedController would be useful again. Therefore, I recommend to use this EncryptedController decorator function only when you must configure different encryption password from the EncryptedModule .

@helper.EncryptedController("payments/webooks", {
    key: "SqwHmmXm1fZteI3URPtoyBWFJDMQ7FBQ",
    iv: "9eSfjygAClnE1JJs"
})
export class PaymentWebhooksController
{
    @helper.TypedRoute.Post()
    public async webhook
        (
            @helper.EncryptedBody() input: IPaymentWebhook
        ): Promise<void>;
}

EncryptedModule

Encrypted module.

EncryptedModule is an extension of the nest.Module class decorator function who configures encryption password of the AES-128/256 algorithm. The encryption algorithm and password would be used by EncryptedRoute and EncryptedBody to encrypt the request and response bod of the HTTP protocol.

By using this EncryptedModule decorator function, all of the controllers configured in the metadata would be automatically changed to the EncryptedController with the password. If there're some original EncryptedController decorated classes in the metadata, their encryption password would be kept.

Therefore, if you're planning to place original EncryptedController decorated classes in the metadata, I hope them to have different encryption password from the module level. If not, I recommend you use the nest.Controller decorator function instead.

In addition, the EncryptedModule supports a convenient dynamic controller importing function, EncryptedModule.dynamic. If you use the function with directory path of the controller classes, it imports and configures the controller classes into the nest.Module, automatically.

import helper from "nestia-helper";
import { NestFactory } from "@nestjs/core";

export class Backend
{
    private application_: nest.INestApplication | null;

    public async open(port: number): Promise<void>
    {
        this.application_ = await NestFactory.create
        (
            await helper.EncryptedModule.dynamic
            (
                __dirname + "/controllers",
                {
                    key: "pJXhbHlYfzkC1CBK8R67faaBgJWB9Myu",
                    iv: "IXJBt4MflFxvxKkn"
                }
            );
        );
        await this.application_.open(port);
    }
}

ExceptionManager

Exception manager for HTTP server.

ExceptionManager is an utility class who can insert or erase custom error class with its convertion method to a regular nest.HttpException instance.

If you define an API function through TypedRoute or EncryptedRoute instead of the basic router decorator functions like nest.Get or nest.Post and the API function throws a custom error whose class has been inserted in this EntityManager, the error would be automatically converted to the regular nest.HttpException instance by the ExceptionManager.Closure function.

Therefore, with this ExceptionManager and TypedRoute or EncryptedRoute, you can manage your custom error classes much systemtically. You can avoid 500 internal server error or hard coding implementation about the custom error classes.

Below error classes are defaultly configured in this ExceptionManager

  • typescript-is.TypeGuardError
  • nestia-fetcher.HttpError
import helper from "nestia-helper";
import * as nest from "@nestjs/common";
import * as orm from "typeorm";

//  ERROR FROM THE DATABASE
helper.ExceptionManager.insert(orm.QueryFailedError, exp => 
{
    if (exp.message.indexOf("ER_DUP_ENTRY: ") !== -1)
        return new nest.ConflictException("Blocked by unique constraint.");
    else if (exp.message.indexOf("ER_NO_REFERENCED_ROW_2") !== -1)
        return new nest.NotFoundException("Blocked by foreign constraint.");
    else
        return new nest.InternalServerErrorException(exp.message);
});

TypedRoute

Router decorator functions.

TypedRoute is an utility class containing router decorator functions.

Unlike the basic router decorator functions provided from the NestJS like nest.Get or nest.Post, router decorator functions in the TypedRoute supports ExceptionManager, who can convert custom error classes to the regular nest.HttpException class.

Therefore, with the TypedRoute and ExceptionManager, you can manage your custom error classes much systematically. You can avoid 500 internal server error or hard coding implementations about the custom error classes.

import helper from "nestia-helper";
import * as nest from "@nestjs/common";
import * as orm from "typeorm";

@nest.Controller("shopping/sales")
export class ShoppingSalesController
{
    @helper.TypedRoute.Get(":id")
    public async at
        (
            @helper.TypedParam("id", "string") id: string,
        ): Promise<IShoppingSale>
    {
        // when `orm.EntityNotFound` occurs, 
        // it would be replaced to the `404` error
        const sale: ShoppingSale = await ShoppingSale.findOneOrFail(id);
        return await ShoppingSaleProvider.json(sale);
    }
}

helper.ExceptionManager.insert(orm.EntityNotFoundError, exp => 
{
    return new nest.NotFoundException(exp.message);
});

TypedParam

URL parameter decorator with type.

TypedParam is a decorator function getting specific typed parameter from the HTTP request URL. It's almost same with the nest.Param, but TypedParam can specify the parameter type manually. Beside, the nest.Param always parses all of the parameters as string type.

@nest.Controller("shopping/sales")
export class ShoppingSalesController
{
    @helper.TypedRoute.Get(":section/:id/:paused")
    public async pause
        (
            @helper.TypedParam("section", "string") section: string,
            @helper.TypedParam("id", "number") id: number,
            @helper.TypedParam("paused", "boolean") paused: boolean
        ): Promise<void>;
}

PlainBody

Plain body decorator.

PlainBody is a decorator function getting full body text from the HTTP request.

If you adjust the regular nest.Body decorator function to the body parameter, you can't get the full body text because the nest.Body tries to convert the body text to JSON object. Therefore, nestia-helper provides this PlainBody decorator function to get the full body text.

@nest.Controller("memo")
export class MemoController
{
    @helper.TypedRoute.Post()
    public async store
        (
            @helper.PlainBody() input: string
        ): Promise<IMemo>;
}

Appendix

Template Project

https://github.com/samchon/backend

I support template backend project using this nestia-helper library, backend.

Also, reading the README content of the backend template repository, you can find lots of example backend projects who've been generated from the backend. Furthermore, the example projects guide how to generate SDK library from the nestia and how to distribute the SDK library thorugh the NPM module.

Therefore, if you're planning to compose your own backend project using this nestia-helper with nestia, I recommend you to create the repository and learn from the backend template project.

Nestia

https://github.com/samchon/nestia

As I've mentioned, this nestia-helper is a type of helper library for the NestJS and nestia. With the nestia, you don't need to write any swagger comment. Just deliver the SDK library who've built by the nestia.

When you're developing a backend server using the NestJS, you don't need any extra dedication, for delivering the Rest API to the client developers, like writing the swagger comments. You just run this nestia up, then nestia would generate the SDK automatically, by analyzing your controller classes in the compliation and runtime level.

With the automatically generated SDK through this nestia, client developer also does not need any extra work, like reading swagger and writing the duplicated interaction code. Client developer only needs to import the SDK and calls matched function with the await symbol.

import api from "@samchon/bbs-api";
import { IBbsArticle } from "@samchon/bbs-api/lib/structures/bbs/IBbsArticle";
import { IPage } from "@samchon/bbs-api/lib/structures/common/IPage";

export async function test_article_read(connection: api.IConnection): Promise<void>
{
    // LIST UP ARTICLE SUMMARIES
    const index: IPage<IBbsArticle.ISummary> = await api.functional.bbs.articles.index
    (
        connection,
        "free",
        { limit: 100, page: 1 }
    );

    // READ AN ARTICLE DETAILY
    const article: IBbsArticle = await api.functional.bbs.articles.at
    (
        connection,
        "free",
        index.data[0].id
    );
    console.log(article.title, aritlce.body, article.files);
}

Safe-TypeORM

https://github.com/samchon/safe-typeorm

safe-typeorm is another library that what I've developed, helping TypeORM in the compilation level and optimizes DB performance automatically without any extra dedication.

Therefore, this nestia makes you to be much convenient in the API interaction level and safe-typeorm helps you to be much convenient in the DB interaction level. With those nestia and safe-typeorm, let's implement the backend server much easily and conveniently.

  • When writing SQL query,
    • Errors would be detected in the compilation level
    • Auto Completion would be provided
    • Type Hint would be supported
  • You can implement App-join very conveniently
  • When SELECTing for JSON conversion
    • App-Join with the related entities would be automatically done
    • Exact JSON type would be automatically deduced
    • The performance would be automatically tuned
  • When INSERTing records
    • Sequence of tables would be automatically sorted by analyzing dependencies
    • The performance would be automatically tuned

Safe-TypeORM Demo