1.0.1 • Published 5 months ago

navia v1.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

Navia

Installation

To install the library

bun add navia
# or in a Node environment
npm install navia

Getting Started

The library is based on TypeScript, so it's necessary to configure it

bun init
# or if you are in a Node environment
npm install --save-dev typescript @types/node
npx tsc --init

In the TypeScript configuration file tsconfig.json, set the following properties to true

{
    ...
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    ...
}

Finally, the application requires two things to work: a main class that acts as the root of the project, and a function that initializes the project

// src/main.ts
import { Navia } from "navia";
import { Root } from "./root";

function main() {
  const app = Navia.create(Root);

  app.start(process.env.PORT || 3000);
}

main();
// src/root.ts
import { Domain } from "navia"

@Domain({ controllers: [] })
export class Root {}

Con estos archivos la aplicacion ya funciona, el resto del proyecto puede ser a consideracion del desarrollador

Operation The operation of the application is mostly based on controllers. Controllers are classes decorated with the @Controller() artifact. To be recognized by the system, these classes must be imported into the @Domain() decorator of the main class. For example:

// src/controllers/todo.ts

@Controller('todo')
export class Todo {
    ...
}
// src/root.ts
import { Domain } from "navia"
import { Todo } from "./controller/todo"

@Domain({ controllers: [Todo] })
export class Root {}

This registers the routes declared in the controller under the path /todo/.... This varies depending on what is specified in the @Controller() decorator.

HTTP Methods

Methods of the class decorated with @Controller() can act as HTTP methods if associated with a method decorator: @Get(), @Post(), @Put(), @Delete(), as well as Patch, All, Options, Head, Search.

These decorators take a string as a parameter, which is the method's path. For example,

// src/controllers/todo.ts
import { Controller, Get, Delete } from "navia"

@Controller('todo')
export class Todo {

    @Get('')
    async index() {
        return ...
    }

    @Delete(':id')
    async remove() {
        return ...
    }

}

The first creates an endpoint at GET /todo/, while the second creates one at DELETE /todo/:id.

Method Parameters

HTTP method functions can receive request parameters by accessing the body, params, query params, or headers through @Body(), @Param(), @Query(), and @Headers(). These decorators take two optional parameters:

data: the name of the property you want to access. parser: an instance of special classes. For example, in the Todo controller, the remove method needs to access the value of id from the path /todo/:id. The way to access it is as follows:

// src/controllers/todo.ts
import { Controller, Get, Delete, Param } from "navia"

@Controller('todo')
export class Todo {

    ...

    @Delete(':id')
    async remove(@Param('id') id: string) {
        return ...
    }

}

By default, params, query params, and headers are treated as strings, but by adding a parser, we can transform the received value into the expected type.

Parser

To apply a parser, you just need to add an extra parameter to the property decorators. For example,

// src/controllers/todo.ts
import { Controller, Get, Delete, Param, IntParser } from "navia"

@Controller('todo')
export class Todo {

    ...

    @Delete(':id')
    async remove(@Param('id', new IntParser()) id: number) {
        return ...
    }

}

This will convert the parameter into an integer before it reaches the function.

!NOTE Currently, only the BoolParser and IntParser parsers exist.

Request Lifecycle

Acting as middleware, there are decorators that apply changes before, after, or if there's an error in the request. These are @OnBefore(), @OnAfter(), @OnError() respectively. They take classes as parameters, which implement:

  • LifeCycle in the case of @OnBefore() and @OnAfter().
  • ErrorHandling in the case of @OnError().

All three decorators can be applied at the class or method level. Examples of these are:

// src/lifecycle/handlers.ts
import { Context, ErrorContext, ErrorHandling, LifeCycle } from "navia";

// Context provides access to Express's Request, Response, and NextFunction
export class After implements LifeCycle {
  async use({ next }: Context): Promise<void> {
    console.log("after");

    next();
  }
}

export class Before implements LifeCycle {
  async use({ next }: Context): Promise<void> {
    console.log("before");

    next();
  }
}

// ErrorContext extends Context, adding the error as a property
export class ErrorHandler implements ErrorHandling {
  async handling({ res, error }: ErrorContext): Promise<void> {
    res.json({ message: "Algo salio mal });
  }
}

To apply them in the controller, you do it as follows:

// src/controllers/todo.ts
import { Controller, Get, Delete, Param, IntParser, OnError } from "navia"
import { ErrorHandler, Before } from "../lifecycle/handlers"

@Controller('todo')
@OnError(ErrorHandler)
export class Todo {

    ...

    @Delete(':id')
    @OnBefore(Before)
    @OnAfter(Before)
    async remove(@Param('id', new IntParser()) id: number) {
        return ...
    }

}

To-Do

  • Add parser for Float, UUID, Array.
  • Add global configuration for CORS and configuration per controllers and methods.
  • Handle file upload and download with multer.
  • Integrate request rate limiter by methods or controllers.
  • Integrate Cron task manager.
  • Develop a dependency injection system.

How to Contribute

  1. Fork the repository.
  2. Create a branch with a descriptive name (git checkout -b descriptive-name).
  3. Make your changes and ensure to follow coding conventions.
  4. Commit your changes (git commit -am 'Add new features').
  5. Push the branch (git push origin descriptive-name).
  6. Open a pull request and describe your changes.