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

roboot

v3.0.0

Published

A dependency injection library with support for circular dependencies and async initialization

Downloads

23

Readme

Roboot

Roboot is a minimal dependency container and bootstrapping library for TypeScript and JavaScript. It provides just enough structure to write clean testable code without sacrificing simplicity and flexibility.

Features

  • Helps avoid module side-effects and global state
  • Supports circular dependencies
  • Manages instance lifecycle with support for asynchronous boot and dispose
  • Zero dependencies (excluding dev dependencies)
  • Well tested

Install

npm install roboot

Lifecycle

Lifecycle Diagram

Basic Usage

import { Container, Service } from "roboot";

class Logger extends Service {
  async boot() {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    this.info("Logger booted");
  }

  async dispose() {
    await this.disposed(Counter);
    this.info("Logger disposed");
  }

  info(message) {
    console.log(`INFO: ${message}`);
  }
}

class Counter extends Service {
  private logger = this.use(Logger);
  private count = 0;
  private intervalHandle?: number;

  async boot() {
    await this.booted(Logger);
    this.logger.info("Counter booted");
  }

  async dispose() {
    clearInterval(this.intervalHandle);
    await new Promise((resolve) => setTimeout(resolve, 1000));
    this.logger.info("Counter disposed");
  }

  start() {
    this.logger.info("Starting counter");
    this.intervalHandle = setInterval(() => {
      this.count += 1;
      this.logger.info(this.count);
    }, 1000);
  }
}

function sigintHandler(container: Container) {
  process.on("SIGINT", async () => {
    await container.dispose();
    process.exit(130);
  });
}

new Container()
  .apply(sigintHandler)
  .boot(Counter)
  .then((counter) => counter.start())
  .catch((err) => console.error(err));

API

Container

A Container handles resolving instances of dependencies (including circular dependencies) and executing lifecycle hooks. It also supports binding alternative implementations for a Provider.

container.boot<T>(Root: ProviderClass<T>) => Promise<T>

Create an instance of a root provider resolving and booting all dependencies before the returned promise is resolved with the instance.

container.bind<T>(Provider: ProviderClass<T>, Implementation: ProviderClass<T>) => Container

Provide an alternate implementation for a given provider/service in the context of this container. This must be called before boot().

container.apply((container: Container) => void)

Call a callback function with the container instance and return the container instance. This can be useful for referencing the container when chaining.

Provider<T> | Service

Provider and Service are both abstract base classes intended to be extended. They enable resolving dependencies from the container and defining lifecycle hooks. A Provider<T> can resolve to any value by implementing the provide() => T method. Service is a special case provider that always provides itself.

provider.use<T>(Dependency: ProviderClass<T>) => T

@protected

Create or re-use an existing instance of the dependency from the container. This should be called synchronously when instantiating the class, typically via an instance field initializer.

provider.booted(Dependency: ProviderClass) => Promise<void>

@protected

The booted method used to support initialization dependency order. The returned promise will resolve once the boot method of the dependency has finished. This should only be called within the boot method of a Provider or Service child class.

provider.disposed(Dependency: ProviderClass) => Promise<void>

@protected

The disposed method used to support clean up dependency order. The returned promise will resolve once the dispose method of the dependency has finished. This should only be called within the dispose method of a Provider or Service child class.

provider.boot(instance: T) => Promise<void>

This may be optionally implemented by a child class to execute initialization code that should run when booting the container. There is no need to call super.boot().

provider.dispose(instance: T) => Promise<void>

This may be optionally implemented by a child class to execute clean up code that should run when disposing of the container. There is no need to call super.boot().

provider.provide() => T

For child classes of Provider<T> only. Service implements its own provide.

The provide method must be implemented by each child class of Provider<T>. It returns the value that will be returned when use is called with this class.

registry?: ProviderClass<Registry<T>>

The provide property allows optionally specifying a Registry class that will hold a reference to the resolved instance.

Registry<T>

Registry is an abstract service used for tracking a collection of Providers or Services that resolve to a compatible type. The registry will implement a boot() and/or dispose() that can call the following protected methods to interact with the registered instances.

this.forEach(callback: (T) => void) => void

Call a callback function with each registered instance.

this.map<U>(callback: (T) => U) => U[]

Create an array with the return values of calling a callback with each registered instance.

this.allBooted() => Promise<void>

Return a promise that resolves when the boot method of all registered providers has resolved.

this.allDisposed() => Promise<void>

Return a promise that resolves when the dispose method of all registered providers has resolved.

License

Roboot is licensed under the MIT license. See LICENSE.md.