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

graublau

v0.3.12

Published

An object-oriented, loosely-coupled, typescript framework for creating REST applications.

Downloads

20

Readme

Travis Codecov NPM

graublau

An object-oriented, loosely-coupled, typescript framework for creating REST applications, build on top of express, inversify, and winston.

Installation

via npm: npm install graublau

via yarn: yarn add graublau

Usage

This section will guide you through the creation of a graublau application. As an example we will build a simple service that returns some customer information. We will call our application CustomerService.

Creating a REST resource

We start by setting up our REST resources. For now we will only use one, the customer resource.

import {Module} from "graublau";
import {ResourceInterface} from "graublau";
import {inject} from "inversify";
import {provide} from "inversify-binding-decorators";

@provide(CustomerResource)
export class CustomerResource implements ResourceInterface {

    private readonly router: Router;

    constructor(@inject(Module.Types.Express) express: any) {
        this.router = express.Router();
    }

    public getRoutes(): Router {
        this.router.get("/", this.getCustomers);
        return this.router;
    }
    
    private getCustomers(request: Request, response: Response): Customer[] {
        ...
    }
}

The first thing to note here is that we use inversify to get an instance of the express module which has been bound by the Module class of graublau. While you can also load express directly we'd recommend making use of dependency injection which makes it easier to create a unit test for the resource.

All routes have to be defined in the getRoutes(): express.Router method. We assume we only have one route: GET /customers and implement the functionality in a private method.

The class is annotated with @provide(CustomerResource), using inversify's binding decorators, avoiding manual binding. All manual binding have to be performed in the Module.

Setting up the Module

The module is responsible for all dependency injection bindings that are not convered by @provide. It also provides the path to the service config file.

import {TYPES} from "./Types";
import {MongoDBStorage} from "./MongoDBStorage";
import {StorageInterface} from "./StorageInterface";
import {Module} from "graublau";
import {Container} from "inversify";

export class CustomerServiceModule extends Module {

    protected bind(container: Container): void {
        const storage: StorageInterface = container.get(MongoDBStorage);
        container.bind(TYPES.Storage).toConstantValue(storage);
    }
}

The bind() can be used for setting up DIC bindings using inversify's container class. In this example we bind the concrete implementation of MongoDBStorage to the StorageInterface. All classes depending on the interface will hence get the instance of MongoDBStorage.

Initializing the config file

The service config file is a JSON file that holds basic information for a graublau application, as well as all the values you need for your business logic. It is required to have port setting to set up the application port.

{
  "application": {
    "port": 5000
  }
}

Additionally it can also be used to customize graublau's included logger (see below).

Creating the service class

The service class bootstraps the application and takes care for registering all REST resources.

import {CustomerServiceModule} from "./CustomerServiceModule";
import {CustomerResource} from "./CustomerResource";
import {Application} from "graublau";

export class CustomerService {

    private module: CustomerServiceModule;

    public constructor(module: CustomerServiceModule) {
        this.module = module;
    }

    public run(): void {
        const application: Application = this.module.getContainer().get(Application);

        application.addResource("customers", this.module.getContainer().get(CustomerResource));
        application.start();
    }
}

The service consumes the CustomerServiceModule and uses it to load all required dependencies. It then loads the graublau Application using the Module's container. All resources have to be registered with addResource(name: string, resource: ResourceInterface). We set the name to customers so when we start the service, we can call GET /customers to call the method defined in our resource.

index.ts file

All that is left to do is instantiate both module and service, and run the application in our index.ts file.

import "reflect-metadata";
import {CustomerService} from "CustomerService";

const module = new CustomerServiceModule("/path/to/config");
const service = new CustomerService(module);
service.run();

We also use this file to load the reflect-metadata module for inversify.

Logger

graublau also provides a logger that on one hand hides away some of winston's complexity and on the other hand enriches it with additional functionality.

You can automatically use the logger using dependency injection. Per default, it will log plain text to the standard output. If you specify a logger section in your config file you can customize this behavior.

"logger": {
      "minLogLevel": "info",
      "format": "plain",
      "output": "/var/log/customer_service.log"
}
  • format can be set to either "plain" (default value), or "json" for JSON logs.
  • output can be either "stdout" for logging to the console (default value), or a file name to log to a file.
  • minLogLevel specifies the minimum log level - either "debug", "info" (default value), "warn", or "error".

You can use the logger calling one of the debug(), info(), warn(), or error() methods. Each of these methods takes two arguments:

  • The first argument is either a string, or an Error object.
  • The second argument is used for specifying the log context and can be any object (including Errors).

Dependency Injection

graublau uses the inversify dependency injection framework. It is totally possible to build a graublau application without any dependency injection support if you don't have any need for that.

When creating a Module the framework internally sets up all required bindings. Most of these bindings are only relevant to the graublau framework itself, but you can re-use them if necessary.

The following symbols are pre-bound and are exposed through Module.Types:

| Symbol | Bound To | | ----------- | ----------- | | configPath | config path | | ApplicationOptions | internal application options | | LoggerOptions | internal logger options | | Express | express module | | ExpressApplication | instance of express application | | FileSystem | "fs" module | | ProcessEnv | process.env |

Background

graublau is a framework I created extracting some common classes and structures I used in a couple of applications.