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

@thenja/di

v0.0.2

Published

Very simple and lean dependency injection for Typescript

Downloads

460

Readme

Test Coverage-shield-badge-1

DI - Dependency Injection

A very simple & lean dependency injection container for Typescript.

Key features

  • Decorator to Inject services
  • Light weight & simple to use
  • No dependencies

How to use

  1. Install the module

npm install @thenja/di --save

  1. Import and use the module
import { DI, IDIProvider } from '@thenja/di';

// our singleton service
class UtilityService {}

class User {
  @DI.Inject(UtilityService)
  private utilSrv: UtilityService;
}

Examples

Inject using a factory

import { DI, IDIProvider } from '@thenja/di';

let env = 'dev';

abstract class BaseStorageService {
  abstract name: string;
}
class FileStorageService extends BaseStorageService {
  name = 'file-storage';
}
class MemoryStorageService extends BaseStorageService {
  name = 'memory-storage';
}

const storageFactory: IDIProvider = {
  provide: BaseStorageService,
  useFactory: () => {
    if (env === 'dev') return new MemoryStorageService();
    return new FileStorageService();
  }
};

class MyTest {
  @DI.Inject(storageFactory)
  public storageSrv: BaseStorageService;
}

Inject using a different class

import { DI, IDIProvider } from '@thenja/di';

class UserModel { name = 'user'; }
class MockUserModel { name = 'mock-user'; }

const userProvider: IDIProvider = {
  provide: UserModel,
  useClass: MockUserModel
};

class MyTest {
  @DI.Inject(userProvider)
  public user: UserModel;
}

Dealing with models

Models are usually not singletons, however, we should still use dependency injection via the factory pattern to create the new model instances.

// BAD

class UserSettingsModel {}

class UserModel {
  private settings: UserSettingsModel;

  constructor() {
    // makes it hard to mock settings, we should be using dependency injection
    this.settings = new UserSettingsModel();
  }
}

// BETTER

class UserSettingsModel {}

class UserModel {
  constructor(private settings: UserSettingsModel) {}
}

class UserModelFactory {
  create(): UserModel {
    return new UserModel(new UserSettingsModel());
  }
}

class UserService {
  @DI.Inject(UserModelFactory)
  private userModelFactory: UserModelFactory;

  getUser(): UserModel {
    // we can now mock the UserModelFactory
    return this.userModelFactory.create();
  }
}

Methods / API

@DI.Inject(service: any|IDIProvider)

Inject a singleton service into a class. You can either pass in a class object, or a IDIProvider object (see examples above).

@DI.override(service: any|IDIProvider, dependencyInstance: any)

Override a service. Useful for mocking services.

@DI.getService(service: any|IDIProvider): any

Get the service instance that is stored inside the dependency container.

@DI.clear()

Clear the dependency container.

@DI.getContainer(): { [key: string]: any }

Get the dependency container. Basically, the container is a json object with the key being the name of the service (randomly generated) and the value being the instance of the service.

@DI.getContainerName(service: any|IDIProvider): string

Get the name used in the dependency container for a particular service.

Development

npm run init - Setup the app for development (run once after cloning)

npm run dev - Run this command when you want to work on this app. It will compile typescript, run tests and watch for file changes.

Distribution

npm run build -- -v <version> - Create a distribution build of the app.

-v (version) - [Optional] Either "patch", "minor" or "major". Increase the version number in the package.json file.

The build command creates a /compiled directory which has all the javascript compiled code and typescript definitions. As well, a /dist directory is created that contains a minified javascript file.

Testing

Tests are automatically ran when you do a build.

npm run test - Run the tests. The tests will be ran in a nodejs environment. You can run the tests in a browser environment by opening the file /spec/in-browser/SpecRunner.html.

License

MIT © Nathan Anderson