A very simple & lean dependency injection container for Typescript.
- Decorator to Inject services
- Light weight & simple to use
- No dependencies
- Install the module
npm install @thenja/di --save
- Import and use the module
import { DI, IDIProvider } from '@thenja/di';
// our singleton service
class UtilityService {}
class User {
@DI.Inject(UtilityService)
private utilSrv: UtilityService;
}
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;
}
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;
}
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();
}
}
Inject a singleton service into a class. You can either pass in a class object, or a IDIProvider object (see examples above).
Override a service. Useful for mocking services.
Get the service instance that is stored inside the dependency container.
Clear the dependency container.
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.
Get the name used in the dependency container for a particular service.
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.
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.
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.
MIT © Nathan Anderson