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 🙏

© 2026 – Pkg Stats / Ryan Hefner

prorestify

v1.0.9

Published

prorestify is a RESTful scalable express router using promises

Readme

prorestify

Tired of spending time organizing your project as you scale?

Tired of all these APIs with random URLs and returning random HTTP codes?

This module is made for you!

  • prorestify is a RESTful scalable express router using promises
  • Version 1.0.0
  • Authors: Javier Rodriguez-Uria & Patrick Mettraux

Installation

$ npm install prorestify

Setup

let app = require('express')();
let prorestify = new require('prorestify')();

prorestify.router(app);

app.listen(8080)

Options

You can pass an object to change the default behaviour. Available options:

Name|Description|Default :-|:-|:- routeFolder | The path where your routes are located | ./routes/ allowUnknown | Defines if you allow unknown parameters during your endpoints' validation | false abortEarly | Defines if you stop validation on the first error | false

WorkFlow

The module execute actions in this order:

HTTP Request -> Endpoint's Middlewares -> Endpoint's Validation -> Endpoint's Controller

Endpoints

Structure-wise

Endpoints are based on the folder structure of your project. The modules will scan the routes folder.

Directory structure example:

├── project/
│   ├── routes/
│   │   ├── v1/
│   │   │   ├── groups/
│   │   │   |   ├── users.js
│   │   │   ├── users/
│   │   │   |   ├── groups.js
│   │   │   ├── users.js
│   │   │   ├── groups.js
│   ├── app.js

In the example above, if you want to create the following routes:

  • GET->https://yourwebsite.com/v1/users you will have to put the code inside the file located in /project/routes/v1/users.js
  • GET->https://yourwebsite.com/v1/groups you will have to put the code inside the file located in /project/routes/v1/groups.js
  • GET->https://yourwebsite.com/v1/users/:userId/groups you will have to put the code inside the file located in /project/routes/v1/users/groups.js
  • POST->https://yourwebsite.com/v1/groups/:groupId/users you will have to put the code inside the file located in /project/routes/v1/groups/users.js

Code-wise

Now that you know how to organize your files and folders according to the kind of endpoint you are trying to do we can have a look at the code itself.

Inside the right file the module is looking for a specific function named accordingly to the type of endpoint you want to do. This function must return an object containing at least a key named controller assigned to the controller function of this endpoint. This is a list on how to name you function accordingly to what kind of endpoint you want to create.

CREATE

A create is a POST call on a collection. Eg: POST->https://yourwebsite.com/v1/users/

module.exports = {
  create: function(app) {
    let controller = body => {
      // put your code inside here
      return app.yourUserCreationFunction(body);
    };

    return {
      controller,
    };
  }
};

LIST

A list is a GET call on a collection. Eg: GET->https://yourwebsite.com/v1/users/

module.exports = {
  list: function(app) {
    let controller = query => {
      // put your code inside here
      return app.yourUserListingFunction(query);
    };

    return {
      controller,
    };
  }
};

GET

A get is a GET call on an item. Eg: GET->https://yourwebsite.com/v1/users/:userId

module.exports = {
  get: function(app) {
    let controller = (query, params) => {
      // put your code inside here
      return app.yourGetUserFunction(params.userId);
    };

    return {
      controller,
    };
  }
};

UPDATE

An update is a PUT call on an item. Eg: PUT->https://yourwebsite.com/v1/users/:userId

module.exports = {
  update: function(app) {
    let controller = (body, params) => {
      // put your code inside here
      return app.yourUpdateUserFunction(params.userId);
    };

    return {
      controller,
    };
  }
};

PATCH

A patch is a PATCH call on an item. Eg: PATCH->https://yourwebsite.com/v1/users/:userId

module.exports = {
  patch: function(app) {
    let controller = (body, params) => {
      // put your code inside here
      return app.yourPatchUserFunction(params.userId);
    };

    return {
      controller,
    };
  }
};

DELETE

A delete is a DELETE call on an item. Eg: DELETE->https://yourwebsite.com/v1/users/:userId

module.exports = {
  del: function(app) {
    let controller = (body, params) => {
      // put your code inside here
      return app.yourDeleteUserFunction(params.userId);
    };

    return {
      controller,
    };
  }
};

POST action

A post action is a non-CRUD POST call. It can be on an item or a collection. You need to specify in the returned object the target using a key set to item or collection. You can use the same code for both if you want as you can see in the following example.

  • Eg: POST->https://yourwebsite.com/v1/users/:userId/hire => type: item
  • Eg: POST->https://yourwebsite.com/v1/users/hire => type: collection
module.exports = {
  hire: function(app) {
    let controller = (body, params) => {
      // put your code inside here
      return app.yourHireUserFunction(params.userId);
    };

    return {
      item: {
        controller
      },
      collection: {
        controller
      }
    };
  }
};

GET action

A get action is a non-CRUD GET call. It can be on an item or a collection. You need to specify in the returned object the target using a key set to item or collection. You can use the same code for both if you want as you can see in the following example.

  • Eg: GET->https://yourwebsite.com/v1/users/:userId/home-address => type: item
  • Eg: GET->https://yourwebsite.com/v1/users/home-address => type: collection
module.exports = {
  getHomeAddress: function(app) {
    let controller = (query, params) => {
      // put your code inside here
      return app.yourGetHomeAddressUserFunction(params.userId);
    };

    return {
      item: {
        controller
      },
      collection: {
        controller
      }
    };
  }
};

Naming Conventions

URLs

Our RESTful API is going to generate URLs with the collections' names using the plural form. This is also why your files and folders must be using the plural form too. We do not allow camelCase inside an URL. You must you dashes. Eg:

- GET=>https://yourwebsite.com/v1/users/:userId/homeAddress - This is WRONG
+ GET=>https://yourwebsite.com/v1/users/:userId/home-address - This is CORRECT

POST actions

POST actions are meant to be read like an order. For an URL like POST=>https://yourwebsite.com/v1/users/login you must read it like "User login!". An Action is like an order this is why unless a GET call we do not preppend post to the function's name. (reminder, a get action looks like this getHomeAddress)

Because of this naming all CRUD endpoints cannot be called like a post action. This means the following:

  • POST=>https://yourwebsite.com/v1/users/create - this url is impossible
  • POST=>https://yourwebsite.com/v1/users/get - this url is impossible
  • POST=>https://yourwebsite.com/v1/users/list - this url is impossible
  • POST=>https://yourwebsite.com/v1/users/patch - this url is impossible
  • POST=>https://yourwebsite.com/v1/users/delete - this url is impossible

Middlewares

This module handles middleware.

Endpoint's specific

If you want to use some middlewares only on one specific endpoint your endpoint function must return a middlewares array containing your middlewares. See the following example.

module.exports = {
  create: function(app) {
    let middlewares = [
      yourSpecificMiddleware1,
      yourSpecificMiddleware2,
    ];

    let controller = body => {
      // put your code inside here
      return app.yourUserCreationFunction(body);
    };

    return {
      controller,
      middlewares
    };
  }
};

Validation

This module uses joi for the validation of what comes into an endpoint.

By default the module will reject all sent parameters that are not specified in your validation schema. If you want to add a validation schema your endpoint function must return a validation Joi object. See the following for an example.

var Joi = require('prorestify').joi;

module.exports = {
  create: function(app) {
    let validation= Joi.object().keys({
      firstName: Joi.string().min(3).max(50)required(),
      lastName: Joi.string().min(3).max(50)required(),
      email: Joi.string().email(),
    }),

    let controller = body => {
      // put your code inside here
      return app.yourUserCreationFunction(body);
    };

    return {
      controller,
      validation
    };
  }
};