0.0.2 • Published 3 years ago

@thenja/di v0.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

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