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

navia

v1.0.1

Published

Backend Framework based on Express

Downloads

3

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

  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.