navia
v1.0.1
Published
Backend Framework based on Express
Downloads
3
Maintainers
Readme
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
- Fork the repository.
- Create a branch with a descriptive name (git checkout -b descriptive-name).
- Make your changes and ensure to follow coding conventions.
- Commit your changes (git commit -am 'Add new features').
- Push the branch (git push origin descriptive-name).
- Open a pull request and describe your changes.