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

@alarife/http

v0.4.0

Published

The open source web development tool based on Express.js that maximizes speed and efficiency during development and maintenance.

Downloads

18

Readme

Alarife - HTTP server plugin

Alarife http plugin is a library that provides a decorator pattern for generating servers with express.

To start a project with this library you first need to know the alarife-core. Application example code alarife.

Decorators

@HttpServer

HttpServer is a class decorator.

HttpServer decorator parameters:

  • Server parameters

    • ip String IP address to server
    • port Number The port address to server
    • apiRoot String The base path to server
    • controllers Array<T> Drivers assigned to server
  • SSL parameters

    • Parameter Object | Boolean default is false. HTTPS Options Setting Guide. (If ssl=true, look for the key.pem and cert.pem files in the project root.)

This decorator instantiates the class to which it is applied to launch its constructor, so you can add additional configuration.

You can add the parameters belonging to HttpServer to your instance with @Value.

HttpServer includes: protocol, ip, port, apiRoot, app, webSocket, hasSsl, options (SSL), accessLog configuration includes: accessLog configuration functions.

import { App, Value } from '@alarife/core/decorators';
import { HttpServer } from '@alarife/http/decorators';

import TestController from '...';

@App()
@HttpServer({ port : 9000, controllers : [TestController] })
class Main {

  @Value('HttpServer.protocol') protocol;

  @Value('HttpServer.ip') ip;

  @Value('HttpServer.port') port;

  @Value('HttpServer.apiRoot') apiRoot;

  @Value('HttpServer.app') app;

  @Value('HttpServer.webSocket') webSocket;

  @Value('HttpServer.ssl.hasSsl') hasSsl;

  @Value('HttpServer.ssl.options') sslOptions;

  @Value('HttpServer.accessLog') accessLog;

  /** Core configuration value */

  @Value('configuration') configuration;

  constructor() {
    this.configuration.traceLog({ levels : ['info', 'debug', 'error', 'warn'] });
    this.configuration.accessLog({ active : true });

    this.app.use(express.json());
    this.app.use(express.urlencoded({ extended : false }));

    this.log.info('ip: ', this.ip);
    this.log.info(`port: ${this.port}`);
  }
}

@Controller

Controller is a class decorator.

Receives a path parameter that would be the parent path, the path is required.

The operation of the controller system is simple.

The @Controller decorator injects the Logger module.

Support for Get, Post, Delete, Put and Ws methods. Just to decorate methods.

import { Controller, Get } from '@alarife/http/decorators';

@Controller('/test')
class TestController {

  @Get('/ping')
  ping(req, res) {
    return res.success(200).json({ message : 'pong' });
  }
}

@Get, @Post, @Delete, @Put and @Ws

This decorator applies to methods.

The REST function receives the parameters of express req, res and next.

The WebSocket function receives the express-ws parameters ws and req.

import { Controller, Get, Ws } from '@alarife/http/decorators';

@Controller('/test')
class TestController {

  @Get('/ping')
  ping(req, res, next) {
    return res.success(200).json({ message : 'pong' });
  }

  @Ws('/status')
  serverStatus(ws, req) {
    ws.on('message', function(msg) {
      this.log.info(msg);
      ws.send('OK');
    });
  }
}

@Use

To make a stack of different methods in the same route we can use the Use.

In the following example we see the Use of Use with various middlewares. The order of execution would be as indicated in the comments.

The input parameter is an express middleware function

import { AutoWired } from '@alarife/core/decorators';
import { Controller, Get, Use } from '@alarife/http/decorators';

// Protect example
const protect = ({ headers }, res, next) => {
  if(!headers.token) {
    return res.unauthorized().end();
  }
}

const roleProtect = (roles = []) => ({ headers }, res, next) => {
  if(!headers.token) {
    return res.unauthorized().end();
  }
}

@Controller('/user')
@Use(protect) //execution 1
class UserController {

  @AutoWired(UserService) userService;

  @Get('/list')
  @Use((req, res, next) => {
    //execution 2

    next();
  })
  @Use(roleProtect(['admin'])) //execution 3
  userList(req, res) {
    //execution 4
    const users = this.userService.getAllUsers();

    res.success().json(users);
  }
}

@Body

Body is a JSON body validator middleware, decorate methods.

ajv is used as a library to validate json objects.

import { AutoWired } from '@alarife/core/decorators';
import { Controller, Post, Body } from '@alarife/core/decorators';

// Ajv schema
const productBody = {
  type: "object",
  properties: {
    name: {type: "string"},
    description : {type: "string"},
    price: {type: "number"}
  },
  required: ["name", "price"],
  additionalProperties: false,
};


@Controller('/store')
class StoreController {

  @AutoWired(ProductsService) productsService;

  @Post('/create')
  @Body(productBody)
  products({ body }, res) {
    return this.productsService.createProduct(body)
      .then(product => {
        this.log.info(product);
        res.success().json(product);
      })
      .catch(err => {
        this.log.error(err);
        res.serverError().json(err).end();
      });
  }
}

@Dto

The DTO class decorator generates validation models for ajv from javascript classes.

The @Dto decorator injects the Logger module.

import { Dto } from '@alarife/http/decorators/dto';

@Dto()
class ProductModel { ... }

Fields

Parameter decorators generate the properties to validate. The decorators are: @String, @Number, @Date, @Boolean, @Enum, @ObjectId and @ArrayId

Field options:

  • name String | undefined Reference name that the validator will get.
  • values Array List of elements, only used in Enum.
  • target Class
  • configuration.optional Boolean Field is optional.
  • configuration.required Boolean Field is required.
  • configuration.nullable Boolean Field is nullable.
  • configuration.error String Custom error message for this field.
import { Dto, String, Enum, ArrayId, ObjectId } from '@alarife/http/decorators/dto';

@Dto 
class Category { ... }

@Dto({
  error : {
    type                 : 'should be an object',
    required             : 'should have property foo',
    additionalProperties : 'should not have properties other than foo'
  }
})
class ProductModel { 

  /**
   * Four parameter variants 
  */

  /** Without parameters, Use the parameter name as the field name and use default options. */
  @String() name;

  /** With String parameter, Use the entered field name and default options. */
  @String('product_name') name;

  /** With object parameter, Use the field name of the parameter as the field name and combine default options and those introduced by parameters. */
  @String({ required: true }) name;

  /** With String and Object parameters, use the field name entered by parameters and combine the default options and those entered by parameters. */
  @String('product_name', { required: true }) name;

  /** Insert by parameters name, values and options */
  @Enum('product_role', [...], {...}) role;

  /**
   * In reference decorators you can insert an AJV class or object.
  */

  /** Insert by parameters name, Schema reference and options */
  @ArrayId('comments_list', Comment, { uniqueItems: true }) comments;

  /** Insert by parameters name, Schema reference and options */
  @ObjectId('image', Image, {...}) image;

  /**
   * Configuration options
   * 
  */
  @String({ 
    required: true,
    required: [true, 'Error message required field'], // Required field with custom error message

    optional: true,
    nullable: true,

    error: 'Error message' // Error message for any field error
  }) name;
  
  ...
}

Full mode of use (Class)

import { Controller, Post, Body } from '@alarife/http/decorators';
import { Dto, String, Number } from '@alarife/http/decorators/dto';

@Dto()
class ProductModel {

  @String({ required: true })
  name

  @String()
  description

  @Number({ required: true })
  price
}


@Controller('/store')
class StoreController {


  /**
   * Simple mode 
  */
  @Post('/create')
  @Body(ProductModel)
  products({ body }, res) {
    ...
  }

  /**
   * Object array mode
  */
  @Post('/import')
  @Body([ProductModel])
  products({ body }, res) {
    ...
  }
}

Addons

Some of the additional functionalities that the library contains are listed.

Response

The response contains new methods that simplify responses a bit.

res.success(200).json({ message : 'pong' });
res.success(204);

res.badRequest().json({ message : 'Error' });
res.badRequest().end();

res.unauthorized().end();
res.notFound().end();
res.serverError().end();

Related