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

hathor

v0.0.10

Published

Hathor is a wrapper over the top of Hapi that includes all the boilerplate code and features out of the box.

Downloads

6

Readme

Server

Hathor is a wrapper over the top of Hapi. The goal is to remove boilerplate code from Hapi projects and introduce an easy and (hopefully) seamless upgrade path between Hapi versions.

If you have built any project and then tried to stay up with the latest version of Hapi you know that many times there are frustrating and/or breaking changes between versions. Some people (including myself) have approached this by creating boiler plate projects. But then you have the pain of keeping all your code bases in sync with your boiler plate. If there are major changes then you have to deal with merging the changes, correcting conflicts, pulling in new libraries, etc...

Hathor aims to solve all of this by abstracting the common things from projects into modules that provide a stable API. This stable version is them mutated to fit the latest "needs" of Hapi without any developer changes necessary. This is the goal, at least as much as possible.

Unless you want to deal with the pain and agony of broken code, bugs, etc... NEVER install a version of Hathor that begins with 0. Instead install the version of Hathor that matches the version of Hapi you want to support.

Hathor is still in early development, no features will be removed but new features will be added. As long as you stick to the basic usage outlined below, you shouldn't notice any changes.

As an example if you need Hapi 16 support, then use npm install --save hathor@16, for version 17 use npm install --save hathor@17

Install

npm install --save hathor@16

What's provided

Out of the box Hathor provides a static file server via inert, automatic route loading, and automatic plugin loading. With a few configuration options and some npm installs Hathor can add authentication to your project. Don't want authentication in your dev environment, simply don't configure it there. Want a different configuration in different environments, then just configure each as you see fit.

Static files

Currently static file serving is built into Hathor, eventually this will be broke out into its own plugin that will be included by default. This will allow users to provide custom static page serving for things like; multiple source folders, server side rendering, rendering templated source files, etc...

Configuration

Configurations are supplied through configuration providers build on top of Hathor-Config. Currently available are:

  • hathor-config - Base configuration provider
  • hathor-file-config - Utilize configuration values from JavaScript configuration files
    • Future: Add support; json, yaml, etc?

Planned configuration loaders are:

  • hathor-cmd-config - Utilize command line arguments as configuration values
  • hathor-env-config - Utilize environment variables as configuration values
  • hathor-consul-config - Utilize the Consul key/value store to provide configuration values

Authentication

Currently supported authentication plugins are:

  • hathor-basic-auth - Basic authentication
  • hathor-jwt-auth - Support for JWT authentication
  • hathor-cookie-auth - Support for Cookie based authentication

Basic Usage

Assumes a setup as follows:

npm install --save hathor hathor-file-config hathor-logger hathor-basic-auth

index.js

const {Server} = require('hathor');
const Config = require('hathor-config');
const FileConfig = require('hathor-file-config');
const logger = require('hathor-logger');

const config = new Config();
config.merge(new FileConfig('config/config'));
config.set('server.logger', logger);

const serverConfig = config.get('server', {});
const server = new Server(serverConfig);
server.plugins.push(require('hathor-swagger'));

server.start((err)=>{
  if(err){
    logger.error(err);
    process.exit(1);
  }
});

config/config.js

const authModule = 'basic-auth';
//const authModule = 'cookie-auth';
//const authModule = 'jwt-auth';

const path = require('path');
// NOTE: This is here in case you want to use JWT or Cookie auth, etc
const key = (()=>{
  const logger = require('hathor-logger');
  const fs = require('fs');
  const keyFilename = path.resolve('./config/key.pem');
  try{
    logger.info('Loading key file from:', keyFilename);
    const key = fs.readFileSync(keyFilename).toString();
    logger.info('Key successfully loaded')
    return key;
  }catch(e){
    logger.error('Error loading key file:', e);
    logger.info('Generating new key file: ', keyFilename);
    const key = require('crypto').randomBytes(256).toString('base64');
    fs.writeFileSync(keyFilename, key);
    logger.info('Generated key file: ', keyFilename);
    return key;
  }
})();

module.exports = {
  server: {
    swagger: {
      ui: {
        title: 'Test application API'
      },
      swagger: {
        info: {
          title: 'API Documentation'
        }
      }
    },

    //static: true, // serve static content
    //webroot: 'ui/build', // Set the webroot for static content
    connection: { // Listen on localhost:9001
      port: 9001,
      host: 'localhost'
    },
    auth: { // Use auth
      //static: true, // secure static content
      key,
      module: authModule,
      ttl: 1000 * 60 * 3, // 3 minutes TTL
      whitelist: [ // Always allow access to the login folder
        'login'
      ],
      blacklist: [ // Never allow access to the login/private.html file
        'login/private.html'
      ],
      users: [ // Setup a test user
        {
          username: 'test',
          password: 'person' // This could also be a bcrypt hash
        }
      ]
    }
  }
};

routes/hello/index.js

const Joi = require('joi');

module.exports = {
  method: 'GET',
  path: '/api/hello',
  auth: true,
  config: {
    description: 'Basic hello route.',
    notes: 'Returns a greeting based on to passed in.',
    tags: ['api'],
    validate: {
      query: {
        to: Joi.string().optional().description('Who to greet')
      }
    },
    response: {
      status: {
        200: Joi.string()
      }
    }
  },
  handler(req, reply){
    const to = req.query.to || 'World';
    return reply(`Hello ${to}!`);
  }
};

API

Server(options)

Options

{
  static: Boolean, // default true
  webroot: String, // defaults to 'ui/build'
  connection: {
    host: String, // default os.hostname
    port: Number, // default 9000
  },
  auth: {
    static: Boolean, // Place auth on static pages or not
    key: String, // Key, certificate, etc for auth modules that require it
    module: String, // Name or location of the auth module to use
    ttl: Number, // The TTL for the connection in ms, EX: for 1 year: 365 * 24 * 60 * 60 * 1000
    whitelist: [ // Whitelist of static assets to not place behind auth
      String
    ],
    blacklist: [ // Blacklist of static assets to always place behind auth
      String
    ],
    users: [ // Array of users for development
      {
        username: String,
        password: String
      }
    ],
    findUser(username, password, callback){ // function to lookup users, returns callback(err, isValid, session)
    },
    plugin: { // configuration overrides for the underlying Hapi auth plugin
    }
  }
}

Core Plugins

  • Logger - Default logger for Hathor
  • Utilities - Utility library providing some generic methods for common tasks.
  • Base Configuration Provider - Configuration Provider for Hathor. Generally this will be combined with other providers and not used in a standalone manor.
  • File Configuration Provider - Provides configuration values from a JSON file.
  • Basic Auth - Provides Basic Authentication to a Hathor application.
  • Cookie Auth - Provides Cookie Authentication to a Hathor application.
  • JWT Auth - Provides JSON Web Token Authentication to a Hathor application.
  • Swagger Documentation - Provides Swagger documentation for properly decorated routes.