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

ravelo

v0.0.12

Published

Just another framework

Readme

Ravelo overview & motivation

CircleCI codecov License: MIT

My motivation for building this project is so that we can build a framework that gives me the ability to split applications into multiple independent services.

It is expected to have a registry service which contains all configuration options for all your services. This service can also be a way to centralize the health of the entire architecture much like a todo list of services with its health/version status.

Prerequisites

Please check the .nvmrc file to see which version of node it is required.

How to install

all you need to do is run npm i -S ravelo.

Build your first service (registry service)

To get started, we are going to build a service that takes care of centralizing config information for all services. And giving you a set of functionality to find out the health of your architecture.

Once you install ravelo as the dependency, do as follows in your index.js:

const Ravelo = require('ravelo');

const init = async () => {
  const server = await Ravelo.init();

  if (require.main === module) {
    server.log(`Ravelo Service: ${server.app.config.name}:${server.app.config.version}`);
    server.log(`Server running at: ${server.info.uri}`);
    await server.start();
  }

  return server;
};

module.exports = init();

the Server that Ravelo.init() returns is a hapijs server. For more information about which version of hapi we are using please refer to our package.js.

Next, create config/local.json and add the following:

{
  "registry": {
    "enableServiceController": true,
    "enableRegistryController": true,
    "service": {
      "port": 3000,
      "host": "localhost"
    },
    "debug": { "request": [ "error" ] },
    "internalURL": "http://localhost:3000"
  }
}

Bare in mind that you will need to replace registry with the name you'll find in your package.json.

The next thing you need to do is run it but make sure that you set the NODE_ENV environment variable to local:

$ NODE_ENV=local node index.js

and visit http://localhost:3000/_service. If everything went well, you should be able to see the following:

{
    "name": "registry",
    "version": "1.0.0",
    "env": "local"
}

Now visit http://localhost:3000/_registry/health. If everything went well, you should be able to see the following:

{
    "registry": {
        "statusCode": 200,
        "version": "1.0.0",
        "env": "local"
    }
}

Build your second service (consumer service)

We're calling this a consumer service thinking that its purpose is to be used by an application through a set of APIs. This service will hit the registry service to pull the configuration options from the registry before running.

The first thing we do is to go back to the registry repo and update the config/local.json to the following and restart the registry service for the configuration changes to take effect system wide:

{
  "registry": {
    "enableServiceController": true,
    "enableRegistryController": true,
    "service": {
      "port": 3000,
      "host": "localhost"
    },
    "debug": { "request": [ "error" ] },
    "internalURL": "http://localhost:3000"
  },
  "consumer": {
    "enableServiceController": true,
    "enableGatewayAccess": true,
    "service": {
      "port": 3002,
      "host": "localhost"
    },
    "debug": {
      "request": [ "error" ]
    },
    "internalURL": "http://localhost:3002"
  }
}

if you hit http://localhost:3000/_registry/health you should see the following response:

{
  "registry": {
    "statusCode": 200,
    "version": "1.0.0",
    "env": "local"
  },
    "consumer": {
    "statusCode": 503,
    "description": "Service not available"
  }
}

now we have 2 services registered in the registry service and now i want to add my consumer registry. Create a new repo, install ravelo as a dependency and add the following to index.js:

const Ravelo = require('ravelo');

const init = async () => {
  const server = await Ravelo.init();

  if (require.main === module) {
    server.log(`Ravelo Service: ${server.app.config.name}:${server.app.config.version}`);
    server.log(`Server running at: ${server.info.uri}`);
    await server.start();
  }

  return server;
};

module.exports = init();

You can see that this snippet of code looks exactly to the index.js file in the registry service look exactly the same as the one placed in the consumer service. Its behaviour comes from the configuration where each service is meant to do different things.

Now start the consuer service by running the following on a new tab:

$ NODE_ENV=local node index.js

.. if you hit http://localhost:3000/_registry/health (which is the registry health endpoint), you should see the following response:

{
  "registry": {
    "statusCode": 200,
    "version": "1.0.0",
    "env": "local"
  },
  "consumer": {
    "statusCode": 200,
    "name": "consumer",
    "version": "1.0.0",
    "env": "local"
  }
}

this means that you now have 2 services running however, my consumer isn't really doing anything at all so i'm going add a simple hello world endpoint by adding the following after const server = await Ravelo.init();:


  // ...
  server.route({
    method: 'GET',
    path: '/hello-world',
    handler: async () => {
      return {
        message: 'Hello World'
      };
    }
  });
  // ...

Remember that the server is a plain hapijs server so what you do with it is read its documentation if you are not familiar with the framework! anyways, restart the server and hit http://localhost:3001/hello-world. If you see the following then you are on the right path:

{
  "message": "Hello World"
}

Build your third service (gateway service)

The next thing you may want to do is to implement a way to protect your endpoints behind a gateway. Say your gateway is in a public subnet and the rest of your services leave within a private subnet SO, the next thing is to build a gateway service.

Lets update the config/local.json to the following:

{
  "registry": {
    "enableRegistryController": true,
    "enableServiceController": true,
    "service": {
      "port": 3000,
      "host": "localhost"
    },
    "debug": { "request": [ "error" ] },
    "internalURL": "http://localhost:3000"
  },
  "consumer": {
    "enableServiceController": true,
    "enableGatewayAccess": true,
    "service": {
      "port": 3001,
      "host": "localhost"
    },
    "debug": { "request": [ "error" ] },
    "internalURL": "http://localhost:3001"
  },
  "gateway": {
    "enableGatewayProxy": true,
    "enableServiceController": true,
    "service": {
      "port": 3002,
      "host": "localhost"
    },
    "debug": { "request": [ "error" ] },
    "internalURL": "http://localhost:3002"
  }
}

NOTE: Don't forget that since you are adding new config options, you need to restart the registry service. The consumer service does not need to be restarted at the moment, because we don't need the consumer to communicate to the gateway service AND the consumer service isn't affected by the changes made in the registry service at the moment.

Now we do the same we've been doing for the other services which is install ravelo as a dependency and create that index.js with the same content:

const Ravelo = require('ravelo');

const init = async () => {
  const server = await Ravelo.init();

  if (require.main === module) {
    server.log(`Ravelo Service: ${server.app.config.name}:${server.app.config.version}`);
    server.log(`Server running at: ${server.info.uri}`);
    await server.start();
  }

  return server;
};

module.exports = init();

and start the gateway service by running:

$ NODE_ENV=local node index.js

then hit http://localhost:3000/_registry/health:

{
  "registry": {
    "statusCode": 200,
    "version": "1.0.0",
    "env": "local"
  },
  "consumer": {
    "statusCode": 200,
    "name": "consumer",
    "version": "1.0.0",
    "env": "local"
  },
  "gateway": {
    "statusCode": 200,
    "name": "gateway",
    "version": "1.0.0",
    "env": "local"
  }
}

Now when hit the consumer API through the gateway http://localhost:3002/consumer/hello-world you should see the same as if you were hitting the consumer api itself http://localhost:3001/hello-world

Troubleshooting

So far we haven't experienced any but we're sure something will come up pretty soon.

Disclaimer

Use this project at your own risk. We do not becom responsible for the security of your application should you choose this project. Make sure you know what you are doing should you use this in production environments.